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

Side by Side Diff: chrome/browser/extensions/crx_installer.cc

Issue 8890086: Issue 71980: Extensions code should use UTF-16 for user-visible Unicode strings (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 source_file_ = source_file; 186 source_file_ = source_file;
187 download_url_ = download_url; 187 download_url_ = download_url;
188 188
189 if (!BrowserThread::PostTask( 189 if (!BrowserThread::PostTask(
190 BrowserThread::FILE, FROM_HERE, 190 BrowserThread::FILE, FROM_HERE,
191 base::Bind(&CrxInstaller::ConvertUserScriptOnFileThread, this))) 191 base::Bind(&CrxInstaller::ConvertUserScriptOnFileThread, this)))
192 NOTREACHED(); 192 NOTREACHED();
193 } 193 }
194 194
195 void CrxInstaller::ConvertUserScriptOnFileThread() { 195 void CrxInstaller::ConvertUserScriptOnFileThread() {
196 std::string error; 196 string16 error;
197 scoped_refptr<Extension> extension = 197 scoped_refptr<Extension> extension =
198 ConvertUserScriptToExtension(source_file_, download_url_, &error); 198 ConvertUserScriptToExtension(source_file_, download_url_, &error);
199 if (!extension) { 199 if (!extension) {
200 ReportFailureFromFileThread(error); 200 ReportFailureFromFileThread(error);
201 return; 201 return;
202 } 202 }
203 203
204 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension); 204 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension);
205 } 205 }
206 206
207 void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) { 207 void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) {
208 if (!BrowserThread::PostTask( 208 if (!BrowserThread::PostTask(
209 BrowserThread::FILE, FROM_HERE, 209 BrowserThread::FILE, FROM_HERE,
210 base::Bind(&CrxInstaller::ConvertWebAppOnFileThread, this, web_app))) 210 base::Bind(&CrxInstaller::ConvertWebAppOnFileThread, this, web_app)))
211 NOTREACHED(); 211 NOTREACHED();
212 } 212 }
213 213
214 void CrxInstaller::ConvertWebAppOnFileThread( 214 void CrxInstaller::ConvertWebAppOnFileThread(
215 const WebApplicationInfo& web_app) { 215 const WebApplicationInfo& web_app) {
216 std::string error; 216 string16 error;
217 scoped_refptr<Extension> extension( 217 scoped_refptr<Extension> extension(
218 ConvertWebAppToExtension(web_app, base::Time::Now())); 218 ConvertWebAppToExtension(web_app, base::Time::Now()));
219 if (!extension) { 219 if (!extension) {
220 // Validation should have stopped any potential errors before getting here. 220 // Validation should have stopped any potential errors before getting here.
221 NOTREACHED() << "Could not convert web app to extension."; 221 NOTREACHED() << "Could not convert web app to extension.";
222 return; 222 return;
223 } 223 }
224 224
225 // TODO(aa): conversion data gets lost here :( 225 // TODO(aa): conversion data gets lost here :(
226 226
227 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension); 227 OnUnpackSuccess(extension->path(), extension->path(), NULL, extension);
228 } 228 }
229 229
230 bool CrxInstaller::AllowInstall(const Extension* extension, 230 bool CrxInstaller::AllowInstall(const Extension* extension,
231 std::string* error) { 231 string16* error) {
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
233 DCHECK(error); 233 DCHECK(error);
234 234
235 // Make sure the expected id matches. 235 // Make sure the expected id matches.
236 if (!expected_id_.empty() && expected_id_ != extension->id()) { 236 if (!expected_id_.empty() && expected_id_ != extension->id()) {
237 *error = base::StringPrintf( 237 *error = ASCIIToUTF16(base::StringPrintf(
238 "ID in new CRX manifest (%s) does not match expected id (%s)", 238 "ID in new CRX manifest (%s) does not match expected id (%s)",
239 extension->id().c_str(), 239 extension->id().c_str(),
240 expected_id_.c_str()); 240 expected_id_.c_str()));
241 return false; 241 return false;
242 } 242 }
243 243
244 if (expected_version_.get() && 244 if (expected_version_.get() &&
245 !expected_version_->Equals(*extension->version())) { 245 !expected_version_->Equals(*extension->version())) {
246 *error = base::StringPrintf( 246 *error = ASCIIToUTF16(base::StringPrintf(
247 "Version in new CRX %s manifest (%s) does not match expected " 247 "Version in new CRX %s manifest (%s) does not match expected "
248 "version (%s)", 248 "version (%s)",
249 extension->id().c_str(), 249 extension->id().c_str(),
250 expected_version_->GetString().c_str(), 250 expected_version_->GetString().c_str(),
251 extension->version()->GetString().c_str()); 251 extension->version()->GetString().c_str()));
252 return false; 252 return false;
253 } 253 }
254 254
255 // The checks below are skipped for themes and external installs. 255 // The checks below are skipped for themes and external installs.
256 if (extension->is_theme() || Extension::IsExternalLocation(install_source_)) 256 if (extension->is_theme() || Extension::IsExternalLocation(install_source_))
257 return true; 257 return true;
258 258
259 if (!extensions_enabled_) { 259 if (!extensions_enabled_) {
260 *error = "Extensions are not enabled."; 260 *error = ASCIIToUTF16("Extensions are not enabled.");
261 return false; 261 return false;
262 } 262 }
263 263
264 if (extension_->is_app()) { 264 if (extension_->is_app()) {
265 // If the app was downloaded, apps_require_extension_mime_type_ 265 // If the app was downloaded, apps_require_extension_mime_type_
266 // will be set. In this case, check that it was served with the 266 // will be set. In this case, check that it was served with the
267 // right mime type. Make an exception for file URLs, which come 267 // right mime type. Make an exception for file URLs, which come
268 // from the users computer and have no headers. 268 // from the users computer and have no headers.
269 if (!download_url_.SchemeIsFile() && 269 if (!download_url_.SchemeIsFile() &&
270 apps_require_extension_mime_type_ && 270 apps_require_extension_mime_type_ &&
271 original_mime_type_ != Extension::kMimeType) { 271 original_mime_type_ != Extension::kMimeType) {
272 *error = base::StringPrintf( 272 *error = ASCIIToUTF16(base::StringPrintf(
273 "Apps must be served with content type %s.", 273 "Apps must be served with content type %s.",
274 Extension::kMimeType); 274 Extension::kMimeType));
275 return false; 275 return false;
276 } 276 }
277 277
278 // If the client_ is NULL, then the app is either being installed via 278 // If the client_ is NULL, then the app is either being installed via
279 // an internal mechanism like sync, external_extensions, or default apps. 279 // an internal mechanism like sync, external_extensions, or default apps.
280 // In that case, we don't want to enforce things like the install origin. 280 // In that case, we don't want to enforce things like the install origin.
281 if (!is_gallery_install() && client_) { 281 if (!is_gallery_install() && client_) {
282 // For apps with a gallery update URL, require that they be installed 282 // For apps with a gallery update URL, require that they be installed
283 // from the gallery. 283 // from the gallery.
284 // TODO(erikkay) Apply this rule for paid extensions and themes as well. 284 // TODO(erikkay) Apply this rule for paid extensions and themes as well.
285 if (extension->UpdatesFromGallery()) { 285 if (extension->UpdatesFromGallery()) {
286 *error = l10n_util::GetStringFUTF8( 286 *error = l10n_util::GetStringFUTF16(
287 IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS, 287 IDS_EXTENSION_DISALLOW_NON_DOWNLOADED_GALLERY_INSTALLS,
288 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)); 288 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE));
289 return false; 289 return false;
290 } 290 }
291 291
292 // For self-hosted apps, verify that the entire extent is on the same 292 // For self-hosted apps, verify that the entire extent is on the same
293 // host (or a subdomain of the host) the download happened from. There's 293 // host (or a subdomain of the host) the download happened from. There's
294 // no way for us to verify that the app controls any other hosts. 294 // no way for us to verify that the app controls any other hosts.
295 URLPattern pattern(URLPattern::USE_PORTS, 295 URLPattern pattern(URLPattern::USE_PORTS,
296 UserScript::kValidUserScriptSchemes); 296 UserScript::kValidUserScriptSchemes);
297 pattern.SetHost(download_url_.host()); 297 pattern.SetHost(download_url_.host());
298 pattern.SetMatchSubdomains(true); 298 pattern.SetMatchSubdomains(true);
299 299
300 URLPatternSet patterns = extension_->web_extent(); 300 URLPatternSet patterns = extension_->web_extent();
301 for (URLPatternSet::const_iterator i = patterns.begin(); 301 for (URLPatternSet::const_iterator i = patterns.begin();
302 i != patterns.end(); ++i) { 302 i != patterns.end(); ++i) {
303 if (!pattern.MatchesHost(i->host())) { 303 if (!pattern.MatchesHost(i->host())) {
304 *error = base::StringPrintf( 304 *error = ASCIIToUTF16(base::StringPrintf(
305 "Apps must be served from the host that they affect."); 305 "Apps must be served from the host that they affect."));
306 return false; 306 return false;
307 } 307 }
308 } 308 }
309 } 309 }
310 } 310 }
311 311
312 return true; 312 return true;
313 } 313 }
314 314
315 void CrxInstaller::OnUnpackFailure(const std::string& error_message) { 315 void CrxInstaller::OnUnpackFailure(const string16& error_message) {
316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
317 317
318 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallSource", 318 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallSource",
319 install_source(), Extension::NUM_LOCATIONS); 319 install_source(), Extension::NUM_LOCATIONS);
320 320
321 321
322 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallCause", 322 UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallCause",
323 install_cause(), 323 install_cause(),
324 extension_misc::NUM_INSTALL_CAUSES); 324 extension_misc::NUM_INSTALL_CAUSES);
325 325
(...skipping 18 matching lines...) Expand all
344 extension_ = extension; 344 extension_ = extension;
345 temp_dir_ = temp_dir; 345 temp_dir_ = temp_dir;
346 346
347 if (original_manifest) 347 if (original_manifest)
348 original_manifest_.reset(original_manifest->DeepCopy()); 348 original_manifest_.reset(original_manifest->DeepCopy());
349 349
350 // We don't have to delete the unpack dir explicity since it is a child of 350 // We don't have to delete the unpack dir explicity since it is a child of
351 // the temp dir. 351 // the temp dir.
352 unpacked_extension_root_ = extension_dir; 352 unpacked_extension_root_ = extension_dir;
353 353
354 std::string error; 354 string16 error;
355 if (!AllowInstall(extension, &error)) { 355 if (!AllowInstall(extension, &error)) {
356 ReportFailureFromFileThread(error); 356 ReportFailureFromFileThread(error);
357 return; 357 return;
358 } 358 }
359 359
360 if (client_) { 360 if (client_) {
361 Extension::DecodeIcon(extension_.get(), Extension::EXTENSION_ICON_LARGE, 361 Extension::DecodeIcon(extension_.get(), Extension::EXTENSION_ICON_LARGE,
362 &install_icon_); 362 &install_icon_);
363 } 363 }
364 364
365 if (!BrowserThread::PostTask( 365 if (!BrowserThread::PostTask(
366 BrowserThread::UI, FROM_HERE, 366 BrowserThread::UI, FROM_HERE,
367 base::Bind(&CrxInstaller::ConfirmInstall, this))) 367 base::Bind(&CrxInstaller::ConfirmInstall, this)))
368 NOTREACHED(); 368 NOTREACHED();
369 } 369 }
370 370
371 void CrxInstaller::ConfirmInstall() { 371 void CrxInstaller::ConfirmInstall() {
372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
373 if (!frontend_weak_.get()) 373 if (!frontend_weak_.get())
374 return; 374 return;
375 375
376 if (frontend_weak_->extension_prefs() 376 if (frontend_weak_->extension_prefs()
377 ->IsExtensionBlacklisted(extension_->id())) { 377 ->IsExtensionBlacklisted(extension_->id())) {
378 VLOG(1) << "This extension: " << extension_->id() 378 VLOG(1) << "This extension: " << extension_->id()
379 << " is blacklisted. Install failed."; 379 << " is blacklisted. Install failed.";
380 ReportFailureFromUIThread( 380 ReportFailureFromUIThread(
381 l10n_util::GetStringUTF8(IDS_EXTENSION_CANT_INSTALL_BLACKLISTED)); 381 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_INSTALL_BLACKLISTED));
382 return; 382 return;
383 } 383 }
384 384
385 if (!frontend_weak_->extension_prefs()->IsExtensionAllowedByPolicy( 385 if (!frontend_weak_->extension_prefs()->IsExtensionAllowedByPolicy(
386 extension_->id(), install_source_)) { 386 extension_->id(), install_source_)) {
387 ReportFailureFromUIThread( 387 ReportFailureFromUIThread(
388 l10n_util::GetStringUTF8(IDS_EXTENSION_CANT_INSTALL_POLICY_BLACKLIST)); 388 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_INSTALL_POLICY_BLACKLIST));
389 return; 389 return;
390 } 390 }
391 391
392 GURL overlapping_url; 392 GURL overlapping_url;
393 const Extension* overlapping_extension = 393 const Extension* overlapping_extension =
394 frontend_weak_->extensions()-> 394 frontend_weak_->extensions()->
395 GetHostedAppByOverlappingWebExtent(extension_->web_extent()); 395 GetHostedAppByOverlappingWebExtent(extension_->web_extent());
396 if (overlapping_extension && 396 if (overlapping_extension &&
397 overlapping_extension->id() != extension_->id()) { 397 overlapping_extension->id() != extension_->id()) {
398 ReportFailureFromUIThread(l10n_util::GetStringFUTF8( 398 ReportFailureFromUIThread(l10n_util::GetStringFUTF16(
399 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT, 399 IDS_EXTENSION_OVERLAPPING_WEB_EXTENT,
400 UTF8ToUTF16(overlapping_extension->name()))); 400 UTF8ToUTF16(overlapping_extension->name())));
401 return; 401 return;
402 } 402 }
403 403
404 current_version_ = 404 current_version_ =
405 frontend_weak_->extension_prefs()->GetVersionString(extension_->id()); 405 frontend_weak_->extension_prefs()->GetVersionString(extension_->id());
406 406
407 // TODO(asargent) - remove this when we fully deprecate the old install api. 407 // TODO(asargent) - remove this when we fully deprecate the old install api.
408 ClearWhitelistedInstallId(extension_->id()); 408 ClearWhitelistedInstallId(extension_->id());
409 409
410 bool whitelisted = false; 410 bool whitelisted = false;
411 scoped_ptr<CrxInstaller::WhitelistEntry> entry( 411 scoped_ptr<CrxInstaller::WhitelistEntry> entry(
412 RemoveWhitelistEntry(extension_->id())); 412 RemoveWhitelistEntry(extension_->id()));
413 if (is_gallery_install() && entry.get() && original_manifest_.get()) { 413 if (is_gallery_install() && entry.get() && original_manifest_.get()) {
414 if (!(original_manifest_->Equals(entry->parsed_manifest.get()))) { 414 if (!(original_manifest_->Equals(entry->parsed_manifest.get()))) {
415 ReportFailureFromUIThread( 415 ReportFailureFromUIThread(
416 l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID)); 416 l10n_util::GetStringUTF16(IDS_EXTENSION_MANIFEST_INVALID));
417 return; 417 return;
418 } 418 }
419 whitelisted = true; 419 whitelisted = true;
420 if (entry->use_app_installed_bubble) 420 if (entry->use_app_installed_bubble)
421 client_->set_use_app_installed_bubble(true); 421 client_->set_use_app_installed_bubble(true);
422 if (entry->skip_post_install_ui) 422 if (entry->skip_post_install_ui)
423 client_->set_skip_post_install_ui(true); 423 client_->set_skip_post_install_ui(true);
424 } 424 }
425 425
426 if (client_ && 426 if (client_ &&
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 } 467 }
468 468
469 void CrxInstaller::CompleteInstall() { 469 void CrxInstaller::CompleteInstall() {
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
471 471
472 if (!current_version_.empty()) { 472 if (!current_version_.empty()) {
473 scoped_ptr<Version> current_version( 473 scoped_ptr<Version> current_version(
474 Version::GetVersionFromString(current_version_)); 474 Version::GetVersionFromString(current_version_));
475 if (current_version->CompareTo(*(extension_->version())) > 0) { 475 if (current_version->CompareTo(*(extension_->version())) > 0) {
476 ReportFailureFromFileThread( 476 ReportFailureFromFileThread(
477 l10n_util::GetStringUTF8(IDS_EXTENSION_CANT_DOWNGRADE_VERSION)); 477 l10n_util::GetStringUTF16(IDS_EXTENSION_CANT_DOWNGRADE_VERSION));
478 return; 478 return;
479 } 479 }
480 } 480 }
481 481
482 // See how long extension install paths are. This is important on 482 // See how long extension install paths are. This is important on
483 // windows, because file operations may fail if the path to a file 483 // windows, because file operations may fail if the path to a file
484 // exceeds a small constant. See crbug.com/69693 . 484 // exceeds a small constant. See crbug.com/69693 .
485 UMA_HISTOGRAM_CUSTOM_COUNTS( 485 UMA_HISTOGRAM_CUSTOM_COUNTS(
486 "Extensions.CrxInstallDirPathLength", 486 "Extensions.CrxInstallDirPathLength",
487 install_directory_.value().length(), 0, 500, 100); 487 install_directory_.value().length(), 0, 500, 100);
488 488
489 FilePath version_dir = extension_file_util::InstallExtension( 489 FilePath version_dir = extension_file_util::InstallExtension(
490 unpacked_extension_root_, 490 unpacked_extension_root_,
491 extension_->id(), 491 extension_->id(),
492 extension_->VersionString(), 492 extension_->VersionString(),
493 install_directory_); 493 install_directory_);
494 if (version_dir.empty()) { 494 if (version_dir.empty()) {
495 ReportFailureFromFileThread( 495 ReportFailureFromFileThread(
496 l10n_util::GetStringUTF8( 496 l10n_util::GetStringUTF16(
497 IDS_EXTENSION_MOVE_DIRECTORY_TO_PROFILE_FAILED)); 497 IDS_EXTENSION_MOVE_DIRECTORY_TO_PROFILE_FAILED));
498 return; 498 return;
499 } 499 }
500 500
501 // This is lame, but we must reload the extension because absolute paths 501 // This is lame, but we must reload the extension because absolute paths
502 // inside the content scripts are established inside InitFromValue() and we 502 // inside the content scripts are established inside InitFromValue() and we
503 // just moved the extension. 503 // just moved the extension.
504 // TODO(aa): All paths to resources inside extensions should be created 504 // TODO(aa): All paths to resources inside extensions should be created
505 // lazily and based on the Extension's root path at that moment. 505 // lazily and based on the Extension's root path at that moment.
506 // TODO(rdevlin.cronin): Continue removing std::string errors and replacing
507 // with string16
506 std::string error; 508 std::string error;
507 extension_ = extension_file_util::LoadExtension( 509 extension_ = extension_file_util::LoadExtension(
508 version_dir, 510 version_dir,
509 install_source_, 511 install_source_,
510 extension_->creation_flags() | Extension::REQUIRE_KEY, 512 extension_->creation_flags() | Extension::REQUIRE_KEY,
511 &error); 513 &error);
512 CHECK(error.empty()) << error; 514 CHECK(error.empty()) << error;
513 515
514 ReportSuccessFromFileThread(); 516 ReportSuccessFromFileThread();
515 } 517 }
516 518
517 void CrxInstaller::ReportFailureFromFileThread(const std::string& error) { 519 void CrxInstaller::ReportFailureFromFileThread(const string16& error) {
518 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 520 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
519 if (!BrowserThread::PostTask( 521 if (!BrowserThread::PostTask(
520 BrowserThread::UI, FROM_HERE, 522 BrowserThread::UI, FROM_HERE,
521 base::Bind(&CrxInstaller::ReportFailureFromUIThread, this, error))) 523 base::Bind(&CrxInstaller::ReportFailureFromUIThread, this, error)))
522 NOTREACHED(); 524 NOTREACHED();
523 } 525 }
524 526
525 void CrxInstaller::ReportFailureFromUIThread(const std::string& error) { 527 void CrxInstaller::ReportFailureFromUIThread(const string16& error) {
526 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
527 529
528 content::NotificationService* service = 530 content::NotificationService* service =
529 content::NotificationService::current(); 531 content::NotificationService::current();
530 service->Notify(chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 532 service->Notify(chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
531 content::Source<CrxInstaller>(this), 533 content::Source<CrxInstaller>(this),
532 content::Details<const std::string>(&error)); 534 content::Details<const string16>(&error));
533 535
534 // This isn't really necessary, it is only used because unit tests expect to 536 // This isn't really necessary, it is only used because unit tests expect to
535 // see errors get reported via this interface. 537 // see errors get reported via this interface.
536 // 538 //
537 // TODO(aa): Need to go through unit tests and clean them up too, probably get 539 // TODO(aa): Need to go through unit tests and clean them up too, probably get
538 // rid of this line. 540 // rid of this line.
539 ExtensionErrorReporter::GetInstance()->ReportError(error, false); // quiet 541 ExtensionErrorReporter::GetInstance()->ReportError(error, false); // quiet
540 542
541 if (client_) 543 if (client_)
542 client_->OnInstallFailure(error); 544 client_->OnInstallFailure(error);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 // Some users (such as the download shelf) need to know when a 603 // Some users (such as the download shelf) need to know when a
602 // CRXInstaller is done. Listening for the EXTENSION_* events 604 // CRXInstaller is done. Listening for the EXTENSION_* events
603 // is problematic because they don't know anything about the 605 // is problematic because they don't know anything about the
604 // extension before it is unpacked, so they cannot filter based 606 // extension before it is unpacked, so they cannot filter based
605 // on the extension. 607 // on the extension.
606 content::NotificationService::current()->Notify( 608 content::NotificationService::current()->Notify(
607 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 609 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
608 content::Source<CrxInstaller>(this), 610 content::Source<CrxInstaller>(this),
609 content::Details<const Extension>(extension)); 611 content::Details<const Extension>(extension));
610 } 612 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/crx_installer.h ('k') | chrome/browser/extensions/crx_installer_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698