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
StartLoading()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
LoadOnFileThread()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