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 16namespace { 17 18// The Registry hive where to look for external extensions. 19const HKEY kRegRoot = HKEY_LOCAL_MACHINE; 20 21// The Registry subkey that contains information about external extensions. 22const char kRegistryExtensions[] = "Software\\Google\\Chrome\\Extensions"; 23 24// Registry value of of that key that defines the path to the .crx file. 25const wchar_t kRegistryExtensionPath[] = L"path"; 26 27// Registry value of that key that defines the current version of the .crx file. 28const wchar_t kRegistryExtensionVersion[] = L"version"; 29 30} // namespace 31 32void 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 41void 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