Unrevert 152017 - Add chrome.runtime.onStartup, which is fired on browser start.

I reused LazyBackgroundTaskQueue so that this works for regular background
pages, which may not be fully loaded by the time this event is dispatched.

BUG=132328
Review URL: https://chromiumcodereview.appspot.com/10828218


Reason for revert: introduced a frequent crash


Review URL: https://chromiumcodereview.appspot.com/10855237

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152238 0039d316-1c4b-4281-b951-d872f2087c98
parent a72e39dc
......@@ -4,24 +4,71 @@
#include "chrome/browser/extensions/api/runtime/runtime_api.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/lazy_background_task_queue.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/extension.h"
#include "googleurl/src/gurl.h"
namespace extensions {
namespace {
const char kOnStartupEvent[] = "runtime.onStartup";
const char kOnInstalledEvent[] = "runtime.onInstalled";
const char kNoBackgroundPageError[] = "You do not have a background page.";
const char kPageLoadError[] = "Background page failed to load.";
static void DispatchOnStartupEventImpl(
Profile* profile,
const std::string& extension_id,
bool first_call,
ExtensionHost* host) {
// A NULL host from the LazyBackgroundTaskQueue means the page failed to
// load. Give up.
if (!host && !first_call)
return;
if (g_browser_process->IsShuttingDown() ||
!g_browser_process->profile_manager()->IsValidProfile(profile))
return;
ExtensionSystem* system = ExtensionSystem::Get(profile);
if (!system)
return;
// If this is a persistent background page, we want to wait for it to load
// (it might not be ready, since this is startup). But only enqueue once.
// If it fails to load the first time, don't bother trying again.
const Extension* extension =
system->extension_service()->extensions()->GetByID(extension_id);
if (extension && extension->has_persistent_background_page() && first_call &&
system->lazy_background_task_queue()->
ShouldEnqueueTask(profile, extension)) {
system->lazy_background_task_queue()->AddPendingTask(
profile, extension_id,
base::Bind(&DispatchOnStartupEventImpl,
profile, extension_id, false));
return;
}
scoped_ptr<ListValue> event_args(new ListValue());
system->event_router()->DispatchEventToExtension(
extension_id, kOnStartupEvent, event_args.Pass(), NULL, GURL());
}
namespace extensions {
} // namespace
// static
void RuntimeEventRouter::DispatchOnStartupEvent(
Profile* profile, const std::string& extension_id) {
DispatchOnStartupEventImpl(profile, extension_id, true, NULL);
}
// static
void RuntimeEventRouter::DispatchOnInstalledEvent(
......
......@@ -15,6 +15,10 @@ class ExtensionHost;
class RuntimeEventRouter {
public:
// Dispatches the onStartup event to all currently-loaded extensions.
static void DispatchOnStartupEvent(Profile* profile,
const std::string& extension_id);
// Dispatches the onInstalled event to the given extension.
static void DispatchOnInstalledEvent(Profile* profile,
const std::string& extension_id);
......
......@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/runtime/runtime_api.h"
#include "chrome/browser/extensions/api/web_request/web_request_api.h"
#include "chrome/browser/extensions/extension_devtools_manager.h"
......@@ -20,6 +21,7 @@
#include "chrome/browser/extensions/lazy_background_task_queue.h"
#include "chrome/browser/extensions/process_map.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
......@@ -32,6 +34,8 @@
using base::Value;
using content::BrowserThread;
namespace extensions {
namespace {
const char kDispatchEvent[] = "Event.dispatchEvent";
......@@ -44,9 +48,15 @@ void NotifyEventListenerRemovedOnIOThread(
profile, extension_id, sub_event_name);
}
} // namespace
void DispatchOnInstalledEvent(
Profile* profile, const std::string& extension_id) {
if (!g_browser_process->profile_manager()->IsValidProfile(profile))
return;
namespace extensions {
RuntimeEventRouter::DispatchOnInstalledEvent(profile, extension_id);
}
} // namespace
struct EventRouter::ListenerProcess {
content::RenderProcessHost* process;
......@@ -558,8 +568,7 @@ void EventRouter::Observe(int type,
const Extension* extension =
content::Details<const Extension>(details).ptr();
MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent,
profile_, extension->id()));
base::Bind(&DispatchOnInstalledEvent, profile_, extension->id()));
break;
}
default:
......
......@@ -10,6 +10,7 @@
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "chrome/browser/extensions/api/runtime/runtime_api.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_info_map.h"
......@@ -89,16 +90,20 @@ class IncognitoExtensionProcessManager : public ExtensionProcessManager {
static void CreateBackgroundHostForExtensionLoad(
ExtensionProcessManager* manager, const Extension* extension) {
if (extension->has_persistent_background_page()) {
if (extension->has_persistent_background_page())
manager->CreateBackgroundHost(extension, extension->GetBackgroundURL());
}
}
static void CreateBackgroundHostsForProfileStartup(
ExtensionProcessManager* manager, const ExtensionSet* extensions) {
Profile* profile,
ExtensionProcessManager* manager,
const ExtensionSet* extensions) {
for (ExtensionSet::const_iterator extension = extensions->begin();
extension != extensions->end(); ++extension) {
CreateBackgroundHostForExtensionLoad(manager, *extension);
extensions::RuntimeEventRouter::DispatchOnStartupEvent(
profile, (*extension)->id());
}
}
......@@ -557,19 +562,19 @@ void ExtensionProcessManager::Observe(
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_EXTENSIONS_READY: {
CreateBackgroundHostsForProfileStartup(this,
content::Source<Profile>(source).ptr()->
GetExtensionService()->extensions());
Profile* profile = content::Source<Profile>(source).ptr();
CreateBackgroundHostsForProfileStartup(profile, this,
profile->GetExtensionService()->extensions());
break;
}
case chrome::NOTIFICATION_EXTENSION_LOADED: {
ExtensionService* service =
content::Source<Profile>(source).ptr()->GetExtensionService();
Profile* profile = content::Source<Profile>(source).ptr();
ExtensionService* service = profile->GetExtensionService();
if (service->is_ready()) {
const Extension* extension =
content::Details<const Extension>(details).ptr();
::CreateBackgroundHostForExtensionLoad(this, extension);
CreateBackgroundHostForExtensionLoad(this, extension);
}
break;
}
......@@ -805,7 +810,8 @@ void IncognitoExtensionProcessManager::Observe(
// service will be NULL.
ExtensionService* service = GetProfile()->GetExtensionService();
if (service && service->is_ready())
CreateBackgroundHostsForProfileStartup(this, service->extensions());
CreateBackgroundHostsForProfileStartup(GetProfile(),
this, service->extensions());
}
break;
}
......
......@@ -42,7 +42,7 @@ LazyBackgroundTaskQueue::~LazyBackgroundTaskQueue() {
bool LazyBackgroundTaskQueue::ShouldEnqueueTask(
Profile* profile, const Extension* extension) {
DCHECK(extension);
if (extension->has_lazy_background_page()) {
if (extension->has_background_page()) {
ExtensionProcessManager* pm = profile->GetExtensionProcessManager();
ExtensionHost* background_host =
pm->GetBackgroundHostForExtension(extension->id());
......@@ -66,16 +66,17 @@ void LazyBackgroundTaskQueue::AddPendingTask(
tasks_list = new PendingTasksList();
pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list);
// If this is the first enqueued task, ensure the background page
// is loaded.
const Extension* extension =
ExtensionSystem::Get(profile)->extension_service()->
extensions()->GetByID(extension_id);
DCHECK(extension->has_lazy_background_page());
ExtensionProcessManager* pm =
ExtensionSystem::Get(profile)->process_manager();
pm->IncrementLazyKeepaliveCount(extension);
pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
if (extension && extension->has_lazy_background_page()) {
// If this is the first enqueued task, and we're not waiting for the
// background page to unload, ensure the background page is loaded.
ExtensionProcessManager* pm =
ExtensionSystem::Get(profile)->process_manager();
pm->IncrementLazyKeepaliveCount(extension);
pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
}
} else {
tasks_list = it->second.get();
}
......@@ -87,14 +88,14 @@ void LazyBackgroundTaskQueue::ProcessPendingTasks(
ExtensionHost* host,
Profile* profile,
const Extension* extension) {
if (!profile->IsSameProfile(profile_) ||
!extension->has_lazy_background_page())
if (!profile->IsSameProfile(profile_))
return;
PendingTasksKey key(profile, extension->id());
PendingTasksMap::iterator map_it = pending_tasks_.find(key);
if (map_it == pending_tasks_.end()) {
CHECK(!host); // lazy page should not load without any pending tasks
if (extension->has_lazy_background_page())
CHECK(!host); // lazy page should not load without any pending tasks
return;
}
......@@ -111,7 +112,7 @@ void LazyBackgroundTaskQueue::ProcessPendingTasks(
// Balance the keepalive in AddPendingTask. Note we don't do this on a
// failure to load, because the keepalive count is reset in that case.
if (host) {
if (host && extension->has_lazy_background_page()) {
ExtensionSystem::Get(profile)->process_manager()->
DecrementLazyKeepaliveCount(extension);
}
......
......@@ -109,6 +109,11 @@
}
],
"events": [
{
"name": "onStartup",
"type": "function",
"description": "Fired when the browser first starts up."
},
{
"name": "onInstalled",
"type": "function",
......
......@@ -193,6 +193,8 @@
<ol>
<li>
<a href="#event-onInstalled">onInstalled</a>
</li><li>
<a href="#event-onStartup">onStartup</a>
</li><li>
<a href="#event-onSuspend">onSuspend</a>
</li><li>
......@@ -497,6 +499,22 @@
</dl>
</div> <!-- /description -->
<!-- /description -->
</div><div class="apiItem">
<a name="event-onStartup"></a>
<h4>onStartup</h4>
<div class="summary">
<!-- Note: intentionally longer 80 columns -->
<span class="subdued">chrome.runtime.</span><span>onStartup</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span><span></span>);
</div>
<div class="description">
<p>Fired when the browser first starts up.</p>
<!-- LISTENER PARAMETERS -->
<!-- EXTRA PARAMETERS -->
<!-- LISTENER RETURN VALUE -->
<dl>
</dl>
</div> <!-- /description -->
<!-- /description -->
</div><div class="apiItem">
<a name="event-onSuspend"></a>
<h4>onSuspend</h4>
......
......@@ -224,6 +224,8 @@
<ol>
<li>
<a href="#event-onInstalled">onInstalled</a>
</li><li>
<a href="#event-onStartup">onStartup</a>
</li><li>
<a href="#event-onSuspend">onSuspend</a>
</li><li>
......@@ -566,6 +568,22 @@
</dl>
</div> <!-- /description -->
<!-- /description -->
</div><div class="apiItem">
<a name="event-onStartup"></a>
<h4>onStartup</h4>
<div class="summary">
<!-- Note: intentionally longer 80 columns -->
<span class="subdued">chrome.runtime.</span><span>onStartup</span><span class="subdued">.addListener</span>(function(<span></span>) <span class="subdued">{...}</span><span></span>);
</div>
<div class="description">
<p>Fired when the browser first starts up.</p>
<!-- LISTENER PARAMETERS -->
<!-- EXTRA PARAMETERS -->
<!-- LISTENER RETURN VALUE -->
<dl>
</dl>
</div> <!-- /description -->
<!-- /description -->
</div><div class="apiItem">
<a name="event-onSuspend"></a>
<h4>onSuspend</h4>
......
......@@ -184,6 +184,7 @@
"chrome.experimental.speechInput.onSoundStart": "experimental.speechInput.html#event-onSoundStart",
"chrome.experimental.speechInput.start": "experimental.speechInput.html#method-start",
"chrome.experimental.speechInput.stop": "experimental.speechInput.html#method-stop",
"chrome.experimental.systemInfo.cpu.get": "experimental.systemInfo.cpu.html#method-get",
"chrome.experimental.usb.bulkTransfer": "experimental.usb.html#method-bulkTransfer",
"chrome.experimental.usb.closeDevice": "experimental.usb.html#method-closeDevice",
"chrome.experimental.usb.controlTransfer": "experimental.usb.html#method-controlTransfer",
......@@ -290,6 +291,7 @@
"chrome.runtime.getManifest": "runtime.html#method-getManifest",
"chrome.runtime.getURL": "runtime.html#method-getURL",
"chrome.runtime.onInstalled": "runtime.html#event-onInstalled",
"chrome.runtime.onStartup": "runtime.html#event-onStartup",
"chrome.runtime.onSuspend": "runtime.html#event-onSuspend",
"chrome.runtime.onSuspendCanceled": "runtime.html#event-onSuspendCanceled",
"chrome.scriptBadge.getAttention": "scriptBadge.html#method-getAttention",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment