Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: chrome/browser/extensions/external_pref_extension_loader.cc

Issue 10692168: Moved ExternalExtensionLoaders/Providers into extensions namespace (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/external_pref_extension_loader.h"
6
7 #include "base/bind.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/json/json_file_value_serializer.h"
11 #include "base/json/json_string_value_serializer.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/path_service.h"
15 #include "base/string_util.h"
16 #include "base/utf_string_conversions.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "content/public/browser/browser_thread.h"
19
20 using content::BrowserThread;
21
22 namespace {
23
24 FilePath::CharType kExternalExtensionJson[] =
25 FILE_PATH_LITERAL("external_extensions.json");
26
27 std::set<FilePath> GetPrefsCandidateFilesFromFolder(
28 const FilePath& external_extension_search_path) {
29 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
30
31 std::set<FilePath> external_extension_paths;
32
33 if (!file_util::PathExists(external_extension_search_path)) {
34 // Does not have to exist.
35 return external_extension_paths;
36 }
37
38 file_util::FileEnumerator json_files(
39 external_extension_search_path,
40 false, // Recursive.
41 file_util::FileEnumerator::FILES);
42 #if defined(OS_WIN)
43 FilePath::StringType extension = UTF8ToWide(std::string(".json"));
44 #elif defined(OS_POSIX)
45 FilePath::StringType extension(".json");
46 #endif
47 do {
48 FilePath file = json_files.Next();
49 if (file.BaseName().value() == kExternalExtensionJson)
50 continue; // Already taken care of elsewhere.
51 if (file.empty())
52 break;
53 if (file.MatchesExtension(extension)) {
54 external_extension_paths.insert(file.BaseName());
55 } else {
56 DVLOG(1) << "Not considering: " << file.LossyDisplayName()
57 << " (does not have a .json extension)";
58 }
59 } while (true);
60
61 return external_extension_paths;
62 }
63
64 // Extracts extension information from a json file serialized by |serializer|.
65 // |path| is only used for informational purposes (outputted when an error
66 // occurs). An empty dictionary is returned in case of failure (e.g. invalid
67 // path or json content).
68 // Caller takes ownership of the returned dictionary.
69 DictionaryValue* ExtractExtensionPrefs(base::ValueSerializer* serializer,
70 const FilePath& path) {
71 std::string error_msg;
72 Value* extensions = serializer->Deserialize(NULL, &error_msg);
73 if (!extensions) {
74 LOG(WARNING) << "Unable to deserialize json data: " << error_msg
75 << " in file " << path.value() << ".";
76 return new DictionaryValue;
77 }
78
79 DictionaryValue* ext_dictionary = NULL;
80 if (extensions->GetAsDictionary(&ext_dictionary))
81 return ext_dictionary;
82
83 LOG(WARNING) << "Expected a JSON dictionary in file "
84 << path.value() << ".";
85 return new DictionaryValue;
86 }
87
88 } // namespace
89
90 ExternalPrefExtensionLoader::ExternalPrefExtensionLoader(int base_path_id,
91 Options options)
92 : base_path_id_(base_path_id),
93 options_(options) {
94 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
95 }
96
97 const FilePath ExternalPrefExtensionLoader::GetBaseCrxFilePath() {
98 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
99
100 // |base_path_| was set in LoadOnFileThread().
101 return base_path_;
102 }
103
104 void ExternalPrefExtensionLoader::StartLoading() {
105 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
106 BrowserThread::PostTask(
107 BrowserThread::FILE, FROM_HERE,
108 base::Bind(&ExternalPrefExtensionLoader::LoadOnFileThread, this));
109 }
110
111 void ExternalPrefExtensionLoader::LoadOnFileThread() {
112 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
113
114 // TODO(skerner): Some values of base_path_id_ will cause
115 // PathService::Get() to return false, because the path does
116 // not exist. Find and fix the build/install scripts so that
117 // this can become a CHECK(). Known examples include chrome
118 // OS developer builds and linux install packages.
119 // Tracked as crbug.com/70402 .
120 if (!PathService::Get(base_path_id_, &base_path_))
121 return;
122
123 scoped_ptr<DictionaryValue> prefs(new DictionaryValue);
124
125 ReadExternalExtensionPrefFile(prefs.get());
126 if (!prefs->empty())
127 LOG(WARNING) << "You are using an old-style extension deployment method "
128 "(external_extensions.json), which will soon be "
129 "deprecated. (see http://code.google.com/chrome/"
130 "extensions/external_extensions.html )";
131
132 ReadStandaloneExtensionPrefFiles(prefs.get());
133
134 prefs_.swap(prefs);
135 if (!prefs_.get())
136 prefs_.reset(new DictionaryValue());
137
138 if (base_path_id_ == chrome::DIR_EXTERNAL_EXTENSIONS) {
139 UMA_HISTOGRAM_COUNTS_100("Extensions.ExternalJsonCount",
140 prefs_->size());
141 }
142
143 // If we have any records to process, then we must have
144 // read at least one .json file. If so, then we should have
145 // set |base_path_|.
146 if (!prefs_->empty())
147 CHECK(!base_path_.empty());
148
149 BrowserThread::PostTask(
150 BrowserThread::UI, FROM_HERE,
151 base::Bind(&ExternalPrefExtensionLoader::LoadFinished, this));
152 }
153
154 void ExternalPrefExtensionLoader::ReadExternalExtensionPrefFile(
155 DictionaryValue* prefs) {
156 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
157 CHECK(NULL != prefs);
158
159 FilePath json_file = base_path_.Append(kExternalExtensionJson);
160
161 if (!file_util::PathExists(json_file)) {
162 // This is not an error. The file does not exist by default.
163 return;
164 }
165
166 if (IsOptionSet(ENSURE_PATH_CONTROLLED_BY_ADMIN)) {
167 #if defined(OS_MACOSX)
168 if (!file_util::VerifyPathControlledByAdmin(json_file)) {
169 LOG(ERROR) << "Can not read external extensions source. The file "
170 << json_file.value() << " and every directory in its path, "
171 << "must be owned by root, have group \"admin\", and not be "
172 << "writable by all users. These restrictions prevent "
173 << "unprivleged users from making chrome install extensions "
174 << "on other users' accounts.";
175 return;
176 }
177 #else
178 // The only platform that uses this check is Mac OS. If you add one,
179 // you need to implement file_util::VerifyPathControlledByAdmin() for
180 // that platform.
181 NOTREACHED();
182 #endif // defined(OS_MACOSX)
183 }
184
185 JSONFileValueSerializer serializer(json_file);
186 scoped_ptr<DictionaryValue> ext_prefs(
187 ExtractExtensionPrefs(&serializer, json_file));
188 if (ext_prefs.get())
189 prefs->MergeDictionary(ext_prefs.get());
190 }
191
192 void ExternalPrefExtensionLoader::ReadStandaloneExtensionPrefFiles(
193 DictionaryValue* prefs) {
194 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
195 CHECK(NULL != prefs);
196
197 // First list the potential .json candidates.
198 std::set<FilePath>
199 candidates = GetPrefsCandidateFilesFromFolder(base_path_);
200 if (candidates.empty()) {
201 DVLOG(1) << "Extension candidates list empty";
202 return;
203 }
204
205 // For each file read the json description & build the proper
206 // associated prefs.
207 for (std::set<FilePath>::const_iterator it = candidates.begin();
208 it != candidates.end();
209 ++it) {
210 FilePath extension_candidate_path = base_path_.Append(*it);
211
212 std::string id =
213 #if defined(OS_WIN)
214 WideToASCII(
215 extension_candidate_path.RemoveExtension().BaseName().value());
216 #elif defined(OS_POSIX)
217 extension_candidate_path.RemoveExtension().BaseName().value().c_str();
218 #endif
219
220 DVLOG(1) << "Reading json file: "
221 << extension_candidate_path.LossyDisplayName().c_str();
222
223 JSONFileValueSerializer serializer(extension_candidate_path);
224 scoped_ptr<DictionaryValue> ext_prefs(
225 ExtractExtensionPrefs(&serializer, extension_candidate_path));
226 if (ext_prefs.get()) {
227 DVLOG(1) << "Adding extension with id: " << id;
228 prefs->Set(id, ext_prefs.release());
229 }
230 }
231 }
232
233 ExternalTestingExtensionLoader::ExternalTestingExtensionLoader(
234 const std::string& json_data,
235 const FilePath& fake_base_path)
236 : fake_base_path_(fake_base_path) {
237 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
238 JSONStringValueSerializer serializer(json_data);
239 FilePath fake_json_path = fake_base_path.AppendASCII("fake.json");
240 testing_prefs_.reset(ExtractExtensionPrefs(&serializer, fake_json_path));
241 }
242
243 void ExternalTestingExtensionLoader::StartLoading() {
244 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
245 prefs_.reset(testing_prefs_->DeepCopy());
246 LoadFinished();
247 }
248
249 ExternalTestingExtensionLoader::~ExternalTestingExtensionLoader() {}
250
251 const FilePath ExternalTestingExtensionLoader::GetBaseCrxFilePath() {
252 return fake_base_path_;
253 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698