• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "base/logging.h"
6 #include "base/stl_util-inl.h"
7 #include "chrome/browser/extensions/extension_service.h"
8 #include "chrome/browser/extensions/pending_extension_manager.h"
9 #include "chrome/common/extensions/extension.h"
10 #include "content/browser/browser_thread.h"
11 
12 namespace {
13 
14 // Install predicate used by AddFromDefaultAppList().
IsApp(const Extension & extension)15 bool IsApp(const Extension& extension) {
16   return extension.is_app();
17 }
18 
19 // Install predicate used by AddFromExternalUpdateUrl().
AlwaysInstall(const Extension & extension)20 bool AlwaysInstall(const Extension& extension) {
21   return true;
22 }
23 
24 }  // namespace
25 
PendingExtensionManager(const ExtensionServiceInterface & service)26 PendingExtensionManager::PendingExtensionManager(
27     const ExtensionServiceInterface& service)
28     : service_(service) {
29 }
30 
~PendingExtensionManager()31 PendingExtensionManager::~PendingExtensionManager() {}
32 
GetById(const std::string & id,PendingExtensionInfo * out_pending_extension_info) const33 bool PendingExtensionManager::GetById(
34     const std::string& id,
35     PendingExtensionInfo* out_pending_extension_info) const {
36 
37   PendingExtensionMap::const_iterator it = pending_extension_map_.find(id);
38   if (it != pending_extension_map_.end()) {
39     *out_pending_extension_info = it->second;
40     return true;
41   }
42 
43   return false;
44 }
45 
Remove(const std::string & id)46 void PendingExtensionManager::Remove(const std::string& id) {
47   pending_extension_map_.erase(id);
48 }
49 
IsIdPending(const std::string & id) const50 bool PendingExtensionManager::IsIdPending(const std::string& id) const {
51   return ContainsKey(pending_extension_map_, id);
52 }
53 
AddFromSync(const std::string & id,const GURL & update_url,PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,bool install_silently,bool enable_on_install,bool enable_incognito_on_install)54 bool PendingExtensionManager::AddFromSync(
55     const std::string& id,
56     const GURL& update_url,
57     PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
58     bool install_silently,
59     bool enable_on_install,
60     bool enable_incognito_on_install) {
61   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62 
63   if (service_.GetExtensionById(id, true)) {
64     LOG(ERROR) << "Trying to add pending extension " << id
65                << " which already exists";
66     return false;
67   }
68 
69   const bool kIsFromSync = true;
70   const Extension::Location kSyncLocation = Extension::INTERNAL;
71 
72   return AddExtensionImpl(id, update_url, should_allow_install,
73                           kIsFromSync, install_silently,
74                           enable_on_install,
75                           enable_incognito_on_install,
76                           kSyncLocation);
77 }
78 
AddFromExternalUpdateUrl(const std::string & id,const GURL & update_url,Extension::Location location)79 void PendingExtensionManager::AddFromExternalUpdateUrl(
80     const std::string& id, const GURL& update_url,
81     Extension::Location location) {
82   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83 
84   const bool kIsFromSync = false;
85   const bool kInstallSilently = true;
86   const bool kEnableOnInstall = true;
87   const bool kEnableIncognitoOnInstall = false;
88 
89   if (service_.IsExternalExtensionUninstalled(id))
90     return;
91 
92   if (service_.GetExtensionById(id, true)) {
93     LOG(DFATAL) << "Trying to add extension " << id
94                 << " by external update, but it is already installed.";
95     return;
96   }
97 
98   AddExtensionImpl(id, update_url, &AlwaysInstall,
99                    kIsFromSync, kInstallSilently,
100                    kEnableOnInstall, kEnableIncognitoOnInstall,
101                    location);
102 }
103 
104 
105 // TODO(akalin): Change DefaultAppList to DefaultExtensionList and
106 // remove the IsApp() check.
AddFromDefaultAppList(const std::string & id)107 void PendingExtensionManager::AddFromDefaultAppList(
108     const std::string& id) {
109   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
110 
111   const bool kIsFromSync = false;
112   const bool kInstallSilently = true;
113   const bool kEnableOnInstall = true;
114   const bool kEnableIncognitoOnInstall = true;
115 
116   // This can legitimately happen if the user manually installed one of the
117   // default apps before this code ran.
118   if (service_.GetExtensionById(id, true))
119     return;
120 
121   AddExtensionImpl(id, GURL(), &IsApp,
122                    kIsFromSync, kInstallSilently,
123                    kEnableOnInstall, kEnableIncognitoOnInstall,
124                    Extension::INTERNAL);
125 }
126 
AddFromExternalFile(const std::string & id,Extension::Location location)127 void PendingExtensionManager::AddFromExternalFile(
128     const std::string& id,
129     Extension::Location location) {
130 
131   GURL kUpdateUrl = GURL();
132   bool kIsFromSync = false;
133   bool kInstallSilently = true;
134   bool kEnableOnInstall = true;
135   bool kEnableIncognitoOnInstall = false;
136 
137   pending_extension_map_[id] =
138       PendingExtensionInfo(kUpdateUrl,
139                            &AlwaysInstall,
140                            kIsFromSync,
141                            kInstallSilently,
142                            kEnableOnInstall,
143                            kEnableIncognitoOnInstall,
144                            location);
145 }
146 
AddExtensionImpl(const std::string & id,const GURL & update_url,PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,bool is_from_sync,bool install_silently,bool enable_on_install,bool enable_incognito_on_install,Extension::Location install_source)147 bool PendingExtensionManager::AddExtensionImpl(
148     const std::string& id, const GURL& update_url,
149     PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
150     bool is_from_sync, bool install_silently,
151     bool enable_on_install, bool enable_incognito_on_install,
152     Extension::Location install_source) {
153   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
154 
155   // Will add a pending extension record unless this variable is set to false.
156   bool should_add_pending_record = true;
157 
158   if (ContainsKey(pending_extension_map_, id)) {
159     // Bugs in this code will manifest as sporadic incorrect extension
160     // locations in situations where multiple install sources run at the
161     // same time. For example, on first login to a chrome os machine, an
162     // extension may be requested by sync sync and the default extension set.
163     // The following logging will help diagnose such issues.
164     VLOG(1) << "Extension id " << id
165             << " was entered for update more than once."
166             << "  old location: " << pending_extension_map_[id].install_source()
167             << "  new location: " << install_source;
168 
169     Extension::Location higher_priority_location =
170         Extension::GetHigherPriorityLocation(
171             install_source, pending_extension_map_[id].install_source());
172 
173     if (higher_priority_location == install_source) {
174       VLOG(1) << "Overwrite existing record.";
175 
176     } else {
177       VLOG(1) << "Keep existing record.";
178       should_add_pending_record = false;
179     }
180   }
181 
182   if (should_add_pending_record) {
183     pending_extension_map_[id] = PendingExtensionInfo(
184         update_url,
185         should_allow_install,
186         is_from_sync,
187         install_silently,
188         enable_on_install,
189         enable_incognito_on_install,
190         install_source);
191     return true;
192   }
193   return false;
194 }
195 
AddForTesting(const std::string & id,const PendingExtensionInfo & pending_extension_info)196 void PendingExtensionManager::AddForTesting(
197     const std::string& id,
198     const PendingExtensionInfo& pending_extension_info) {
199   pending_extension_map_[id] = pending_extension_info;
200 }
201