172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// found in the LICENSE file.
472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/external_extension_provider_impl.h"
672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "app/app_paths.h"
872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/file_path.h"
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/logging.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/linked_ptr.h"
1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/path_service.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/values.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/version.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/external_extension_provider_interface.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/external_policy_extension_loader.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/external_pref_extension_loader.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/profiles/profile.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/chrome_paths.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN)
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/external_registry_extension_loader_win.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Constants for keeping track of extension preferences in a dictionary.
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char ExternalExtensionProviderImpl::kLocation[] = "location";
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char ExternalExtensionProviderImpl::kState[] = "state";
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char ExternalExtensionProviderImpl::kExternalCrx[] = "external_crx";
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char ExternalExtensionProviderImpl::kExternalVersion[] =
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "external_version";
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char ExternalExtensionProviderImpl::kExternalUpdateUrl[] =
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "external_update_url";
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExternalExtensionProviderImpl::ExternalExtensionProviderImpl(
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    VisitorInterface* service,
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ExternalExtensionLoader* loader,
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    Extension::Location crx_location,
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    Extension::Location download_location)
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  : crx_location_(crx_location),
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    download_location_(download_location),
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    service_(service),
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    prefs_(NULL),
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ready_(false),
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    loader_(loader) {
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  loader_->Init(this);
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExternalExtensionProviderImpl::~ExternalExtensionProviderImpl() {
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  loader_->OwnerShutdown();
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExternalExtensionProviderImpl::VisitRegisteredExtension() const {
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The loader will call back to SetPrefs.
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  loader_->StartLoading();
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExternalExtensionProviderImpl::SetPrefs(DictionaryValue* prefs) {
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Check if the service is still alive. It is possible that it had went
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // away while |loader_| was working on the FILE thread.
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!service_) return;
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  prefs_.reset(prefs);
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ready_ = true; // Queries for extensions are allowed from this point.
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Notify ExtensionService about all the extensions this provider has.
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (DictionaryValue::key_iterator i = prefs_->begin_keys();
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       i != prefs_->end_keys(); ++i) {
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& extension_id = *i;
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DictionaryValue* extension;
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!Extension::IdIsValid(extension_id)) {
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      LOG(WARNING) << "Malformed extension dictionary: key "
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << extension_id.c_str() << " is not a valid id.";
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!prefs_->GetDictionaryWithoutPathExpansion(extension_id, &extension)) {
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      LOG(WARNING) << "Malformed extension dictionary: key "
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << extension_id.c_str()
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << " has a value that is not a dictionary.";
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    FilePath::StringType external_crx;
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string external_version;
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string external_update_url;
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool has_external_crx = extension->GetString(kExternalCrx, &external_crx);
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool has_external_version = extension->GetString(kExternalVersion,
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                     &external_version);
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool has_external_update_url = extension->GetString(kExternalUpdateUrl,
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                        &external_update_url);
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (has_external_crx != has_external_version) {
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      LOG(WARNING) << "Malformed extension dictionary for extension: "
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << extension_id.c_str() << ".  " << kExternalCrx
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << " and " << kExternalVersion << " must be used together.";
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (has_external_crx == has_external_update_url) {
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      LOG(WARNING) << "Malformed extension dictionary for extension: "
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << extension_id.c_str() << ".  Exactly one of the "
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << "followng keys should be used: " << kExternalCrx
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   << ", " << kExternalUpdateUrl << ".";
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (has_external_crx) {
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (crx_location_ == Extension::INVALID) {
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(WARNING) << "This provider does not support installing external "
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << "extensions from crx files.";
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        continue;
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (external_crx.find(FilePath::kParentDirectory) !=
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          base::StringPiece::npos) {
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(WARNING) << "Path traversal not allowed in path: "
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << external_crx.c_str();
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        continue;
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // If the path is relative, and the provider has a base path,
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // build the absolute path to the crx file.
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      FilePath path(external_crx);
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!path.IsAbsolute()) {
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        FilePath base_path = loader_->GetBaseCrxFilePath();
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (base_path.empty()) {
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          LOG(WARNING) << "File path " << external_crx.c_str()
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                       << " is relative.  An absolute path is required.";
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          continue;
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        }
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        path = base_path.Append(external_crx);
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      scoped_ptr<Version> version;
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      version.reset(Version::GetVersionFromString(external_version));
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!version.get()) {
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(WARNING) << "Malformed extension dictionary for extension: "
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << extension_id.c_str() << ".  Invalid version string \""
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << external_version << "\".";
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        continue;
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      service_->OnExternalExtensionFileFound(extension_id, version.get(), path,
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             crx_location_);
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else { // if (has_external_update_url)
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      CHECK(has_external_update_url);  // Checking of keys above ensures this.
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (download_location_ == Extension::INVALID) {
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(WARNING) << "This provider does not support installing external "
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << "extensions from update URLs.";
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        continue;
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      GURL update_url(external_update_url);
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (!update_url.is_valid()) {
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        LOG(WARNING) << "Malformed extension dictionary for extension: "
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << extension_id.c_str() << ".  Key " << kExternalUpdateUrl
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << " has value \"" << external_update_url
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                     << "\", which is not a valid URL.";
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        continue;
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      service_->OnExternalExtensionUpdateUrlFound(
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          extension_id, update_url, download_location_);
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  service_->OnExternalProviderReady();
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExternalExtensionProviderImpl::ServiceShutdown() {
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  service_ = NULL;
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ExternalExtensionProviderImpl::IsReady() {
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ready_;
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ExternalExtensionProviderImpl::HasExtension(
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& id) const {
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(prefs_.get());
18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(ready_);
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return prefs_->HasKey(id);
18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ExternalExtensionProviderImpl::GetExtensionDetails(
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& id, Extension::Location* location,
18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_ptr<Version>* version) const {
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(prefs_.get());
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CHECK(ready_);
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DictionaryValue* extension = NULL;
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!prefs_->GetDictionary(id, &extension))
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Extension::Location loc = Extension::INVALID;
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (extension->HasKey(kExternalUpdateUrl)) {
19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    loc = download_location_;
19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (extension->HasKey(kExternalCrx)) {
20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    loc = crx_location_;
20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string external_version;
20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!extension->GetString(kExternalVersion, &external_version))
20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return false;
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (version)
20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      version->reset(Version::GetVersionFromString(external_version));
20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
21172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED();  // Chrome should not allow prefs to get into this state.
21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (location)
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *location = loc;
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExternalExtensionProviderImpl::CreateExternalProviders(
22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    VisitorInterface* service,
22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    Profile* profile,
22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ProviderCollection* provider_list) {
22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  provider_list->push_back(
22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      linked_ptr<ExternalExtensionProviderInterface>(
22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          new ExternalExtensionProviderImpl(
22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              service,
23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              new ExternalPrefExtensionLoader(
23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                  app::DIR_EXTERNAL_EXTENSIONS),
23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::EXTERNAL_PREF,
23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::EXTERNAL_PREF_DOWNLOAD)));
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_CHROMEOS)
23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Chrome OS specific source for OEM customization.
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  provider_list->push_back(
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      linked_ptr<ExternalExtensionProviderInterface>(
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          new ExternalExtensionProviderImpl(
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              service,
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              new ExternalPrefExtensionLoader(
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                  chrome::DIR_USER_EXTERNAL_EXTENSIONS),
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::EXTERNAL_PREF,
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::EXTERNAL_PREF_DOWNLOAD)));
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN)
24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  provider_list->push_back(
24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      linked_ptr<ExternalExtensionProviderInterface>(
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          new ExternalExtensionProviderImpl(
25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              service,
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              new ExternalRegistryExtensionLoader,
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::EXTERNAL_REGISTRY,
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::INVALID)));
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  provider_list->push_back(
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      linked_ptr<ExternalExtensionProviderInterface>(
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          new ExternalExtensionProviderImpl(
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              service,
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              new ExternalPolicyExtensionLoader(profile),
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::INVALID,
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              Extension::EXTERNAL_POLICY_DOWNLOAD)));
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
263