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