From 39a5b53280853e94a95f8cc8b05582cf10e0d88a Mon Sep 17 00:00:00 2001
From: "mpcomplete@chromium.org"
 <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Sat, 22 Oct 2011 01:47:07 +0000
Subject: Redo how page load time stats are gathered for webrequest extensions:
 - keep track of whether an extension registers for a webrequest event. -
 gather stats for webrequest extensions other than adblock.

BUG=100411
TEST=no


Review URL: http://codereview.chromium.org/8360021

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106834 0039d316-1c4b-4281-b951-d872f2087c98
---
 chrome/browser/chrome_content_browser_client.cc    |  3 ++
 chrome/browser/extensions/extension_service.cc     |  9 ++++
 chrome/browser/extensions/extension_service.h      |  9 ++++
 .../browser/extensions/extension_webrequest_api.cc | 53 ++++++++++++++++++++++
 .../browser/extensions/extension_webrequest_api.h  |  6 +++
 chrome/common/extensions/extension_messages.h      |  6 +++
 chrome/renderer/chrome_content_renderer_client.cc  | 24 +++-------
 chrome/renderer/chrome_content_renderer_client.h   |  1 +
 chrome/renderer/extensions/extension_dispatcher.cc | 13 +++++-
 chrome/renderer/extensions/extension_dispatcher.h  | 21 +++++++++
 chrome/renderer/page_load_histograms.cc            | 34 +++++++++++++-
 11 files changed, 159 insertions(+), 20 deletions(-)

diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index ccc45ba..80720469 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/extensions/extension_message_handler.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_web_ui.h"
+#include "chrome/browser/extensions/extension_webrequest_api.h"
 #include "chrome/browser/geolocation/chrome_access_token_store.h"
 #include "chrome/browser/google/google_util.h"
 #include "chrome/browser/net/chrome_net_log.h"
@@ -264,6 +265,8 @@ void ChromeContentBrowserClient::BrowserRenderProcessHostCreated(
 
   host->Send(new ChromeViewMsg_SetIsIncognitoProcess(
       profile->IsOffTheRecord()));
+
+  SendExtensionWebRequestStatusToHost(host);
 }
 
 void ChromeContentBrowserClient::PluginProcessHostCreated(
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index f646e2e..91fb896 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -2943,6 +2943,15 @@ void ExtensionService::SetBeingUpgraded(const Extension* extension,
   extension_runtime_data_[extension->id()].being_upgraded = value;
 }
 
+bool ExtensionService::HasUsedWebRequest(const Extension* extension) {
+  return extension_runtime_data_[extension->id()].has_used_webrequest;
+}
+
+void ExtensionService::SetHasUsedWebRequest(const Extension* extension,
+                                            bool value) {
+  extension_runtime_data_[extension->id()].has_used_webrequest = value;
+}
+
 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) {
   return &extension_runtime_data_[extension->id()].property_bag;
 }
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index aa71121..4673c89 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -241,6 +241,12 @@ class ExtensionService
   bool IsBeingUpgraded(const Extension* extension);
   void SetBeingUpgraded(const Extension* extension, bool value);
 
+  // Getter and setter for the flag that specifies if the extension has used
+  // the webrequest API.
+  // TODO(mpcomplete): remove. http://crbug.com/100411
+  bool HasUsedWebRequest(const Extension* extension);
+  void SetHasUsedWebRequest(const Extension* extension, bool value);
+
   // Getter for the extension's runtime data PropertyBag.
   PropertyBag* GetPropertyBag(const Extension* extension);
 
@@ -591,6 +597,9 @@ class ExtensionService
     // True while the extension is being upgraded.
     bool being_upgraded;
 
+    // True if the extension has used the webRequest API.
+    bool has_used_webrequest;
+
     // Generic bag of runtime data that users can associate with extensions.
     PropertyBag property_bag;
 
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc
index 616dea4..f22f692 100644
--- a/chrome/browser/extensions/extension_webrequest_api.cc
+++ b/chrome/browser/extensions/extension_webrequest_api.cc
@@ -6,11 +6,14 @@
 
 #include <algorithm>
 
+#include "base/bind.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram.h"
 #include "base/string_number_conversions.h"
 #include "base/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/extensions/extension_event_router.h"
 #include "chrome/browser/extensions/extension_info_map.h"
 #include "chrome/browser/extensions/extension_prefs.h"
@@ -19,10 +22,12 @@
 #include "chrome/browser/extensions/extension_webrequest_api_constants.h"
 #include "chrome/browser/extensions/extension_webrequest_time_tracker.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
 #include "chrome/browser/renderer_host/web_cache_manager.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_error_utils.h"
+#include "chrome/common/extensions/extension_messages.h"
 #include "chrome/common/extensions/url_pattern.h"
 #include "chrome/common/url_constants.h"
 #include "content/browser/browser_message_filter.h"
@@ -284,6 +289,24 @@ bool InDecreasingExtensionInstallationTimeOrder(
   return a->extension_install_time > b->extension_install_time;
 }
 
+void NotifyWebRequestAPIUsed(void* profile_id, const Extension* extension) {
+  Profile* profile = reinterpret_cast<Profile*>(profile_id);
+  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
+    return;
+
+  if (profile->GetExtensionService()->HasUsedWebRequest(extension))
+    return;
+  profile->GetExtensionService()->SetHasUsedWebRequest(extension, true);
+
+  content::BrowserContext* browser_context = profile;
+  for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
+       !it.IsAtEnd(); it.Advance()) {
+    RenderProcessHost* host = it.GetCurrentValue();
+    if (host->browser_context() == browser_context)
+      SendExtensionWebRequestStatusToHost(host);
+  }
+}
+
 }  // namespace
 
 // Represents a single unique listener to an event, along with whatever filter
@@ -1683,6 +1706,10 @@ bool WebRequestEventHandled::RunImpl() {
       profile_id(), extension_id(), event_name, sub_event_name, request_id,
       response.release());
 
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+      &NotifyWebRequestAPIUsed,
+      profile_id(), make_scoped_refptr(GetExtension())));
+
   return true;
 }
 
@@ -1690,3 +1717,29 @@ bool WebRequestHandlerBehaviorChanged::RunImpl() {
   WebCacheManager::GetInstance()->ClearCacheOnNavigation();
   return true;
 }
+
+void SendExtensionWebRequestStatusToHost(RenderProcessHost* host) {
+  Profile* profile = Profile::FromBrowserContext(host->browser_context());
+  if (!profile || !profile->GetExtensionService())
+    return;
+
+  bool adblock = false;
+  bool adblock_plus = false;
+  bool other = false;
+  const ExtensionList* extensions =
+      profile->GetExtensionService()->extensions();
+  for (ExtensionList::const_iterator it = extensions->begin();
+       it != extensions->end(); ++it) {
+    if (profile->GetExtensionService()->HasUsedWebRequest(*it)) {
+      if ((*it)->name().find("Adblock Plus") != std::string::npos) {
+        adblock_plus = true;
+      } else if ((*it)->name().find("AdBlock") != std::string::npos) {
+        adblock = true;
+      } else {
+        other = true;
+      }
+    }
+  }
+
+  host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other));
+}
diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h
index 8cf5f69..2644411 100644
--- a/chrome/browser/extensions/extension_webrequest_api.h
+++ b/chrome/browser/extensions/extension_webrequest_api.h
@@ -25,6 +25,7 @@
 class ExtensionInfoMap;
 class ExtensionWebRequestTimeTracker;
 class GURL;
+class RenderProcessHost;
 
 namespace base {
 class DictionaryValue;
@@ -410,4 +411,9 @@ class WebRequestHandlerBehaviorChanged : public AsyncExtensionFunction {
       "experimental.webRequest.handlerBehaviorChanged");
 };
 
+// Send updates to |host| with information about what webRequest-related
+// extensions are installed.
+// TODO(mpcomplete): remove. http://crbug.com/100411
+void SendExtensionWebRequestStatusToHost(RenderProcessHost* host);
+
 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBREQUEST_API_H_
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index 352b454..6d4e567 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -238,6 +238,12 @@ IPC_MESSAGE_CONTROL5(ExtensionMsg_UpdatePermissions,
 IPC_MESSAGE_ROUTED1(ExtensionMsg_NotifyRenderViewType,
                     content::ViewType /* view_type */)
 
+// Deliver a message sent with ExtensionHostMsg_PostMessage.
+IPC_MESSAGE_CONTROL3(ExtensionMsg_UsingWebRequestAPI,
+                     bool /* adblock */,
+                     bool /* adblock_plus */,
+                     bool /* other_webrequest */)
+
 // Messages sent from the renderer to the browser.
 
 // A renderer sends this message when an extension process starts an API
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index de72527..7b7b3d2 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -849,27 +849,15 @@ bool ChromeContentRendererClient::IsAdblockPlusInstalled() {
 }
 
 bool ChromeContentRendererClient::IsAdblockWithWebRequestInstalled() {
-  const ExtensionSet& extensions = *extension_dispatcher_->extensions();
-  for (ExtensionSet::const_iterator it = extensions.begin();
-       it != extensions.end(); ++it) {
-    if (it->second->HasAPIPermission(ExtensionAPIPermission::kExperimental) &&
-        it->second->name().find("Adblock") != std::string::npos &&
-        it->second->name().find("Plus") == std::string::npos)
-      return true;
-  }
-  return false;
+  return extension_dispatcher_->IsAdblockWithWebRequestInstalled();
 }
 
 bool ChromeContentRendererClient::IsAdblockPlusWithWebRequestInstalled() {
-  const ExtensionSet& extensions = *extension_dispatcher_->extensions();
-  for (ExtensionSet::const_iterator it = extensions.begin();
-       it != extensions.end(); ++it) {
-    if (it->second->HasAPIPermission(ExtensionAPIPermission::kExperimental) &&
-        it->second->name().find("Adblock") != std::string::npos &&
-        it->second->name().find("Plus") != std::string::npos)
-      return true;
-  }
-  return false;
+  return extension_dispatcher_->IsAdblockPlusWithWebRequestInstalled();
+}
+
+bool ChromeContentRendererClient::IsOtherExtensionWithWebRequestInstalled() {
+  return extension_dispatcher_->IsOtherExtensionWithWebRequestInstalled();
 }
 
 }  // namespace chrome
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index f70d4e1..e77f9a8 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -96,6 +96,7 @@ class ChromeContentRendererClient : public content::ContentRendererClient {
   bool IsAdblockPlusInstalled();
   bool IsAdblockWithWebRequestInstalled();
   bool IsAdblockPlusWithWebRequestInstalled();
+  bool IsOtherExtensionWithWebRequestInstalled();
 
   // For testing.
   void SetExtensionDispatcher(ExtensionDispatcher* extension_dispatcher);
diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc
index 03f6393..e6c6d12 100644
--- a/chrome/renderer/extensions/extension_dispatcher.cc
+++ b/chrome/renderer/extensions/extension_dispatcher.cc
@@ -43,7 +43,10 @@ using WebKit::WebString;
 using content::RenderThread;
 
 ExtensionDispatcher::ExtensionDispatcher()
-    : is_webkit_initialized_(false) {
+    : is_webkit_initialized_(false),
+      webrequest_adblock_(false),
+      webrequest_adblock_plus_(false),
+      webrequest_other_(false) {
   const CommandLine& command_line = *(CommandLine::ForCurrentProcess());
   is_extension_process_ =
       command_line.HasSwitch(switches::kExtensionProcess) ||
@@ -75,6 +78,7 @@ bool ExtensionDispatcher::OnControlMessageReceived(
     IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateApplication, OnActivateApplication)
     IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePermissions, OnUpdatePermissions)
     IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts)
+    IPC_MESSAGE_HANDLER(ExtensionMsg_UsingWebRequestAPI, OnUsingWebRequestAPI)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -395,3 +399,10 @@ void ExtensionDispatcher::RegisterExtension(v8::Extension* extension,
 
   RenderThread::Get()->RegisterExtension(extension);
 }
+
+void ExtensionDispatcher::OnUsingWebRequestAPI(
+    bool adblock, bool adblock_plus, bool other) {
+  webrequest_adblock_ = adblock;
+  webrequest_adblock_plus_ = adblock_plus;
+  webrequest_other_ = other;
+}
diff --git a/chrome/renderer/extensions/extension_dispatcher.h b/chrome/renderer/extensions/extension_dispatcher.h
index 5b6f4b5..d6822ec 100644
--- a/chrome/renderer/extensions/extension_dispatcher.h
+++ b/chrome/renderer/extensions/extension_dispatcher.h
@@ -70,6 +70,17 @@ class ExtensionDispatcher : public content::RenderProcessObserver {
 
   void SetTestExtensionId(const std::string& extension_id);
 
+  // TODO(mpcomplete): remove. http://crbug.com/100411
+  bool IsAdblockWithWebRequestInstalled() const {
+    return webrequest_adblock_;
+  }
+  bool IsAdblockPlusWithWebRequestInstalled() const {
+    return webrequest_adblock_plus_;
+  }
+  bool IsOtherExtensionWithWebRequestInstalled() const {
+    return webrequest_other_;
+  }
+
  private:
   friend class RenderViewTest;
 
@@ -98,6 +109,10 @@ class ExtensionDispatcher : public content::RenderProcessObserver {
                            const URLPatternSet& explicit_hosts,
                            const URLPatternSet& scriptable_hosts);
   void OnUpdateUserScripts(base::SharedMemoryHandle table);
+  void OnUsingWebRequestAPI(
+      bool adblock,
+      bool adblock_plus,
+      bool other_webrequest);
 
   // Update the list of active extensions that will be reported when we crash.
   void UpdateActiveExtensions();
@@ -147,6 +162,12 @@ class ExtensionDispatcher : public content::RenderProcessObserver {
 
   std::string test_extension_id_;
 
+  // Status of webrequest usage for known extensions.
+  // TODO(mpcomplete): remove. http://crbug.com/100411
+  bool webrequest_adblock_;
+  bool webrequest_adblock_plus_;
+  bool webrequest_other_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionDispatcher);
 };
 
diff --git a/chrome/renderer/page_load_histograms.cc b/chrome/renderer/page_load_histograms.cc
index be99f00..e786618 100644
--- a/chrome/renderer/page_load_histograms.cc
+++ b/chrome/renderer/page_load_histograms.cc
@@ -618,7 +618,7 @@ void PageLoadHistograms::Dump(WebFrame* frame) {
   const bool use_adblockplus_histogram = client->IsAdblockPlusInstalled();
   if (use_adblockplus_histogram) {
     UMA_HISTOGRAM_ENUMERATION(
-        "PLT.Abandoned_ExtensionAdblock",
+        "PLT.Abandoned_ExtensionAdblockPlus",
         abandoned_page ? 1 : 0, 2);
     switch (load_type) {
       case NavigationState::NORMAL_LOAD:
@@ -710,6 +710,38 @@ void PageLoadHistograms::Dump(WebFrame* frame) {
     }
   }
 
+  const bool use_webrequest_other_histogram =
+      client->IsOtherExtensionWithWebRequestInstalled();
+  if (use_webrequest_other_histogram) {
+    UMA_HISTOGRAM_ENUMERATION(
+        "PLT.Abandoned_ExtensionWebRequestOther",
+        abandoned_page ? 1 : 0, 2);
+    switch (load_type) {
+      case NavigationState::NORMAL_LOAD:
+        PLT_HISTOGRAM(
+            "PLT.BeginToFinish_NormalLoad_ExtensionWebRequestOther",
+            begin_to_finish_all_loads);
+        break;
+      case NavigationState::LINK_LOAD_NORMAL:
+        PLT_HISTOGRAM(
+            "PLT.BeginToFinish_LinkLoadNormal_ExtensionWebRequestOther",
+            begin_to_finish_all_loads);
+        break;
+      case NavigationState::LINK_LOAD_RELOAD:
+        PLT_HISTOGRAM(
+            "PLT.BeginToFinish_LinkLoadReload_ExtensionWebRequestOther",
+            begin_to_finish_all_loads);
+        break;
+      case NavigationState::LINK_LOAD_CACHE_STALE_OK:
+        PLT_HISTOGRAM(
+            "PLT.BeginToFinish_LinkLoadStaleOk_ExtensionWebRequestOther",
+            begin_to_finish_all_loads);
+        break;
+      default:
+        break;
+    }
+  }
+
   // For the SPDY field trials, we need to verify that the page loaded was
   // the type we requested:
   //   if we asked for a SPDY request, we got a SPDY request
-- 
cgit v1.1