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

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

Issue 6992047: Change the web store private install API to accept a localized extension name. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/crx_installer.h" 5 #include "chrome/browser/extensions/crx_installer.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 9
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 23 matching lines...) Expand all
34 #include "content/common/notification_type.h" 34 #include "content/common/notification_type.h"
35 #include "grit/chromium_strings.h" 35 #include "grit/chromium_strings.h"
36 #include "grit/generated_resources.h" 36 #include "grit/generated_resources.h"
37 #include "grit/theme_resources.h" 37 #include "grit/theme_resources.h"
38 #include "third_party/skia/include/core/SkBitmap.h" 38 #include "third_party/skia/include/core/SkBitmap.h"
39 #include "ui/base/l10n/l10n_util.h" 39 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h" 40 #include "ui/base/resource/resource_bundle.h"
41 41
42 namespace { 42 namespace {
43 43
44 struct WhitelistedInstallData { 44 struct Whitelist {
45 WhitelistedInstallData() {} 45 Whitelist() {}
46 std::set<std::string> ids; 46 std::set<std::string> ids;
47 std::map<std::string, linked_ptr<DictionaryValue> > manifests; 47 std::map<std::string, linked_ptr<CrxInstaller::WhitelistEntry> > entries;
48 }; 48 };
49 49
50 static base::LazyInstance<WhitelistedInstallData> 50 static base::LazyInstance<Whitelist>
51 g_whitelisted_install_data(base::LINKER_INITIALIZED); 51 g_whitelisted_install_data(base::LINKER_INITIALIZED);
52 52
53 } // namespace 53 } // namespace
54 54
55 // static 55 // static
56 void CrxInstaller::SetWhitelistedInstallId(const std::string& id) { 56 void CrxInstaller::SetWhitelistedInstallId(const std::string& id) {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 57 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
58 g_whitelisted_install_data.Get().ids.insert(id); 58 g_whitelisted_install_data.Get().ids.insert(id);
59 } 59 }
60 60
61 // static 61 // static
62 void CrxInstaller::SetWhitelistedManifest(const std::string& id, 62 void CrxInstaller::SetWhitelistEntry(const std::string& id,
63 DictionaryValue* parsed_manifest) { 63 CrxInstaller::WhitelistEntry* entry) {
64 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 64 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
65 WhitelistedInstallData& data = g_whitelisted_install_data.Get(); 65 Whitelist& data = g_whitelisted_install_data.Get();
66 data.manifests[id] = linked_ptr<DictionaryValue>(parsed_manifest); 66 data.entries[id] = linked_ptr<CrxInstaller::WhitelistEntry>(entry);
67 } 67 }
68 68
69 // static 69 // static
70 const DictionaryValue* CrxInstaller::GetWhitelistedManifest( 70 const CrxInstaller::WhitelistEntry* CrxInstaller::GetWhitelistEntry(
71 const std::string& id) { 71 const std::string& id) {
72 WhitelistedInstallData& data = g_whitelisted_install_data.Get(); 72 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
73 if (ContainsKey(data.manifests, id)) 73 Whitelist& data = g_whitelisted_install_data.Get();
74 return data.manifests[id].get(); 74 if (ContainsKey(data.entries, id))
75 return data.entries[id].get();
75 else 76 else
76 return NULL; 77 return NULL;
77 } 78 }
78 79
79 // static 80 // static
80 DictionaryValue* CrxInstaller::RemoveWhitelistedManifest( 81 CrxInstaller::WhitelistEntry* CrxInstaller::RemoveWhitelistEntry(
81 const std::string& id) { 82 const std::string& id) {
82 WhitelistedInstallData& data = g_whitelisted_install_data.Get(); 83 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83 if (ContainsKey(data.manifests, id)) { 84 Whitelist& data = g_whitelisted_install_data.Get();
84 DictionaryValue* manifest = data.manifests[id].release(); 85 if (ContainsKey(data.entries, id)) {
85 data.manifests.erase(id); 86 CrxInstaller::WhitelistEntry* entry = data.entries[id].release();
86 return manifest; 87 data.entries.erase(id);
88 return entry;
87 } 89 }
88 return NULL; 90 return NULL;
89 } 91 }
90 92
91 // static 93 // static
92 bool CrxInstaller::IsIdWhitelisted(const std::string& id) { 94 bool CrxInstaller::IsIdWhitelisted(const std::string& id) {
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 95 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94 std::set<std::string>& ids = g_whitelisted_install_data.Get().ids; 96 std::set<std::string>& ids = g_whitelisted_install_data.Get().ids;
95 return ContainsKey(ids, id); 97 return ContainsKey(ids, id);
96 } 98 }
97 99
98 // static 100 // static
99 bool CrxInstaller::ClearWhitelistedInstallId(const std::string& id) { 101 bool CrxInstaller::ClearWhitelistedInstallId(const std::string& id) {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 102 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
101 std::set<std::string>& ids = g_whitelisted_install_data.Get().ids; 103 std::set<std::string>& ids = g_whitelisted_install_data.Get().ids;
102 if (ContainsKey(ids, id)) { 104 if (ContainsKey(ids, id)) {
103 ids.erase(id); 105 ids.erase(id);
104 return true; 106 return true;
105 } 107 }
106 return false; 108 return false;
107 } 109 }
108 110
109 CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> frontend_weak, 111 CrxInstaller::CrxInstaller(base::WeakPtr<ExtensionService> frontend_weak,
110 ExtensionInstallUI* client) 112 ExtensionInstallUI* client)
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 180
179 void CrxInstaller::ConvertUserScriptOnFileThread() { 181 void CrxInstaller::ConvertUserScriptOnFileThread() {
180 std::string error; 182 std::string error;
181 scoped_refptr<Extension> extension = 183 scoped_refptr<Extension> extension =
182 ConvertUserScriptToExtension(source_file_, original_url_, &error); 184 ConvertUserScriptToExtension(source_file_, original_url_, &error);
183 if (!extension) { 185 if (!extension) {
184 ReportFailureFromFileThread(error); 186 ReportFailureFromFileThread(error);
185 return; 187 return;
186 } 188 }
187 189
188 OnUnpackSuccess(extension->path(), extension->path(), extension); 190 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension);
189 } 191 }
190 192
191 void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) { 193 void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) {
192 if (!BrowserThread::PostTask( 194 if (!BrowserThread::PostTask(
193 BrowserThread::FILE, FROM_HERE, 195 BrowserThread::FILE, FROM_HERE,
194 NewRunnableMethod(this, &CrxInstaller::ConvertWebAppOnFileThread, 196 NewRunnableMethod(this, &CrxInstaller::ConvertWebAppOnFileThread,
195 web_app))) 197 web_app)))
196 NOTREACHED(); 198 NOTREACHED();
197 } 199 }
198 200
199 void CrxInstaller::ConvertWebAppOnFileThread( 201 void CrxInstaller::ConvertWebAppOnFileThread(
200 const WebApplicationInfo& web_app) { 202 const WebApplicationInfo& web_app) {
201 std::string error; 203 std::string error;
202 scoped_refptr<Extension> extension( 204 scoped_refptr<Extension> extension(
203 ConvertWebAppToExtension(web_app, base::Time::Now())); 205 ConvertWebAppToExtension(web_app, base::Time::Now()));
204 if (!extension) { 206 if (!extension) {
205 // Validation should have stopped any potential errors before getting here. 207 // Validation should have stopped any potential errors before getting here.
206 NOTREACHED() << "Could not convert web app to extension."; 208 NOTREACHED() << "Could not convert web app to extension.";
207 return; 209 return;
208 } 210 }
209 211
210 // TODO(aa): conversion data gets lost here :( 212 // TODO(aa): conversion data gets lost here :(
211 213
212 OnUnpackSuccess(extension->path(), extension->path(), extension); 214 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension);
213 } 215 }
214 216
215 bool CrxInstaller::AllowInstall(const Extension* extension, 217 bool CrxInstaller::AllowInstall(const Extension* extension,
216 std::string* error) { 218 std::string* error) {
217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
218 DCHECK(error); 220 DCHECK(error);
219 221
220 // Make sure the expected id matches. 222 // Make sure the expected id matches.
221 if (!expected_id_.empty() && expected_id_ != extension->id()) { 223 if (!expected_id_.empty() && expected_id_ != extension->id()) {
222 *error = base::StringPrintf( 224 *error = base::StringPrintf(
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 306
305 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallCause", 307 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallCause",
306 install_cause(), 308 install_cause(),
307 extension_misc::NUM_INSTALL_CAUSES); 309 extension_misc::NUM_INSTALL_CAUSES);
308 310
309 ReportFailureFromFileThread(error_message); 311 ReportFailureFromFileThread(error_message);
310 } 312 }
311 313
312 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir, 314 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
313 const FilePath& extension_dir, 315 const FilePath& extension_dir,
316 const DictionaryValue* original_manifest,
314 const Extension* extension) { 317 const Extension* extension) {
315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
316 319
317 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", 320 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource",
318 install_source(), Extension::NUM_LOCATIONS); 321 install_source(), Extension::NUM_LOCATIONS);
319 322
320 323
321 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", 324 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause",
322 install_cause(), 325 install_cause(),
323 extension_misc::NUM_INSTALL_CAUSES); 326 extension_misc::NUM_INSTALL_CAUSES);
324 327
325 // Note: We take ownership of |extension| and |temp_dir|. 328 // Note: We take ownership of |extension| and |temp_dir|.
326 extension_ = extension; 329 extension_ = extension;
327 temp_dir_ = temp_dir; 330 temp_dir_ = temp_dir;
328 331
332 original_manifest_.reset(original_manifest->DeepCopy());
333
329 // We don't have to delete the unpack dir explicity since it is a child of 334 // We don't have to delete the unpack dir explicity since it is a child of
330 // the temp dir. 335 // the temp dir.
331 unpacked_extension_root_ = extension_dir; 336 unpacked_extension_root_ = extension_dir;
332 337
333 std::string error; 338 std::string error;
334 if (!AllowInstall(extension, &error)) { 339 if (!AllowInstall(extension, &error)) {
335 ReportFailureFromFileThread(error); 340 ReportFailureFromFileThread(error);
336 return; 341 return;
337 } 342 }
338 343
339 if (client_) { 344 if (client_) {
340 Extension::DecodeIcon(extension_.get(), Extension::EXTENSION_ICON_LARGE, 345 Extension::DecodeIcon(extension_.get(), Extension::EXTENSION_ICON_LARGE,
341 &install_icon_); 346 &install_icon_);
342 } 347 }
343 348
344 if (!BrowserThread::PostTask( 349 if (!BrowserThread::PostTask(
345 BrowserThread::UI, FROM_HERE, 350 BrowserThread::UI, FROM_HERE,
346 NewRunnableMethod(this, &CrxInstaller::ConfirmInstall))) 351 NewRunnableMethod(this, &CrxInstaller::ConfirmInstall)))
347 NOTREACHED(); 352 NOTREACHED();
348 } 353 }
349 354
355 #if 0
Matt Perry 2011/05/25 01:46:06 Remove dead code, unless you mean to use it. In th
asargent_no_longer_on_chrome 2011/05/25 04:42:00 Oops, I had meant to remove this whole block. Done
350 // Helper method to let us compare a whitelisted manifest with the actual 356 // Helper method to let us compare a whitelisted manifest with the actual
351 // downloaded extension's manifest, but ignoring the kPublicKey since the 357 // downloaded extension's manifest, but ignoring certain keys.
352 // whitelisted manifest doesn't have that value. 358 static bool WhitelistMatches(
353 static bool EqualsIgnoringPublicKey(
354 const DictionaryValue& extension_manifest, 359 const DictionaryValue& extension_manifest,
355 const DictionaryValue& whitelisted_manifest) { 360 const DictionaryValue& whitelisted_manifest) {
356 scoped_ptr<DictionaryValue> manifest_copy(extension_manifest.DeepCopy()); 361 scoped_ptr<DictionaryValue> manifest_copy(extension_manifest.DeepCopy());
357 manifest_copy->Remove(extension_manifest_keys::kPublicKey, NULL); 362 manifest_copy->Remove(extension_manifest_keys::kPublicKey, NULL);
358 return manifest_copy->Equals(&whitelisted_manifest); 363 manifest_copy->Remove(extension_manifest_keys::kCurrentLocale, NULL);
364
365 for (DictionaryValue::key_iterator i = extension_manifest.begin_keys();
366 i != extension_manifest.end_keys();
367 ++i) {
368 const std::string& key = *i;
369 if (key == extension_manifest_keys::kPublicKey ||
370 key == extension_manifest_keys::kCurrentLocale)
371 continue;
372
373 Value* extension_value = NULL;
374 Value* whitelist_value = NULL;
375
376 if (!extension_manifest.Get(key, &extension_value) ||
377 !whitelisted_manifest.Get(key, &whitelist_value))
378 return false;
379
380 if (!extension_value->Equals(whitelist_value))
381 return false;
382 }
383 return true;
359 } 384 }
385 #endif
360 386
361 void CrxInstaller::ConfirmInstall() { 387 void CrxInstaller::ConfirmInstall() {
362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
363 if (!frontend_weak_.get()) 389 if (!frontend_weak_.get())
364 return; 390 return;
365 391
366 if (frontend_weak_->extension_prefs() 392 if (frontend_weak_->extension_prefs()
367 ->IsExtensionBlacklisted(extension_->id())) { 393 ->IsExtensionBlacklisted(extension_->id())) {
368 VLOG(1) << "This extension: " << extension_->id() 394 VLOG(1) << "This extension: " << extension_->id()
369 << " is blacklisted. Install failed."; 395 << " is blacklisted. Install failed.";
(...skipping 21 matching lines...) Expand all
391 return; 417 return;
392 } 418 }
393 419
394 current_version_ = 420 current_version_ =
395 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); 421 frontend_weak_->extension_prefs()->GetVersionString(extension_->id());
396 422
397 // First see if it's whitelisted by id (the old mechanism). 423 // First see if it's whitelisted by id (the old mechanism).
398 bool whitelisted = ClearWhitelistedInstallId(extension_->id()) && 424 bool whitelisted = ClearWhitelistedInstallId(extension_->id()) &&
399 extension_->plugins().empty() && is_gallery_install_; 425 extension_->plugins().empty() && is_gallery_install_;
400 426
401 // Now check if it's whitelisted by manifest. 427 // Now check if there's a WhitelistEntry.
402 scoped_ptr<DictionaryValue> whitelisted_manifest( 428 scoped_ptr<CrxInstaller::WhitelistEntry> entry(
403 RemoveWhitelistedManifest(extension_->id())); 429 RemoveWhitelistEntry(extension_->id()));
404 if (is_gallery_install_ && whitelisted_manifest.get()) { 430 if (is_gallery_install_ && entry.get() && original_manifest_.get()) {
405 if (!EqualsIgnoringPublicKey(*extension_->manifest_value(), 431 if (!(original_manifest_->Equals(entry->parsed_manifest.get()))) {
Matt Perry 2011/05/25 01:46:06 isn't the Extension::manifest_value supposed to be
asargent_no_longer_on_chrome 2011/05/25 04:42:00 The Extension::manifest_value has already had a co
Matt Perry 2011/05/25 19:03:24 Should we also check to ensure that the localized
406 *whitelisted_manifest)) {
407 ReportFailureFromUIThread( 432 ReportFailureFromUIThread(
408 l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID)); 433 l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID));
409 return; 434 return;
410 } 435 }
411 whitelisted = true; 436 whitelisted = true;
412 } 437 }
413 438
414 if (client_ && 439 if (client_ &&
415 (!allow_silent_install_ || !whitelisted)) { 440 (!allow_silent_install_ || !whitelisted)) {
416 AddRef(); // Balanced in Proceed() and Abort(). 441 AddRef(); // Balanced in Proceed() and Abort().
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 client_->OnInstallSuccess(extension_.get(), install_icon_.get()); 572 client_->OnInstallSuccess(extension_.get(), install_icon_.get());
548 573
549 // Tell the frontend about the installation and hand off ownership of 574 // Tell the frontend about the installation and hand off ownership of
550 // extension_ to it. 575 // extension_ to it.
551 frontend_weak_->OnExtensionInstalled(extension_); 576 frontend_weak_->OnExtensionInstalled(extension_);
552 extension_ = NULL; 577 extension_ = NULL;
553 578
554 // We're done. We don't post any more tasks to ourselves so we are deleted 579 // We're done. We don't post any more tasks to ourselves so we are deleted
555 // soon. 580 // soon.
556 } 581 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698