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

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

Issue 125004: Revert "BUG=12114" (Closed)
Patch Set: Created 11 years, 6 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
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/extensions_service.h" 5 #include "chrome/browser/extensions/extensions_service.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/crypto/signature_verifier.h"
10 #include "base/file_util.h" 9 #include "base/file_util.h"
11 #include "base/gfx/png_encoder.h" 10 #include "base/gfx/png_encoder.h"
12 #include "base/scoped_handle.h" 11 #include "base/scoped_handle.h"
13 #include "base/scoped_temp_dir.h" 12 #include "base/scoped_temp_dir.h"
14 #include "base/string_util.h" 13 #include "base/string_util.h"
15 #include "base/third_party/nss/blapi.h" 14 #include "base/third_party/nss/blapi.h"
16 #include "base/third_party/nss/sha256.h" 15 #include "base/third_party/nss/sha256.h"
17 #include "base/thread.h" 16 #include "base/thread.h"
18 #include "base/values.h" 17 #include "base/values.h"
19 #include "net/base/file_stream.h" 18 #include "net/base/file_stream.h"
20 #include "chrome/browser/browser.h" 19 #include "chrome/browser/browser.h"
21 #include "chrome/browser/browser_list.h" 20 #include "chrome/browser/browser_list.h"
22 #include "chrome/browser/browser_process.h" 21 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chrome_thread.h" 22 #include "chrome/browser/chrome_thread.h"
24 #include "chrome/browser/extensions/extension_creator.h"
25 #include "chrome/browser/extensions/extension_browser_event_router.h" 23 #include "chrome/browser/extensions/extension_browser_event_router.h"
26 #include "chrome/browser/extensions/extension_process_manager.h" 24 #include "chrome/browser/extensions/extension_process_manager.h"
27 #include "chrome/browser/profile.h" 25 #include "chrome/browser/profile.h"
28 #include "chrome/browser/utility_process_host.h" 26 #include "chrome/browser/utility_process_host.h"
29 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/extensions/extension.h" 28 #include "chrome/common/extensions/extension.h"
31 #include "chrome/common/extensions/extension_error_reporter.h" 29 #include "chrome/common/extensions/extension_error_reporter.h"
32 #include "chrome/common/extensions/extension_unpacker.h" 30 #include "chrome/common/extensions/extension_unpacker.h"
33 #include "chrome/common/json_value_serializer.h" 31 #include "chrome/common/json_value_serializer.h"
34 #include "chrome/common/notification_service.h" 32 #include "chrome/common/notification_service.h"
35 #include "chrome/common/pref_names.h" 33 #include "chrome/common/pref_names.h"
36 #include "chrome/common/pref_service.h" 34 #include "chrome/common/pref_service.h"
37 #include "chrome/common/zip.h" 35 #include "chrome/common/zip.h"
38 #include "chrome/common/url_constants.h" 36 #include "chrome/common/url_constants.h"
39 #include "grit/chromium_strings.h" 37 #include "grit/chromium_strings.h"
40 #include "grit/generated_resources.h" 38 #include "grit/generated_resources.h"
41 #include "net/base/base64.h"
42 #include "third_party/skia/include/core/SkBitmap.h" 39 #include "third_party/skia/include/core/SkBitmap.h"
43 40
44 #if defined(OS_WIN) 41 #if defined(OS_WIN)
45 #include "app/win_util.h" 42 #include "app/win_util.h"
46 #include "base/registry.h" 43 #include "base/registry.h"
47 #include "base/win_util.h" 44 #include "base/win_util.h"
48 #endif 45 #endif
49 46
50 // ExtensionsService. 47 // ExtensionsService.
51 48
52 const char ExtensionsService::kExtensionHeaderMagic[] = "Cr24";
53
54 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; 49 const char* ExtensionsService::kInstallDirectoryName = "Extensions";
55 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; 50 const char* ExtensionsService::kCurrentVersionFileName = "Current Version";
56 const char* ExtensionsServiceBackend::kTempExtensionName = "TEMP_INSTALL"; 51 const char* ExtensionsServiceBackend::kTempExtensionName = "TEMP_INSTALL";
57 52
58 namespace { 53 namespace {
59 54
60 // A preference that keeps track of extension settings. This is a dictionary 55 // A preference that keeps track of extension settings. This is a dictionary
61 // object read from the Preferences file, keyed off of extension id's. 56 // object read from the Preferences file, keyed off of extension id's.
62 const wchar_t kExternalExtensionsPref[] = L"extensions.settings"; 57 const wchar_t kExternalExtensionsPref[] = L"extensions.settings";
63 58
(...skipping 16 matching lines...) Expand all
80 75
81 #endif 76 #endif
82 77
83 // A marker file to indicate that an extension was installed from an external 78 // A marker file to indicate that an extension was installed from an external
84 // source. 79 // source.
85 const char kExternalInstallFile[] = "EXTERNAL_INSTALL"; 80 const char kExternalInstallFile[] = "EXTERNAL_INSTALL";
86 81
87 // A temporary subdirectory where we unpack extensions. 82 // A temporary subdirectory where we unpack extensions.
88 const char* kUnpackExtensionDir = "TEMP_UNPACK"; 83 const char* kUnpackExtensionDir = "TEMP_UNPACK";
89 84
90 // Unpacking errors 85 // The version of the extension package that this code understands.
91 const char* kBadMagicNumberError = "Bad magic number"; 86 const uint32 kExpectedVersion = 1;
92 const char* kBadHeaderSizeError = "Excessively large key or signature";
93 const char* kBadVersionNumberError = "Bad version number";
94 const char* kInvalidExtensionHeaderError = "Invalid extension header";
95 const char* kInvalidPublicKeyError = "Invalid public key";
96 const char* kInvalidSignatureError = "Invalid signature";
97 const char* kSignatureVerificationFailed = "Signature verification failed";
98 const char* kSignatureVerificationInitFailed =
99 "Signature verification initialization failed. This is most likely "
100 "caused by a public key in the wrong format (should encode algorithm).";
101 } 87 }
102 88
103 // This class coordinates an extension unpack task which is run in a separate 89 // This class coordinates an extension unpack task which is run in a separate
104 // process. Results are sent back to this class, which we route to the 90 // process. Results are sent back to this class, which we route to the
105 // ExtensionServiceBackend. 91 // ExtensionServiceBackend.
106 class ExtensionsServiceBackend::UnpackerClient 92 class ExtensionsServiceBackend::UnpackerClient
107 : public UtilityProcessHost::Client { 93 : public UtilityProcessHost::Client {
108 public: 94 public:
109 UnpackerClient(ExtensionsServiceBackend* backend, 95 UnpackerClient(ExtensionsServiceBackend* backend,
110 const FilePath& extension_path, 96 const FilePath& extension_path,
111 const std::string& public_key,
112 const std::string& expected_id, 97 const std::string& expected_id,
113 bool from_external) 98 bool from_external)
114 : backend_(backend), extension_path_(extension_path), 99 : backend_(backend), extension_path_(extension_path),
115 public_key_(public_key), expected_id_(expected_id), 100 expected_id_(expected_id), from_external_(from_external),
116 from_external_(from_external), got_response_(false) { 101 got_response_(false) {
117 } 102 }
118 103
119 // Starts the unpack task. We call back to the backend when the task is done, 104 // Starts the unpack task. We call back to the backend when the task is done,
120 // or a problem occurs. 105 // or a problem occurs.
121 void Start() { 106 void Start() {
122 AddRef(); // balanced in OnUnpackExtensionReply() 107 AddRef(); // balanced in OnUnpackExtensionReply()
123 108
124 // TODO(mpcomplete): handle multiple installs 109 // TODO(mpcomplete): handle multiple installs
125 FilePath temp_dir = backend_->install_directory_.AppendASCII( 110 FilePath temp_dir = backend_->install_directory_.AppendASCII(
126 kUnpackExtensionDir); 111 kUnpackExtensionDir);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 &images)) { 156 &images)) {
172 OnUnpackExtensionFailed("Couldn't read image data from disk."); 157 OnUnpackExtensionFailed("Couldn't read image data from disk.");
173 } else { 158 } else {
174 OnUnpackExtensionSucceededImpl(manifest, images); 159 OnUnpackExtensionSucceededImpl(manifest, images);
175 } 160 }
176 } 161 }
177 162
178 void OnUnpackExtensionSucceededImpl( 163 void OnUnpackExtensionSucceededImpl(
179 const DictionaryValue& manifest, 164 const DictionaryValue& manifest,
180 const ExtensionUnpacker::DecodedImages& images) { 165 const ExtensionUnpacker::DecodedImages& images) {
181 // Add our public key into the parsed manifest. We want it to be saved so
182 // that we can later refer to it (eg for generating ids, validating
183 // signatures, etc).
184 // The const_cast is hacky, but seems like the right thing here, rather than
185 // making a full copy just to make this change.
186 const_cast<DictionaryValue*>(&manifest)->SetString(
187 Extension::kPublicKeyKey, public_key_);
188
189 // The extension was unpacked to the temp dir inside our unpacking dir. 166 // The extension was unpacked to the temp dir inside our unpacking dir.
190 FilePath extension_dir = temp_extension_path_.DirName().AppendASCII( 167 FilePath extension_dir = temp_extension_path_.DirName().AppendASCII(
191 ExtensionsServiceBackend::kTempExtensionName); 168 ExtensionsServiceBackend::kTempExtensionName);
192 backend_->OnExtensionUnpacked(extension_path_, extension_dir, 169 backend_->OnExtensionUnpacked(extension_path_, extension_dir,
193 expected_id_, from_external_, 170 expected_id_, from_external_,
194 manifest, images); 171 manifest, images);
195 Cleanup(); 172 Cleanup();
196 } 173 }
197 174
198 virtual void OnUnpackExtensionFailed(const std::string& error_message) { 175 virtual void OnUnpackExtensionFailed(const std::string& error_message) {
(...skipping 16 matching lines...) Expand all
215 MessageLoop* file_loop) { 192 MessageLoop* file_loop) {
216 UtilityProcessHost* host = new UtilityProcessHost(rdh, this, file_loop); 193 UtilityProcessHost* host = new UtilityProcessHost(rdh, this, file_loop);
217 host->StartExtensionUnpacker(temp_extension_path_); 194 host->StartExtensionUnpacker(temp_extension_path_);
218 } 195 }
219 196
220 scoped_refptr<ExtensionsServiceBackend> backend_; 197 scoped_refptr<ExtensionsServiceBackend> backend_;
221 198
222 // The path to the crx file that we're installing. 199 // The path to the crx file that we're installing.
223 FilePath extension_path_; 200 FilePath extension_path_;
224 201
225 // The public key of the extension we're installing.
226 std::string public_key_;
227
228 // The path to the copy of the crx file in the temporary directory where we're 202 // The path to the copy of the crx file in the temporary directory where we're
229 // unpacking it. 203 // unpacking it.
230 FilePath temp_extension_path_; 204 FilePath temp_extension_path_;
231 205
232 // The ID we expect this extension to have, if any. 206 // The ID we expect this extension to have, if any.
233 std::string expected_id_; 207 std::string expected_id_;
234 208
235 // True if this is being installed from an external source. 209 // True if this is being installed from an external source.
236 bool from_external_; 210 bool from_external_;
237 211
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 364
391 NotificationService::current()->Notify( 365 NotificationService::current()->Notify(
392 NotificationType::EXTENSIONS_LOADED, 366 NotificationType::EXTENSIONS_LOADED,
393 NotificationService::AllSources(), 367 NotificationService::AllSources(),
394 Details<ExtensionList>(&enabled_extensions)); 368 Details<ExtensionList>(&enabled_extensions));
395 369
396 delete new_extensions; 370 delete new_extensions;
397 } 371 }
398 372
399 void ExtensionsService::OnExtensionInstalled(Extension* extension, 373 void ExtensionsService::OnExtensionInstalled(Extension* extension,
400 Extension::InstallType install_type) { 374 bool update) {
401 UpdateExtensionPref(ASCIIToWide(extension->id()), kState, 375 UpdateExtensionPref(ASCIIToWide(extension->id()), kState,
402 Value::CreateIntegerValue(Extension::ENABLED), false); 376 Value::CreateIntegerValue(Extension::ENABLED), false);
403 UpdateExtensionPref(ASCIIToWide(extension->id()), kLocation, 377 UpdateExtensionPref(ASCIIToWide(extension->id()), kLocation,
404 Value::CreateIntegerValue(Extension::INTERNAL), true); 378 Value::CreateIntegerValue(Extension::INTERNAL), true);
405 379
406 // If the extension is a theme, tell the profile (and therefore ThemeProvider) 380 // If the extension is a theme, tell the profile (and therefore ThemeProvider)
407 // to apply it. 381 // to apply it.
408 if (extension->IsTheme()) { 382 if (extension->IsTheme()) {
409 NotificationService::current()->Notify( 383 NotificationService::current()->Notify(
410 NotificationType::THEME_INSTALLED, 384 NotificationType::THEME_INSTALLED,
411 NotificationService::AllSources(), 385 NotificationService::AllSources(),
412 Details<Extension>(extension)); 386 Details<Extension>(extension));
413 } else { 387 } else {
414 NotificationService::current()->Notify( 388 NotificationService::current()->Notify(
415 NotificationType::EXTENSION_INSTALLED, 389 NotificationType::EXTENSION_INSTALLED,
416 NotificationService::AllSources(), 390 NotificationService::AllSources(),
417 Details<Extension>(extension)); 391 Details<Extension>(extension));
418 } 392 }
419 } 393 }
420 394
421 void ExtensionsService::OnExternalExtensionInstalled( 395 void ExtensionsService::OnExternalExtensionInstalled(
422 const std::string& id, Extension::Location location) { 396 const std::string& id, Extension::Location location) {
423 DCHECK(Extension::IsExternalLocation(location)); 397 DCHECK(Extension::IsExternalLocation(location));
424 UpdateExtensionPref(ASCIIToWide(id), kState, 398 UpdateExtensionPref(ASCIIToWide(id), kState,
425 Value::CreateIntegerValue(Extension::ENABLED), false); 399 Value::CreateIntegerValue(Extension::ENABLED), false);
426 UpdateExtensionPref(ASCIIToWide(id), kLocation, 400 UpdateExtensionPref(ASCIIToWide(id), kLocation,
427 Value::CreateIntegerValue(location), true); 401 Value::CreateIntegerValue(location), true);
428 } 402 }
429 403
430 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { 404 void ExtensionsService::OnExtensionVersionReinstalled(const std::string& id) {
431 Extension* extension = GetExtensionByID(id); 405 Extension* extension = GetExtensionByID(id);
432 if (extension && extension->IsTheme()) { 406 if (extension && extension->IsTheme()) {
433 NotificationService::current()->Notify( 407 NotificationService::current()->Notify(
434 NotificationType::THEME_INSTALLED, 408 NotificationType::THEME_INSTALLED,
435 NotificationService::AllSources(), 409 NotificationService::AllSources(),
436 Details<Extension>(extension)); 410 Details<Extension>(extension));
437 } 411 }
438 } 412 }
439 413
440 Extension* ExtensionsService::GetExtensionByID(std::string id) { 414 Extension* ExtensionsService::GetExtensionByID(std::string id) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 Extension* extension = LoadExtension(extension_path, 615 Extension* extension = LoadExtension(extension_path,
642 false); // don't require ID 616 false); // don't require ID
643 if (extension) { 617 if (extension) {
644 extension->set_location(Extension::LOAD); 618 extension->set_location(Extension::LOAD);
645 ExtensionList* extensions = new ExtensionList; 619 ExtensionList* extensions = new ExtensionList;
646 extensions->push_back(extension); 620 extensions->push_back(extension);
647 ReportExtensionsLoaded(extensions); 621 ReportExtensionsLoaded(extensions);
648 } 622 }
649 } 623 }
650 624
651 DictionaryValue* ExtensionsServiceBackend::ReadManifest(FilePath manifest_path,
652 std::string* error) {
653 JSONFileValueSerializer serializer(manifest_path);
654 scoped_ptr<Value> root(serializer.Deserialize(error));
655 if (!root.get())
656 return NULL;
657
658 if (!root->IsType(Value::TYPE_DICTIONARY)) {
659 *error = Extension::kInvalidManifestError;
660 return NULL;
661 }
662
663 return static_cast<DictionaryValue*>(root.release());
664 }
665
666 Extension* ExtensionsServiceBackend::LoadExtension( 625 Extension* ExtensionsServiceBackend::LoadExtension(
667 const FilePath& extension_path, bool require_id) { 626 const FilePath& extension_path, bool require_id) {
668 FilePath manifest_path = 627 FilePath manifest_path =
669 extension_path.AppendASCII(Extension::kManifestFilename); 628 extension_path.AppendASCII(Extension::kManifestFilename);
670 if (!file_util::PathExists(manifest_path)) { 629 if (!file_util::PathExists(manifest_path)) {
671 ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError); 630 ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError);
672 return NULL; 631 return NULL;
673 } 632 }
674 633
634 JSONFileValueSerializer serializer(manifest_path);
675 std::string error; 635 std::string error;
676 scoped_ptr<DictionaryValue> root(ReadManifest(manifest_path, &error)); 636 scoped_ptr<Value> root(serializer.Deserialize(&error));
677 if (!root.get()) { 637 if (!root.get()) {
678 ReportExtensionLoadError(extension_path, error); 638 ReportExtensionLoadError(extension_path, error);
679 return NULL; 639 return NULL;
680 } 640 }
681 641
642 if (!root->IsType(Value::TYPE_DICTIONARY)) {
643 ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError);
644 return NULL;
645 }
646
682 scoped_ptr<Extension> extension(new Extension(extension_path)); 647 scoped_ptr<Extension> extension(new Extension(extension_path));
683 if (!extension->InitFromValue(*root.get(), require_id, &error)) { 648 if (!extension->InitFromValue(*static_cast<DictionaryValue*>(root.get()),
649 require_id, &error)) {
684 ReportExtensionLoadError(extension_path, error); 650 ReportExtensionLoadError(extension_path, error);
685 return NULL; 651 return NULL;
686 } 652 }
687 653
688 FilePath external_marker = extension_path.AppendASCII(kExternalInstallFile); 654 FilePath external_marker = extension_path.AppendASCII(kExternalInstallFile);
689 if (file_util::PathExists(external_marker)) { 655 if (file_util::PathExists(external_marker)) {
690 extension->set_location( 656 extension->set_location(
691 extension->ExternalExtensionInstallType(registry_path_)); 657 extension->ExternalExtensionInstallType(registry_path_));
692 } else { 658 } else {
693 extension->set_location(Extension::INTERNAL); 659 extension->set_location(Extension::INTERNAL);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 dir.AppendASCII(ExtensionsService::kCurrentVersionFileName); 754 dir.AppendASCII(ExtensionsService::kCurrentVersionFileName);
789 if (file_util::PathExists(current_version)) { 755 if (file_util::PathExists(current_version)) {
790 if (file_util::ReadFileToString(current_version, version_string)) { 756 if (file_util::ReadFileToString(current_version, version_string)) {
791 TrimWhitespace(*version_string, TRIM_ALL, version_string); 757 TrimWhitespace(*version_string, TRIM_ALL, version_string);
792 return true; 758 return true;
793 } 759 }
794 } 760 }
795 return false; 761 return false;
796 } 762 }
797 763
798 Extension::InstallType ExtensionsServiceBackend::CompareToInstalledVersion( 764 bool ExtensionsServiceBackend::CheckCurrentVersion(
799 const std::string& id,
800 const std::string& new_version_str, 765 const std::string& new_version_str,
801 std::string *current_version_str) { 766 const std::string& current_version_str,
802 CHECK(current_version_str); 767 const FilePath& dest_dir) {
803 FilePath dir(install_directory_.AppendASCII(id.c_str()));
804 if (!ReadCurrentVersion(dir, current_version_str))
805 return Extension::NEW_INSTALL;
806
807 scoped_ptr<Version> current_version( 768 scoped_ptr<Version> current_version(
808 Version::GetVersionFromString(*current_version_str)); 769 Version::GetVersionFromString(current_version_str));
809 scoped_ptr<Version> new_version( 770 scoped_ptr<Version> new_version(
810 Version::GetVersionFromString(new_version_str)); 771 Version::GetVersionFromString(new_version_str));
811 int comp = new_version->CompareTo(*current_version); 772 if (current_version->CompareTo(*new_version) >= 0) {
812 if (comp > 0) 773 // Verify that the directory actually exists. If it doesn't we'll return
813 return Extension::UPGRADE; 774 // true so that the install code will repair the broken installation.
814 else if (comp == 0) 775 // TODO(erikkay): A further step would be to verify that the extension
815 return Extension::REINSTALL; 776 // has actually loaded successfully.
816 else 777 FilePath version_dir = dest_dir.AppendASCII(current_version_str);
817 return Extension::DOWNGRADE; 778 if (file_util::PathExists(version_dir)) {
818 } 779 std::string id = WideToASCII(dest_dir.BaseName().ToWStringHack());
819 780 StringToLowerASCII(&id);
820 bool ExtensionsServiceBackend::NeedsReinstall(const std::string& id, 781 ReportExtensionVersionReinstalled(id);
821 const std::string& current_version) { 782 return false;
822 // Verify that the directory actually exists. 783 }
823 // TODO(erikkay): A further step would be to verify that the extension 784 }
824 // has actually loaded successfully. 785 return true;
825 FilePath dir(install_directory_.AppendASCII(id.c_str()));
826 FilePath version_dir(dir.AppendASCII(current_version));
827 return !file_util::PathExists(version_dir);
828 } 786 }
829 787
830 bool ExtensionsServiceBackend::InstallDirSafely(const FilePath& source_dir, 788 bool ExtensionsServiceBackend::InstallDirSafely(const FilePath& source_dir,
831 const FilePath& dest_dir) { 789 const FilePath& dest_dir) {
832 if (file_util::PathExists(dest_dir)) { 790 if (file_util::PathExists(dest_dir)) {
833 // By the time we get here, it should be safe to assume that this directory 791 // By the time we get here, it should be safe to assume that this directory
834 // is not currently in use (it's not the current active version). 792 // is not currently in use (it's not the current active version).
835 if (!file_util::Delete(dest_dir, true)) { 793 if (!file_util::Delete(dest_dir, true)) {
836 ReportExtensionInstallError(source_dir, 794 ReportExtensionInstallError(source_dir,
837 "Can't delete existing version directory."); 795 "Can't delete existing version directory.");
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 LOG(INFO) << "Installing extension " << extension_path.value(); 862 LOG(INFO) << "Installing extension " << extension_path.value();
905 863
906 frontend_ = frontend; 864 frontend_ = frontend;
907 alert_on_error_ = true; 865 alert_on_error_ = true;
908 866
909 bool from_external = false; 867 bool from_external = false;
910 InstallOrUpdateExtension(extension_path, std::string(), from_external); 868 InstallOrUpdateExtension(extension_path, std::string(), from_external);
911 } 869 }
912 870
913 void ExtensionsServiceBackend::InstallOrUpdateExtension( 871 void ExtensionsServiceBackend::InstallOrUpdateExtension(
914 const FilePath& extension_path, 872 const FilePath& extension_path, const std::string& expected_id,
915 const std::string& expected_id,
916 bool from_external) { 873 bool from_external) {
917 std::string actual_public_key; 874 UnpackerClient* client =
918 if (!ValidateSignature(extension_path, &actual_public_key)) 875 new UnpackerClient(this, extension_path, expected_id, from_external);
919 return; // Failures reported within ValidateSignature().
920
921 UnpackerClient* client = new UnpackerClient(
922 this, extension_path, actual_public_key, expected_id, from_external);
923 client->Start(); 876 client->Start();
924 } 877 }
925 878
926 bool ExtensionsServiceBackend::ValidateSignature(const FilePath& extension_path,
927 std::string* key_out) {
928 ScopedStdioHandle file(file_util::OpenFile(extension_path, "rb"));
929 if (!file.get()) {
930 ReportExtensionInstallError(extension_path, "Could not open file.");
931 return NULL;
932 }
933
934 // Read and verify the header.
935 ExtensionsService::ExtensionHeader header;
936 size_t len;
937
938 // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it
939 // appears that we don't have any endian/alignment aware serialization
940 // code in the code base. So for now, this assumes that we're running
941 // on a little endian machine with 4 byte alignment.
942 len = fread(&header, 1, sizeof(ExtensionsService::ExtensionHeader),
943 file.get());
944 if (len < sizeof(ExtensionsService::ExtensionHeader)) {
945 ReportExtensionInstallError(extension_path, kInvalidExtensionHeaderError);
946 return false;
947 }
948 if (strncmp(ExtensionsService::kExtensionHeaderMagic, header.magic,
949 sizeof(header.magic))) {
950 ReportExtensionInstallError(extension_path, kBadMagicNumberError);
951 return false;
952 }
953 if (header.version != ExtensionsService::kCurrentVersion) {
954 ReportExtensionInstallError(extension_path, kBadVersionNumberError);
955 return false;
956 }
957 if (header.key_size > ExtensionsService::kMaxPublicKeySize ||
958 header.signature_size > ExtensionsService::kMaxSignatureSize) {
959 ReportExtensionInstallError(extension_path, kBadHeaderSizeError);
960 return false;
961 }
962
963 std::vector<uint8> key;
964 key.resize(header.key_size);
965 len = fread(&key.front(), sizeof(uint8), header.key_size, file.get());
966 if (len < header.key_size) {
967 ReportExtensionInstallError(extension_path, kInvalidPublicKeyError);
968 return false;
969 }
970
971 std::vector<uint8> signature;
972 signature.resize(header.signature_size);
973 len = fread(&signature.front(), sizeof(uint8), header.signature_size,
974 file.get());
975 if (len < header.signature_size) {
976 ReportExtensionInstallError(extension_path, kInvalidSignatureError);
977 return false;
978 }
979
980 // Note: this structure is an ASN.1 which encodes the algorithm used
981 // with its parameters. This is defined in PKCS #1 v2.1 (RFC 3447).
982 // It is encoding: { OID sha1WithRSAEncryption PARAMETERS NULL }
983 // TODO(aa): This needs to be factored away someplace common.
984 const uint8 signature_algorithm[15] = {
985 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
986 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
987 };
988
989 base::SignatureVerifier verifier;
990 if (!verifier.VerifyInit(signature_algorithm,
991 sizeof(signature_algorithm),
992 &signature.front(),
993 signature.size(),
994 &key.front(),
995 key.size())) {
996 ReportExtensionInstallError(extension_path,
997 kSignatureVerificationInitFailed);
998 return false;
999 }
1000
1001 unsigned char buf[1 << 12];
1002 while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0)
1003 verifier.VerifyUpdate(buf, len);
1004
1005 if (!verifier.VerifyFinal()) {
1006 ReportExtensionInstallError(extension_path, kSignatureVerificationFailed);
1007 return false;
1008 }
1009
1010 net::Base64Encode(std::string(reinterpret_cast<char*>(&key.front()),
1011 key.size()), key_out);
1012 return true;
1013 }
1014
1015 void ExtensionsServiceBackend::OnExtensionUnpacked( 879 void ExtensionsServiceBackend::OnExtensionUnpacked(
1016 const FilePath& extension_path, 880 const FilePath& extension_path,
1017 const FilePath& temp_extension_dir, 881 const FilePath& temp_extension_dir,
1018 const std::string expected_id, 882 const std::string expected_id,
1019 bool from_external, 883 bool from_external,
1020 const DictionaryValue& manifest, 884 const DictionaryValue& manifest,
1021 const std::vector< Tuple2<SkBitmap, FilePath> >& images) { 885 const std::vector< Tuple2<SkBitmap, FilePath> >& images) {
1022 Extension extension; 886 Extension extension;
1023 std::string error; 887 std::string error;
1024 if (!extension.InitFromValue(manifest, 888 if (!extension.InitFromValue(manifest,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 error_msg += expected_id; 931 error_msg += expected_id;
1068 error_msg += ")"; 932 error_msg += ")";
1069 ReportExtensionInstallError(extension_path, error_msg); 933 ReportExtensionInstallError(extension_path, error_msg);
1070 return; 934 return;
1071 } 935 }
1072 936
1073 // <profile>/Extensions/<id> 937 // <profile>/Extensions/<id>
1074 FilePath dest_dir = install_directory_.AppendASCII(extension.id()); 938 FilePath dest_dir = install_directory_.AppendASCII(extension.id());
1075 std::string version = extension.VersionString(); 939 std::string version = extension.VersionString();
1076 std::string current_version; 940 std::string current_version;
1077 Extension::InstallType install_type = 941 bool was_update = false;
1078 CompareToInstalledVersion(extension.id(), version, &current_version); 942 if (ReadCurrentVersion(dest_dir, &current_version)) {
1079 943 if (!CheckCurrentVersion(version, current_version, dest_dir))
1080 // Do not allow downgrade.
1081 if (install_type == Extension::DOWNGRADE) {
1082 ReportExtensionInstallError(extension_path,
1083 "Error: Attempt to downgrade extension from more recent version.");
1084 return;
1085 }
1086
1087 if (install_type == Extension::REINSTALL) {
1088 if (NeedsReinstall(extension.id(), current_version)) {
1089 // Treat corrupted existing installation as new install case.
1090 install_type = Extension::NEW_INSTALL;
1091 } else {
1092 // The client may use this as a signal (to switch themes, for instance).
1093 ReportExtensionOverinstallAttempted(extension.id());
1094 return; 944 return;
1095 } 945 was_update = true;
1096 } 946 }
1097 947
1098 // Write our parsed manifest back to disk, to ensure it doesn't contain an 948 // Write our parsed manifest back to disk, to ensure it doesn't contain an
1099 // exploitable bug that can be used to compromise the browser. 949 // exploitable bug that can be used to compromise the browser.
1100 std::string manifest_json; 950 std::string manifest_json;
1101 JSONStringValueSerializer serializer(&manifest_json); 951 JSONStringValueSerializer serializer(&manifest_json);
1102 serializer.set_pretty_print(true); 952 serializer.set_pretty_print(true);
1103 if (!serializer.Serialize(manifest)) { 953 if (!serializer.Serialize(manifest)) {
1104 ReportExtensionInstallError(extension_path, 954 ReportExtensionInstallError(extension_path,
1105 "Error serializing manifest.json."); 955 "Error serializing manifest.json.");
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 // occurs before the normal startup so we just let startup pick them up. We 1034 // occurs before the normal startup so we just let startup pick them up. We
1185 // notify on installation of external extensions because we need to update 1035 // notify on installation of external extensions because we need to update
1186 // the preferences for these extensions to reflect that they've just been 1036 // the preferences for these extensions to reflect that they've just been
1187 // installed. 1037 // installed.
1188 if (!from_external) { 1038 if (!from_external) {
1189 Extension* extension = LoadExtension(version_dir, true); // require id 1039 Extension* extension = LoadExtension(version_dir, true); // require id
1190 CHECK(extension); 1040 CHECK(extension);
1191 1041
1192 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( 1042 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(
1193 frontend_, &ExtensionsService::OnExtensionInstalled, extension, 1043 frontend_, &ExtensionsService::OnExtensionInstalled, extension,
1194 install_type)); 1044 was_update));
1195 1045
1196 // Only one extension, but ReportExtensionsLoaded can handle multiple, 1046 // Only one extension, but ReportExtensionsLoaded can handle multiple,
1197 // so we need to construct a list. 1047 // so we need to construct a list.
1198 scoped_ptr<ExtensionList> extensions(new ExtensionList); 1048 scoped_ptr<ExtensionList> extensions(new ExtensionList);
1199 extensions->push_back(extension); 1049 extensions->push_back(extension);
1200 LOG(INFO) << "Done."; 1050 LOG(INFO) << "Done.";
1201 // Hand off ownership of the loaded extensions to the frontend. 1051 // Hand off ownership of the loaded extensions to the frontend.
1202 ReportExtensionsLoaded(extensions.release()); 1052 ReportExtensionsLoaded(extensions.release());
1203 } else { 1053 } else {
1204 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( 1054 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(
1205 frontend_, &ExtensionsService::OnExternalExtensionInstalled, 1055 frontend_, &ExtensionsService::OnExternalExtensionInstalled,
1206 extension.id(), 1056 extension.id(),
1207 extension.ExternalExtensionInstallType(registry_path_))); 1057 extension.ExternalExtensionInstallType(registry_path_)));
1208 } 1058 }
1209 1059
1210 scoped_version_dir.Take(); 1060 scoped_version_dir.Take();
1211 } 1061 }
1212 1062
1213 void ExtensionsServiceBackend::ReportExtensionInstallError( 1063 void ExtensionsServiceBackend::ReportExtensionInstallError(
1214 const FilePath& extension_path, const std::string &error) { 1064 const FilePath& extension_path, const std::string &error) {
1215 1065
1216 // TODO(erikkay): note that this isn't guaranteed to work properly on Linux. 1066 // TODO(erikkay): note that this isn't guaranteed to work properly on Linux.
1217 std::string path_str = WideToASCII(extension_path.ToWStringHack()); 1067 std::string path_str = WideToASCII(extension_path.ToWStringHack());
1218 std::string message = 1068 std::string message =
1219 StringPrintf("Could not install extension from '%s'. %s", 1069 StringPrintf("Could not install extension from '%s'. %s",
1220 path_str.c_str(), error.c_str()); 1070 path_str.c_str(), error.c_str());
1221 ExtensionErrorReporter::GetInstance()->ReportError(message, alert_on_error_); 1071 ExtensionErrorReporter::GetInstance()->ReportError(message, alert_on_error_);
1222 } 1072 }
1223 1073
1224 void ExtensionsServiceBackend::ReportExtensionOverinstallAttempted( 1074 void ExtensionsServiceBackend::ReportExtensionVersionReinstalled(
1225 const std::string& id) { 1075 const std::string& id) {
1226 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( 1076 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(
1227 frontend_, &ExtensionsService::OnExtensionOverinstallAttempted, id)); 1077 frontend_, &ExtensionsService::OnExtensionVersionReinstalled, id));
1228 } 1078 }
1229 1079
1230 bool ExtensionsServiceBackend::ShouldSkipInstallingExtension( 1080 bool ExtensionsServiceBackend::ShouldSkipInstallingExtension(
1231 const std::set<std::string>& ids_to_ignore, 1081 const std::set<std::string>& ids_to_ignore,
1232 const std::string& id) { 1082 const std::string& id) {
1233 if (ids_to_ignore.find(id) != ids_to_ignore.end()) { 1083 if (ids_to_ignore.find(id) != ids_to_ignore.end()) {
1234 LOG(INFO) << "Skipping uninstalled external extension " << id; 1084 LOG(INFO) << "Skipping uninstalled external extension " << id;
1235 return true; 1085 return true;
1236 } 1086 }
1237 return false; 1087 return false;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 // not a big deal though, because we'll notice next time we startup that the 1253 // not a big deal though, because we'll notice next time we startup that the
1404 // Current Version file is gone and finish the delete then. 1254 // Current Version file is gone and finish the delete then.
1405 if (!file_util::Delete(extension_directory, true)) { 1255 if (!file_util::Delete(extension_directory, true)) {
1406 LOG(WARNING) << "Could not delete directory for extension " 1256 LOG(WARNING) << "Could not delete directory for extension "
1407 << extension_id; 1257 << extension_id;
1408 } 1258 }
1409 } 1259 }
1410 1260
1411 bool ExtensionsServiceBackend::ShouldInstall(const std::string& id, 1261 bool ExtensionsServiceBackend::ShouldInstall(const std::string& id,
1412 const std::string& version) { 1262 const std::string& version) {
1263 FilePath dir(install_directory_.AppendASCII(id.c_str()));
1413 std::string current_version; 1264 std::string current_version;
1414 Extension::InstallType install_type = CompareToInstalledVersion(id, version, 1265 if (ReadCurrentVersion(dir, &current_version)) {
1415 &current_version); 1266 return CheckCurrentVersion(version, current_version, dir);
1416 1267 }
1417 if (install_type == Extension::DOWNGRADE) 1268 return true;
1418 return false;
1419
1420 return (install_type == Extension::UPGRADE ||
1421 install_type == Extension::NEW_INSTALL ||
1422 NeedsReinstall(id, current_version));
1423 } 1269 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extensions_service.h ('k') | chrome/browser/extensions/extensions_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698