diff options
5 files changed, 206 insertions, 74 deletions
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc index 8e8c1dc..e94d2d8 100644 --- a/chrome/browser/extensions/active_tab_permission_granter.cc +++ b/chrome/browser/extensions/active_tab_permission_granter.cc @@ -21,32 +21,34 @@ #include "content/public/browser/web_contents.h" #include "extensions/common/user_script.h" -using content::RenderProcessHost; -using content::WebContentsObserver; - namespace extensions { ActiveTabPermissionGranter::ActiveTabPermissionGranter( - content::WebContents* web_contents, int tab_id, Profile* profile) - : WebContentsObserver(web_contents), tab_id_(tab_id) { - registrar_.Add(this, - chrome::NOTIFICATION_EXTENSION_UNLOADED, - content::Source<Profile>(profile)); + content::WebContents* web_contents, + int tab_id, + Profile* profile) + : tab_id_(tab_id), + web_contents_(web_contents), + tab_capability_tracker_(web_contents, profile) { + tab_capability_tracker_.AddObserver(this); } -ActiveTabPermissionGranter::~ActiveTabPermissionGranter() {} +ActiveTabPermissionGranter::~ActiveTabPermissionGranter() { + tab_capability_tracker_.RemoveObserver(this); +} void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) { - if (granted_extensions_.Contains(extension->id())) - return; + tab_capability_tracker_.Grant(extension); +} +void ActiveTabPermissionGranter::OnGranted(const Extension* extension) { APIPermissionSet new_apis; URLPatternSet new_hosts; if (extension->HasAPIPermission(APIPermission::kActiveTab)) { URLPattern pattern(UserScript::ValidUserScriptSchemes()); // Pattern parsing could fail if this is an unsupported URL e.g. chrome://. - if (pattern.Parse(web_contents()->GetURL().spec()) == + if (pattern.Parse(web_contents_->GetURL().spec()) == URLPattern::PARSE_SUCCESS) { new_hosts.AddPattern(pattern); } @@ -57,63 +59,34 @@ void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) { new_apis.insert(APIPermission::kTabCaptureForTab); if (!new_apis.empty() || !new_hosts.is_empty()) { - granted_extensions_.Insert(extension); scoped_refptr<const PermissionSet> new_permissions = new PermissionSet(new_apis, new_hosts, URLPatternSet()); PermissionsData::UpdateTabSpecificPermissions(extension, tab_id_, new_permissions); - Send(new ExtensionMsg_UpdateTabSpecificPermissions(GetPageID(), - tab_id_, - extension->id(), - new_hosts)); + web_contents_->Send( + new ExtensionMsg_UpdateTabSpecificPermissions(GetPageID(), + tab_id_, + extension->id(), + new_hosts)); } } -void ActiveTabPermissionGranter::DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) { - if (details.is_in_page) - return; - DCHECK(details.is_main_frame); // important: sub-frames don't get granted! - ClearActiveExtensionsAndNotify(); -} - -void ActiveTabPermissionGranter::WebContentsDestroyed( - content::WebContents* web_contents) { - ClearActiveExtensionsAndNotify(); -} - -void ActiveTabPermissionGranter::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_UNLOADED); - const Extension* extension = - content::Details<UnloadedExtensionInfo>(details)->extension; - // Note: don't need to clear the permissions (nor tell the renderer about it) - // because it's being unloaded anyway. - granted_extensions_.Remove(extension->id()); -} - -void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() { - if (granted_extensions_.is_empty()) - return; - +void ActiveTabPermissionGranter::OnRevoked(const ExtensionSet* extensions) { std::vector<std::string> extension_ids; - for (ExtensionSet::const_iterator it = granted_extensions_.begin(); - it != granted_extensions_.end(); ++it) { + for (ExtensionSet::const_iterator it = extensions->begin(); + it != extensions->end(); ++it) { PermissionsData::ClearTabSpecificPermissions(it->get(), tab_id_); extension_ids.push_back((*it)->id()); } - Send(new ExtensionMsg_ClearTabSpecificPermissions(tab_id_, extension_ids)); - granted_extensions_.Clear(); + web_contents_->Send( + new ExtensionMsg_ClearTabSpecificPermissions(tab_id_, extension_ids)); } int32 ActiveTabPermissionGranter::GetPageID() { - return web_contents()->GetController().GetVisibleEntry()->GetPageID(); + return web_contents_->GetController().GetVisibleEntry()->GetPageID(); } } // namespace extensions diff --git a/chrome/browser/extensions/active_tab_permission_granter.h b/chrome/browser/extensions/active_tab_permission_granter.h index 0ef0336..186f165 100644 --- a/chrome/browser/extensions/active_tab_permission_granter.h +++ b/chrome/browser/extensions/active_tab_permission_granter.h @@ -8,6 +8,8 @@ #include <set> #include <string> +#include "base/compiler_specific.h" +#include "chrome/browser/extensions/tab_capability_tracker.h" #include "chrome/common/extensions/extension_set.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -26,8 +28,7 @@ class Extension; // Responsible for granting and revoking tab-specific permissions to extensions // with the activeTab or tabCapture permission. -class ActiveTabPermissionGranter : public content::WebContentsObserver, - public content::NotificationObserver { +class ActiveTabPermissionGranter : public TabCapabilityTracker::Observer { public: ActiveTabPermissionGranter(content::WebContents* web_contents, int tab_id, @@ -39,21 +40,9 @@ class ActiveTabPermissionGranter : public content::WebContentsObserver, void GrantIfRequested(const Extension* extension); private: - // content::WebContentsObserver implementation. - virtual void DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) OVERRIDE; - virtual void WebContentsDestroyed(content::WebContents* web_contents) - OVERRIDE; - - // content::NotificationObserver implementation. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; - - // Clears any tab-specific permissions for all extensions on |tab_id_| and - // notifies renderers. - void ClearActiveExtensionsAndNotify(); + // TabCapabilityTracker::Observer implementation. + virtual void OnGranted(const Extension* extension) OVERRIDE; + virtual void OnRevoked(const ExtensionSet* extensions) OVERRIDE; // Gets the current page id. int32 GetPageID(); @@ -61,12 +50,9 @@ class ActiveTabPermissionGranter : public content::WebContentsObserver, // The tab ID for this tab. int tab_id_; - // Extensions with the activeTab permission that have been granted - // tab-specific permissions until the next navigation/refresh. - ExtensionSet granted_extensions_; + content::WebContents* web_contents_; - // Listen to extension unloaded notifications. - content::NotificationRegistrar registrar_; + TabCapabilityTracker tab_capability_tracker_; DISALLOW_COPY_AND_ASSIGN(ActiveTabPermissionGranter); }; diff --git a/chrome/browser/extensions/tab_capability_tracker.cc b/chrome/browser/extensions/tab_capability_tracker.cc new file mode 100644 index 0000000..e42d0f7 --- /dev/null +++ b/chrome/browser/extensions/tab_capability_tracker.cc @@ -0,0 +1,88 @@ +// Copyright (c) 2012 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_capability_tracker.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sessions/session_id.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_messages.h" +#include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/permissions/permissions_data.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "extensions/common/user_script.h" + +using content::RenderProcessHost; +using content::WebContentsObserver; + +namespace extensions { + +TabCapabilityTracker::TabCapabilityTracker( + content::WebContents* web_contents, Profile* profile) + : WebContentsObserver(web_contents) { + registrar_.Add(this, + chrome::NOTIFICATION_EXTENSION_UNLOADED, + content::Source<Profile>(profile)); +} + +TabCapabilityTracker::~TabCapabilityTracker() {} + +void TabCapabilityTracker::Grant(const Extension* extension) { + if (granted_extensions_.Contains(extension->id())) + return; + FOR_EACH_OBSERVER(Observer, observers_, OnGranted(extension)); + granted_extensions_.Insert(extension); +} + +void TabCapabilityTracker::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void TabCapabilityTracker::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +void TabCapabilityTracker::DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + if (details.is_in_page) + return; + DCHECK(details.is_main_frame); // important: sub-frames don't get granted! + ClearActiveExtensionsAndNotify(); +} + +void TabCapabilityTracker::WebContentsDestroyed( + content::WebContents* web_contents) { + ClearActiveExtensionsAndNotify(); +} + +void TabCapabilityTracker::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_UNLOADED); + const Extension* extension = + content::Details<UnloadedExtensionInfo>(details)->extension; + // Note: don't need to tell anybody about this because it's being unloaded + // anyway, and all state should go away. Callers should track the unload + // state themselves if they care. + granted_extensions_.Remove(extension->id()); +} + +void TabCapabilityTracker::ClearActiveExtensionsAndNotify() { + if (granted_extensions_.is_empty()) + return; + FOR_EACH_OBSERVER(Observer, observers_, OnRevoked(&granted_extensions_)); + granted_extensions_.Clear(); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/tab_capability_tracker.h b/chrome/browser/extensions/tab_capability_tracker.h new file mode 100644 index 0000000..8b3b300 --- /dev/null +++ b/chrome/browser/extensions/tab_capability_tracker.h @@ -0,0 +1,83 @@ +// Copyright (c) 2012 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_TAB_CAPABILITY_TRACKER_H_ +#define CHROME_BROWSER_EXTENSIONS_TAB_CAPABILITY_TRACKER_H_ + +#include <set> +#include <string> + +#include "base/observer_list.h" +#include "chrome/common/extensions/extension_set.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/web_contents_observer.h" + +class Profile; + +namespace extensions { + +class Extension; + +// Grants capabilities to extensions for the lifetime of a tab session. +// +// When Grant() is called, OnGranted() is run for each observer if it hasn't +// already been. When the tab is navigated OnRevoked() is called with every +// extension that had been granted for that session. +class TabCapabilityTracker : public content::WebContentsObserver, + public content::NotificationObserver { + public: + // Observer for tab session changes. + class Observer { + public: + virtual ~Observer() {} + + // Called when Grant() is called and |extension| hasn't already been + // granted. + virtual void OnGranted(const Extension* extension) = 0; + + // Called when the tab is navigated or destroyed with every extension that + // had been Grant()ed. + virtual void OnRevoked(const ExtensionSet* extensions) = 0; + }; + + TabCapabilityTracker(content::WebContents* web_contents, Profile* profile); + virtual ~TabCapabilityTracker(); + + // Grants the capability to the extension (idempotent). + void Grant(const Extension* extension); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + private: + // content::WebContentsObserver implementation. + virtual void DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) OVERRIDE; + virtual void WebContentsDestroyed(content::WebContents* web_contents) + OVERRIDE; + + // content::NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // Revokes the capabilities of every extension and calls OnRevoked. + void ClearActiveExtensionsAndNotify(); + + // The extensions that have been granted capabilities so far in this tab + // session. + ExtensionSet granted_extensions_; + + ObserverList<Observer> observers_; + + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(TabCapabilityTracker); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_TAB_CAPABILITY_TRACKER_H_ diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 67c942f..3343ca5 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -832,6 +832,8 @@ 'browser/extensions/suggest_permission_util.h', 'browser/extensions/suggest_permission_util.cc', 'browser/extensions/sync_bundle.h', + 'browser/extensions/tab_capability_tracker.cc', + 'browser/extensions/tab_capability_tracker.h', 'browser/extensions/tab_helper.cc', 'browser/extensions/tab_helper.h', 'browser/extensions/theme_installed_infobar_delegate.cc', |