| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/logging.h" |
| #include "base/stl_util-inl.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/pending_extension_manager.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "content/browser/browser_thread.h" |
| |
| namespace { |
| |
| // Install predicate used by AddFromDefaultAppList(). |
| bool IsApp(const Extension& extension) { |
| return extension.is_app(); |
| } |
| |
| // Install predicate used by AddFromExternalUpdateUrl(). |
| bool AlwaysInstall(const Extension& extension) { |
| return true; |
| } |
| |
| } // namespace |
| |
| PendingExtensionManager::PendingExtensionManager( |
| const ExtensionServiceInterface& service) |
| : service_(service) { |
| } |
| |
| PendingExtensionManager::~PendingExtensionManager() {} |
| |
| bool PendingExtensionManager::GetById( |
| const std::string& id, |
| PendingExtensionInfo* out_pending_extension_info) const { |
| |
| PendingExtensionMap::const_iterator it = pending_extension_map_.find(id); |
| if (it != pending_extension_map_.end()) { |
| *out_pending_extension_info = it->second; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void PendingExtensionManager::Remove(const std::string& id) { |
| pending_extension_map_.erase(id); |
| } |
| |
| bool PendingExtensionManager::IsIdPending(const std::string& id) const { |
| return ContainsKey(pending_extension_map_, id); |
| } |
| |
| bool PendingExtensionManager::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) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| if (service_.GetExtensionById(id, true)) { |
| LOG(ERROR) << "Trying to add pending extension " << id |
| << " which already exists"; |
| return false; |
| } |
| |
| const bool kIsFromSync = true; |
| const Extension::Location kSyncLocation = Extension::INTERNAL; |
| |
| return AddExtensionImpl(id, update_url, should_allow_install, |
| kIsFromSync, install_silently, |
| enable_on_install, |
| enable_incognito_on_install, |
| kSyncLocation); |
| } |
| |
| void PendingExtensionManager::AddFromExternalUpdateUrl( |
| const std::string& id, const GURL& update_url, |
| Extension::Location location) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| const bool kIsFromSync = false; |
| const bool kInstallSilently = true; |
| const bool kEnableOnInstall = true; |
| const bool kEnableIncognitoOnInstall = false; |
| |
| if (service_.IsExternalExtensionUninstalled(id)) |
| return; |
| |
| if (service_.GetExtensionById(id, true)) { |
| LOG(DFATAL) << "Trying to add extension " << id |
| << " by external update, but it is already installed."; |
| return; |
| } |
| |
| AddExtensionImpl(id, update_url, &AlwaysInstall, |
| kIsFromSync, kInstallSilently, |
| kEnableOnInstall, kEnableIncognitoOnInstall, |
| location); |
| } |
| |
| |
| // TODO(akalin): Change DefaultAppList to DefaultExtensionList and |
| // remove the IsApp() check. |
| void PendingExtensionManager::AddFromDefaultAppList( |
| const std::string& id) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| const bool kIsFromSync = false; |
| const bool kInstallSilently = true; |
| const bool kEnableOnInstall = true; |
| const bool kEnableIncognitoOnInstall = true; |
| |
| // This can legitimately happen if the user manually installed one of the |
| // default apps before this code ran. |
| if (service_.GetExtensionById(id, true)) |
| return; |
| |
| AddExtensionImpl(id, GURL(), &IsApp, |
| kIsFromSync, kInstallSilently, |
| kEnableOnInstall, kEnableIncognitoOnInstall, |
| Extension::INTERNAL); |
| } |
| |
| void PendingExtensionManager::AddFromExternalFile( |
| const std::string& id, |
| Extension::Location location) { |
| |
| GURL kUpdateUrl = GURL(); |
| bool kIsFromSync = false; |
| bool kInstallSilently = true; |
| bool kEnableOnInstall = true; |
| bool kEnableIncognitoOnInstall = false; |
| |
| pending_extension_map_[id] = |
| PendingExtensionInfo(kUpdateUrl, |
| &AlwaysInstall, |
| kIsFromSync, |
| kInstallSilently, |
| kEnableOnInstall, |
| kEnableIncognitoOnInstall, |
| location); |
| } |
| |
| bool PendingExtensionManager::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) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| // Will add a pending extension record unless this variable is set to false. |
| bool should_add_pending_record = true; |
| |
| if (ContainsKey(pending_extension_map_, id)) { |
| // Bugs in this code will manifest as sporadic incorrect extension |
| // locations in situations where multiple install sources run at the |
| // same time. For example, on first login to a chrome os machine, an |
| // extension may be requested by sync sync and the default extension set. |
| // The following logging will help diagnose such issues. |
| VLOG(1) << "Extension id " << id |
| << " was entered for update more than once." |
| << " old location: " << pending_extension_map_[id].install_source() |
| << " new location: " << install_source; |
| |
| Extension::Location higher_priority_location = |
| Extension::GetHigherPriorityLocation( |
| install_source, pending_extension_map_[id].install_source()); |
| |
| if (higher_priority_location == install_source) { |
| VLOG(1) << "Overwrite existing record."; |
| |
| } else { |
| VLOG(1) << "Keep existing record."; |
| should_add_pending_record = false; |
| } |
| } |
| |
| if (should_add_pending_record) { |
| pending_extension_map_[id] = PendingExtensionInfo( |
| update_url, |
| should_allow_install, |
| is_from_sync, |
| install_silently, |
| enable_on_install, |
| enable_incognito_on_install, |
| install_source); |
| return true; |
| } |
| return false; |
| } |
| |
| void PendingExtensionManager::AddForTesting( |
| const std::string& id, |
| const PendingExtensionInfo& pending_extension_info) { |
| pending_extension_map_[id] = pending_extension_info; |
| } |