Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2010 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 "chrome/browser/extensions/external_registry_extension_loader_win.h"
      6 
      7 #include "base/file_path.h"
      8 #include "base/string_util.h"
      9 #include "base/utf_string_conversions.h"
     10 #include "base/values.h"
     11 #include "base/version.h"
     12 #include "base/win/registry.h"
     13 #include "content/browser/browser_thread.h"
     14 #include "chrome/browser/extensions/external_extension_provider_impl.h"
     15 
     16 namespace {
     17 
     18 // The Registry hive where to look for external extensions.
     19 const HKEY kRegRoot = HKEY_LOCAL_MACHINE;
     20 
     21 // The Registry subkey that contains information about external extensions.
     22 const char kRegistryExtensions[] = "Software\\Google\\Chrome\\Extensions";
     23 
     24 // Registry value of of that key that defines the path to the .crx file.
     25 const wchar_t kRegistryExtensionPath[] = L"path";
     26 
     27 // Registry value of that key that defines the current version of the .crx file.
     28 const wchar_t kRegistryExtensionVersion[] = L"version";
     29 
     30 }  // namespace
     31 
     32 void ExternalRegistryExtensionLoader::StartLoading() {
     33   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     34   BrowserThread::PostTask(
     35       BrowserThread::FILE, FROM_HERE,
     36       NewRunnableMethod(
     37           this,
     38           &ExternalRegistryExtensionLoader::LoadOnFileThread));
     39 }
     40 
     41 void ExternalRegistryExtensionLoader::LoadOnFileThread() {
     42   CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     43   scoped_ptr<DictionaryValue> prefs(new DictionaryValue);
     44 
     45   base::win::RegistryKeyIterator iterator(
     46       kRegRoot, ASCIIToWide(kRegistryExtensions).c_str());
     47   while (iterator.Valid()) {
     48     base::win::RegKey key;
     49     std::wstring key_path = ASCIIToWide(kRegistryExtensions);
     50     key_path.append(L"\\");
     51     key_path.append(iterator.Name());
     52     if (key.Open(kRegRoot, key_path.c_str(), KEY_READ)  == ERROR_SUCCESS) {
     53       std::wstring extension_path_str;
     54       if (key.ReadValue(kRegistryExtensionPath, &extension_path_str)
     55           == ERROR_SUCCESS) {
     56         FilePath extension_path(extension_path_str);
     57         if (!extension_path.IsAbsolute()) {
     58           LOG(ERROR) << "Path " << extension_path_str
     59                      << " needs to be absolute in key "
     60                      << key_path;
     61           ++iterator;
     62           continue;
     63         }
     64         std::wstring extension_version;
     65         if (key.ReadValue(kRegistryExtensionVersion, &extension_version)
     66             == ERROR_SUCCESS) {
     67           std::string id = WideToASCII(iterator.Name());
     68           StringToLowerASCII(&id);
     69 
     70           if (!Extension::IdIsValid(id)) {
     71             LOG(ERROR) << "Invalid id value " << id
     72                        << " for key " << key_path << " .";
     73             ++iterator;
     74             continue;
     75           }
     76 
     77           scoped_ptr<Version> version;
     78           version.reset(Version::GetVersionFromString(
     79                             WideToASCII(extension_version)));
     80           if (!version.get()) {
     81             LOG(ERROR) << "Invalid version value " << extension_version
     82                        << " for key " << key_path << " .";
     83             ++iterator;
     84             continue;
     85           }
     86 
     87           prefs->SetString(
     88               id + "." + ExternalExtensionProviderImpl::kExternalVersion,
     89               WideToASCII(extension_version));
     90           prefs->SetString(
     91               id + "." + ExternalExtensionProviderImpl::kExternalCrx,
     92               extension_path_str);
     93         } else {
     94           // TODO(erikkay): find a way to get this into about:extensions
     95           LOG(ERROR) << "Missing value " << kRegistryExtensionVersion
     96                      << " for key " << key_path << " .";
     97         }
     98       } else {
     99         // TODO(erikkay): find a way to get this into about:extensions
    100         LOG(ERROR) << "Missing value " << kRegistryExtensionPath
    101                    << " for key " << key_path << " .";
    102       }
    103     }
    104     ++iterator;
    105   }
    106 
    107   prefs_.reset(prefs.release());
    108   BrowserThread::PostTask(
    109       BrowserThread::UI, FROM_HERE,
    110       NewRunnableMethod(
    111           this,
    112           &ExternalRegistryExtensionLoader::LoadFinished));
    113 }
    114