Chromium Code Reviews| Index: chrome/browser/extensions/network_delay_listener.cc |
| =================================================================== |
| --- chrome/browser/extensions/network_delay_listener.cc (revision 0) |
| +++ chrome/browser/extensions/network_delay_listener.cc (revision 0) |
| @@ -0,0 +1,161 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/extensions/network_delay_listener.h" |
| + |
| +#include "base/metrics/histogram.h" |
| +#include "chrome/browser/extensions/extension_service.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "chrome/common/extensions/extension.h" |
| +#include "chrome/common/url_constants.h" |
| +#include "chrome/browser/extensions/extension_host.h" |
| +#include "content/browser/browser_thread.h" |
| +#include "content/common/notification_service.h" |
| +#include "net/url_request/url_request.h" |
| + |
| +NetworkDelayListener::NetworkDelayListener() |
| + : resource_queue_(NULL), |
| + extensions_ready_(false), |
| + recorded_startup_delay_(false) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
| + NotificationService::AllSources()); |
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| + NotificationService::AllSources()); |
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
| + NotificationService::AllSources()); |
| + AddRef(); // Will be balanced in Cleanup(). |
| +} |
| + |
| +void NetworkDelayListener::Initialize(ResourceQueue* resource_queue) { |
| + resource_queue_ = resource_queue; |
| +} |
| + |
| +bool NetworkDelayListener::ShouldDelayRequest( |
| + net::URLRequest* request, |
| + const ResourceDispatcherHostRequestInfo& request_info, |
| + const GlobalRequestID& request_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + // Don't block internal URLs. |
| + if (request->url().SchemeIs(chrome::kChromeUIScheme) || |
| + request->url().SchemeIs(chrome::kExtensionScheme)) { |
| + return false; |
| + } |
| + |
| + return extensions_ready_; |
| +} |
| + |
| +NetworkDelayListener::~NetworkDelayListener() { |
| +} |
| + |
| +void NetworkDelayListener::WillShutdownResourceQueue() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + resource_queue_ = NULL; |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + NewRunnableMethod(this, &NetworkDelayListener::Cleanup)); |
| +} |
| + |
| +void NetworkDelayListener::OnExtensionPending(const Extension* extension) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + DCHECK(pending_extensions_.count(extension->id()) == 0); |
| + |
| + // We only wait for background pages to load. If the extension has no |
| + // background page, ignore it. |
| + if (!extension->background_url().is_empty()) { |
| + extensions_ready_ = false; |
| + pending_extensions_.insert(extension->id()); |
| + delay_start_times_[extension->id()] = base::TimeTicks::Now(); |
| + } |
| +} |
| + |
| +void NetworkDelayListener::OnExtensionReady(const Extension* extension) { |
| + // This may be called multiple times, if an extension finishes loading and is |
| + // then disabled or uninstalled. |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + // Quick escape to save work in the common case. |
| + if (pending_extensions_.count(extension->id()) == 0) |
| + return; |
| + |
| + UMA_HISTOGRAM_TIMES("Extensions.StartupDelay", |
| + base::TimeTicks::Now() - delay_start_times_[extension->id()]); |
| + delay_start_times_.erase(extension->id()); |
| + pending_extensions_.erase(extension->id()); |
| + |
| + if (pending_extensions_.empty()) { |
| + extensions_ready_ = true; |
| + if (!recorded_startup_delay_) { |
| + UMA_HISTOGRAM_TIMES("Extensions.StartupDelay_Total", |
| + overall_start_time_.Elapsed()); |
| + recorded_startup_delay_ = true; |
| + } |
| + if (resource_queue_) |
| + resource_queue_->StartDelayedRequests(this); |
| + } |
| +} |
| + |
| +void NetworkDelayListener::Cleanup() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
|
Aaron Boodman
2011/10/10 22:59:29
I think these should be CHECK. Being on the wrong
|
| + registrar_.RemoveAll(); |
| + Release(); |
| +} |
| + |
| +void NetworkDelayListener::Observe(int type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + switch (type) { |
| + case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| + const Extension* extension = Details<const Extension>(details).ptr(); |
| + ExtensionService* service = |
| + Source<Profile>(source).ptr()->GetExtensionService(); |
| + if (service->DelaysNetworkRequests(extension)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod( |
|
battre
2011/10/10 15:33:29
This is old-school ;-)
Check Albert J Wong's emai
|
| + this, &NetworkDelayListener::OnExtensionPending, extension)); |
| + } |
| + break; |
| + } |
| + case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| + const Extension* extension = |
| + Details<UnloadedExtensionInfo>(details)->extension; |
| + ExtensionService* service = |
| + Source<Profile>(source).ptr()->GetExtensionService(); |
| + if (service->DelaysNetworkRequests(extension)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod( |
| + this, &NetworkDelayListener::OnExtensionReady, extension)); |
| + } |
| + break; |
| + } |
| + case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { |
| + const ExtensionHost* eh = Details<ExtensionHost>(details).ptr(); |
| + if (eh->extension_host_type() != ViewType::EXTENSION_BACKGROUND_PAGE) |
| + return; |
| + |
| + const Extension* extension = eh ->extension(); |
|
battre
2011/10/10 15:33:29
nit: space before ->
|
| + ExtensionService* service = |
| + Source<Profile>(source).ptr()->GetExtensionService(); |
| + if (service->DelaysNetworkRequests(extension)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod( |
| + this, &NetworkDelayListener::OnExtensionReady, extension)); |
| + } |
| + break; |
| + } |
| + |
| + default: |
| + NOTREACHED(); |
| + } |
| +} |
| Property changes on: chrome\browser\extensions\network_delay_listener.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |