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

Side by Side Diff: chrome/browser/ui/views/create_application_shortcut_view.cc

Issue 1038573002: Fixed thread-unsafe use of gfx::Image in app shortcut creation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 5 years, 8 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
OLDNEW
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/ui/views/create_application_shortcut_view.h" 5 #include "chrome/browser/ui/views/create_application_shortcut_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 } 245 }
246 246
247 } // namespace chrome 247 } // namespace chrome
248 248
249 CreateApplicationShortcutView::CreateApplicationShortcutView(Profile* profile) 249 CreateApplicationShortcutView::CreateApplicationShortcutView(Profile* profile)
250 : profile_(profile), 250 : profile_(profile),
251 app_info_(NULL), 251 app_info_(NULL),
252 create_shortcuts_label_(NULL), 252 create_shortcuts_label_(NULL),
253 desktop_check_box_(NULL), 253 desktop_check_box_(NULL),
254 menu_check_box_(NULL), 254 menu_check_box_(NULL),
255 quick_launch_check_box_(NULL) {} 255 quick_launch_check_box_(NULL) {
256 }
256 257
257 CreateApplicationShortcutView::~CreateApplicationShortcutView() {} 258 CreateApplicationShortcutView::~CreateApplicationShortcutView() {}
258 259
259 void CreateApplicationShortcutView::InitControls(DialogLayout dialog_layout) { 260 void CreateApplicationShortcutView::InitControls(DialogLayout dialog_layout) {
260 if (dialog_layout == DIALOG_LAYOUT_URL_SHORTCUT) { 261 if (dialog_layout == DIALOG_LAYOUT_URL_SHORTCUT && shortcut_info_) {
261 app_info_ = new AppInfoView(shortcut_info_.title, 262 app_info_ =
262 shortcut_info_.description, 263 new AppInfoView(shortcut_info_->title, shortcut_info_->description,
263 shortcut_info_.favicon); 264 shortcut_info_->favicon);
264 } 265 }
265 create_shortcuts_label_ = new views::Label( 266 create_shortcuts_label_ = new views::Label(
266 l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_LABEL)); 267 l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_LABEL));
267 create_shortcuts_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 268 create_shortcuts_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
268 269
269 desktop_check_box_ = AddCheckbox( 270 desktop_check_box_ = AddCheckbox(
270 l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX), 271 l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX),
271 profile_->GetPrefs()->GetBoolean(prefs::kWebAppCreateOnDesktop)); 272 profile_->GetPrefs()->GetBoolean(prefs::kWebAppCreateOnDesktop));
272 273
273 menu_check_box_ = NULL; 274 menu_check_box_ = NULL;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 364
364 ui::ModalType CreateApplicationShortcutView::GetModalType() const { 365 ui::ModalType CreateApplicationShortcutView::GetModalType() const {
365 return ui::MODAL_TYPE_WINDOW; 366 return ui::MODAL_TYPE_WINDOW;
366 } 367 }
367 368
368 base::string16 CreateApplicationShortcutView::GetWindowTitle() const { 369 base::string16 CreateApplicationShortcutView::GetWindowTitle() const {
369 return l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_TITLE); 370 return l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_TITLE);
370 } 371 }
371 372
372 bool CreateApplicationShortcutView::Accept() { 373 bool CreateApplicationShortcutView::Accept() {
374 // NOTE: This procedure will reset |shortcut_info_| to null.
375
376 // Can happen if the shortcut data is not yet loaded.
377 if (!shortcut_info_)
378 return false;
379
373 if (!IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)) 380 if (!IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK))
374 return false; 381 return false;
375 382
376 web_app::ShortcutLocations creation_locations; 383 web_app::ShortcutLocations creation_locations;
377 creation_locations.on_desktop = desktop_check_box_->checked(); 384 creation_locations.on_desktop = desktop_check_box_->checked();
378 if (menu_check_box_ != NULL && menu_check_box_->checked()) { 385 if (menu_check_box_ != NULL && menu_check_box_->checked()) {
379 creation_locations.applications_menu_location = 386 creation_locations.applications_menu_location =
380 create_in_chrome_apps_subdir_ ? 387 create_in_chrome_apps_subdir_ ?
381 web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS : 388 web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS :
382 web_app::APP_MENU_LOCATION_ROOT; 389 web_app::APP_MENU_LOCATION_ROOT;
383 } 390 }
384 391
385 #if defined(OS_WIN) 392 #if defined(OS_WIN)
386 creation_locations.in_quick_launch_bar = quick_launch_check_box_ == NULL ? 393 creation_locations.in_quick_launch_bar = quick_launch_check_box_ == NULL ?
387 NULL : quick_launch_check_box_->checked(); 394 NULL : quick_launch_check_box_->checked();
388 #elif defined(OS_POSIX) 395 #elif defined(OS_POSIX)
389 // Create shortcut in Mac dock or as Linux (gnome/kde) application launcher 396 // Create shortcut in Mac dock or as Linux (gnome/kde) application launcher
390 // are not implemented yet. 397 // are not implemented yet.
391 creation_locations.in_quick_launch_bar = false; 398 creation_locations.in_quick_launch_bar = false;
392 #endif 399 #endif
393 400
394 web_app::CreateShortcutsWithInfo(web_app::SHORTCUT_CREATION_BY_USER, 401 web_app::CreateShortcutsWithInfo(web_app::SHORTCUT_CREATION_BY_USER,
395 creation_locations, 402 creation_locations, shortcut_info_.Pass(),
396 shortcut_info_,
397 file_handlers_info_); 403 file_handlers_info_);
398 return true; 404 return true;
399 } 405 }
400 406
401 views::Checkbox* CreateApplicationShortcutView::AddCheckbox( 407 views::Checkbox* CreateApplicationShortcutView::AddCheckbox(
402 const base::string16& text, bool checked) { 408 const base::string16& text, bool checked) {
403 views::Checkbox* checkbox = new views::Checkbox(text); 409 views::Checkbox* checkbox = new views::Checkbox(text);
404 checkbox->SetChecked(checked); 410 checkbox->SetChecked(checked);
405 checkbox->set_listener(this); 411 checkbox->set_listener(this);
406 return checkbox; 412 return checkbox;
(...skipping 16 matching lines...) Expand all
423 GetDialogClientView()->UpdateDialogButtons(); 429 GetDialogClientView()->UpdateDialogButtons();
424 } 430 }
425 431
426 CreateUrlApplicationShortcutView::CreateUrlApplicationShortcutView( 432 CreateUrlApplicationShortcutView::CreateUrlApplicationShortcutView(
427 content::WebContents* web_contents) 433 content::WebContents* web_contents)
428 : CreateApplicationShortcutView( 434 : CreateApplicationShortcutView(
429 Profile::FromBrowserContext(web_contents->GetBrowserContext())), 435 Profile::FromBrowserContext(web_contents->GetBrowserContext())),
430 web_contents_(web_contents), 436 web_contents_(web_contents),
431 pending_download_id_(-1), 437 pending_download_id_(-1),
432 weak_ptr_factory_(this) { 438 weak_ptr_factory_(this) {
433 web_app::GetShortcutInfoForTab(web_contents_, &shortcut_info_); 439 shortcut_info_ = web_app::GetShortcutInfoForTab(web_contents_);
434 const WebApplicationInfo& app_info = 440 const WebApplicationInfo& app_info =
435 extensions::TabHelper::FromWebContents(web_contents_)->web_app_info(); 441 extensions::TabHelper::FromWebContents(web_contents_)->web_app_info();
436 if (!app_info.icons.empty()) { 442 if (!app_info.icons.empty()) {
437 web_app::GetIconsInfo(app_info, &unprocessed_icons_); 443 web_app::GetIconsInfo(app_info, &unprocessed_icons_);
438 FetchIcon(); 444 FetchIcon();
439 } 445 }
440 446
441 // Create URL app shortcuts in the top-level menu. 447 // Create URL app shortcuts in the top-level menu.
442 create_in_chrome_apps_subdir_ = false; 448 create_in_chrome_apps_subdir_ = false;
443 449
444 InitControls(DIALOG_LAYOUT_URL_SHORTCUT); 450 InitControls(DIALOG_LAYOUT_URL_SHORTCUT);
445 } 451 }
446 452
447 CreateUrlApplicationShortcutView::~CreateUrlApplicationShortcutView() { 453 CreateUrlApplicationShortcutView::~CreateUrlApplicationShortcutView() {
448 } 454 }
449 455
450 bool CreateUrlApplicationShortcutView::Accept() { 456 bool CreateUrlApplicationShortcutView::Accept() {
457 // Get the smallest icon in the icon family (should have only 1). This must be
458 // done before the call to Accept(), which will reset |shortcut_info_|.
459 DCHECK(shortcut_info_);
460 const gfx::Image* icon = shortcut_info_->favicon.GetBest(0, 0);
461 SkBitmap bitmap = icon ? icon->AsBitmap() : SkBitmap();
462
451 if (!CreateApplicationShortcutView::Accept()) 463 if (!CreateApplicationShortcutView::Accept())
452 return false; 464 return false;
453 465
454 // Get the smallest icon in the icon family (should have only 1).
455 const gfx::Image* icon = shortcut_info_.favicon.GetBest(0, 0);
456 SkBitmap bitmap = icon ? icon->AsBitmap() : SkBitmap();
457 extensions::TabHelper::FromWebContents(web_contents_)->SetAppIcon(bitmap); 466 extensions::TabHelper::FromWebContents(web_contents_)->SetAppIcon(bitmap);
458 Browser* browser = chrome::FindBrowserWithWebContents(web_contents_); 467 Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
459 if (browser) 468 if (browser)
460 chrome::ConvertTabToAppWindow(browser, web_contents_); 469 chrome::ConvertTabToAppWindow(browser, web_contents_);
461 return true; 470 return true;
462 } 471 }
463 472
464 void CreateUrlApplicationShortcutView::FetchIcon() { 473 void CreateUrlApplicationShortcutView::FetchIcon() {
465 // There should only be fetch job at a time. 474 // There should only be fetch job at a time.
466 DCHECK_EQ(-1, pending_download_id_); 475 DCHECK_EQ(-1, pending_download_id_);
(...skipping 18 matching lines...) Expand all
485 int requested_size, 494 int requested_size,
486 int id, 495 int id,
487 int http_status_code, 496 int http_status_code,
488 const GURL& image_url, 497 const GURL& image_url,
489 const std::vector<SkBitmap>& bitmaps, 498 const std::vector<SkBitmap>& bitmaps,
490 const std::vector<gfx::Size>& original_bitmap_sizes) { 499 const std::vector<gfx::Size>& original_bitmap_sizes) {
491 if (id != pending_download_id_) 500 if (id != pending_download_id_)
492 return; 501 return;
493 pending_download_id_ = -1; 502 pending_download_id_ = -1;
494 503
504 // Can happen if the dialog has already been accepted.
505 if (!shortcut_info_)
506 return;
507
495 gfx::ImageSkia image_skia = CreateFaviconImageSkia( 508 gfx::ImageSkia image_skia = CreateFaviconImageSkia(
496 bitmaps, 509 bitmaps,
497 original_bitmap_sizes, 510 original_bitmap_sizes,
498 requested_size, 511 requested_size,
499 NULL); 512 NULL);
500 if (!image_skia.isNull()) { 513 if (!image_skia.isNull()) {
501 // As |shortcut_info_| will be passed to the FILE thread upon accepting the 514 // As |shortcut_info_| will be passed to the FILE thread upon accepting the
502 // dialog, this image must be made read-only and thread-safe. 515 // dialog, this image must be made read-only and thread-safe.
503 image_skia.MakeThreadSafe(); 516 image_skia.MakeThreadSafe();
504 shortcut_info_.favicon.Add(image_skia); 517 shortcut_info_->favicon.Add(image_skia);
505 static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); 518 static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_->favicon);
506 } else { 519 } else {
507 FetchIcon(); 520 FetchIcon();
508 } 521 }
509 } 522 }
510 523
511 CreateChromeApplicationShortcutView::CreateChromeApplicationShortcutView( 524 CreateChromeApplicationShortcutView::CreateChromeApplicationShortcutView(
512 Profile* profile, 525 Profile* profile,
513 const extensions::Extension* app, 526 const extensions::Extension* app,
514 const base::Callback<void(bool)>& close_callback) 527 const base::Callback<void(bool)>& close_callback)
515 : CreateApplicationShortcutView(profile), 528 : CreateApplicationShortcutView(profile),
(...skipping 21 matching lines...) Expand all
537 return CreateApplicationShortcutView::Accept(); 550 return CreateApplicationShortcutView::Accept();
538 } 551 }
539 552
540 bool CreateChromeApplicationShortcutView::Cancel() { 553 bool CreateChromeApplicationShortcutView::Cancel() {
541 if (!close_callback_.is_null()) 554 if (!close_callback_.is_null())
542 close_callback_.Run(false); 555 close_callback_.Run(false);
543 return CreateApplicationShortcutView::Cancel(); 556 return CreateApplicationShortcutView::Cancel();
544 } 557 }
545 558
546 void CreateChromeApplicationShortcutView::OnAppInfoLoaded( 559 void CreateChromeApplicationShortcutView::OnAppInfoLoaded(
547 const web_app::ShortcutInfo& shortcut_info, 560 scoped_ptr<web_app::ShortcutInfo> shortcut_info,
548 const extensions::FileHandlersInfo& file_handlers_info) { 561 const extensions::FileHandlersInfo& file_handlers_info) {
549 shortcut_info_ = shortcut_info; 562 shortcut_info_ = shortcut_info.Pass();
550 file_handlers_info_ = file_handlers_info; 563 file_handlers_info_ = file_handlers_info;
551 } 564 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698