Home | History | Annotate | Download | only in browser
      1 // Copyright 2013 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 "extensions/browser/info_map.h"
      6 
      7 #include "content/public/browser/browser_thread.h"
      8 #include "extensions/browser/content_verifier.h"
      9 #include "extensions/common/constants.h"
     10 #include "extensions/common/extension.h"
     11 #include "extensions/common/extension_set.h"
     12 #include "extensions/common/manifest_handlers/incognito_info.h"
     13 #include "extensions/common/permissions/permissions_data.h"
     14 
     15 using content::BrowserThread;
     16 
     17 namespace extensions {
     18 
     19 namespace {
     20 
     21 void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
     22 
     23 }  // namespace
     24 
     25 struct InfoMap::ExtraData {
     26   // When the extension was installed.
     27   base::Time install_time;
     28 
     29   // True if the user has allowed this extension to run in incognito mode.
     30   bool incognito_enabled;
     31 
     32   // True if the user has disabled notifications for this extension manually.
     33   bool notifications_disabled;
     34 
     35   ExtraData();
     36   ~ExtraData();
     37 };
     38 
     39 InfoMap::ExtraData::ExtraData() : incognito_enabled(false) {}
     40 
     41 InfoMap::ExtraData::~ExtraData() {}
     42 
     43 InfoMap::InfoMap() : signin_process_id_(-1) {}
     44 
     45 const ProcessMap& InfoMap::process_map() const { return process_map_; }
     46 
     47 const ProcessMap& InfoMap::worker_process_map() const {
     48   return worker_process_map_;
     49 }
     50 
     51 void InfoMap::AddExtension(const Extension* extension,
     52                            base::Time install_time,
     53                            bool incognito_enabled,
     54                            bool notifications_disabled) {
     55   CheckOnValidThread();
     56   extensions_.Insert(extension);
     57   disabled_extensions_.Remove(extension->id());
     58 
     59   extra_data_[extension->id()].install_time = install_time;
     60   extra_data_[extension->id()].incognito_enabled = incognito_enabled;
     61   extra_data_[extension->id()].notifications_disabled = notifications_disabled;
     62 }
     63 
     64 void InfoMap::RemoveExtension(const std::string& extension_id,
     65                               const UnloadedExtensionInfo::Reason reason) {
     66   CheckOnValidThread();
     67   const Extension* extension = extensions_.GetByID(extension_id);
     68   extra_data_.erase(extension_id);  // we don't care about disabled extra data
     69   bool was_uninstalled = (reason != UnloadedExtensionInfo::REASON_DISABLE &&
     70                           reason != UnloadedExtensionInfo::REASON_TERMINATE);
     71   if (extension) {
     72     if (!was_uninstalled)
     73       disabled_extensions_.Insert(extension);
     74     extensions_.Remove(extension_id);
     75   } else if (was_uninstalled) {
     76     // If the extension was uninstalled, make sure it's removed from the map of
     77     // disabled extensions.
     78     disabled_extensions_.Remove(extension_id);
     79   } else {
     80     // NOTE: This can currently happen if we receive multiple unload
     81     // notifications, e.g. setting incognito-enabled state for a
     82     // disabled extension (e.g., via sync).  See
     83     // http://code.google.com/p/chromium/issues/detail?id=50582 .
     84     NOTREACHED() << extension_id;
     85   }
     86 }
     87 
     88 base::Time InfoMap::GetInstallTime(const std::string& extension_id) const {
     89   ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
     90   if (iter != extra_data_.end())
     91     return iter->second.install_time;
     92   return base::Time();
     93 }
     94 
     95 bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const {
     96   // Keep in sync with duplicate in extensions/browser/process_manager.cc.
     97   ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
     98   if (iter != extra_data_.end())
     99     return iter->second.incognito_enabled;
    100   return false;
    101 }
    102 
    103 bool InfoMap::CanCrossIncognito(const Extension* extension) const {
    104   // This is duplicated from ExtensionService :(.
    105   return IsIncognitoEnabled(extension->id()) &&
    106          !IncognitoInfo::IsSplitMode(extension);
    107 }
    108 
    109 void InfoMap::RegisterExtensionProcess(const std::string& extension_id,
    110                                        int process_id,
    111                                        int site_instance_id) {
    112   if (!process_map_.Insert(extension_id, process_id, site_instance_id)) {
    113     NOTREACHED() << "Duplicate extension process registration for: "
    114                  << extension_id << "," << process_id << ".";
    115   }
    116 }
    117 
    118 void InfoMap::UnregisterExtensionProcess(const std::string& extension_id,
    119                                          int process_id,
    120                                          int site_instance_id) {
    121   if (!process_map_.Remove(extension_id, process_id, site_instance_id)) {
    122     NOTREACHED() << "Unknown extension process registration for: "
    123                  << extension_id << "," << process_id << ".";
    124   }
    125 }
    126 
    127 void InfoMap::UnregisterAllExtensionsInProcess(int process_id) {
    128   process_map_.RemoveAllFromProcess(process_id);
    129 }
    130 
    131 void InfoMap::RegisterExtensionWorkerProcess(const std::string& extension_id,
    132                                              int process_id,
    133                                              int site_instance_id) {
    134   if (!worker_process_map_.Insert(extension_id, process_id, site_instance_id)) {
    135     NOTREACHED() << "Duplicate extension worker process registration for: "
    136                  << extension_id << "," << process_id << ".";
    137   }
    138 }
    139 
    140 void InfoMap::UnregisterExtensionWorkerProcess(int process_id) {
    141   worker_process_map_.RemoveAllFromProcess(process_id);
    142 }
    143 
    144 void InfoMap::GetExtensionsWithAPIPermissionForSecurityOrigin(
    145     const GURL& origin,
    146     int process_id,
    147     APIPermission::ID permission,
    148     ExtensionSet* extensions) const {
    149   DCHECK(extensions);
    150 
    151   if (origin.SchemeIs(kExtensionScheme)) {
    152     const std::string& id = origin.host();
    153     const Extension* extension = extensions_.GetByID(id);
    154     if (extension &&
    155         extension->permissions_data()->HasAPIPermission(permission) &&
    156         process_map_.Contains(id, process_id)) {
    157       extensions->Insert(extension);
    158     }
    159     return;
    160   }
    161 
    162   ExtensionSet::const_iterator i = extensions_.begin();
    163   for (; i != extensions_.end(); ++i) {
    164     if ((*i)->web_extent().MatchesSecurityOrigin(origin) &&
    165         process_map_.Contains((*i)->id(), process_id) &&
    166         (*i)->permissions_data()->HasAPIPermission(permission)) {
    167       extensions->Insert(*i);
    168     }
    169   }
    170 }
    171 
    172 bool InfoMap::SecurityOriginHasAPIPermission(const GURL& origin,
    173                                              int process_id,
    174                                              APIPermission::ID permission)
    175     const {
    176   ExtensionSet extensions;
    177   GetExtensionsWithAPIPermissionForSecurityOrigin(
    178       origin, process_id, permission, &extensions);
    179   return !extensions.is_empty();
    180 }
    181 
    182 QuotaService* InfoMap::GetQuotaService() {
    183   CheckOnValidThread();
    184   if (!quota_service_)
    185     quota_service_.reset(new QuotaService());
    186   return quota_service_.get();
    187 }
    188 
    189 void InfoMap::SetSigninProcess(int process_id) {
    190   signin_process_id_ = process_id;
    191 }
    192 
    193 bool InfoMap::IsSigninProcess(int process_id) const {
    194   return process_id == signin_process_id_;
    195 }
    196 
    197 void InfoMap::SetNotificationsDisabled(
    198     const std::string& extension_id,
    199     bool notifications_disabled) {
    200   ExtraDataMap::iterator iter = extra_data_.find(extension_id);
    201   if (iter != extra_data_.end())
    202     iter->second.notifications_disabled = notifications_disabled;
    203 }
    204 
    205 bool InfoMap::AreNotificationsDisabled(
    206     const std::string& extension_id) const {
    207   ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
    208   if (iter != extra_data_.end())
    209     return iter->second.notifications_disabled;
    210   return false;
    211 }
    212 
    213 void InfoMap::SetContentVerifier(ContentVerifier* verifier) {
    214   content_verifier_ = verifier;
    215 }
    216 
    217 InfoMap::~InfoMap() {
    218   if (quota_service_) {
    219     BrowserThread::DeleteSoon(
    220         BrowserThread::IO, FROM_HERE, quota_service_.release());
    221   }
    222 }
    223 
    224 }  // namespace extensions
    225