OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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/component_updater/cros_component_installer.h" | |
6 | |
7 using content::BrowserThread; | |
8 using content::PluginService; | |
9 | |
10 namespace component_updater { | |
11 | |
12 #if defined(OS_CHROMEOS) | |
13 // CRX hash for Chrome OS. | |
14 // appid: iibmmgakkjjfeplohmmninjahpefocna | |
15 const uint8_t kSha2Hash[] = {0x88, 0x1c, 0xc6, 0x0a, 0xa9, 0x95, 0x4f, 0xbe, | |
16 0x7c, 0xcd, 0x8d, 0x90, 0x7f, 0x45, 0xe2, 0xd0, | |
17 0xe6, 0x30, 0x8c, 0x37, 0x7d, 0x4e, 0x61, 0x8b, | |
18 0xe7, 0x08, 0xe6, 0x93, 0x2d, 0x13, 0x5d, 0x8a}; | |
waffles
2017/02/21 21:16:04
Delete these lines.
xiaochu
2017/02/21 21:39:40
Done.
| |
19 #else | |
20 #endif // defined(OS_CHROMEOS) | |
21 | |
22 #if defined(OS_CHROMEOS) | |
23 void LogRegistrationResult(chromeos::DBusMethodCallStatus call_status, | |
24 bool result) { | |
25 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
26 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) { | |
27 LOG(ERROR) << "Call to imageloader service failed."; | |
28 return; | |
29 } | |
30 if (!result) { | |
31 LOG(ERROR) << "Component registration failed"; | |
32 return; | |
33 } | |
34 } | |
35 void ImageLoaderRegistration(const std::string& version, | |
36 const base::FilePath& install_dir, | |
37 const std::string& name) { | |
38 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
39 chromeos::ImageLoaderClient* loader = | |
40 chromeos::DBusThreadManager::Get()->GetImageLoaderClient(); | |
41 | |
42 if (loader) { | |
43 loader->RegisterComponent(name, version, install_dir.value(), | |
44 base::Bind(&LogRegistrationResult)); | |
45 } else { | |
46 LOG(ERROR) << "Failed to get ImageLoaderClient object."; | |
47 } | |
48 } | |
49 | |
50 // Determine whether or not to skip registering this cros component updates. | |
51 bool SkipCupsRegistration(ComponentUpdateService* cus) { | |
52 return false; | |
53 } | |
54 #endif // defined(OS_CHROMEOS) | |
55 | |
56 CrOSComponentInstallerTraits::CrOSComponentInstallerTraits( | |
57 std::string dir_name, | |
58 std::string name, | |
59 std::string sha2HashStr) | |
60 : dir_name(dir_name), name(name) { | |
61 if (sha2HashStr.length() != 64) | |
62 return; | |
63 for (unsigned int i = 0; i < sizeof(kSha2Hash_); i++) { | |
64 kSha2Hash_[i] = stoul(sha2HashStr.substr(i * 2, 2), nullptr, 16); | |
65 } | |
66 } | |
67 | |
68 bool CrOSComponentInstallerTraits::SupportsGroupPolicyEnabledComponentUpdates() | |
69 const { | |
70 return true; | |
71 } | |
72 | |
73 bool CrOSComponentInstallerTraits::RequiresNetworkEncryption() const { | |
74 return false; | |
75 } | |
76 | |
77 update_client::CrxInstaller::Result | |
78 CrOSComponentInstallerTraits::OnCustomInstall( | |
79 const base::DictionaryValue& manifest, | |
80 const base::FilePath& install_dir) { | |
81 #if defined(OS_CHROMEOS) | |
82 std::string version; | |
83 if (!manifest.GetString("version", &version)) { | |
84 return ToInstallerResult(update_client::InstallError::GENERIC_ERROR); | |
85 } | |
86 BrowserThread::PostTask( | |
87 BrowserThread::UI, FROM_HERE, | |
88 base::Bind(&ImageLoaderRegistration, version, install_dir, name)); | |
89 return update_client::CrxInstaller::Result(update_client::InstallError::NONE); | |
90 #else | |
91 return ToInstallerResult(update_client::InstallError::GENERIC_ERROR); | |
92 #endif // defined(OS_LINUX) | |
waffles
2017/02/21 21:16:04
OS_LINUX → OS_CHROMEOS
xiaochu
2017/02/21 21:39:39
Done.
| |
93 } | |
94 | |
95 void CrOSComponentInstallerTraits::ComponentReady( | |
96 const base::Version& version, | |
97 const base::FilePath& path, | |
98 std::unique_ptr<base::DictionaryValue> manifest) {} | |
99 | |
100 bool CrOSComponentInstallerTraits::VerifyInstallation( | |
101 const base::DictionaryValue& manifest, | |
102 const base::FilePath& install_dir) const { | |
103 // TODO: verify installation. | |
waffles
2017/02/21 21:16:03
What does verifying the installation look like?
waffles
2017/02/21 21:39:25
Maybe I should be more clear: if there isn't a con
xiaochu
2017/02/21 21:39:40
For adobe flash, it checks the content of the mani
| |
104 return true; | |
105 } | |
106 | |
107 base::FilePath CrOSComponentInstallerTraits::GetRelativeInstallDir() const { | |
108 return base::FilePath(FILE_PATH_LITERAL(dir_name)); | |
109 } | |
110 | |
111 void CrOSComponentInstallerTraits::GetHash(std::vector<uint8_t>* hash) const { | |
112 hash->assign(kSha2Hash_, kSha2Hash_ + arraysize(kSha2Hash_)); | |
113 } | |
114 | |
115 std::string CrOSComponentInstallerTraits::GetName() const { | |
116 return name; | |
117 } | |
118 | |
119 update_client::InstallerAttributes | |
120 CrOSComponentInstallerTraits::GetInstallerAttributes() const { | |
121 return update_client::InstallerAttributes(); | |
122 } | |
123 | |
124 std::vector<std::string> CrOSComponentInstallerTraits::GetMimeTypes() const { | |
125 std::vector<std::string> mime_types; | |
126 return mime_types; | |
127 } | |
128 | |
129 void ConfigParser::XmlErrorFunc(void* context, const char* message, ...) { | |
130 va_list args; | |
131 va_start(args, message); | |
132 std::string* error = static_cast<std::string*>(context); | |
133 base::StringAppendV(error, message, args); | |
134 va_end(args); | |
135 } | |
136 bool ConfigParser::TagNameEquals(const xmlNode* node, | |
137 const char* expected_name) { | |
138 return 0 == strcmp(expected_name, reinterpret_cast<const char*>(node->name)); | |
139 } | |
140 std::unique_ptr<std::string> ConfigParser::GetAttributePtr( | |
141 xmlNode* node, | |
142 const char* attribute_name) { | |
143 const xmlChar* name = reinterpret_cast<const xmlChar*>(attribute_name); | |
144 for (xmlAttr* attr = node->properties; attr != NULL; attr = attr->next) { | |
145 if (!xmlStrcmp(attr->name, name) && attr->children && | |
146 attr->children->content) { | |
147 return base::MakeUnique<std::string>( | |
148 reinterpret_cast<const char*>(attr->children->content)); | |
149 } | |
150 } | |
151 return nullptr; | |
152 } | |
153 void ConfigParser::ParseError(const char* details, ...) { | |
154 va_list args; | |
155 va_start(args, details); | |
156 | |
157 if (!errors_.empty()) { | |
158 errors_ += "\r\n"; | |
159 } | |
160 | |
161 base::StringAppendV(&errors_, details, args); | |
162 va_end(args); | |
163 } | |
164 | |
165 bool ConfigParser::IsValidSha256(const std::string& sha2hashstr) { | |
166 for (unsigned long i = 0; i < sha2hashstr.size(); i++) { | |
167 char c = sha2hashstr.at(i); | |
168 if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || | |
169 (c >= 'A' && c <= 'F'))) { | |
170 return false; | |
171 } | |
172 } | |
173 return true; | |
174 } | |
175 | |
176 bool ConfigParser::ParseComponentTag(xmlNode* component, | |
177 Result* result, | |
178 std::string* error) { | |
179 auto name = GetAttributePtr(component, "name"); | |
180 auto dir_name = GetAttributePtr(component, "dir_name"); | |
181 auto sha2hashstr = GetAttributePtr(component, "sha2hashstr"); | |
182 // empty attibute is not allowed. | |
183 if (name == nullptr || dir_name == nullptr || sha2hashstr == nullptr || | |
184 dir_name->size() == 0 || name->size() == 0 || sha2hashstr->size() == 0) | |
185 return false; | |
186 // invalid sha2hashstr is not allowed. | |
187 if (sha2hashstr->size() != 64) { | |
188 return false; | |
189 } | |
190 if (!IsValidSha256(*sha2hashstr)) { | |
191 return false; | |
192 } | |
193 result->name = *name; | |
194 result->dir_name = *dir_name; | |
195 result->sha2hashstr = *sha2hashstr; | |
196 return true; | |
197 } | |
198 | |
199 std::vector<xmlNode*> ConfigParser::GetChildren(xmlNode* root, | |
200 const char* name) { | |
201 std::vector<xmlNode*> result; | |
202 for (xmlNode* child = root->children; child != NULL; child = child->next) { | |
203 if (!TagNameEquals(child, name)) { | |
204 continue; | |
205 } | |
206 result.push_back(child); | |
207 } | |
208 return result; | |
209 } | |
210 | |
211 bool ConfigParser::Parse(std::string config_xml, std::vector<Result>& results) { | |
212 if (config_xml.length() < 1) { | |
213 ParseError("Empty config_xml"); | |
214 return false; | |
215 } | |
216 | |
217 std::string xml_errors; | |
218 ScopedXmlErrorFunc error_func(&xml_errors, &XmlErrorFunc); | |
219 | |
220 ScopedXmlDocument document( | |
221 xmlParseDoc(reinterpret_cast<const xmlChar*>(config_xml.c_str()))); | |
222 if (!document.get()) { | |
223 ParseError("%s", xml_errors.c_str()); | |
224 return false; | |
225 } | |
226 xmlNode* root = xmlDocGetRootElement(document.get()); | |
227 if (!root) { | |
228 ParseError("Missing root node"); | |
229 return false; | |
230 } | |
231 if (!TagNameEquals(root, "components")) { | |
232 ParseError("Missing components tag"); | |
233 return false; | |
234 } | |
235 std::vector<xmlNode*> components = GetChildren(root, "component"); | |
236 for (size_t i = 0; i != components.size(); ++i) { | |
237 Result result; | |
238 std::string error; | |
239 if (ParseComponentTag(components[i], &result, &error)) { | |
240 results.push_back(result); | |
241 } else { | |
242 results.clear(); | |
243 ParseError("%s", error.c_str()); | |
244 return false; | |
245 } | |
246 } | |
247 return true; | |
248 } | |
249 | |
250 void RegisterCrOSComponent(ComponentUpdateService* cus, | |
251 ConfigParser::Result& result) { | |
252 std::unique_ptr<ComponentInstallerTraits> traits( | |
253 new CrOSComponentInstallerTraits(result.dir_name, result.name, | |
254 result.sha2hashstr)); | |
255 // |cus| will take ownership of |installer| during | |
256 // installer->Register(cus). | |
257 DefaultComponentInstaller* installer = | |
258 new DefaultComponentInstaller(std::move(traits)); | |
259 installer->Register(cus, base::Closure()); | |
260 } | |
261 | |
262 bool RegisterCrOSComponent(ComponentUpdateService* cus, std::string name) { | |
263 #if defined(OS_CHROMEOS) | |
264 base::FilePath configFilePath("/var/lib/imageloader/cros_dc.config"); | |
265 #else | |
266 base::FilePath configFilePath("/tmp/cros_dc.config"); | |
267 #endif // OS_CHROMEOS | |
268 std::string contents; | |
269 if (base::ReadFileToString(configFilePath, &contents)) { | |
270 VLOG(1) << "[RegisterCrOSComponents] configuration loaded:" << contents; | |
271 ConfigParser parser; | |
272 std::vector<ConfigParser::Result> results; | |
273 if (parser.Parse(contents, results)) { | |
274 VLOG(1) << "[RegisterCrOSComponents] xml parse succeeded"; | |
275 for (auto result : results) { | |
276 if (name.compare(result.name)) { | |
277 RegisterCrOSComponent(cus, result); | |
278 return true; | |
279 } | |
280 } | |
281 } else { | |
282 VLOG(0) << "[RegisterCrOSComponents] xml parse failed"; | |
283 } | |
284 } else { | |
285 VLOG(0) << "[RegisterCrOSComponents] configuration not exist."; | |
286 } | |
287 return false; | |
288 } | |
289 | |
290 bool InstallCrOSComponent(std::string name) { | |
291 const auto cus = g_browser_process->component_updater(); | |
292 if (RegisterCrOSComponent(cus, name)) { | |
293 // component registered successfully. | |
294 // you can wait until component_updater automatically install later; | |
295 // or you can trigger an on-demand install right-away. | |
296 // notes: non-block install is suggested; since it gives flexibility to API | |
297 // callers. API callers can schedule other activities while polling isReady | |
298 // to learn install progress. | |
299 // e.g: cus->GetOnDemandUpdater().OnDemandUpdater(""); | |
300 return true; | |
301 } else { | |
302 return false; | |
303 } | |
304 } | |
305 | |
306 bool IsReadyCrOSComponent(std::string name) { | |
307 return false; | |
308 } | |
309 | |
310 } // namespace component_updater | |
OLD | NEW |