1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/api/runtime/runtime_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <utility>
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/lazy_instance.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/metrics/histogram.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/version.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/browser_context.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/child_process_security_policy.h"
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h"
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/api/runtime/runtime_api_delegate.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/extension_prefs.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_util.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/browser/lazy_background_task_queue.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_manager.h"
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/common/api/runtime.h"
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "extensions/common/error_utils.h"
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h"
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "extensions/common/manifest_handlers/shared_module_info.h"
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/isolated_context.h"
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using content::BrowserContext;
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace runtime = core_api::runtime;
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoBackgroundPageError[] = "You do not have a background page.";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPageLoadError[] = "Background page failed to load.";
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kInstallId[] = "id";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInstallReason[] = "reason";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInstallReasonChromeUpdate[] = "chrome_update";
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInstallReasonUpdate[] = "update";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInstallReasonInstall[] = "install";
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char kInstallReasonSharedModuleUpdate[] = "shared_module_update";
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInstallPreviousVersion[] = "previousVersion";
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kInvalidUrlError[] = "Invalid URL.";
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kPlatformInfoUnavailable[] = "Platform information unavailable.";
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kUpdatesDisabledError[] = "Autoupdate is not enabled.";
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// A preference key storing the url loaded when an extension is uninstalled.
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kUninstallUrl[] = "uninstall_url";
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// The name of the directory to be returned by getPackageDirectoryEntry. This
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// particular value does not matter to user code, but is chosen for consistency
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// with the equivalent Pepper API.
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char kPackageDirectoryPath[] = "crxfs";
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DispatchOnStartupEventImpl(BrowserContext* browser_context,
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const std::string& extension_id,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                bool first_call,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                ExtensionHost* host) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A NULL host from the LazyBackgroundTaskQueue means the page failed to
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // load. Give up.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!host && !first_call)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Don't send onStartup events to incognito browser contexts.
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (browser_context->IsOffTheRecord())
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (ExtensionsBrowserClient::Get()->IsShuttingDown() ||
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(browser_context);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!system)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is a persistent background page, we want to wait for it to load
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (it might not be ready, since this is startup). But only enqueue once.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it fails to load the first time, don't bother trying again.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          extension_id);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extension && BackgroundInfo::HasPersistentBackgroundPage(extension) &&
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      first_call &&
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      system->lazy_background_task_queue()->ShouldEnqueueTask(browser_context,
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                              extension)) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    system->lazy_background_task_queue()->AddPendingTask(
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        browser_context,
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        extension_id,
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            &DispatchOnStartupEventImpl, browser_context, extension_id, false));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::ListValue> event_args(new base::ListValue());
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<Event> event(
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new Event(runtime::OnStartup::kEventName, event_args.Pass()));
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  system->event_router()->DispatchEventToExtension(extension_id, event.Pass());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SetUninstallURL(ExtensionPrefs* prefs,
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     const std::string& extension_id,
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                     const std::string& url_string) {
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  prefs->UpdateExtensionPref(
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      extension_id, kUninstallUrl, new base::StringValue(url_string));
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetUninstallURL(ExtensionPrefs* prefs,
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const std::string& extension_id) {
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string url_string;
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  prefs->ReadPrefAsString(extension_id, kUninstallUrl, &url_string);
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return url_string;
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<RuntimeAPI> >
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<RuntimeAPI>* RuntimeAPI::GetFactoryInstance() {
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return g_factory.Pointer();
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RuntimeAPI::RuntimeAPI(content::BrowserContext* context)
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : browser_context_(context),
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      dispatch_chrome_updated_event_(false),
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_observer_(this) {
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  registrar_.Add(this,
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 content::Source<BrowserContext>(context));
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_ = ExtensionsBrowserClient::Get()->CreateRuntimeAPIDelegate(
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      browser_context_);
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Check if registered events are up-to-date. We can only do this once
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // per browser context, since it updates internal state when called.
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dispatch_chrome_updated_event_ =
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ExtensionsBrowserClient::Get()->DidVersionUpdate(browser_context_);
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)RuntimeAPI::~RuntimeAPI() {
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_->RemoveUpdateObserver(this);
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RuntimeAPI::Observe(int type,
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         const content::NotificationSource& source,
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         const content::NotificationDetails& details) {
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, type);
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We're done restarting Chrome after an update.
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  dispatch_chrome_updated_event_ = false;
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_->AddUpdateObserver(this);
1694ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
1704ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // RuntimeAPI is redirected in incognito, so |browser_context_| is never
1714ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // incognito. We don't observe incognito ProcessManagers but that is OK
1724ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // because we don't send onStartup events to incognito browser contexts.
1734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  DCHECK(!browser_context_->IsOffTheRecord());
1744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Some tests use partially constructed Profiles without a process manager.
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_);
1764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (extension_system->process_manager())
1774ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    extension_system->process_manager()->AddObserver(this);
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void RuntimeAPI::OnExtensionLoaded(content::BrowserContext* browser_context,
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   const Extension* extension) {
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!dispatch_chrome_updated_event_)
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Dispatch the onInstalled event with reason "chrome_update".
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent,
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 browser_context_,
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 extension->id(),
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 Version(),
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 true));
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void RuntimeAPI::OnExtensionWillBeInstalled(
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    content::BrowserContext* browser_context,
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Extension* extension,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool is_update,
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool from_ephemeral,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& old_name) {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ephemeral apps are not considered to be installed and do not receive
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the onInstalled() event.
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (util::IsEphemeralApp(extension->id(), browser_context_))
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Version old_version = delegate_->GetPreviousExtensionVersion(extension);
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Dispatch the onInstalled event.
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent,
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 browser_context_,
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 extension->id(),
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 old_version,
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 false));
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void RuntimeAPI::OnExtensionUninstalled(
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    content::BrowserContext* browser_context,
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Extension* extension,
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UninstallReason reason) {
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ephemeral apps are not considered to be installed, so the uninstall URL
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is not invoked when they are removed.
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (util::IsEphemeralApp(extension->id(), browser_context_))
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RuntimeEventRouter::OnExtensionUninstalled(
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      browser_context_, extension->id(), reason);
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2314ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid RuntimeAPI::Shutdown() {
2324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // ExtensionSystem deletes its ProcessManager during the Shutdown() phase, so
2334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // the observer must be removed here and not in the RuntimeAPI destructor.
2344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  ProcessManager* process_manager =
2354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      ExtensionSystem::Get(browser_context_)->process_manager();
2364ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Some tests use partially constructed Profiles without a process manager.
2374ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (process_manager)
2384ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    process_manager->RemoveObserver(this);
2394ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
2404ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void RuntimeAPI::OnAppUpdateAvailable(const Extension* extension) {
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      browser_context_, extension->id(), extension->manifest()->value());
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void RuntimeAPI::OnChromeUpdateAvailable() {
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(browser_context_);
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid RuntimeAPI::OnBackgroundHostStartup(const Extension* extension) {
2514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  RuntimeEventRouter::DispatchOnStartupEvent(browser_context_, extension->id());
2524ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
2534ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void RuntimeAPI::ReloadExtension(const std::string& extension_id) {
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_->ReloadExtension(extension_id);
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool RuntimeAPI::CheckForUpdates(
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& extension_id,
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const RuntimeAPIDelegate::UpdateCheckCallback& callback) {
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return delegate_->CheckForUpdates(extension_id, callback);
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void RuntimeAPI::OpenURL(const GURL& update_url) {
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegate_->OpenURL(update_url);
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool RuntimeAPI::GetPlatformInfo(runtime::PlatformInfo* info) {
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return delegate_->GetPlatformInfo(info);
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool RuntimeAPI::RestartDevice(std::string* error_message) {
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return delegate_->RestartDevice(error_message);
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RuntimeEventRouter::DispatchOnStartupEvent(
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context,
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& extension_id) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DispatchOnStartupEventImpl(context, extension_id, true, NULL);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RuntimeEventRouter::DispatchOnInstalledEvent(
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::BrowserContext* context,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Version& old_version,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool chrome_updated) {
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!ExtensionsBrowserClient::Get()->IsValidContext(context))
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(context);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!system)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::ListValue> event_args(new base::ListValue());
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue* info = new base::DictionaryValue();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_args->Append(info);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_version.IsValid()) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->SetString(kInstallReason, kInstallReasonUpdate);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->SetString(kInstallPreviousVersion, old_version.GetString());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (chrome_updated) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->SetString(kInstallReason, kInstallReasonChromeUpdate);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->SetString(kInstallReason, kInstallReasonInstall);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(system->event_router());
309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<Event> event(
310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new Event(runtime::OnInstalled::kEventName, event_args.Pass()));
311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  system->event_router()->DispatchEventWithLazyListener(extension_id,
312ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                        event.Pass());
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (old_version.IsValid()) {
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const Extension* extension =
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ExtensionRegistry::Get(context)->enabled_extensions().GetByID(
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            extension_id);
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (extension && SharedModuleInfo::IsSharedModule(extension)) {
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      scoped_ptr<ExtensionSet> dependents =
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          system->GetDependentExtensions(extension);
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      for (ExtensionSet::const_iterator i = dependents->begin();
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           i != dependents->end();
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           i++) {
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        scoped_ptr<base::ListValue> sm_event_args(new base::ListValue());
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        base::DictionaryValue* sm_info = new base::DictionaryValue();
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        sm_event_args->Append(sm_info);
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        sm_info->SetString(kInstallReason, kInstallReasonSharedModuleUpdate);
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        sm_info->SetString(kInstallPreviousVersion, old_version.GetString());
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        sm_info->SetString(kInstallId, extension_id);
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        scoped_ptr<Event> sm_event(
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            new Event(runtime::OnInstalled::kEventName, sm_event_args.Pass()));
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        system->event_router()->DispatchEventWithLazyListener((*i)->id(),
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                              sm_event.Pass());
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RuntimeEventRouter::DispatchOnUpdateAvailableEvent(
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::DictionaryValue* manifest) {
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(context);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!system)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::ListValue> args(new base::ListValue);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->Append(manifest->DeepCopy());
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(system->event_router());
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<Event> event(
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new Event(runtime::OnUpdateAvailable::kEventName, args.Pass()));
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  system->event_router()->DispatchEventToExtension(extension_id, event.Pass());
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context) {
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(context);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!system)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<base::ListValue> args(new base::ListValue);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(system->event_router());
365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<Event> event(
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new Event(runtime::OnBrowserUpdateAvailable::kEventName, args.Pass()));
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  system->event_router()->BroadcastEvent(event.Pass());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RuntimeEventRouter::DispatchOnRestartRequiredEvent(
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context,
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& app_id,
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    core_api::runtime::OnRestartRequired::Reason reason) {
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(context);
376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!system)
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<Event> event(
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new Event(runtime::OnRestartRequired::kEventName,
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                core_api::runtime::OnRestartRequired::Create(reason)));
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(system->event_router());
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  system->event_router()->DispatchEventToExtension(app_id, event.Pass());
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void RuntimeEventRouter::OnExtensionUninstalled(
389010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::BrowserContext* context,
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& extension_id,
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UninstallReason reason) {
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!(reason == UNINSTALL_REASON_USER_INITIATED ||
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reason == UNINSTALL_REASON_MANAGEMENT_API)) {
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
397010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GURL uninstall_url(
398010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GetUninstallURL(ExtensionPrefs::Get(context), extension_id));
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (uninstall_url.is_empty())
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RuntimeAPI::GetFactoryInstance()->Get(context)->OpenURL(uninstall_url);
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
406010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction RuntimeGetBackgroundPageFunction::Run() {
407010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionSystem* system = ExtensionSystem::Get(browser_context());
408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ExtensionHost* host =
409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      system->process_manager()->GetBackgroundHostForExtension(extension_id());
410010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (system->lazy_background_task_queue()->ShouldEnqueueTask(browser_context(),
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                              extension())) {
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system->lazy_background_task_queue()->AddPendingTask(
413010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        browser_context(),
4141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        extension_id(),
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        base::Bind(&RuntimeGetBackgroundPageFunction::OnPageLoaded, this));
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (host) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnPageLoaded(host);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
419010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return RespondNow(Error(kNoBackgroundPageError));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return RespondLater();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RuntimeGetBackgroundPageFunction::OnPageLoaded(ExtensionHost* host) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host) {
427010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    Respond(NoArguments());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    Respond(Error(kPageLoadError));
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction RuntimeSetUninstallURLFunction::Run() {
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string url_string;
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url_string));
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url(url_string);
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!url.is_valid()) {
439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return RespondNow(
440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        Error(ErrorUtils::FormatErrorMessage(kInvalidUrlError, url_string)));
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetUninstallURL(
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ExtensionPrefs::Get(browser_context()), extension_id(), url_string);
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return RespondNow(NoArguments());
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction RuntimeReloadFunction::Run() {
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RuntimeAPI::GetFactoryInstance()->Get(browser_context())->ReloadExtension(
4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      extension_id());
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return RespondNow(NoArguments());
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction RuntimeRequestUpdateCheckFunction::Run() {
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!RuntimeAPI::GetFactoryInstance()
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           ->Get(browser_context())
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           ->CheckForUpdates(
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               extension_id(),
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               base::Bind(&RuntimeRequestUpdateCheckFunction::CheckComplete,
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          this))) {
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return RespondNow(Error(kUpdatesDisabledError));
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return RespondLater();
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void RuntimeRequestUpdateCheckFunction::CheckComplete(
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const RuntimeAPIDelegate::UpdateCheckResult& result) {
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result.success) {
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::DictionaryValue* details = new base::DictionaryValue;
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    details->SetString("version", result.version);
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Respond(TwoArguments(new base::StringValue(result.response), details));
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // HMM(kalman): Why does !success not imply Error()?
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Respond(OneArgument(new base::StringValue(result.response)));
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
477010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction RuntimeRestartFunction::Run() {
478010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string message;
479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool result =
480010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      RuntimeAPI::GetFactoryInstance()->Get(browser_context())->RestartDevice(
481010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &message);
482010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!result) {
483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return RespondNow(Error(message));
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return RespondNow(NoArguments());
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction RuntimeGetPlatformInfoFunction::Run() {
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  runtime::PlatformInfo info;
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!RuntimeAPI::GetFactoryInstance()
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           ->Get(browser_context())
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           ->GetPlatformInfo(&info)) {
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return RespondNow(Error(kPlatformInfoUnavailable));
494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return RespondNow(
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ArgumentList(runtime::GetPlatformInfo::Results::Create(info)));
497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)ExtensionFunction::ResponseAction
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)RuntimeGetPackageDirectoryEntryFunction::Run() {
50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::IsolatedContext* isolated_context =
50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::IsolatedContext::GetInstance();
5037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(isolated_context);
5047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string relative_path = kPackageDirectoryPath;
5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::FilePath path = extension_->path();
5077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string filesystem_id = isolated_context->RegisterFileSystemForPath(
50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::kFileSystemTypeNativeLocal, std::string(), path, &relative_path);
5097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  int renderer_id = render_view_host_->GetProcess()->GetID();
5117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  content::ChildProcessSecurityPolicy* policy =
5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      content::ChildProcessSecurityPolicy::GetInstance();
5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  policy->GrantReadFileSystem(renderer_id, filesystem_id);
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::DictionaryValue* dict = new base::DictionaryValue();
5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  dict->SetString("fileSystemId", filesystem_id);
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  dict->SetString("baseName", relative_path);
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return RespondNow(OneArgument(dict));
5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace extensions
521