OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/api/runtime/runtime_api.h" | 5 #include "extensions/browser/api/runtime/runtime_api.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
17 #include "base/threading/thread_task_runner_handle.h" | 17 #include "base/threading/thread_task_runner_handle.h" |
18 #include "base/values.h" | 18 #include "base/values.h" |
19 #include "base/version.h" | 19 #include "base/version.h" |
20 #include "components/prefs/pref_registry_simple.h" | 20 #include "components/prefs/pref_registry_simple.h" |
21 #include "components/prefs/pref_service.h" | 21 #include "components/prefs/pref_service.h" |
22 #include "content/public/browser/browser_context.h" | 22 #include "content/public/browser/browser_context.h" |
23 #include "content/public/browser/child_process_security_policy.h" | 23 #include "content/public/browser/child_process_security_policy.h" |
24 #include "content/public/browser/render_frame_host.h" | 24 #include "content/public/browser/render_frame_host.h" |
25 #include "content/public/browser/render_process_host.h" | 25 #include "content/public/browser/render_process_host.h" |
26 #include "extensions/browser/api/runtime/runtime_api_delegate.h" | 26 #include "extensions/browser/api/runtime/runtime_api_delegate.h" |
27 #include "extensions/browser/event_router.h" | 27 #include "extensions/browser/event_router.h" |
| 28 #include "extensions/browser/events/lazy_event_dispatch_util.h" |
28 #include "extensions/browser/extension_host.h" | 29 #include "extensions/browser/extension_host.h" |
29 #include "extensions/browser/extension_prefs.h" | 30 #include "extensions/browser/extension_prefs.h" |
30 #include "extensions/browser/extension_registry.h" | 31 #include "extensions/browser/extension_registry.h" |
31 #include "extensions/browser/extension_system.h" | 32 #include "extensions/browser/extension_system.h" |
32 #include "extensions/browser/extension_util.h" | 33 #include "extensions/browser/extension_util.h" |
33 #include "extensions/browser/extensions_browser_client.h" | 34 #include "extensions/browser/extensions_browser_client.h" |
34 #include "extensions/browser/lazy_background_task_queue.h" | 35 #include "extensions/browser/lazy_background_task_queue.h" |
35 #include "extensions/browser/process_manager_factory.h" | 36 #include "extensions/browser/process_manager_factory.h" |
36 #include "extensions/common/api/runtime.h" | 37 #include "extensions/common/api/runtime.h" |
37 #include "extensions/common/error_utils.h" | 38 #include "extensions/common/error_utils.h" |
(...skipping 23 matching lines...) Expand all Loading... |
61 const char kInstallReasonSharedModuleUpdate[] = "shared_module_update"; | 62 const char kInstallReasonSharedModuleUpdate[] = "shared_module_update"; |
62 const char kInstallPreviousVersion[] = "previousVersion"; | 63 const char kInstallPreviousVersion[] = "previousVersion"; |
63 const char kInvalidUrlError[] = "Invalid URL: \"*\"."; | 64 const char kInvalidUrlError[] = "Invalid URL: \"*\"."; |
64 const char kPlatformInfoUnavailable[] = "Platform information unavailable."; | 65 const char kPlatformInfoUnavailable[] = "Platform information unavailable."; |
65 | 66 |
66 const char kUpdatesDisabledError[] = "Autoupdate is not enabled."; | 67 const char kUpdatesDisabledError[] = "Autoupdate is not enabled."; |
67 | 68 |
68 // A preference key storing the url loaded when an extension is uninstalled. | 69 // A preference key storing the url loaded when an extension is uninstalled. |
69 const char kUninstallUrl[] = "uninstall_url"; | 70 const char kUninstallUrl[] = "uninstall_url"; |
70 | 71 |
71 // A preference key storing the information about an extension that was | |
72 // installed but not loaded. We keep the pending info here so that we can send | |
73 // chrome.runtime.onInstalled event during the extension load. | |
74 const char kPrefPendingOnInstalledEventDispatchInfo[] = | |
75 "pending_on_installed_event_dispatch_info"; | |
76 | |
77 // Previously installed version number. | |
78 const char kPrefPreviousVersion[] = "previous_version"; | |
79 | |
80 // The name of the directory to be returned by getPackageDirectoryEntry. This | 72 // The name of the directory to be returned by getPackageDirectoryEntry. This |
81 // particular value does not matter to user code, but is chosen for consistency | 73 // particular value does not matter to user code, but is chosen for consistency |
82 // with the equivalent Pepper API. | 74 // with the equivalent Pepper API. |
83 const char kPackageDirectoryPath[] = "crxfs"; | 75 const char kPackageDirectoryPath[] = "crxfs"; |
84 | 76 |
85 // Preference key for storing the last successful restart due to a call to | 77 // Preference key for storing the last successful restart due to a call to |
86 // chrome.runtime.restartAfterDelay(). | 78 // chrome.runtime.restartAfterDelay(). |
87 constexpr char kPrefLastRestartAfterDelayTime[] = | 79 constexpr char kPrefLastRestartAfterDelayTime[] = |
88 "last_restart_after_delay_time"; | 80 "last_restart_after_delay_time"; |
89 // Preference key for storing whether the most recent restart was due to a | 81 // Preference key for storing whether the most recent restart was due to a |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 203 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
212 process_manager_observer_.Add(ProcessManager::Get(browser_context_)); | 204 process_manager_observer_.Add(ProcessManager::Get(browser_context_)); |
213 | 205 |
214 delegate_ = ExtensionsBrowserClient::Get()->CreateRuntimeAPIDelegate( | 206 delegate_ = ExtensionsBrowserClient::Get()->CreateRuntimeAPIDelegate( |
215 browser_context_); | 207 browser_context_); |
216 | 208 |
217 // Check if registered events are up to date. We can only do this once | 209 // Check if registered events are up to date. We can only do this once |
218 // per browser context, since it updates internal state when called. | 210 // per browser context, since it updates internal state when called. |
219 dispatch_chrome_updated_event_ = | 211 dispatch_chrome_updated_event_ = |
220 ExtensionsBrowserClient::Get()->DidVersionUpdate(browser_context_); | 212 ExtensionsBrowserClient::Get()->DidVersionUpdate(browser_context_); |
| 213 |
| 214 EventRouter::Get(browser_context_) |
| 215 ->lazy_event_dispatch_util() |
| 216 ->AddObserver(this); |
221 } | 217 } |
222 | 218 |
223 RuntimeAPI::~RuntimeAPI() { | 219 RuntimeAPI::~RuntimeAPI() { |
224 } | 220 } |
225 | 221 |
226 void RuntimeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, | 222 void RuntimeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, |
227 const Extension* extension) { | 223 const Extension* extension) { |
228 base::Version previous_version; | |
229 if (ReadPendingOnInstallInfoFromPref(extension->id(), &previous_version)) { | |
230 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
231 FROM_HERE, | |
232 base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent, | |
233 browser_context_, extension->id(), previous_version, false)); | |
234 RemovePendingOnInstallInfoFromPref(extension->id()); | |
235 } | |
236 | |
237 if (!dispatch_chrome_updated_event_) | 224 if (!dispatch_chrome_updated_event_) |
238 return; | 225 return; |
239 | 226 |
240 // Dispatch the onInstalled event with reason "chrome_update". | 227 // Dispatch the onInstalled event with reason "chrome_update". |
241 base::ThreadTaskRunnerHandle::Get()->PostTask( | 228 base::ThreadTaskRunnerHandle::Get()->PostTask( |
242 FROM_HERE, | 229 FROM_HERE, |
243 base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent, | 230 base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent, |
244 browser_context_, extension->id(), base::Version(), true)); | 231 browser_context_, extension->id(), base::Version(), true)); |
245 } | 232 } |
246 | 233 |
247 void RuntimeAPI::OnExtensionWillBeInstalled( | |
248 content::BrowserContext* browser_context, | |
249 const Extension* extension, | |
250 bool is_update, | |
251 const std::string& old_name) { | |
252 // This extension might be disabled before it has a chance to load, e.g. if | |
253 // the extension increased its permissions. So instead of trying to send the | |
254 // onInstalled event here, we remember the fact in prefs and fire the event | |
255 // when the extension is actually loaded. | |
256 StorePendingOnInstallInfoToPref(extension); | |
257 } | |
258 | |
259 void RuntimeAPI::OnExtensionUninstalled( | 234 void RuntimeAPI::OnExtensionUninstalled( |
260 content::BrowserContext* browser_context, | 235 content::BrowserContext* browser_context, |
261 const Extension* extension, | 236 const Extension* extension, |
262 UninstallReason reason) { | 237 UninstallReason reason) { |
263 RemovePendingOnInstallInfoFromPref(extension->id()); | |
264 | |
265 RuntimeEventRouter::OnExtensionUninstalled( | 238 RuntimeEventRouter::OnExtensionUninstalled( |
266 browser_context_, extension->id(), reason); | 239 browser_context_, extension->id(), reason); |
267 } | 240 } |
268 | 241 |
269 void RuntimeAPI::Shutdown() { | 242 void RuntimeAPI::Shutdown() { |
270 delegate_->RemoveUpdateObserver(this); | 243 delegate_->RemoveUpdateObserver(this); |
| 244 EventRouter::Get(browser_context_) |
| 245 ->lazy_event_dispatch_util() |
| 246 ->RemoveObserver(this); |
271 } | 247 } |
272 | 248 |
273 void RuntimeAPI::OnAppUpdateAvailable(const Extension* extension) { | 249 void RuntimeAPI::OnAppUpdateAvailable(const Extension* extension) { |
274 RuntimeEventRouter::DispatchOnUpdateAvailableEvent( | 250 RuntimeEventRouter::DispatchOnUpdateAvailableEvent( |
275 browser_context_, extension->id(), extension->manifest()->value()); | 251 browser_context_, extension->id(), extension->manifest()->value()); |
276 } | 252 } |
277 | 253 |
278 void RuntimeAPI::OnChromeUpdateAvailable() { | 254 void RuntimeAPI::OnChromeUpdateAvailable() { |
279 RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(browser_context_); | 255 RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(browser_context_); |
280 } | 256 } |
281 | 257 |
282 void RuntimeAPI::OnBackgroundHostStartup(const Extension* extension) { | 258 void RuntimeAPI::OnBackgroundHostStartup(const Extension* extension) { |
283 RuntimeEventRouter::DispatchOnStartupEvent(browser_context_, extension->id()); | 259 RuntimeEventRouter::DispatchOnStartupEvent(browser_context_, extension->id()); |
284 } | 260 } |
285 | 261 |
286 bool RuntimeAPI::ReadPendingOnInstallInfoFromPref( | |
287 const ExtensionId& extension_id, | |
288 base::Version* previous_version) { | |
289 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_); | |
290 DCHECK(prefs); | |
291 | |
292 const base::DictionaryValue* info = nullptr; | |
293 if (!prefs->ReadPrefAsDictionary( | |
294 extension_id, kPrefPendingOnInstalledEventDispatchInfo, &info)) { | |
295 return false; | |
296 } | |
297 | |
298 std::string previous_version_string; | |
299 info->GetString(kPrefPreviousVersion, &previous_version_string); | |
300 // |previous_version_string| can be empty. | |
301 *previous_version = base::Version(previous_version_string); | |
302 return true; | |
303 } | |
304 | |
305 void RuntimeAPI::RemovePendingOnInstallInfoFromPref( | |
306 const ExtensionId& extension_id) { | |
307 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_); | |
308 DCHECK(prefs); | |
309 | |
310 prefs->UpdateExtensionPref(extension_id, | |
311 kPrefPendingOnInstalledEventDispatchInfo, nullptr); | |
312 } | |
313 | |
314 void RuntimeAPI::StorePendingOnInstallInfoToPref(const Extension* extension) { | |
315 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_); | |
316 DCHECK(prefs); | |
317 | |
318 // |pending_on_install_info| currently only contains a version string. Instead | |
319 // of making the pref hold a plain string, we store it as a dictionary value | |
320 // so that we can add more stuff to it in the future if necessary. | |
321 std::unique_ptr<base::DictionaryValue> pending_on_install_info( | |
322 new base::DictionaryValue()); | |
323 base::Version previous_version = ExtensionRegistry::Get(browser_context_) | |
324 ->GetStoredVersion(extension->id()); | |
325 pending_on_install_info->SetString( | |
326 kPrefPreviousVersion, | |
327 previous_version.IsValid() ? previous_version.GetString() : ""); | |
328 prefs->UpdateExtensionPref(extension->id(), | |
329 kPrefPendingOnInstalledEventDispatchInfo, | |
330 std::move(pending_on_install_info)); | |
331 } | |
332 | |
333 void RuntimeAPI::ReloadExtension(const std::string& extension_id) { | 262 void RuntimeAPI::ReloadExtension(const std::string& extension_id) { |
334 delegate_->ReloadExtension(extension_id); | 263 delegate_->ReloadExtension(extension_id); |
335 } | 264 } |
336 | 265 |
337 bool RuntimeAPI::CheckForUpdates( | 266 bool RuntimeAPI::CheckForUpdates( |
338 const std::string& extension_id, | 267 const std::string& extension_id, |
339 const RuntimeAPIDelegate::UpdateCheckCallback& callback) { | 268 const RuntimeAPIDelegate::UpdateCheckCallback& callback) { |
340 return delegate_->CheckForUpdates(extension_id, callback); | 269 return delegate_->CheckForUpdates(extension_id, callback); |
341 } | 270 } |
342 | 271 |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 | 556 |
628 if (!uninstall_url.SchemeIsHTTPOrHTTPS()) { | 557 if (!uninstall_url.SchemeIsHTTPOrHTTPS()) { |
629 // Previous versions of Chrome allowed non-http(s) URLs to be stored in the | 558 // Previous versions of Chrome allowed non-http(s) URLs to be stored in the |
630 // prefs. Now they're disallowed, but the old data may still exist. | 559 // prefs. Now they're disallowed, but the old data may still exist. |
631 return; | 560 return; |
632 } | 561 } |
633 | 562 |
634 RuntimeAPI::GetFactoryInstance()->Get(context)->OpenURL(uninstall_url); | 563 RuntimeAPI::GetFactoryInstance()->Get(context)->OpenURL(uninstall_url); |
635 } | 564 } |
636 | 565 |
| 566 void RuntimeAPI::OnExtensionInstalledAndLoaded( |
| 567 content::BrowserContext* browser_context, |
| 568 const Extension* extension, |
| 569 const base::Version& previous_version) { |
| 570 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 571 FROM_HERE, |
| 572 base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent, |
| 573 browser_context_, extension->id(), previous_version, false)); |
| 574 } |
| 575 |
637 ExtensionFunction::ResponseAction RuntimeGetBackgroundPageFunction::Run() { | 576 ExtensionFunction::ResponseAction RuntimeGetBackgroundPageFunction::Run() { |
638 ExtensionHost* host = ProcessManager::Get(browser_context()) | 577 ExtensionHost* host = ProcessManager::Get(browser_context()) |
639 ->GetBackgroundHostForExtension(extension_id()); | 578 ->GetBackgroundHostForExtension(extension_id()); |
640 if (LazyBackgroundTaskQueue::Get(browser_context()) | 579 if (LazyBackgroundTaskQueue::Get(browser_context()) |
641 ->ShouldEnqueueTask(browser_context(), extension())) { | 580 ->ShouldEnqueueTask(browser_context(), extension())) { |
642 LazyBackgroundTaskQueue::Get(browser_context()) | 581 LazyBackgroundTaskQueue::Get(browser_context()) |
643 ->AddPendingTask( | 582 ->AddPendingTask( |
644 browser_context(), extension_id(), | 583 browser_context(), extension_id(), |
645 base::Bind(&RuntimeGetBackgroundPageFunction::OnPageLoaded, this)); | 584 base::Bind(&RuntimeGetBackgroundPageFunction::OnPageLoaded, this)); |
646 } else if (host) { | 585 } else if (host) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 content::ChildProcessSecurityPolicy* policy = | 721 content::ChildProcessSecurityPolicy* policy = |
783 content::ChildProcessSecurityPolicy::GetInstance(); | 722 content::ChildProcessSecurityPolicy::GetInstance(); |
784 policy->GrantReadFileSystem(renderer_id, filesystem_id); | 723 policy->GrantReadFileSystem(renderer_id, filesystem_id); |
785 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 724 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
786 dict->SetString("fileSystemId", filesystem_id); | 725 dict->SetString("fileSystemId", filesystem_id); |
787 dict->SetString("baseName", relative_path); | 726 dict->SetString("baseName", relative_path); |
788 return RespondNow(OneArgument(std::move(dict))); | 727 return RespondNow(OneArgument(std::move(dict))); |
789 } | 728 } |
790 | 729 |
791 } // namespace extensions | 730 } // namespace extensions |
OLD | NEW |