Home | History | Annotate | Download | only in extensions
      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/chrome_notification_types.h"
      8 #include "chrome/browser/extensions/extension_service.h"
      9 #include "chrome/browser/extensions/extension_system.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/browser/sessions/session_id.h"
     12 #include "chrome/common/extensions/extension_messages.h"
     13 #include "content/public/browser/navigation_details.h"
     14 #include "content/public/browser/navigation_entry.h"
     15 #include "content/public/browser/notification_service.h"
     16 #include "content/public/browser/notification_source.h"
     17 #include "content/public/browser/render_process_host.h"
     18 #include "content/public/browser/web_contents.h"
     19 #include "extensions/common/extension.h"
     20 #include "extensions/common/permissions/permission_set.h"
     21 #include "extensions/common/permissions/permissions_data.h"
     22 #include "extensions/common/user_script.h"
     23 
     24 using content::RenderProcessHost;
     25 using content::WebContentsObserver;
     26 
     27 namespace extensions {
     28 
     29 ActiveTabPermissionGranter::ActiveTabPermissionGranter(
     30     content::WebContents* web_contents, int tab_id, Profile* profile)
     31     : WebContentsObserver(web_contents), tab_id_(tab_id) {
     32   registrar_.Add(this,
     33                  chrome::NOTIFICATION_EXTENSION_UNLOADED,
     34                  content::Source<Profile>(profile));
     35 }
     36 
     37 ActiveTabPermissionGranter::~ActiveTabPermissionGranter() {}
     38 
     39 void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) {
     40   if (granted_extensions_.Contains(extension->id()))
     41     return;
     42 
     43   APIPermissionSet new_apis;
     44   URLPatternSet new_hosts;
     45 
     46   if (extension->HasAPIPermission(APIPermission::kActiveTab)) {
     47     URLPattern pattern(UserScript::ValidUserScriptSchemes());
     48     // Pattern parsing could fail if this is an unsupported URL e.g. chrome://.
     49     if (pattern.Parse(web_contents()->GetURL().spec()) ==
     50             URLPattern::PARSE_SUCCESS) {
     51       new_hosts.AddPattern(pattern);
     52     }
     53     new_apis.insert(APIPermission::kTab);
     54   }
     55 
     56   if (extension->HasAPIPermission(APIPermission::kTabCapture))
     57     new_apis.insert(APIPermission::kTabCaptureForTab);
     58 
     59   if (!new_apis.empty() || !new_hosts.is_empty()) {
     60     granted_extensions_.Insert(extension);
     61     scoped_refptr<const PermissionSet> new_permissions =
     62         new PermissionSet(new_apis, ManifestPermissionSet(),
     63                           new_hosts, URLPatternSet());
     64     PermissionsData::UpdateTabSpecificPermissions(extension,
     65                                                   tab_id_,
     66                                                   new_permissions);
     67     const content::NavigationEntry* navigation_entry =
     68         web_contents()->GetController().GetVisibleEntry();
     69     if (navigation_entry) {
     70       Send(new ExtensionMsg_UpdateTabSpecificPermissions(
     71           navigation_entry->GetPageID(),
     72           tab_id_,
     73           extension->id(),
     74           new_hosts));
     75     }
     76   }
     77 }
     78 
     79 void ActiveTabPermissionGranter::DidNavigateMainFrame(
     80     const content::LoadCommittedDetails& details,
     81     const content::FrameNavigateParams& params) {
     82   if (details.is_in_page)
     83     return;
     84   DCHECK(details.is_main_frame);  // important: sub-frames don't get granted!
     85   ClearActiveExtensionsAndNotify();
     86 }
     87 
     88 void ActiveTabPermissionGranter::WebContentsDestroyed(
     89     content::WebContents* web_contents) {
     90   ClearActiveExtensionsAndNotify();
     91 }
     92 
     93 void ActiveTabPermissionGranter::Observe(
     94     int type,
     95     const content::NotificationSource& source,
     96     const content::NotificationDetails& details) {
     97   DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_UNLOADED);
     98   const Extension* extension =
     99       content::Details<UnloadedExtensionInfo>(details)->extension;
    100   // Note: don't need to clear the permissions (nor tell the renderer about it)
    101   // because it's being unloaded anyway.
    102   granted_extensions_.Remove(extension->id());
    103 }
    104 
    105 void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() {
    106   if (granted_extensions_.is_empty())
    107     return;
    108 
    109   std::vector<std::string> extension_ids;
    110 
    111   for (ExtensionSet::const_iterator it = granted_extensions_.begin();
    112        it != granted_extensions_.end(); ++it) {
    113     PermissionsData::ClearTabSpecificPermissions(it->get(), tab_id_);
    114     extension_ids.push_back((*it)->id());
    115   }
    116 
    117   Send(new ExtensionMsg_ClearTabSpecificPermissions(tab_id_, extension_ids));
    118   granted_extensions_.Clear();
    119 }
    120 
    121 }  // namespace extensions
    122