• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/extensions/active_tab_permission_granter.h"
6 
7 #include "chrome/browser/extensions/active_script_controller.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "content/public/browser/navigation_details.h"
10 #include "content/public/browser/navigation_entry.h"
11 #include "content/public/browser/web_contents.h"
12 #include "extensions/browser/extension_registry.h"
13 #include "extensions/common/extension_messages.h"
14 #include "extensions/common/permissions/permission_set.h"
15 #include "extensions/common/permissions/permissions_data.h"
16 #include "extensions/common/user_script.h"
17 #include "url/gurl.h"
18 
19 using content::RenderProcessHost;
20 using content::WebContentsObserver;
21 
22 namespace extensions {
23 
ActiveTabPermissionGranter(content::WebContents * web_contents,int tab_id,Profile * profile)24 ActiveTabPermissionGranter::ActiveTabPermissionGranter(
25     content::WebContents* web_contents,
26     int tab_id,
27     Profile* profile)
28     : WebContentsObserver(web_contents),
29       tab_id_(tab_id),
30       extension_registry_observer_(this) {
31   extension_registry_observer_.Add(ExtensionRegistry::Get(profile));
32 }
33 
~ActiveTabPermissionGranter()34 ActiveTabPermissionGranter::~ActiveTabPermissionGranter() {}
35 
GrantIfRequested(const Extension * extension)36 void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) {
37   if (granted_extensions_.Contains(extension->id()))
38     return;
39 
40   APIPermissionSet new_apis;
41   URLPatternSet new_hosts;
42 
43   const PermissionsData* permissions_data = extension->permissions_data();
44 
45   // If the extension requires action for script execution, we grant it
46   // active tab-style permissions, even if it doesn't have the activeTab
47   // permission in the manifest.
48   // We don't take tab id into account, because we want to know if the extension
49   // should require active tab in general (not for the current tab).
50   bool requires_action_for_script_execution =
51       permissions_data->RequiresActionForScriptExecution(extension,
52                                                          -1,  // No tab id.
53                                                          GURL());
54 
55   if (extension->permissions_data()->HasAPIPermission(
56           APIPermission::kActiveTab) ||
57       requires_action_for_script_execution) {
58     URLPattern pattern(UserScript::ValidUserScriptSchemes());
59     // Pattern parsing could fail if this is an unsupported URL e.g. chrome://.
60     if (pattern.Parse(web_contents()->GetURL().spec()) ==
61             URLPattern::PARSE_SUCCESS) {
62       new_hosts.AddPattern(pattern);
63     }
64     new_apis.insert(APIPermission::kTab);
65   }
66 
67   if (extension->permissions_data()->HasAPIPermission(
68           APIPermission::kTabCapture))
69     new_apis.insert(APIPermission::kTabCaptureForTab);
70 
71   if (!new_apis.empty() || !new_hosts.is_empty()) {
72     granted_extensions_.Insert(extension);
73     scoped_refptr<const PermissionSet> new_permissions =
74         new PermissionSet(new_apis, ManifestPermissionSet(),
75                           new_hosts, URLPatternSet());
76     permissions_data->UpdateTabSpecificPermissions(tab_id_, new_permissions);
77     const content::NavigationEntry* navigation_entry =
78         web_contents()->GetController().GetVisibleEntry();
79     if (navigation_entry) {
80       Send(new ExtensionMsg_UpdateTabSpecificPermissions(
81           navigation_entry->GetPageID(),
82           tab_id_,
83           extension->id(),
84           new_hosts));
85       // If more things ever need to know about this, we should consider making
86       // an observer class.
87       // It's important that this comes after the IPC is sent to the renderer,
88       // so that any tasks executing in the renderer occur after it has the
89       // updated permissions.
90       ActiveScriptController::GetForWebContents(web_contents())
91           ->OnActiveTabPermissionGranted(extension);
92     }
93   }
94 }
95 
DidNavigateMainFrame(const content::LoadCommittedDetails & details,const content::FrameNavigateParams & params)96 void ActiveTabPermissionGranter::DidNavigateMainFrame(
97     const content::LoadCommittedDetails& details,
98     const content::FrameNavigateParams& params) {
99   if (details.is_in_page)
100     return;
101   DCHECK(details.is_main_frame);  // important: sub-frames don't get granted!
102   ClearActiveExtensionsAndNotify();
103 }
104 
WebContentsDestroyed()105 void ActiveTabPermissionGranter::WebContentsDestroyed() {
106   ClearActiveExtensionsAndNotify();
107 }
108 
OnExtensionUnloaded(content::BrowserContext * browser_context,const Extension * extension,UnloadedExtensionInfo::Reason reason)109 void ActiveTabPermissionGranter::OnExtensionUnloaded(
110     content::BrowserContext* browser_context,
111     const Extension* extension,
112     UnloadedExtensionInfo::Reason reason) {
113   // Note: don't need to clear the permissions (nor tell the renderer about it)
114   // because it's being unloaded anyway.
115   granted_extensions_.Remove(extension->id());
116 }
117 
ClearActiveExtensionsAndNotify()118 void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() {
119   if (granted_extensions_.is_empty())
120     return;
121 
122   std::vector<std::string> extension_ids;
123 
124   for (ExtensionSet::const_iterator it = granted_extensions_.begin();
125        it != granted_extensions_.end(); ++it) {
126     it->get()->permissions_data()->ClearTabSpecificPermissions(tab_id_);
127     extension_ids.push_back((*it)->id());
128   }
129 
130   Send(new ExtensionMsg_ClearTabSpecificPermissions(tab_id_, extension_ids));
131   granted_extensions_.Clear();
132 }
133 
134 }  // namespace extensions
135