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(). 15 bool IsApp(const Extension& extension) { 16 return extension.is_app(); 17 } 18 19 // Install predicate used by AddFromExternalUpdateUrl(). 20 bool AlwaysInstall(const Extension& extension) { 21 return true; 22 } 23 24 } // namespace 25 26 PendingExtensionManager::PendingExtensionManager( 27 const ExtensionServiceInterface& service) 28 : service_(service) { 29 } 30 31 PendingExtensionManager::~PendingExtensionManager() {} 32 33 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 46 void PendingExtensionManager::Remove(const std::string& id) { 47 pending_extension_map_.erase(id); 48 } 49 50 bool PendingExtensionManager::IsIdPending(const std::string& id) const { 51 return ContainsKey(pending_extension_map_, id); 52 } 53 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 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. 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 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 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 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