| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/views/create_application_shortcut_view.h" | 5 #include "chrome/browser/views/create_application_shortcut_view.h" |
| 6 | 6 |
| 7 #include "app/gfx/canvas.h" | 7 #include "app/gfx/canvas.h" |
| 8 #include "app/gfx/codec/png_codec.h" | 8 #include "app/gfx/codec/png_codec.h" |
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "views/window/window.h" | 28 #include "views/window/window.h" |
| 29 | 29 |
| 30 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
| 31 #include "base/win_util.h" | 31 #include "base/win_util.h" |
| 32 #endif // defined(OS_WIN) | 32 #endif // defined(OS_WIN) |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 const int kAppIconSize = 32; | 36 const int kAppIconSize = 32; |
| 37 | 37 |
| 38 bool IconPrecedes( | |
| 39 const webkit_glue::WebApplicationInfo::IconInfo& left, | |
| 40 const webkit_glue::WebApplicationInfo::IconInfo& right) { | |
| 41 return left.width < right.width; | |
| 42 } | |
| 43 | |
| 44 // AppInfoView shows the application icon and title. | 38 // AppInfoView shows the application icon and title. |
| 45 class AppInfoView : public views::View { | 39 class AppInfoView : public views::View { |
| 46 public: | 40 public: |
| 47 AppInfoView(const string16& title, | 41 AppInfoView(const string16& title, |
| 48 const string16& description, | 42 const string16& description, |
| 49 const SkBitmap& icon); | 43 const SkBitmap& icon); |
| 50 | 44 |
| 51 // Updates the title/description of the web app. | 45 // Updates the title/description of the web app. |
| 52 void UpdateText(const string16& title, const string16& description); | 46 void UpdateText(const string16& title, const string16& description); |
| 53 | 47 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 namespace browser { | 190 namespace browser { |
| 197 | 191 |
| 198 void ShowCreateShortcutsDialog(gfx::NativeWindow parent_window, | 192 void ShowCreateShortcutsDialog(gfx::NativeWindow parent_window, |
| 199 TabContents* tab_contents) { | 193 TabContents* tab_contents) { |
| 200 views::Window::CreateChromeWindow(parent_window, gfx::Rect(), | 194 views::Window::CreateChromeWindow(parent_window, gfx::Rect(), |
| 201 new CreateApplicationShortcutView(tab_contents))->Show(); | 195 new CreateApplicationShortcutView(tab_contents))->Show(); |
| 202 } | 196 } |
| 203 | 197 |
| 204 }; // namespace browser | 198 }; // namespace browser |
| 205 | 199 |
| 200 class CreateApplicationShortcutView::IconDownloadCallbackFunctor { |
| 201 public: |
| 202 explicit IconDownloadCallbackFunctor(CreateApplicationShortcutView* owner) |
| 203 : owner_(owner) { |
| 204 } |
| 205 |
| 206 void Run(int download_id, bool errored, const SkBitmap& image) { |
| 207 if (owner_) |
| 208 owner_->OnIconDownloaded(errored, image); |
| 209 delete this; |
| 210 } |
| 211 |
| 212 void Cancel() { |
| 213 owner_ = NULL; |
| 214 } |
| 215 |
| 216 private: |
| 217 CreateApplicationShortcutView* owner_; |
| 218 }; |
| 219 |
| 206 CreateApplicationShortcutView::CreateApplicationShortcutView( | 220 CreateApplicationShortcutView::CreateApplicationShortcutView( |
| 207 TabContents* tab_contents) | 221 TabContents* tab_contents) |
| 208 : tab_contents_(tab_contents) { | 222 : tab_contents_(tab_contents), |
| 223 pending_download_(NULL) { |
| 209 Init(); | 224 Init(); |
| 210 } | 225 } |
| 211 | 226 |
| 212 CreateApplicationShortcutView::~CreateApplicationShortcutView() { | 227 CreateApplicationShortcutView::~CreateApplicationShortcutView() { |
| 228 if (pending_download_) |
| 229 pending_download_->Cancel(); |
| 213 } | 230 } |
| 214 | 231 |
| 215 void CreateApplicationShortcutView::Init() { | 232 void CreateApplicationShortcutView::Init() { |
| 216 // Prepare data | 233 // Prepare data |
| 234 web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_); |
| 235 |
| 217 const webkit_glue::WebApplicationInfo& app_info = | 236 const webkit_glue::WebApplicationInfo& app_info = |
| 218 tab_contents_->web_app_info(); | 237 tab_contents_->web_app_info(); |
| 219 | |
| 220 url_ = app_info.app_url.is_empty() ? tab_contents_->GetURL() : | |
| 221 app_info.app_url; | |
| 222 title_ = app_info.title.empty() ? tab_contents_->GetTitle() : | |
| 223 app_info.title; | |
| 224 description_ = app_info.description; | |
| 225 | |
| 226 icon_ = tab_contents_->GetFavIcon(); | |
| 227 if (!app_info.icons.empty()) { | 238 if (!app_info.icons.empty()) { |
| 228 SetIconsInfo(app_info.icons); | 239 web_app::GetIconsInfo(app_info, &unprocessed_icons_); |
| 229 FetchIcon(); | 240 FetchIcon(); |
| 230 } | 241 } |
| 231 | 242 |
| 232 if (title_.empty()) | |
| 233 title_ = UTF8ToUTF16(url_.spec()); | |
| 234 | |
| 235 // Create controls | 243 // Create controls |
| 236 app_info_ = new AppInfoView(title_, description_, icon_); | 244 app_info_ = new AppInfoView(shortcut_info_.title, shortcut_info_.description, |
| 245 shortcut_info_.favicon); |
| 237 create_shortcuts_label_ = new views::Label( | 246 create_shortcuts_label_ = new views::Label( |
| 238 l10n_util::GetString(IDS_CREATE_SHORTCUTS_LABEL)); | 247 l10n_util::GetString(IDS_CREATE_SHORTCUTS_LABEL)); |
| 239 create_shortcuts_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 248 create_shortcuts_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 240 | 249 |
| 241 Profile* profile = tab_contents_->profile(); | 250 Profile* profile = tab_contents_->profile(); |
| 242 | 251 |
| 243 desktop_check_box_ = AddCheckbox( | 252 desktop_check_box_ = AddCheckbox( |
| 244 l10n_util::GetString(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX), | 253 l10n_util::GetString(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX), |
| 245 profile->GetPrefs()->GetBoolean(prefs::kWebAppCreateOnDesktop)); | 254 profile->GetPrefs()->GetBoolean(prefs::kWebAppCreateOnDesktop)); |
| 246 | 255 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 | 361 |
| 353 std::wstring CreateApplicationShortcutView::GetWindowTitle() const { | 362 std::wstring CreateApplicationShortcutView::GetWindowTitle() const { |
| 354 return l10n_util::GetString(IDS_CREATE_SHORTCUTS_TITLE); | 363 return l10n_util::GetString(IDS_CREATE_SHORTCUTS_TITLE); |
| 355 } | 364 } |
| 356 | 365 |
| 357 bool CreateApplicationShortcutView::Accept() { | 366 bool CreateApplicationShortcutView::Accept() { |
| 358 if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { | 367 if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { |
| 359 return false; | 368 return false; |
| 360 } | 369 } |
| 361 | 370 |
| 362 ShellIntegration::ShortcutInfo shortcut_info; | 371 shortcut_info_.create_on_desktop = desktop_check_box_->checked(); |
| 363 shortcut_info.url = url_; | 372 shortcut_info_.create_in_applications_menu = menu_check_box_ == NULL ? false : |
| 364 shortcut_info.title = title_; | |
| 365 shortcut_info.description = description_; | |
| 366 shortcut_info.favicon = icon_; | |
| 367 shortcut_info.create_on_desktop = desktop_check_box_->checked(); | |
| 368 shortcut_info.create_in_applications_menu = menu_check_box_ == NULL ? false : | |
| 369 menu_check_box_->checked(); | 373 menu_check_box_->checked(); |
| 370 | 374 |
| 371 #if defined(OS_WIN) | 375 #if defined(OS_WIN) |
| 372 shortcut_info.create_in_quick_launch_bar = quick_launch_check_box_ == NULL ? | 376 shortcut_info_.create_in_quick_launch_bar = quick_launch_check_box_ == NULL ? |
| 373 NULL : quick_launch_check_box_->checked(); | 377 NULL : quick_launch_check_box_->checked(); |
| 374 #elif defined(OS_POSIX) | 378 #elif defined(OS_POSIX) |
| 375 // Create shortcut in Mac dock or as Linux (gnome/kde) application launcher | 379 // Create shortcut in Mac dock or as Linux (gnome/kde) application launcher |
| 376 // are not implemented yet. | 380 // are not implemented yet. |
| 377 shortcut_info.create_in_quick_launch_bar = false; | 381 shortcut_info_.create_in_quick_launch_bar = false; |
| 378 #endif | 382 #endif |
| 379 | 383 |
| 380 web_app::CreateShortcut( | 384 web_app::CreateShortcut(web_app::GetDataDir(tab_contents_->profile()), |
| 381 tab_contents_->profile()->GetPath().Append(chrome::kWebAppDirname), | 385 shortcut_info_, |
| 382 shortcut_info, NULL); | 386 NULL); |
| 383 | 387 |
| 384 if (tab_contents_->delegate()) | 388 if (tab_contents_->delegate()) |
| 385 tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_); | 389 tab_contents_->delegate()->ConvertContentsToApplication(tab_contents_); |
| 386 return true; | 390 return true; |
| 387 } | 391 } |
| 388 | 392 |
| 389 views::View* CreateApplicationShortcutView::GetContentsView() { | 393 views::View* CreateApplicationShortcutView::GetContentsView() { |
| 390 return this; | 394 return this; |
| 391 } | 395 } |
| 392 | 396 |
| 393 views::Checkbox* CreateApplicationShortcutView::AddCheckbox( | 397 views::Checkbox* CreateApplicationShortcutView::AddCheckbox( |
| 394 const std::wstring& text, bool checked) { | 398 const std::wstring& text, bool checked) { |
| 395 views::Checkbox* checkbox = new views::Checkbox(text); | 399 views::Checkbox* checkbox = new views::Checkbox(text); |
| 396 checkbox->SetChecked(checked); | 400 checkbox->SetChecked(checked); |
| 397 checkbox->set_listener(this); | 401 checkbox->set_listener(this); |
| 398 return checkbox; | 402 return checkbox; |
| 399 } | 403 } |
| 400 | 404 |
| 401 void CreateApplicationShortcutView::SetIconsInfo(const IconInfoList& icons) { | |
| 402 unprocessed_icons_.clear(); | |
| 403 for (size_t i = 0; i < icons.size(); ++i) { | |
| 404 // We only take square shaped icons (i.e. width == height). | |
| 405 if (icons[i].width == icons[i].height) { | |
| 406 unprocessed_icons_.push_back(icons[i]); | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 std::sort(unprocessed_icons_.begin(), unprocessed_icons_.end(), | |
| 411 &IconPrecedes); | |
| 412 } | |
| 413 | |
| 414 void CreateApplicationShortcutView::FetchIcon() { | 405 void CreateApplicationShortcutView::FetchIcon() { |
| 415 // There should only be fetch job at a time. | 406 // There should only be fetch job at a time. |
| 416 DCHECK(icon_fetcher_ == NULL); | 407 DCHECK(pending_download_ == NULL); |
| 417 | 408 |
| 418 if (unprocessed_icons_.empty()) { | 409 if (unprocessed_icons_.empty()) { |
| 419 // No icons to fetch. | 410 // No icons to fetch. |
| 420 return; | 411 return; |
| 421 } | 412 } |
| 422 | 413 |
| 423 icon_fetcher_.reset(new URLFetcher(unprocessed_icons_.back().url, | 414 pending_download_ = new IconDownloadCallbackFunctor(this); |
| 424 URLFetcher::GET, | 415 DCHECK(pending_download_); |
| 425 this)); | 416 |
| 426 DCHECK(icon_fetcher_.get() != NULL); | 417 tab_contents_->fav_icon_helper().DownloadImage( |
| 418 unprocessed_icons_.back().url, |
| 419 std::max(unprocessed_icons_.back().width, |
| 420 unprocessed_icons_.back().height), |
| 421 NewCallback(pending_download_, &IconDownloadCallbackFunctor::Run)); |
| 422 |
| 427 unprocessed_icons_.pop_back(); | 423 unprocessed_icons_.pop_back(); |
| 428 | |
| 429 icon_fetcher_->set_load_flags(icon_fetcher_->load_flags() | | |
| 430 net::LOAD_IS_DOWNLOAD); | |
| 431 icon_fetcher_->set_request_context( | |
| 432 tab_contents_->profile()->GetRequestContext()); | |
| 433 icon_fetcher_->Start(); | |
| 434 } | 424 } |
| 435 | 425 |
| 436 void CreateApplicationShortcutView::ButtonPressed(views::Button* sender, | 426 void CreateApplicationShortcutView::ButtonPressed(views::Button* sender, |
| 437 const views::Event& event) { | 427 const views::Event& event) { |
| 438 Profile* profile = tab_contents_->profile(); | 428 Profile* profile = tab_contents_->profile(); |
| 439 if (sender == desktop_check_box_) | 429 if (sender == desktop_check_box_) |
| 440 profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateOnDesktop, | 430 profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateOnDesktop, |
| 441 desktop_check_box_->checked() ? true : false); | 431 desktop_check_box_->checked() ? true : false); |
| 442 else if (sender == menu_check_box_) | 432 else if (sender == menu_check_box_) |
| 443 profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateInAppsMenu, | 433 profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateInAppsMenu, |
| 444 menu_check_box_->checked() ? true : false); | 434 menu_check_box_->checked() ? true : false); |
| 445 else if (sender == quick_launch_check_box_) | 435 else if (sender == quick_launch_check_box_) |
| 446 profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateInQuickLaunchBar, | 436 profile->GetPrefs()->SetBoolean(prefs::kWebAppCreateInQuickLaunchBar, |
| 447 quick_launch_check_box_->checked() ? true : false); | 437 quick_launch_check_box_->checked() ? true : false); |
| 448 | 438 |
| 449 // When no checkbox is checked we should not have the action button enabled. | 439 // When no checkbox is checked we should not have the action button enabled. |
| 450 GetDialogClientView()->UpdateDialogButtons(); | 440 GetDialogClientView()->UpdateDialogButtons(); |
| 451 } | 441 } |
| 452 | 442 |
| 453 void CreateApplicationShortcutView::OnURLFetchComplete(const URLFetcher* source, | 443 void CreateApplicationShortcutView::OnIconDownloaded(bool errored, |
| 454 const GURL& url, | 444 const SkBitmap& image) { |
| 455 const URLRequestStatus& status, | 445 pending_download_ = NULL; |
| 456 int response_code, | |
| 457 const ResponseCookies& cookies, | |
| 458 const std::string& data) { | |
| 459 // Delete the fetcher on this function's exit. | |
| 460 scoped_ptr<URLFetcher> clean_up_fetcher(icon_fetcher_.release()); | |
| 461 | 446 |
| 462 bool success = status.is_success() && (response_code == 200) && !data.empty(); | 447 if (!errored && !image.isNull()) { |
| 463 | 448 shortcut_info_.favicon = image; |
| 464 if (success) { | 449 static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); |
| 465 success = gfx::PNGCodec::Decode( | 450 } else { |
| 466 reinterpret_cast<const unsigned char*>(data.c_str()), | 451 FetchIcon(); |
| 467 data.size(), | |
| 468 &icon_); | |
| 469 | |
| 470 if (success) | |
| 471 static_cast<AppInfoView*>(app_info_)->UpdateIcon(icon_); | |
| 472 } | 452 } |
| 473 | |
| 474 if (!success) | |
| 475 FetchIcon(); | |
| 476 } | 453 } |
| OLD | NEW |