| 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,178 @@
|
| +// 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/bind.h"
|
| +#include "base/metrics/histogram.h"
|
| +#include "chrome/browser/extensions/extension_host.h"
|
| +#include "chrome/browser/extensions/extension_service.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/common/chrome_notification_types.h"
|
| +#include "chrome/common/chrome_view_types.h"
|
| +#include "chrome/common/extensions/extension.h"
|
| +#include "chrome/common/url_constants.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) {
|
| + CHECK(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());
|
| + registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
|
| + 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) {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + // Don't block internal URLs.
|
| + if (request->url().SchemeIs(chrome::kChromeUIScheme) ||
|
| + request->url().SchemeIs(chrome::kExtensionScheme) ||
|
| + request->url().SchemeIs(chrome::kChromeDevToolsScheme)) {
|
| + return false;
|
| + }
|
| +
|
| + return !extensions_ready_;
|
| +}
|
| +
|
| +NetworkDelayListener::~NetworkDelayListener() {
|
| +}
|
| +
|
| +void NetworkDelayListener::WillShutdownResourceQueue() {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + resource_queue_ = NULL;
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&NetworkDelayListener::Cleanup, this));
|
| +}
|
| +
|
| +void NetworkDelayListener::OnExtensionPending(const std::string& id) {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + DCHECK(pending_extensions_.count(id) == 0);
|
| + extensions_ready_ = false;
|
| + pending_extensions_.insert(id);
|
| + delay_start_times_[id] = base::TimeTicks::Now();
|
| +}
|
| +
|
| +void NetworkDelayListener::OnExtensionReady(const std::string& id) {
|
| + // This may be called multiple times, if an extension finishes loading and is
|
| + // then disabled or uninstalled.
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + // Quick escape to save work in the common case.
|
| + if (pending_extensions_.count(id) == 0)
|
| + return;
|
| +
|
| + UMA_HISTOGRAM_TIMES("Extensions.StartupDelay",
|
| + base::TimeTicks::Now() - delay_start_times_[id]);
|
| + delay_start_times_.erase(id);
|
| + pending_extensions_.erase(id);
|
| +
|
| + StartDelayedRequestsIfReady();
|
| +}
|
| +
|
| +void NetworkDelayListener::StartDelayedRequestsIfReady() {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + 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() {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + registrar_.RemoveAll();
|
| + Release();
|
| +}
|
| +
|
| +void NetworkDelayListener::Observe(int type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + CHECK(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();
|
| + // We only wait for background pages to load. If the extension has no
|
| + // background page, ignore it.
|
| + if (service->extension_prefs()->DelaysNetworkRequests(extension->id()) &&
|
| + !extension->background_url().is_empty()) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NetworkDelayListener::OnExtensionPending,
|
| + this, extension->id()));
|
| + }
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
|
| + const Extension* extension =
|
| + Details<UnloadedExtensionInfo>(details)->extension;
|
| + ExtensionService* service =
|
| + Source<Profile>(source).ptr()->GetExtensionService();
|
| + if (service->extension_prefs()->DelaysNetworkRequests(extension->id())) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NetworkDelayListener::OnExtensionReady,
|
| + this, extension->id()));
|
| + }
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
|
| + const ExtensionHost* eh = Details<ExtensionHost>(details).ptr();
|
| + if (eh->extension_host_type() !=
|
| + chrome::ViewType::EXTENSION_BACKGROUND_PAGE)
|
| + return;
|
| +
|
| + const Extension* extension = eh->extension();
|
| + ExtensionService* service =
|
| + Source<Profile>(source).ptr()->GetExtensionService();
|
| + if (service->extension_prefs()->DelaysNetworkRequests(extension->id())) {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NetworkDelayListener::OnExtensionReady,
|
| + this, extension->id()));
|
| + }
|
| + break;
|
| + }
|
| +
|
| + case chrome::NOTIFICATION_EXTENSIONS_READY: {
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NetworkDelayListener::StartDelayedRequestsIfReady, this));
|
| + break;
|
| + }
|
| +
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| +}
|
|
|
| Property changes on: chrome\browser\extensions\network_delay_listener.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|