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