Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: chrome/nacl/pnacl_component_installer.cc

Issue 8348026: Add a component installer for Portable NaCl. Registration of installer is (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/nacl/pnacl_component_installer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/nacl/pnacl_component_installer.h"
6
7 #include <string.h>
8
9 #include "base/base_paths.h"
10 #include "base/compiler_specific.h"
11 #include "base/file_path.h"
12 #include "base/file_util.h"
13 #include "base/logging.h"
14 #include "base/path_service.h"
15 #include "base/string_util.h"
16 #include "base/stringprintf.h"
17 #include "base/values.h"
18 #include "base/version.h"
19 #include "build/build_config.h"
20 #include "chrome/browser/component_updater/component_updater_service.h"
21 #include "chrome/browser/plugin_prefs.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "content/browser/browser_thread.h"
24
25 namespace {
26
27 // CRX hash. This made up extension id is: haoikncodblmdapadglhmehplknoaddl
28 // TODO(jvoung): update the ID and hash when we go into production.
29 // See tools/crx_id/crx_id.py for gathering this information.
30 const uint8 sha256_hash[] =
31 {0x70, 0xe8, 0xad, 0x2e, 0x31, 0xbc, 0x30, 0xf0, 0x36, 0xb7,
32 0xc4, 0x7f, 0xba, 0xde, 0x03, 0x3b, 0x48, 0xd2, 0xe8, 0x58,
33 0x04, 0x45, 0xa1, 0x6c, 0xc8, 0xac, 0x86, 0x9e, 0xf1, 0x9b,
34 0xf6, 0xea};
35
36 // One of the PNaCl component files, for checking that expected files exist.
37 // TODO(jvoung): perhaps replace this with a file that contains a list of
38 // the expected files. Use that to check that everything is unpacked.
39 // However, that would make startup detection even slower (need to check for
40 // more than one file!).
41 const FilePath::CharType kPNaClCompilerFileName[] =
42 FILE_PATH_LITERAL("llc");
43
44 // Name of the PNaCl component specified in the manifest.
45 const char kPNaClManifestName[] = "PNaCl";
46
47 // Name of the PNaCl architecture in the component manifest.
48 // NOTE: this can be independent of the Omaha query parameter.
49 // TODO(jvoung): will this pre-processor define work with 64-bit Windows?
50 // NaCl's sel_ldr is 64-bit, but the browser process is 32-bit.
51 // Will the Omaha query do the right thing as well?
52 const char kPNaClArch[] =
53 #if defined(ARCH_CPU_X86)
54 "x86";
55 #elif defined(ARCH_CPU_X86_64)
56 "x64";
57 #elif defined(ARCH_CPU_ARMEL)
58 "arm";
59 #else
60 #error "Unknown Architecture in PNaCl Component Installer."
61 #endif
62
63 // The PNaCl components are in a directory with this name.
64 const FilePath::CharType kPNaClBaseDirectory[] =
65 FILE_PATH_LITERAL("PNaCl");
66
67 // If we don't have PNaCl installed, this is the version we claim.
68 // TODO(jvoung): Is there a way to trick the configurator to ping the server
69 // earlier if there are components that are not yet installed (version 0.0.0.0),
jvoung - send to chromium... 2011/11/11 22:57:34 Would such a change make sense?
cpu_(ooo_6.6-7.5) 2011/11/23 01:39:12 Sounds like an interesting possibility.
70 // So that they will be available ASAP? Be careful not to hurt startup speed.
71 // Make kNullVersion part of ComponentUpdater in that case, to avoid skew?
72 const char kNullVersion[] = "0.0.0.0";
73
74 // The base directory on Windows looks like:
75 // <profile>\AppData\Local\Google\Chrome\User Data\PNaCl\.
76 FilePath GetPNaClBaseDirectory() {
77 FilePath result;
78 PathService::Get(chrome::DIR_USER_DATA, &result);
79 return result.Append(kPNaClBaseDirectory);
80 }
81
82 // PNaCl components have the version encoded in the path itself
83 // so we need to enumerate the directories to find the full path.
84 // On success it returns something like:
85 // <profile>\AppData\Local\Google\Chrome\User Data\PNaCl\0.1.2.3\.
86 //
87 // TODO(jvoung): Does it garbage collect old versions when a new version is
88 // installed? Do we need the architecture in the path too? That is for handling
89 // cases when you share a profile but switch between machine-types.
90 bool GetLatestPNaClDirectory(FilePath* result, Version* latest) {
91 *result = GetPNaClBaseDirectory();
92 bool found = false;
93 file_util::FileEnumerator
94 file_enumerator(*result, false, file_util::FileEnumerator::DIRECTORIES);
95 for (FilePath path = file_enumerator.Next(); !path.value().empty();
96 path = file_enumerator.Next()) {
97 Version version(path.BaseName().MaybeAsASCII());
98 if (!version.IsValid())
99 continue;
100 if (version.CompareTo(*latest) > 0) {
101 *latest = version;
102 *result = path;
103 found = true;
104 }
105 }
106 return found;
107 }
108
109 } // namespace
110
111 class PNaClComponentInstaller : public ComponentInstaller {
112 public:
113 explicit PNaClComponentInstaller(const Version& version);
114
115 virtual ~PNaClComponentInstaller() {}
116
117 virtual void OnUpdateError(int error) OVERRIDE;
118
119 virtual bool Install(base::DictionaryValue* manifest,
120 const FilePath& unpack_path) OVERRIDE;
121
122 private:
123 Version current_version_;
124 };
125
126 PNaClComponentInstaller::PNaClComponentInstaller(
127 const Version& version) : current_version_(version) {
128 DCHECK(version.IsValid());
129 }
130
131 void PNaClComponentInstaller::OnUpdateError(int error) {
132 NOTREACHED() << "PNaCl update error: " << error;
133 }
134
135 bool PNaClComponentInstaller::Install(base::DictionaryValue* manifest,
136 const FilePath& unpack_path) {
137 Version version;
138 if (!CheckPNaClComponentManifest(manifest, &version))
139 return false;
140 if (current_version_.CompareTo(version) > 0)
141 return false;
142
143 // Make sure that at least one of the compiler files exists.
144 if (!file_util::PathExists(unpack_path.Append(kPNaClCompilerFileName)))
145 return false;
146
147 // Passed the basic tests. Time to install it.
148 FilePath path =
149 GetPNaClBaseDirectory().AppendASCII(version.GetString());
150 if (file_util::PathExists(path))
151 return false;
152 if (!file_util::Move(unpack_path, path))
153 return false;
154
155 // Installation is done. Now tell the rest of chrome (just the path service
156 // for now). TODO(jvoung): we need notifications if someone surfed to a
157 // PNaCl webpage and PNaCl was just installed at this time. They should
158 // then be able to reload the page and retry (or something).
159 current_version_ = version;
160
161 PathService::Override(chrome::FILE_PNACL_COMPONENT, path);
162 return true;
163 }
164
165 bool CheckPNaClComponentManifest(base::DictionaryValue* manifest,
166 Version* version_out) {
167 // Make sure we have the right manifest file.
168 std::string name;
169 manifest->GetStringASCII("name", &name);
170 if (name != kPNaClManifestName)
171 return false;
172
173 std::string proposed_version;
174 manifest->GetStringASCII("version", &proposed_version);
175 Version version(proposed_version.c_str());
176 if (!version.IsValid())
177 return false;
178
179 std::string arch;
180 manifest->GetStringASCII("x-pnacl-arch", &arch);
181 if (arch != kPNaClArch)
182 return false;
183
184 *version_out = version;
185 return true;
186 }
187
188 namespace {
189
190 // Finally, do the registration with the right version number.
191 void FinishPNaClUpdateRegistration(ComponentUpdateService* cus,
192 const Version& version) {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 CrxComponent pnacl;
195 pnacl.name = "pnacl";
196 pnacl.installer = new PNaClComponentInstaller(version);
197 pnacl.version = version;
198 pnacl.pk_hash.assign(sha256_hash, &sha256_hash[sizeof(sha256_hash)]);
199 if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) {
200 NOTREACHED() << "PNaCl component registration failed.";
201 }
202 }
203
204 // Check if there is an existing version on disk first to know when
205 // a hosted version is actually newer.
206 void StartPNaClUpdateRegistration(ComponentUpdateService* cus) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
208 FilePath path = GetPNaClBaseDirectory();
209 if (!file_util::PathExists(path)) {
210 if (!file_util::CreateDirectory(path)) {
211 NOTREACHED() << "Could not create PNaCl directory.";
212 return;
213 }
214 }
215
216 Version version(kNullVersion);
217 if (GetLatestPNaClDirectory(&path, &version)) {
218 // Check if one of the PNaCl files is really there.
219 FilePath compiler_path = path.Append(kPNaClCompilerFileName);
220 if (!file_util::PathExists(compiler_path)) {
221 version = Version(kNullVersion);
222 } else {
223 // Register the existing path for now, before checking for updates.
224 // TODO(jvoung): Will this race with the NaCl plugin in browser tests
225 // if we pre-populate the user profile directory with the components?
jvoung - send to chromium... 2011/11/11 22:57:34 Is this a race we need to worry about for testing
cpu_(ooo_6.6-7.5) 2011/11/23 01:39:12 Not sure, who is pre-populating? other thread? oth
jvoung - send to chromium... 2011/12/14 19:34:31 At the very least we don't want to be pinging serv
226 PathService::Override(chrome::FILE_PNACL_COMPONENT, path);
227 }
228 }
229
230 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
231 NewRunnableFunction(&FinishPNaClUpdateRegistration, cus, version));
232 }
233
234 } // namespace
235
236 void RegisterPNaClComponent(ComponentUpdateService* cus) {
237 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
238 NewRunnableFunction(&StartPNaClUpdateRegistration, cus));
239 }
OLDNEW
« no previous file with comments | « chrome/nacl/pnacl_component_installer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698