summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-13 16:14:05 +0000
committerjstritar@chromium.org <jstritar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-13 16:14:05 +0000
commitf9c292b369b9d6d0f6a5221952f936979a3e4f68 (patch)
tree043e4d68f01bcb5d06b59ac4183b75e7e38bb678
parent1aff64f14088ef913cf2c6a932489bb01f4fb6dc (diff)
downloadchromium_src-f9c292b369b9d6d0f6a5221952f936979a3e4f68.zip
chromium_src-f9c292b369b9d6d0f6a5221952f936979a3e4f68.tar.gz
chromium_src-f9c292b369b9d6d0f6a5221952f936979a3e4f68.tar.bz2
Prompt to enable permission-disabled apps when navigating to them.
We now prompt the user to enable permission disabled apps when they navigate to the app, rather than only when launching the app from the NTP. BUG=93983 TEST=navigate to app that was disabled due to permission increase Review URL: http://codereview.chromium.org/7782011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100922 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_navigation_observer.cc106
-rw-r--r--chrome/browser/extensions/extension_navigation_observer.h61
-rw-r--r--chrome/browser/extensions/extension_service.cc9
-rw-r--r--chrome/browser/extensions/extension_service.h6
-rw-r--r--chrome/browser/profiles/profile_impl.cc2
-rw-r--r--chrome/browser/profiles/profile_impl.h2
-rw-r--r--chrome/chrome_browser.gypi2
7 files changed, 186 insertions, 2 deletions
diff --git a/chrome/browser/extensions/extension_navigation_observer.cc b/chrome/browser/extensions/extension_navigation_observer.cc
new file mode 100644
index 0000000..8c33d7a
--- /dev/null
+++ b/chrome/browser/extensions/extension_navigation_observer.cc
@@ -0,0 +1,106 @@
+// 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/extension_navigation_observer.h"
+
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/browser/tab_contents/navigation_controller.h"
+#include "content/browser/tab_contents/navigation_entry.h"
+#include "content/common/notification_service.h"
+
+ExtensionNavigationObserver::ExtensionNavigationObserver(Profile* profile)
+ : profile_(profile) {
+ RegisterForNotifications();
+}
+
+ExtensionNavigationObserver::~ExtensionNavigationObserver() {}
+
+void ExtensionNavigationObserver::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type != content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
+ NOTREACHED();
+ return;
+ }
+
+ NavigationController* controller = Source<NavigationController>(source).ptr();
+ if (!profile_->IsSameProfile(
+ Profile::FromBrowserContext(controller->browser_context())))
+ return;
+
+ PromptToEnableExtensionIfNecessary(controller);
+}
+
+void ExtensionNavigationObserver::RegisterForNotifications() {
+ registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ NotificationService::AllSources());
+}
+
+void ExtensionNavigationObserver::PromptToEnableExtensionIfNecessary(
+ NavigationController* nav_controller) {
+ // Bail out if we're already running a prompt.
+ if (!in_progress_prompt_extension_id_.empty())
+ return;
+
+ NavigationEntry* nav_entry = nav_controller->GetActiveEntry();
+ if (!nav_entry)
+ return;
+
+ ExtensionService* extension_service = profile_->GetExtensionService();
+ const Extension* extension =
+ extension_service->GetDisabledExtensionByWebExtent(nav_entry->url());
+ if (!extension)
+ return;
+
+ // Try not to repeatedly prompt the user about the same extension.
+ if (prompted_extensions_.find(extension->id()) != prompted_extensions_.end())
+ return;
+ prompted_extensions_.insert(extension->id());
+
+ ExtensionPrefs* extension_prefs = extension_service->extension_prefs();
+ if (extension_prefs->DidExtensionEscalatePermissions(extension->id())) {
+ // Keep track of the extension id and nav controller we're prompting for.
+ // These must be reset in InstallUIProceed and InstallUIAbort.
+ in_progress_prompt_extension_id_ = extension->id();
+ in_progress_prompt_navigation_controller_ = nav_controller;
+
+ extension_install_ui_.reset(new ExtensionInstallUI(profile_));
+ extension_install_ui_->ConfirmReEnable(this, extension);
+ }
+}
+
+void ExtensionNavigationObserver::InstallUIProceed() {
+ ExtensionService* extension_service = profile_->GetExtensionService();
+ const Extension* extension = extension_service->GetExtensionById(
+ in_progress_prompt_extension_id_, true);
+ NavigationController* nav_controller =
+ in_progress_prompt_navigation_controller_;
+ CHECK(extension);
+ CHECK(nav_controller);
+
+ in_progress_prompt_extension_id_ = "";
+ in_progress_prompt_navigation_controller_ = NULL;
+ extension_install_ui_.reset();
+
+ // Grant permissions, re-enable the extension, and then reload the tab.
+ extension_service->GrantPermissionsAndEnableExtension(extension);
+ nav_controller->Reload(true);
+}
+
+void ExtensionNavigationObserver::InstallUIAbort(bool user_initiated) {
+ ExtensionService* extension_service = profile_->GetExtensionService();
+ const Extension* extension = extension_service->GetExtensionById(
+ in_progress_prompt_extension_id_, true);
+
+ in_progress_prompt_extension_id_ = "";
+ in_progress_prompt_navigation_controller_ = NULL;
+ extension_install_ui_.reset();
+
+ std::string histogram_name = user_initiated ?
+ "Extensions.Permissions_ReEnableCancel" :
+ "Extensions.Permissions_ReEnableAbort";
+ ExtensionService::RecordPermissionMessagesHistogram(
+ extension, histogram_name.c_str());
+}
diff --git a/chrome/browser/extensions/extension_navigation_observer.h b/chrome/browser/extensions/extension_navigation_observer.h
new file mode 100644
index 0000000..385e4a4
--- /dev/null
+++ b/chrome/browser/extensions/extension_navigation_observer.h
@@ -0,0 +1,61 @@
+// 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_NAVIGATION_OBSERVER_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_NAVIGATION_OBSERVER_H_
+#pragma once
+
+#include <set>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "content/common/notification_registrar.h"
+
+class Profile;
+class NavigationController;
+
+// The ExtensionNavigationObserver listens to navigation notifications. If the
+// user navigates into an extension that has been disabled due to a permission
+// increase, it prompts the user to accept the new permissions and re-enables
+// the extension.
+class ExtensionNavigationObserver : public ExtensionInstallUI::Delegate,
+ public NotificationObserver {
+ public:
+ explicit ExtensionNavigationObserver(Profile* profile);
+ virtual ~ExtensionNavigationObserver();
+
+ // NotificationObserver
+ virtual void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) OVERRIDE;
+ private:
+ // Registers for the NOTIFICATION_NAV_ENTRY_COMMITTED notification.
+ void RegisterForNotifications();
+
+ // Checks if |nav_controller| has entered an extension's web extent. If it
+ // has and the extension is disabled due to a permissions increase, this
+ // prompts the user to accept the new permissions and enables the extension.
+ void PromptToEnableExtensionIfNecessary(NavigationController* nav_controller);
+
+ // ExtensionInstallUI::Delegate callbacks used for the permissions prompt.
+ virtual void InstallUIProceed() OVERRIDE;
+ virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
+
+ NotificationRegistrar registrar_;
+
+ Profile* profile_;
+
+ // The UI used to confirm enabling extensions.
+ scoped_ptr<ExtensionInstallUI> extension_install_ui_;
+
+ // The data we keep track of when prompting to enable extensions.
+ std::string in_progress_prompt_extension_id_;
+ NavigationController* in_progress_prompt_navigation_controller_;
+
+ // The extension ids we've already prompted the user about.
+ std::set<std::string> prompted_extensions_;
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_NAVIGATION_OBSERVER_H_
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index d3818a6..473c283 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -2579,6 +2579,15 @@ const Extension* ExtensionService::GetExtensionByWebExtent(const GURL& url) {
return NULL;
}
+const Extension* ExtensionService::GetDisabledExtensionByWebExtent(
+ const GURL& url) {
+ for (size_t i = 0; i < disabled_extensions_.size(); ++i) {
+ if (disabled_extensions_[i]->web_extent().MatchesURL(url))
+ return disabled_extensions_[i];
+ }
+ return NULL;
+}
+
bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) {
// Allow bindings for all packaged extensions.
// Note that GetExtensionByURL may return an Extension for hosted apps
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 276406c..5e791ba 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -356,10 +356,12 @@ class ExtensionService
// Lookup an extension by |url|.
const Extension* GetExtensionByURL(const GURL& url);
- // If there is an extension for the specified url it is returned. Otherwise
- // returns the extension whose web extent contains |url|.
+ // Returns the extension whose web extent contains |url|.
const Extension* GetExtensionByWebExtent(const GURL& url);
+ // Returns the disabled extension whose web extent contains |url|.
+ const Extension* GetDisabledExtensionByWebExtent(const GURL& url);
+
// Returns an extension that contains any URL that overlaps with the given
// extent, if one exists.
const Extension* GetExtensionByOverlappingWebExtent(
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 61b8453..83e45df 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -32,6 +32,7 @@
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/extensions/extension_info_map.h"
#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extension_navigation_observer.h"
#include "chrome/browser/extensions/extension_pref_store.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -482,6 +483,7 @@ void ProfileImpl::InitExtensions(bool extensions_enabled) {
extension_process_manager_.reset(ExtensionProcessManager::Create(this));
extension_event_router_.reset(new ExtensionEventRouter(this));
extension_message_service_ = new ExtensionMessageService(this);
+ extension_navigation_observer_.reset(new ExtensionNavigationObserver(this));
ExtensionErrorReporter::Init(true); // allow noisy errors.
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 71aa59b..df45efb 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -19,6 +19,7 @@
#include "content/common/notification_registrar.h"
class ChromeDownloadManagerDelegate;
+class ExtensionNavigationObserver;
class ExtensionPrefs;
class ExtensionPrefValueMap;
class ExtensionSettings;
@@ -201,6 +202,7 @@ class ProfileImpl : public Profile,
scoped_ptr<ExtensionProcessManager> extension_process_manager_;
scoped_refptr<ExtensionMessageService> extension_message_service_;
scoped_ptr<ExtensionEventRouter> extension_event_router_;
+ scoped_ptr<ExtensionNavigationObserver> extension_navigation_observer_;
scoped_refptr<ExtensionSpecialStoragePolicy>
extension_special_storage_policy_;
scoped_ptr<SSLHostState> ssl_host_state_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 44b5433..a574764 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1030,6 +1030,8 @@
'browser/extensions/extension_metrics_module.h',
'browser/extensions/extension_module.cc',
'browser/extensions/extension_module.h',
+ 'browser/extensions/extension_navigation_observer.cc',
+ 'browser/extensions/extension_navigation_observer.h',
'browser/extensions/extension_omnibox_api.cc',
'browser/extensions/extension_omnibox_api.h',
'browser/extensions/extension_page_actions_module.cc',