| Index: chrome/browser/extensions/active_tab_permission_granter.cc
|
| diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc
|
| index 4e7383864a1e63706427d5b868767a1dc8504a9e..32cbd69fa5e4e62ade52f4373a400ae5100d79a9 100644
|
| --- a/chrome/browser/extensions/active_tab_permission_granter.cc
|
| +++ b/chrome/browser/extensions/active_tab_permission_granter.cc
|
| @@ -8,9 +8,11 @@
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "content/public/browser/navigation_details.h"
|
| #include "content/public/browser/navigation_entry.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| #include "content/public/browser/render_view_host.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "extensions/browser/extension_registry.h"
|
| +#include "extensions/browser/process_manager.h"
|
| #include "extensions/common/extension_messages.h"
|
| #include "extensions/common/feature_switch.h"
|
| #include "extensions/common/permissions/permission_set.h"
|
| @@ -18,16 +20,59 @@
|
| #include "extensions/common/user_script.h"
|
| #include "url/gurl.h"
|
|
|
| -using content::RenderProcessHost;
|
| -using content::WebContentsObserver;
|
| -
|
| namespace extensions {
|
|
|
| +namespace {
|
| +
|
| +using CreateMessageFunction = base::Callback<IPC::Message*(bool)>;
|
| +
|
| +// Creates a new IPC message for updating tab-specific permissions.
|
| +IPC::Message* CreateUpdateMessage(const GURL& visible_url,
|
| + const std::string& extension_id,
|
| + const URLPatternSet& new_hosts,
|
| + int tab_id,
|
| + bool update_whitelist) {
|
| + return new ExtensionMsg_UpdateTabSpecificPermissions(
|
| + visible_url, extension_id, new_hosts, update_whitelist, tab_id);
|
| +}
|
| +
|
| +// Creates a new IPC message for clearing tab-specific permissions.
|
| +IPC::Message* CreateClearMessage(const std::vector<std::string>& ids,
|
| + int tab_id,
|
| + bool update_whitelist) {
|
| + return new ExtensionMsg_ClearTabSpecificPermissions(
|
| + ids, update_whitelist, tab_id);
|
| +}
|
| +
|
| +// Sends a message exactly once to each render process host owning one of the
|
| +// given |view_hosts| and |tab_process|. If |tab_process| doesn't own any of the
|
| +// |view_hosts|, it will not be signaled to update its origin whitelist.
|
| +void SendMessageToProcesses(
|
| + const std::set<content::RenderViewHost*>& view_hosts,
|
| + content::RenderProcessHost* tab_process,
|
| + const CreateMessageFunction& create_message) {
|
| + std::set<content::RenderProcessHost*> sent_to_hosts;
|
| + for (content::RenderViewHost* view_host : view_hosts) {
|
| + content::RenderProcessHost* process_host = view_host->GetProcess();
|
| + if (sent_to_hosts.count(process_host) == 0) {
|
| + // Extension processes have to update the origin whitelists.
|
| + process_host->Send(create_message.Run(true));
|
| + sent_to_hosts.insert(view_host->GetProcess());
|
| + }
|
| + }
|
| + // If the tab wasn't one of those processes already updated (it likely
|
| + // wasn't), update it. Tabs don't need to update the origin whitelist.
|
| + if (sent_to_hosts.count(tab_process) == 0)
|
| + tab_process->Send(create_message.Run(false));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| ActiveTabPermissionGranter::ActiveTabPermissionGranter(
|
| content::WebContents* web_contents,
|
| int tab_id,
|
| Profile* profile)
|
| - : WebContentsObserver(web_contents),
|
| + : content::WebContentsObserver(web_contents),
|
| tab_id_(tab_id),
|
| extension_registry_observer_(this) {
|
| extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
|
| @@ -66,13 +111,20 @@ void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) {
|
| const content::NavigationEntry* navigation_entry =
|
| web_contents()->GetController().GetVisibleEntry();
|
| if (navigation_entry) {
|
| - content::RenderViewHost* render_view_host =
|
| - web_contents()->GetRenderViewHost();
|
| - render_view_host->Send(new ExtensionMsg_UpdateTabSpecificPermissions(
|
| - render_view_host->GetRoutingID(),
|
| - navigation_entry->GetURL(),
|
| - extension->id(),
|
| - new_hosts));
|
| + // We update all extension render views with the new tab permissions, and
|
| + // also the tab itself.
|
| + CreateMessageFunction update_message =
|
| + base::Bind(&CreateUpdateMessage,
|
| + navigation_entry->GetURL(),
|
| + extension->id(),
|
| + new_hosts,
|
| + tab_id_);
|
| + SendMessageToProcesses(
|
| + ProcessManager::Get(web_contents()->GetBrowserContext())->
|
| + GetRenderViewHostsForExtension(extension->id()),
|
| + web_contents()->GetRenderProcessHost(),
|
| + update_message);
|
| +
|
| // If more things ever need to know about this, we should consider making
|
| // an observer class.
|
| // It's important that this comes after the IPC is sent to the renderer,
|
| @@ -128,18 +180,24 @@ void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() {
|
| if (granted_extensions_.is_empty())
|
| return;
|
|
|
| + std::set<content::RenderViewHost*> view_hosts;
|
| std::vector<std::string> extension_ids;
|
| -
|
| - for (ExtensionSet::const_iterator it = granted_extensions_.begin();
|
| - it != granted_extensions_.end(); ++it) {
|
| - it->get()->permissions_data()->ClearTabSpecificPermissions(tab_id_);
|
| - extension_ids.push_back((*it)->id());
|
| + ProcessManager* process_manager =
|
| + ProcessManager::Get(web_contents()->GetBrowserContext());
|
| + for (const scoped_refptr<const Extension>& extension : granted_extensions_) {
|
| + extension->permissions_data()->ClearTabSpecificPermissions(tab_id_);
|
| + extension_ids.push_back(extension->id());
|
| + std::set<content::RenderViewHost*> extension_view_hosts =
|
| + process_manager->GetRenderViewHostsForExtension(extension->id());
|
| + view_hosts.insert(extension_view_hosts.begin(), extension_view_hosts.end());
|
| }
|
|
|
| - content::RenderViewHost* render_view_host =
|
| - web_contents()->GetRenderViewHost();
|
| - render_view_host->Send(new ExtensionMsg_ClearTabSpecificPermissions(
|
| - render_view_host->GetRoutingID(), extension_ids));
|
| + CreateMessageFunction clear_message =
|
| + base::Bind(&CreateClearMessage, extension_ids, tab_id_);
|
| + SendMessageToProcesses(view_hosts,
|
| + web_contents()->GetRenderProcessHost(),
|
| + clear_message);
|
| +
|
| granted_extensions_.Clear();
|
| }
|
|
|
|
|