Commit 1f047f7b authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

[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}
parent bcfff021
......@@ -84,6 +84,7 @@ TabHelper::TabHelper(content::WebContents* web_contents)
location_bar_controller_(new LocationBarController(web_contents)),
extension_action_runner_(new ExtensionActionRunner(web_contents)),
webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()),
registry_observer_(this),
image_loader_ptr_factory_(this),
weak_ptr_factory_(this) {
// The ActiveTabPermissionManager requires a session ID; ensure this
......@@ -169,6 +170,13 @@ void TabHelper::SetExtensionApp(const Extension* extension) {
extension_app_ = extension;
if (extension_app_) {
registry_observer_.Add(
ExtensionRegistry::Get(web_contents()->GetBrowserContext()));
} else {
registry_observer_.RemoveAll();
}
UpdateExtensionAppIcon(extension_app_);
content::NotificationService::current()->Notify(
......@@ -532,6 +540,15 @@ WebContents* TabHelper::GetAssociatedWebContents() const {
return web_contents();
}
void TabHelper::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) {
DCHECK(extension_app_);
if (extension == extension_app_)
SetExtensionApp(nullptr);
}
void TabHelper::GetApplicationInfo(WebAppAction action) {
NavigationEntry* entry =
web_contents()->GetController().GetLastCommittedEntry();
......
......@@ -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 @@ class WebstoreInlineInstallerFactory;
// 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 @@ class TabHelper : public content::WebContentsObserver,
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 @@ class TabHelper : public content::WebContentsObserver,
// 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_;
......
// Copyright 2016 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/tab_helper.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_with_install.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/test/web_contents_tester.h"
namespace extensions {
TEST_F(ExtensionServiceTestWithInstall, TabHelperClearsExtensionOnUnload) {
InitializeEmptyExtensionService();
const Extension* extension =
PackAndInstallCRX(data_dir().AppendASCII("hosted_app"), INSTALL_NEW);
ASSERT_TRUE(extension);
std::unique_ptr<content::WebContents> web_contents(
content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
TabHelper::CreateForWebContents(web_contents.get());
TabHelper* tab_helper = TabHelper::FromWebContents(web_contents.get());
tab_helper->SetExtensionApp(extension);
EXPECT_EQ(extension, tab_helper->extension_app());
EXPECT_TRUE(tab_helper->is_app());
service()->UnloadExtension(extension->id(),
UnloadedExtensionInfo::REASON_UNDEFINED);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(nullptr, tab_helper->extension_app());
}
} // namespace extensions
......@@ -547,6 +547,7 @@
'browser/extensions/scripting_permissions_modifier_unittest.cc',
'browser/extensions/shared_module_service_unittest.cc',
'browser/extensions/standard_management_policy_provider_unittest.cc',
'browser/extensions/tab_helper_unittest.cc',
'browser/extensions/token_cache/token_cache_service_unittest.cc',
'browser/extensions/update_install_gate_unittest.cc',
'browser/extensions/updater/extension_cache_fake.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment