[Extensions] Observe unloading extensions in the TabHelper

The extension TabHelper can have an associated extension if the
WebContents holds a hosted app. Watch for that extension being
unloaded and reset the reference to the extension if it is so that
we don't UAF it.

BUG=616057
BUG=616113

Review-Url: https://codereview.chromium.org/2037873002
Cr-Commit-Position: refs/heads/master@{#398072}
diff --git a/chrome/browser/extensions/tab_helper.h b/chrome/browser/extensions/tab_helper.h
index 17846b5c..c3d368ec 100644
--- a/chrome/browser/extensions/tab_helper.h
+++ b/chrome/browser/extensions/tab_helper.h
@@ -13,6 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/extensions/active_tab_permission_granter.h"
 #include "chrome/browser/extensions/extension_reenabler.h"
 #include "chrome/common/extensions/webstore_install_result.h"
@@ -22,6 +23,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "extensions/browser/extension_function_dispatcher.h"
+#include "extensions/browser/extension_registry_observer.h"
 #include "extensions/browser/script_execution_observer.h"
 #include "extensions/browser/script_executor.h"
 #include "extensions/common/stack_frame.h"
@@ -47,7 +49,8 @@
 
 // Per-tab extension helper. Also handles non-extension apps.
 class TabHelper : public content::WebContentsObserver,
-                  public extensions::ExtensionFunctionDispatcher::Delegate,
+                  public ExtensionFunctionDispatcher::Delegate,
+                  public ExtensionRegistryObserver,
                   public base::SupportsWeakPtr<TabHelper>,
                   public content::NotificationObserver,
                   public content::WebContentsUserData<TabHelper> {
@@ -160,6 +163,11 @@
   extensions::WindowController* GetExtensionWindowController() const override;
   content::WebContents* GetAssociatedWebContents() const override;
 
+  // ExtensionRegistryObserver:
+  void OnExtensionUnloaded(content::BrowserContext* browser_context,
+                           const Extension* extension,
+                           UnloadedExtensionInfo::Reason reason) override;
+
   // Message handlers.
   void OnDidGetWebApplicationInfo(const WebApplicationInfo& info);
   void OnInlineWebstoreInstall(content::RenderFrameHost* host,
@@ -259,6 +267,9 @@
   // The reenable prompt for disabled extensions, if any.
   std::unique_ptr<ExtensionReenabler> extension_reenabler_;
 
+  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
+      registry_observer_;
+
   // Vend weak pointers that can be invalidated to stop in-progress loads.
   base::WeakPtrFactory<TabHelper> image_loader_ptr_factory_;