OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/histogram.h" | 10 #include "base/histogram.h" |
11 #include "base/string16.h" | 11 #include "base/string16.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/time.h" | 13 #include "base/time.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "base/version.h" |
15 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
16 #include "chrome/browser/chrome_thread.h" | 17 #include "chrome/browser/chrome_thread.h" |
17 #include "chrome/browser/debugger/devtools_manager.h" | 18 #include "chrome/browser/debugger/devtools_manager.h" |
18 #include "chrome/browser/extensions/crx_installer.h" | 19 #include "chrome/browser/extensions/crx_installer.h" |
19 #include "chrome/browser/extensions/extension_accessibility_api.h" | 20 #include "chrome/browser/extensions/extension_accessibility_api.h" |
20 #include "chrome/browser/extensions/extension_bookmarks_module.h" | 21 #include "chrome/browser/extensions/extension_bookmarks_module.h" |
21 #include "chrome/browser/extensions/extension_browser_event_router.h" | 22 #include "chrome/browser/extensions/extension_browser_event_router.h" |
22 #include "chrome/browser/extensions/extension_data_deleter.h" | 23 #include "chrome/browser/extensions/extension_data_deleter.h" |
23 #include "chrome/browser/extensions/extension_dom_ui.h" | 24 #include "chrome/browser/extensions/extension_dom_ui.h" |
24 #include "chrome/browser/extensions/extension_history_api.h" | 25 #include "chrome/browser/extensions/extension_history_api.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 // independent of the manifest in our prefs. | 91 // independent of the manifest in our prefs. |
91 if (info.extension_location == Extension::LOAD) | 92 if (info.extension_location == Extension::LOAD) |
92 return true; | 93 return true; |
93 | 94 |
94 // Otherwise, reload the manifest it needs to be relocalized. | 95 // Otherwise, reload the manifest it needs to be relocalized. |
95 return extension_l10n_util::ShouldRelocalizeManifest(info); | 96 return extension_l10n_util::ShouldRelocalizeManifest(info); |
96 } | 97 } |
97 | 98 |
98 } // namespace | 99 } // namespace |
99 | 100 |
| 101 PendingExtensionInfo::PendingExtensionInfo(const GURL& update_url, |
| 102 const Version& version, |
| 103 bool is_theme, |
| 104 bool install_silently) |
| 105 : update_url(update_url), |
| 106 version(version), |
| 107 is_theme(is_theme), |
| 108 install_silently(install_silently) {} |
| 109 |
| 110 PendingExtensionInfo::PendingExtensionInfo() |
| 111 : update_url(), |
| 112 version(), |
| 113 is_theme(false), |
| 114 install_silently(false) {} |
| 115 |
100 // ExtensionsService. | 116 // ExtensionsService. |
101 | 117 |
102 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; | 118 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; |
103 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; | 119 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; |
104 | 120 |
105 // static | 121 // static |
106 bool ExtensionsService::IsDownloadFromGallery(const GURL& download_url, | 122 bool ExtensionsService::IsDownloadFromGallery(const GURL& download_url, |
107 const GURL& referrer_url) { | 123 const GURL& referrer_url) { |
108 if (StartsWithASCII(download_url.spec(), | 124 if (StartsWithASCII(download_url.spec(), |
109 extension_urls::kMiniGalleryDownloadPrefix, false) && | 125 extension_urls::kMiniGalleryDownloadPrefix, false) && |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 | 212 |
197 void ExtensionsService::InstallExtension(const FilePath& extension_path) { | 213 void ExtensionsService::InstallExtension(const FilePath& extension_path) { |
198 scoped_refptr<CrxInstaller> installer( | 214 scoped_refptr<CrxInstaller> installer( |
199 new CrxInstaller(install_directory_, | 215 new CrxInstaller(install_directory_, |
200 this, // frontend | 216 this, // frontend |
201 NULL)); // no client (silent install) | 217 NULL)); // no client (silent install) |
202 installer->set_allow_privilege_increase(true); | 218 installer->set_allow_privilege_increase(true); |
203 installer->InstallCrx(extension_path); | 219 installer->InstallCrx(extension_path); |
204 } | 220 } |
205 | 221 |
| 222 namespace { |
| 223 // TODO(akalin): Put this somewhere where both crx_installer.cc and |
| 224 // this file can use it. |
| 225 void DeleteFileHelper(const FilePath& path, bool recursive) { |
| 226 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 227 file_util::Delete(path, recursive); |
| 228 } |
| 229 } // namespace |
| 230 |
206 void ExtensionsService::UpdateExtension(const std::string& id, | 231 void ExtensionsService::UpdateExtension(const std::string& id, |
207 const FilePath& extension_path, | 232 const FilePath& extension_path, |
208 const GURL& download_url) { | 233 const GURL& download_url) { |
209 if (!GetExtensionByIdInternal(id, true, true)) { | 234 PendingExtensionMap::const_iterator it = pending_extensions_.find(id); |
210 LOG(WARNING) << "Will not update extension " << id << " because it is not " | 235 if ((it == pending_extensions_.end()) && |
211 << "installed"; | 236 !GetExtensionByIdInternal(id, true, true)) { |
| 237 LOG(WARNING) << "Will not update extension " << id |
| 238 << " because it is not installed or pending"; |
| 239 // Delete extension_path since we're not creating a CrxInstaller |
| 240 // that would do it for us. |
| 241 ChromeThread::PostTask( |
| 242 ChromeThread::FILE, FROM_HERE, |
| 243 NewRunnableFunction(&DeleteFileHelper, extension_path, false)); |
212 return; | 244 return; |
213 } | 245 } |
214 | 246 |
| 247 // We want a silent install only for non-pending extensions and |
| 248 // pending extensions that have install_silently set. |
| 249 ExtensionInstallUI* client = |
| 250 ((it == pending_extensions_.end()) || it->second.install_silently) ? |
| 251 NULL : new ExtensionInstallUI(profile_); |
| 252 |
215 scoped_refptr<CrxInstaller> installer( | 253 scoped_refptr<CrxInstaller> installer( |
216 new CrxInstaller(install_directory_, | 254 new CrxInstaller(install_directory_, |
217 this, // frontend | 255 this, // frontend |
218 NULL)); // no client (silent install) | 256 client)); |
219 installer->set_expected_id(id); | 257 installer->set_expected_id(id); |
220 installer->set_delete_source(true); | 258 installer->set_delete_source(true); |
221 installer->set_force_web_origin_to_download_url(true); | 259 installer->set_force_web_origin_to_download_url(true); |
222 installer->set_original_url(download_url); | 260 installer->set_original_url(download_url); |
223 installer->InstallCrx(extension_path); | 261 installer->InstallCrx(extension_path); |
224 } | 262 } |
225 | 263 |
| 264 void ExtensionsService::AddPendingExtension( |
| 265 const std::string& id, const GURL& update_url, |
| 266 const Version& version, bool is_theme, bool install_silently) { |
| 267 if (GetExtensionByIdInternal(id, true, true)) { |
| 268 return; |
| 269 } |
| 270 AddPendingExtensionInternal(id, update_url, version, |
| 271 is_theme, install_silently); |
| 272 } |
| 273 |
| 274 void ExtensionsService::AddPendingExtensionInternal( |
| 275 const std::string& id, const GURL& update_url, |
| 276 const Version& version, bool is_theme, bool install_silently) { |
| 277 pending_extensions_[id] = |
| 278 PendingExtensionInfo(update_url, version, is_theme, install_silently); |
| 279 } |
| 280 |
226 void ExtensionsService::ReloadExtension(const std::string& extension_id) { | 281 void ExtensionsService::ReloadExtension(const std::string& extension_id) { |
227 FilePath path; | 282 FilePath path; |
228 Extension* current_extension = GetExtensionById(extension_id, false); | 283 Extension* current_extension = GetExtensionById(extension_id, false); |
229 | 284 |
230 // Unload the extension if it's loaded. It might not be loaded if it crashed. | 285 // Unload the extension if it's loaded. It might not be loaded if it crashed. |
231 if (current_extension) { | 286 if (current_extension) { |
232 // If the extension has an inspector open for its background page, detach | 287 // If the extension has an inspector open for its background page, detach |
233 // the inspector and hang onto a cookie for it, so that we can reattach | 288 // the inspector and hang onto a cookie for it, so that we can reattach |
234 // later. | 289 // later. |
235 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); | 290 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 for (size_t i = 0; i < extensions_.size(); ++i) { | 871 for (size_t i = 0; i < extensions_.size(); ++i) { |
817 if (!extensions_[i]->IsTheme()) | 872 if (!extensions_[i]->IsTheme()) |
818 extension_ids.insert(extensions_[i]->id()); | 873 extension_ids.insert(extensions_[i]->id()); |
819 } | 874 } |
820 | 875 |
821 child_process_logging::SetActiveExtensions(extension_ids); | 876 child_process_logging::SetActiveExtensions(extension_ids); |
822 } | 877 } |
823 | 878 |
824 void ExtensionsService::OnExtensionInstalled(Extension* extension, | 879 void ExtensionsService::OnExtensionInstalled(Extension* extension, |
825 bool allow_privilege_increase) { | 880 bool allow_privilege_increase) { |
| 881 PendingExtensionMap::iterator it = |
| 882 pending_extensions_.find(extension->id()); |
| 883 if (it != pending_extensions_.end() && |
| 884 (it->second.is_theme != extension->IsTheme())) { |
| 885 LOG(WARNING) << "Not installing pending extension " << extension->id() |
| 886 << " with is_theme = " << extension->IsTheme() |
| 887 << "; expected is_theme = " << it->second.is_theme; |
| 888 // Delete the extension directory since we're not going to load |
| 889 // it. |
| 890 ChromeThread::PostTask( |
| 891 ChromeThread::FILE, FROM_HERE, |
| 892 NewRunnableFunction(&DeleteFileHelper, extension->path(), true)); |
| 893 delete extension; |
| 894 return; |
| 895 } |
| 896 |
826 extension_prefs_->OnExtensionInstalled(extension); | 897 extension_prefs_->OnExtensionInstalled(extension); |
827 | 898 |
828 // If the extension is a theme, tell the profile (and therefore ThemeProvider) | 899 // If the extension is a theme, tell the profile (and therefore ThemeProvider) |
829 // to apply it. | 900 // to apply it. |
830 if (extension->IsTheme()) { | 901 if (extension->IsTheme()) { |
831 NotificationService::current()->Notify( | 902 NotificationService::current()->Notify( |
832 NotificationType::THEME_INSTALLED, | 903 NotificationType::THEME_INSTALLED, |
833 Source<Profile>(profile_), | 904 Source<Profile>(profile_), |
834 Details<Extension>(extension)); | 905 Details<Extension>(extension)); |
835 } else { | 906 } else { |
836 NotificationService::current()->Notify( | 907 NotificationService::current()->Notify( |
837 NotificationType::EXTENSION_INSTALLED, | 908 NotificationType::EXTENSION_INSTALLED, |
838 Source<Profile>(profile_), | 909 Source<Profile>(profile_), |
839 Details<Extension>(extension)); | 910 Details<Extension>(extension)); |
840 } | 911 } |
841 | 912 |
842 // Also load the extension. | 913 // Also load the extension. |
843 OnExtensionLoaded(extension, allow_privilege_increase); | 914 OnExtensionLoaded(extension, allow_privilege_increase); |
| 915 |
| 916 // Erase any pending extension. |
| 917 if (it != pending_extensions_.end()) { |
| 918 pending_extensions_.erase(it); |
| 919 } |
844 } | 920 } |
845 | 921 |
846 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { | 922 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { |
847 Extension* extension = GetExtensionById(id, false); | 923 Extension* extension = GetExtensionById(id, false); |
848 if (extension && extension->IsTheme()) { | 924 if (extension && extension->IsTheme()) { |
849 NotificationService::current()->Notify( | 925 NotificationService::current()->Notify( |
850 NotificationType::THEME_INSTALLED, | 926 NotificationType::THEME_INSTALLED, |
851 Source<Profile>(profile_), | 927 Source<Profile>(profile_), |
852 Details<Extension>(extension)); | 928 Details<Extension>(extension)); |
853 } else { | 929 } else { |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 // Finish installing on UI thread. | 1238 // Finish installing on UI thread. |
1163 ChromeThread::PostTask( | 1239 ChromeThread::PostTask( |
1164 ChromeThread::UI, FROM_HERE, | 1240 ChromeThread::UI, FROM_HERE, |
1165 NewRunnableMethod( | 1241 NewRunnableMethod( |
1166 frontend_, | 1242 frontend_, |
1167 &ExtensionsService::ContinueLoadAllExtensions, | 1243 &ExtensionsService::ContinueLoadAllExtensions, |
1168 extensions_to_reload, | 1244 extensions_to_reload, |
1169 start_time, | 1245 start_time, |
1170 true)); | 1246 true)); |
1171 } | 1247 } |
OLD | NEW |