Ensure ChromeURLRequestContext finds out first about extension loading.

This prevents races from arising where extension renderers may try to navigate to extension urls before the request context knows how to map the urls to extension resources.

BUG=22668

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27781 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 1258e849..4f61ac4f 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/extensions/external_extension_provider.h"
 #include "chrome/browser/extensions/external_pref_extension_provider.h"
 #include "chrome/browser/profile.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension.h"
 #include "chrome/common/extensions/extension_error_reporter.h"
@@ -242,10 +243,7 @@
   ExtensionDOMUI::RegisterChromeURLOverrides(profile_,
       extension->GetChromeURLOverrides());
 
-  NotificationService::current()->Notify(
-      NotificationType::EXTENSION_LOADED,
-      Source<ExtensionsService>(this),
-      Details<Extension>(extension));
+  NotifyExtensionLoaded(extension);
 }
 
 void ExtensionsService::DisableExtension(const std::string& extension_id) {
@@ -269,10 +267,7 @@
   ExtensionDOMUI::UnregisterChromeURLOverrides(profile_,
       extension->GetChromeURLOverrides());
 
-  NotificationService::current()->Notify(
-      NotificationType::EXTENSION_UNLOADED,
-      Source<ExtensionsService>(this),
-      Details<Extension>(extension));
+  NotifyExtensionUnloaded(extension);
 }
 
 void ExtensionsService::LoadExtension(const FilePath& extension_path) {
@@ -324,6 +319,51 @@
   }
 }
 
+void ExtensionsService::NotifyExtensionLoaded(Extension* extension) {
+  LOG(INFO) << "Sending EXTENSION_LOADED";
+
+  // The ChromeURLRequestContext needs to be first to know that the extension
+  // was loaded, otherwise a race can arise where a renderer that is created
+  // for the extension may try to load an extension URL with an extension id
+  // that the request context doesn't yet know about.
+  if (profile_ && !profile_->IsOffTheRecord()) {
+    ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>(
+        profile_->GetRequestContext());
+    if (context) {
+      g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+          NewRunnableMethod(context,
+                            &ChromeURLRequestContext::OnNewExtensions,
+                            extension->id(),
+                            extension->path()));
+    }
+  }
+
+  NotificationService::current()->Notify(
+      NotificationType::EXTENSION_LOADED,
+      Source<ExtensionsService>(this),
+      Details<Extension>(extension));
+}
+
+void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) {
+  LOG(INFO) << "Sending EXTENSION_UNLOADED";
+
+  NotificationService::current()->Notify(
+      NotificationType::EXTENSION_UNLOADED,
+      Source<ExtensionsService>(this),
+      Details<Extension>(extension));
+
+  if (profile_ && !profile_->IsOffTheRecord()) {
+    ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>(
+        profile_->GetRequestContext());
+    if (context) {
+      g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+          NewRunnableMethod(context,
+                            &ChromeURLRequestContext::OnUnloadedExtension,
+                            extension->id()));
+    }
+  }
+}
+
 std::vector<ExtensionAction*> ExtensionsService::GetExtensionActions(
     ExtensionAction::ExtensionActionType action_type) const {
   std::vector<ExtensionAction*> result;
@@ -413,10 +453,7 @@
   // Remove the extension from our list.
   extensions_.erase(iter);
 
-  // Tell other services the extension is gone.
-  NotificationService::current()->Notify(NotificationType::EXTENSION_UNLOADED,
-                                         Source<ExtensionsService>(this),
-                                         Details<Extension>(extension.get()));
+  NotifyExtensionUnloaded(extension.get());
 }
 
 void ExtensionsService::UnloadAllExtensions() {
@@ -498,11 +535,7 @@
         if (extension->location() != Extension::LOAD)
           extension_prefs_->MigrateToPrefs(extension);
 
-        LOG(INFO) << "Sending EXTENSION_LOADED";
-        NotificationService::current()->Notify(
-            NotificationType::EXTENSION_LOADED,
-            Source<ExtensionsService>(this),
-            Details<Extension>(extension));
+        NotifyExtensionLoaded(extension);
 
         if (extension->IsTheme() && extension->location() == Extension::LOAD) {
           NotificationService::current()->Notify(