OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/crx_installer.h" | 5 #include "chrome/browser/extensions/crx_installer.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 BrowserThread::FILE, FROM_HERE, | 165 BrowserThread::FILE, FROM_HERE, |
166 base::Bind(&CrxInstaller::ConvertUserScriptOnFileThread, this))) | 166 base::Bind(&CrxInstaller::ConvertUserScriptOnFileThread, this))) |
167 NOTREACHED(); | 167 NOTREACHED(); |
168 } | 168 } |
169 | 169 |
170 void CrxInstaller::ConvertUserScriptOnFileThread() { | 170 void CrxInstaller::ConvertUserScriptOnFileThread() { |
171 string16 error; | 171 string16 error; |
172 scoped_refptr<Extension> extension = | 172 scoped_refptr<Extension> extension = |
173 ConvertUserScriptToExtension(source_file_, download_url_, &error); | 173 ConvertUserScriptToExtension(source_file_, download_url_, &error); |
174 if (!extension) { | 174 if (!extension) { |
175 ReportFailureFromFileThread(error); | 175 ReportFailureFromFileThread(CrxInstallerError(error)); |
176 return; | 176 return; |
177 } | 177 } |
178 | 178 |
179 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension); | 179 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension); |
180 } | 180 } |
181 | 181 |
182 void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) { | 182 void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) { |
183 if (!BrowserThread::PostTask( | 183 if (!BrowserThread::PostTask( |
184 BrowserThread::FILE, FROM_HERE, | 184 BrowserThread::FILE, FROM_HERE, |
185 base::Bind(&CrxInstaller::ConvertWebAppOnFileThread, this, web_app))) | 185 base::Bind(&CrxInstaller::ConvertWebAppOnFileThread, this, web_app))) |
186 NOTREACHED(); | 186 NOTREACHED(); |
187 } | 187 } |
188 | 188 |
189 void CrxInstaller::ConvertWebAppOnFileThread( | 189 void CrxInstaller::ConvertWebAppOnFileThread( |
190 const WebApplicationInfo& web_app) { | 190 const WebApplicationInfo& web_app) { |
191 string16 error; | 191 string16 error; |
192 scoped_refptr<Extension> extension( | 192 scoped_refptr<Extension> extension( |
193 ConvertWebAppToExtension(web_app, base::Time::Now())); | 193 ConvertWebAppToExtension(web_app, base::Time::Now())); |
194 if (!extension) { | 194 if (!extension) { |
195 // Validation should have stopped any potential errors before getting here. | 195 // Validation should have stopped any potential errors before getting here. |
196 NOTREACHED() << "Could not convert web app to extension."; | 196 NOTREACHED() << "Could not convert web app to extension."; |
197 return; | 197 return; |
198 } | 198 } |
199 | 199 |
200 // TODO(aa): conversion data gets lost here :( | 200 // TODO(aa): conversion data gets lost here :( |
201 | 201 |
202 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension); | 202 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension); |
203 } | 203 } |
204 | 204 |
205 bool CrxInstaller::AllowInstall(const Extension* extension, | 205 CrxInstallerError CrxInstaller::AllowInstall(const Extension* extension) { |
206 string16* error) { | |
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
208 DCHECK(error); | |
209 | 207 |
210 // Make sure the expected ID matches if one was supplied or if we want to | 208 // Make sure the expected ID matches if one was supplied or if we want to |
211 // bypass the prompt. | 209 // bypass the prompt. |
212 if ((approved_ || !expected_id_.empty()) && | 210 if ((approved_ || !expected_id_.empty()) && |
213 expected_id_ != extension->id()) { | 211 expected_id_ != extension->id()) { |
214 *error = l10n_util::GetStringFUTF16(IDS_EXTENSION_INSTALL_UNEXPECTED_ID, | 212 return CrxInstallerError( |
215 ASCIIToUTF16(expected_id_), | 213 l10n_util::GetStringFUTF16(IDS_EXTENSION_INSTALL_UNEXPECTED_ID, |
216 ASCIIToUTF16(extension->id())); | 214 ASCIIToUTF16(expected_id_), |
217 return false; | 215 ASCIIToUTF16(extension->id()))); |
218 } | 216 } |
219 | 217 |
220 if (expected_version_.get() && | 218 if (expected_version_.get() && |
221 !expected_version_->Equals(*extension->version())) { | 219 !expected_version_->Equals(*extension->version())) { |
222 *error = l10n_util::GetStringFUTF16( | 220 return CrxInstallerError( |
223 IDS_EXTENSION_INSTALL_UNEXPECTED_VERSION, | 221 l10n_util::GetStringFUTF16( |
224 ASCIIToUTF16(expected_version_->GetString()), | 222 IDS_EXTENSION_INSTALL_UNEXPECTED_VERSION, |
225 ASCIIToUTF16(extension->version()->GetString())); | 223 ASCIIToUTF16(expected_version_->GetString()), |
226 return false; | 224 ASCIIToUTF16(extension->version()->GetString()))); |
227 } | 225 } |
228 | 226 |
229 // Make sure the manifests match if we want to bypass the prompt. | 227 // Make sure the manifests match if we want to bypass the prompt. |
230 if (approved_ && | 228 if (approved_ && |
231 (!expected_manifest_.get() || | 229 (!expected_manifest_.get() || |
232 !expected_manifest_->Equals(original_manifest_.get()))) { | 230 !expected_manifest_->Equals(original_manifest_.get()))) { |
233 *error = l10n_util::GetStringUTF16(IDS_EXTENSION_MANIFEST_INVALID); | 231 return CrxInstallerError( |
234 return false; | 232 l10n_util::GetStringUTF16(IDS_EXTENSION_MANIFEST_INVALID)); |
235 } | 233 } |
236 | 234 |
237 // The checks below are skipped for themes and external installs. | 235 // The checks below are skipped for themes and external installs. |
238 // TODO(pamg): After ManagementPolicy refactoring is complete, remove this | 236 // TODO(pamg): After ManagementPolicy refactoring is complete, remove this |
239 // and other uses of install_source_ that are no longer needed now that the | 237 // and other uses of install_source_ that are no longer needed now that the |
240 // SandboxedExtensionUnpacker sets extension->location. | 238 // SandboxedExtensionUnpacker sets extension->location. |
241 if (extension->is_theme() || Extension::IsExternalLocation(install_source_)) | 239 if (extension->is_theme() || Extension::IsExternalLocation(install_source_)) |
242 return true; | 240 return CrxInstallerError(); |
243 | 241 |
244 if (!extensions_enabled_) { | 242 if (!extensions_enabled_) { |
245 *error = l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_NOT_ENABLED); | 243 return CrxInstallerError( |
246 return false; | 244 l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_NOT_ENABLED)); |
247 } | 245 } |
248 | 246 |
249 if (install_cause_ == extension_misc::INSTALL_CAUSE_USER_DOWNLOAD) { | 247 if (install_cause_ == extension_misc::INSTALL_CAUSE_USER_DOWNLOAD) { |
250 if (extensions::switch_utils::IsEasyOffStoreInstallEnabled()) { | 248 if (extensions::switch_utils::IsEasyOffStoreInstallEnabled()) { |
251 const char* kHistogramName = "Extensions.OffStoreInstallDecisionEasy"; | 249 const char* kHistogramName = "Extensions.OffStoreInstallDecisionEasy"; |
252 if (is_gallery_install()) { | 250 if (is_gallery_install()) { |
253 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OnStoreInstall, | 251 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OnStoreInstall, |
254 NumOffStoreInstallDecision); | 252 NumOffStoreInstallDecision); |
255 } else { | 253 } else { |
256 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OffStoreInstallAllowed, | 254 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OffStoreInstallAllowed, |
257 NumOffStoreInstallDecision); | 255 NumOffStoreInstallDecision); |
258 } | 256 } |
259 } else { | 257 } else { |
260 const char* kHistogramName = "Extensions.OffStoreInstallDecisionHard"; | 258 const char* kHistogramName = "Extensions.OffStoreInstallDecisionHard"; |
261 if (is_gallery_install()) { | 259 if (is_gallery_install()) { |
262 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OnStoreInstall, | 260 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OnStoreInstall, |
263 NumOffStoreInstallDecision); | 261 NumOffStoreInstallDecision); |
264 } else if (off_store_install_allow_reason_ != OffStoreInstallDisallowed) { | 262 } else if (off_store_install_allow_reason_ != OffStoreInstallDisallowed) { |
265 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OffStoreInstallAllowed, | 263 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OffStoreInstallAllowed, |
266 NumOffStoreInstallDecision); | 264 NumOffStoreInstallDecision); |
267 UMA_HISTOGRAM_ENUMERATION("Extensions.OffStoreInstallAllowReason", | 265 UMA_HISTOGRAM_ENUMERATION("Extensions.OffStoreInstallAllowReason", |
268 off_store_install_allow_reason_, | 266 off_store_install_allow_reason_, |
269 NumOffStoreInstallAllowReasons); | 267 NumOffStoreInstallAllowReasons); |
270 } else { | 268 } else { |
271 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OffStoreInstallDisallowed, | 269 UMA_HISTOGRAM_ENUMERATION(kHistogramName, OffStoreInstallDisallowed, |
272 NumOffStoreInstallDecision); | 270 NumOffStoreInstallDecision); |
273 *error = l10n_util::GetStringUTF16( | |
274 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE); | |
275 // Don't delete source in this case so that the user can install | 271 // Don't delete source in this case so that the user can install |
276 // manually if they want. | 272 // manually if they want. |
277 delete_source_ = false; | 273 delete_source_ = false; |
278 did_handle_successfully_ = false; | 274 did_handle_successfully_ = false; |
279 return false; | 275 |
| 276 return CrxInstallerError( |
| 277 CrxInstallerError::ERROR_OFF_STORE, |
| 278 l10n_util::GetStringUTF16( |
| 279 IDS_EXTENSION_INSTALL_DISALLOWED_ON_SITE)); |
280 } | 280 } |
281 } | 281 } |
282 } | 282 } |
283 | 283 |
284 if (extension_->is_app()) { | 284 if (extension_->is_app()) { |
285 // If the app was downloaded, apps_require_extension_mime_type_ | 285 // If the app was downloaded, apps_require_extension_mime_type_ |
286 // will be set. In this case, check that it was served with the | 286 // will be set. In this case, check that it was served with the |
287 // right mime type. Make an exception for file URLs, which come | 287 // right mime type. Make an exception for file URLs, which come |
288 // from the users computer and have no headers. | 288 // from the users computer and have no headers. |
289 if (!download_url_.SchemeIsFile() && | 289 if (!download_url_.SchemeIsFile() && |
290 apps_require_extension_mime_type_ && | 290 apps_require_extension_mime_type_ && |
291 original_mime_type_ != Extension::kMimeType) { | 291 original_mime_type_ != Extension::kMimeType) { |
292 *error = l10n_util::GetStringFUTF16( | 292 return CrxInstallerError( |
293 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE, | 293 l10n_util::GetStringFUTF16( |
294 ASCIIToUTF16(Extension::kMimeType)); | 294 IDS_EXTENSION_INSTALL_INCORRECT_APP_CONTENT_TYPE, |
295 return false; | 295 ASCIIToUTF16(Extension::kMimeType))); |
296 } | 296 } |
297 | 297 |
298 // If the client_ is NULL, then the app is either being installed via | 298 // If the client_ is NULL, then the app is either being installed via |
299 // an internal mechanism like sync, external_extensions, or default apps. | 299 // an internal mechanism like sync, external_extensions, or default apps. |
300 // In that case, we don't want to enforce things like the install origin. | 300 // In that case, we don't want to enforce things like the install origin. |
301 if (!is_gallery_install() && client_) { | 301 if (!is_gallery_install() && client_) { |
302 // For apps with a gallery update URL, require that they be installed | 302 // For apps with a gallery update URL, require that they be installed |
303 // from the gallery. | 303 // from the gallery. |
304 // TODO(erikkay) Apply this rule for paid extensions and themes as well. | 304 // TODO(erikkay) Apply this rule for paid extensions and themes as well. |
305 if (extension->UpdatesFromGallery()) { | 305 if (extension->UpdatesFromGallery()) { |
306 *error = l10n_util::GetStringFUTF16( | 306 return CrxInstallerError( |
307 IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS, | 307 l10n_util::GetStringFUTF16( |
308 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)); | 308 IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS, |
309 return false; | 309 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE))); |
310 } | 310 } |
311 | 311 |
312 // For self-hosted apps, verify that the entire extent is on the same | 312 // For self-hosted apps, verify that the entire extent is on the same |
313 // host (or a subdomain of the host) the download happened from. There's | 313 // host (or a subdomain of the host) the download happened from. There's |
314 // no way for us to verify that the app controls any other hosts. | 314 // no way for us to verify that the app controls any other hosts. |
315 URLPattern pattern(UserScript::kValidUserScriptSchemes); | 315 URLPattern pattern(UserScript::kValidUserScriptSchemes); |
316 pattern.SetHost(download_url_.host()); | 316 pattern.SetHost(download_url_.host()); |
317 pattern.SetMatchSubdomains(true); | 317 pattern.SetMatchSubdomains(true); |
318 | 318 |
319 URLPatternSet patterns = extension_->web_extent(); | 319 URLPatternSet patterns = extension_->web_extent(); |
320 for (URLPatternSet::const_iterator i = patterns.begin(); | 320 for (URLPatternSet::const_iterator i = patterns.begin(); |
321 i != patterns.end(); ++i) { | 321 i != patterns.end(); ++i) { |
322 if (!pattern.MatchesHost(i->host())) { | 322 if (!pattern.MatchesHost(i->host())) { |
323 *error = l10n_util::GetStringUTF16( | 323 return CrxInstallerError( |
324 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST); | 324 l10n_util::GetStringUTF16( |
325 return false; | 325 IDS_EXTENSION_INSTALL_INCORRECT_INSTALL_HOST)); |
326 } | 326 } |
327 } | 327 } |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 return true; | 331 return CrxInstallerError(); |
332 } | 332 } |
333 | 333 |
334 void CrxInstaller::OnUnpackFailure(const string16& error_message) { | 334 void CrxInstaller::OnUnpackFailure(const string16& error_message) { |
335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
336 | 336 |
337 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallSource", | 337 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallSource", |
338 install_source(), Extension::NUM_LOCATIONS); | 338 install_source(), Extension::NUM_LOCATIONS); |
339 | 339 |
340 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallCause", | 340 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallCause", |
341 install_cause(), | 341 install_cause(), |
342 extension_misc::NUM_INSTALL_CAUSES); | 342 extension_misc::NUM_INSTALL_CAUSES); |
343 | 343 |
344 ReportFailureFromFileThread(error_message); | 344 ReportFailureFromFileThread(CrxInstallerError(error_message)); |
345 } | 345 } |
346 | 346 |
347 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir, | 347 void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir, |
348 const FilePath& extension_dir, | 348 const FilePath& extension_dir, |
349 const DictionaryValue* original_manifest, | 349 const DictionaryValue* original_manifest, |
350 const Extension* extension) { | 350 const Extension* extension) { |
351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
352 | 352 |
353 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", | 353 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource", |
354 install_source(), Extension::NUM_LOCATIONS); | 354 install_source(), Extension::NUM_LOCATIONS); |
355 | 355 |
356 | 356 |
357 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", | 357 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallCause", |
358 install_cause(), | 358 install_cause(), |
359 extension_misc::NUM_INSTALL_CAUSES); | 359 extension_misc::NUM_INSTALL_CAUSES); |
360 | 360 |
361 // Note: We take ownership of |extension| and |temp_dir|. | 361 // Note: We take ownership of |extension| and |temp_dir|. |
362 extension_ = extension; | 362 extension_ = extension; |
363 temp_dir_ = temp_dir; | 363 temp_dir_ = temp_dir; |
364 | 364 |
365 if (original_manifest) | 365 if (original_manifest) |
366 original_manifest_.reset(original_manifest->DeepCopy()); | 366 original_manifest_.reset(original_manifest->DeepCopy()); |
367 | 367 |
368 // We don't have to delete the unpack dir explicity since it is a child of | 368 // We don't have to delete the unpack dir explicity since it is a child of |
369 // the temp dir. | 369 // the temp dir. |
370 unpacked_extension_root_ = extension_dir; | 370 unpacked_extension_root_ = extension_dir; |
371 | 371 |
372 string16 error; | 372 CrxInstallerError error = AllowInstall(extension); |
373 if (!AllowInstall(extension, &error)) { | 373 if (error.type() != CrxInstallerError::ERROR_NONE) { |
374 ReportFailureFromFileThread(error); | 374 ReportFailureFromFileThread(error); |
375 return; | 375 return; |
376 } | 376 } |
377 | 377 |
378 if (client_) { | 378 if (client_) { |
379 Extension::DecodeIcon(extension_.get(), | 379 Extension::DecodeIcon(extension_.get(), |
380 ExtensionIconSet::EXTENSION_ICON_LARGE, | 380 ExtensionIconSet::EXTENSION_ICON_LARGE, |
381 ExtensionIconSet::MATCH_BIGGER, | 381 ExtensionIconSet::MATCH_BIGGER, |
382 &install_icon_); | 382 &install_icon_); |
383 } | 383 } |
384 | 384 |
385 if (!BrowserThread::PostTask( | 385 if (!BrowserThread::PostTask( |
386 BrowserThread::UI, FROM_HERE, | 386 BrowserThread::UI, FROM_HERE, |
387 base::Bind(&CrxInstaller::ConfirmInstall, this))) | 387 base::Bind(&CrxInstaller::ConfirmInstall, this))) |
388 NOTREACHED(); | 388 NOTREACHED(); |
389 } | 389 } |
390 | 390 |
391 void CrxInstaller::ConfirmInstall() { | 391 void CrxInstaller::ConfirmInstall() { |
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
393 if (!frontend_weak_.get()) | 393 if (!frontend_weak_.get()) |
394 return; | 394 return; |
395 | 395 |
396 if (frontend_weak_->extension_prefs() | 396 if (frontend_weak_->extension_prefs() |
397 ->IsExtensionBlacklisted(extension_->id())) { | 397 ->IsExtensionBlacklisted(extension_->id())) { |
398 VLOG(1) << "This extension: " << extension_->id() | 398 VLOG(1) << "This extension: " << extension_->id() |
399 << " is blacklisted. Install failed."; | 399 << " is blacklisted. Install failed."; |
400 ReportFailureFromUIThread( | 400 ReportFailureFromUIThread( |
401 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_INSTALL_BLACKLISTED)); | 401 CrxInstallerError( |
| 402 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_INSTALL_BLACKLISTED))); |
402 return; | 403 return; |
403 } | 404 } |
404 | 405 |
405 string16 error; | 406 string16 error; |
406 if (!ExtensionSystem::Get(profile_)->management_policy()->UserMayLoad( | 407 if (!ExtensionSystem::Get(profile_)->management_policy()->UserMayLoad( |
407 extension_, &error)) { | 408 extension_, &error)) { |
408 ReportFailureFromUIThread(error); | 409 ReportFailureFromUIThread(CrxInstallerError(error)); |
409 return; | 410 return; |
410 } | 411 } |
411 | 412 |
412 GURL overlapping_url; | 413 GURL overlapping_url; |
413 const Extension* overlapping_extension = | 414 const Extension* overlapping_extension = |
414 frontend_weak_->extensions()-> | 415 frontend_weak_->extensions()-> |
415 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); | 416 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); |
416 if (overlapping_extension && | 417 if (overlapping_extension && |
417 overlapping_extension->id() != extension_->id()) { | 418 overlapping_extension->id() != extension_->id()) { |
418 ReportFailureFromUIThread(l10n_util::GetStringFUTF16( | 419 ReportFailureFromUIThread( |
419 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, | 420 CrxInstallerError( |
420 UTF8ToUTF16(overlapping_extension->name()))); | 421 l10n_util::GetStringFUTF16( |
| 422 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, |
| 423 UTF8ToUTF16(overlapping_extension->name())))); |
421 return; | 424 return; |
422 } | 425 } |
423 | 426 |
424 current_version_ = | 427 current_version_ = |
425 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); | 428 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); |
426 | 429 |
427 if (client_ && (!allow_silent_install_ || !approved_)) { | 430 if (client_ && (!allow_silent_install_ || !approved_)) { |
428 AddRef(); // Balanced in Proceed() and Abort(). | 431 AddRef(); // Balanced in Proceed() and Abort(). |
429 client_->ConfirmInstall(this, extension_.get()); | 432 client_->ConfirmInstall(this, extension_.get()); |
430 } else { | 433 } else { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 } | 470 } |
468 | 471 |
469 void CrxInstaller::CompleteInstall() { | 472 void CrxInstaller::CompleteInstall() { |
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
471 | 474 |
472 if (!current_version_.empty()) { | 475 if (!current_version_.empty()) { |
473 scoped_ptr<Version> current_version( | 476 scoped_ptr<Version> current_version( |
474 Version::GetVersionFromString(current_version_)); | 477 Version::GetVersionFromString(current_version_)); |
475 if (current_version->CompareTo(*(extension_->version())) > 0) { | 478 if (current_version->CompareTo(*(extension_->version())) > 0) { |
476 ReportFailureFromFileThread( | 479 ReportFailureFromFileThread( |
477 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_DOWNGRADE_VERSION)); | 480 CrxInstallerError( |
| 481 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_DOWNGRADE_VERSION))); |
478 return; | 482 return; |
479 } | 483 } |
480 } | 484 } |
481 | 485 |
482 // See how long extension install paths are. This is important on | 486 // See how long extension install paths are. This is important on |
483 // windows, because file operations may fail if the path to a file | 487 // windows, because file operations may fail if the path to a file |
484 // exceeds a small constant. See crbug.com/69693 . | 488 // exceeds a small constant. See crbug.com/69693 . |
485 UMA_HISTOGRAM_CUSTOM_COUNTS( | 489 UMA_HISTOGRAM_CUSTOM_COUNTS( |
486 "Extensions.CrxInstallDirPathLength", | 490 "Extensions.CrxInstallDirPathLength", |
487 install_directory_.value().length(), 0, 500, 100); | 491 install_directory_.value().length(), 0, 500, 100); |
488 | 492 |
489 FilePath version_dir = extension_file_util::InstallExtension( | 493 FilePath version_dir = extension_file_util::InstallExtension( |
490 unpacked_extension_root_, | 494 unpacked_extension_root_, |
491 extension_->id(), | 495 extension_->id(), |
492 extension_->VersionString(), | 496 extension_->VersionString(), |
493 install_directory_); | 497 install_directory_); |
494 if (version_dir.empty()) { | 498 if (version_dir.empty()) { |
495 ReportFailureFromFileThread( | 499 ReportFailureFromFileThread( |
496 l10n_util::GetStringUTF16( | 500 CrxInstallerError( |
497 IDS_EXTENSION_MOVE_DIRECTORY_TO_PROFILE_FAILED)); | 501 l10n_util::GetStringUTF16( |
| 502 IDS_EXTENSION_MOVE_DIRECTORY_TO_PROFILE_FAILED))); |
498 return; | 503 return; |
499 } | 504 } |
500 | 505 |
501 // This is lame, but we must reload the extension because absolute paths | 506 // This is lame, but we must reload the extension because absolute paths |
502 // inside the content scripts are established inside InitFromValue() and we | 507 // inside the content scripts are established inside InitFromValue() and we |
503 // just moved the extension. | 508 // just moved the extension. |
504 // TODO(aa): All paths to resources inside extensions should be created | 509 // TODO(aa): All paths to resources inside extensions should be created |
505 // lazily and based on the Extension's root path at that moment. | 510 // lazily and based on the Extension's root path at that moment. |
506 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing | 511 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing |
507 // with string16 | 512 // with string16 |
508 std::string error; | 513 std::string error; |
509 extension_ = extension_file_util::LoadExtension( | 514 extension_ = extension_file_util::LoadExtension( |
510 version_dir, | 515 version_dir, |
511 install_source_, | 516 install_source_, |
512 extension_->creation_flags() | Extension::REQUIRE_KEY, | 517 extension_->creation_flags() | Extension::REQUIRE_KEY, |
513 &error); | 518 &error); |
514 CHECK(error.empty()) << error; | 519 CHECK(error.empty()) << error; |
515 | 520 |
516 ReportSuccessFromFileThread(); | 521 ReportSuccessFromFileThread(); |
517 } | 522 } |
518 | 523 |
519 void CrxInstaller::ReportFailureFromFileThread(const string16& error) { | 524 void CrxInstaller::ReportFailureFromFileThread(const CrxInstallerError& error) { |
520 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
521 if (!BrowserThread::PostTask( | 526 if (!BrowserThread::PostTask( |
522 BrowserThread::UI, FROM_HERE, | 527 BrowserThread::UI, FROM_HERE, |
523 base::Bind(&CrxInstaller::ReportFailureFromUIThread, this, error))) | 528 base::Bind(&CrxInstaller::ReportFailureFromUIThread, this, error))) { |
524 NOTREACHED(); | 529 NOTREACHED(); |
| 530 } |
525 } | 531 } |
526 | 532 |
527 void CrxInstaller::ReportFailureFromUIThread(const string16& error) { | 533 void CrxInstaller::ReportFailureFromUIThread(const CrxInstallerError& error) { |
528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
529 | 535 |
530 content::NotificationService* service = | 536 content::NotificationService* service = |
531 content::NotificationService::current(); | 537 content::NotificationService::current(); |
532 service->Notify(chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | 538 service->Notify(chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
533 content::Source<CrxInstaller>(this), | 539 content::Source<CrxInstaller>(this), |
534 content::Details<const string16>(&error)); | 540 content::Details<const string16>(&error.message())); |
535 | 541 |
536 // This isn't really necessary, it is only used because unit tests expect to | 542 // This isn't really necessary, it is only used because unit tests expect to |
537 // see errors get reported via this interface. | 543 // see errors get reported via this interface. |
538 // | 544 // |
539 // TODO(aa): Need to go through unit tests and clean them up too, probably get | 545 // TODO(aa): Need to go through unit tests and clean them up too, probably get |
540 // rid of this line. | 546 // rid of this line. |
541 ExtensionErrorReporter::GetInstance()->ReportError(error, false); // quiet | 547 ExtensionErrorReporter::GetInstance()->ReportError( |
| 548 error.message(), false); // quiet |
542 | 549 |
543 if (client_) | 550 if (client_) |
544 client_->OnInstallFailure(error); | 551 client_->OnInstallFailure(error); |
545 | 552 |
546 NotifyCrxInstallComplete(NULL); | 553 NotifyCrxInstallComplete(NULL); |
547 } | 554 } |
548 | 555 |
549 void CrxInstaller::ReportSuccessFromFileThread() { | 556 void CrxInstaller::ReportSuccessFromFileThread() { |
550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
551 | 558 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 // Some users (such as the download shelf) need to know when a | 612 // Some users (such as the download shelf) need to know when a |
606 // CRXInstaller is done. Listening for the EXTENSION_* events | 613 // CRXInstaller is done. Listening for the EXTENSION_* events |
607 // is problematic because they don't know anything about the | 614 // is problematic because they don't know anything about the |
608 // extension before it is unpacked, so they cannot filter based | 615 // extension before it is unpacked, so they cannot filter based |
609 // on the extension. | 616 // on the extension. |
610 content::NotificationService::current()->Notify( | 617 content::NotificationService::current()->Notify( |
611 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 618 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
612 content::Source<CrxInstaller>(this), | 619 content::Source<CrxInstaller>(this), |
613 content::Details<const Extension>(extension)); | 620 content::Details<const Extension>(extension)); |
614 } | 621 } |
OLD | NEW |