15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/shell_integration.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/shell_integration_linux.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_commands.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_dialogs.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/web_applications/web_app_ui.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/web_applications/web_app.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/icons_handler.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_delegate.h" 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/locale_settings.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_hig_constants.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/gtk_util.h" 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image.h" 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image_family.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image_skia.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size (in pixels) of the icon preview. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kIconPreviewSizePixels = 32; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Minimum width (in pixels) of the shortcut description label. 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDescriptionLabelMinimumWidthPixels = 200; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowCreateWebAppShortcutsDialog(gfx::NativeWindow parent_window, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new CreateWebApplicationShortcutsDialogGtk(parent_window, web_contents); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShowCreateChromeAppShortcutsDialog( 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) gfx::NativeWindow parent_window, 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Profile* profile, 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const extensions::Extension* app, 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const base::Closure& close_callback) { 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) new CreateChromeApplicationShortcutsDialogGtk(parent_window, profile, app, 658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) close_callback); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace chrome 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreateApplicationShortcutsDialogGtk::CreateApplicationShortcutsDialogGtk( 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWindow* parent) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : parent_(parent), 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desktop_checkbox_(NULL), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_checkbox_(NULL), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_pixbuf_(NULL), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_dialog_(NULL), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_dialog_(NULL) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be balanced by Release later. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::CreateIconPixBuf( 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::ImageFamily& image) { 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Get the icon closest to the desired preview size. 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Image* icon = image.GetBest(kIconPreviewSizePixels, 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kIconPreviewSizePixels); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // There must be at least one icon in the image family. 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(icon); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GdkPixbuf* pixbuf = icon->CopyGdkPixbuf(); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Prepare the icon. Scale it to the correct size to display in the dialog. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pixbuf_width = gdk_pixbuf_get_width(pixbuf); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pixbuf_height = gdk_pixbuf_get_height(pixbuf); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pixbuf_width == pixbuf_height) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only scale the pixbuf if it's a square (for simplicity). 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generally it should be square, if it's a favicon or app icon. 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use the highest quality interpolation. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_pixbuf_ = gdk_pixbuf_scale_simple(pixbuf, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kIconPreviewSizePixels, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kIconPreviewSizePixels, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GDK_INTERP_HYPER); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_object_unref(pixbuf); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_pixbuf_ = pixbuf; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::CreateDialogBox(GtkWindow* parent) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build the dialog. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) create_dialog_ = gtk_dialog_new_with_buttons( 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_TITLE).c_str(), 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_realize(create_dialog_); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_window_set_resizable(GTK_WINDOW(create_dialog_), false); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_util::AddButtonToDialog(create_dialog_, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CANCEL).c_str(), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_util::AddButtonToDialog(create_dialog_, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_COMMIT).c_str(), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* content_area = 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_dialog_get_content_area(GTK_DIALOG(create_dialog_)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_set_spacing(GTK_BOX(content_area), ui::kContentAreaSpacing); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kControlSpacing); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_container_add(GTK_CONTAINER(content_area), vbox); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a box containing basic information about the new shortcut: an image 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on the left, and a description on the right. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* hbox = gtk_hbox_new(FALSE, ui::kControlSpacing); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_container_set_border_width(GTK_CONTAINER(hbox), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::kControlSpacing); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Put the icon preview in place. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* favicon_image = gtk_image_new_from_pixbuf(favicon_pixbuf_); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(hbox), favicon_image, FALSE, FALSE, 0); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the label with application shortcut description. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* description_label = gtk_label_new(NULL); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(hbox), description_label, FALSE, FALSE, 0); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_realize(description_label); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the size request on the label so it knows where to line wrap. The width 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is the desired size of the dialog less the space reserved for padding and 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the image. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int label_width; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_util::GetWidgetSizeFromResources( 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description_label, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_CREATE_SHORTCUTS_DIALOG_WIDTH_CHARS, -1, &label_width, NULL); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_width -= ui::kControlSpacing * 3 + 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_pixbuf_get_width(favicon_pixbuf_); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Enforce a minimum width, so that very large icons do not cause the label 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // width to shrink to unreadable size, or become negative (which would crash). 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (label_width < kDescriptionLabelMinimumWidthPixels) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) label_width = kDescriptionLabelMinimumWidthPixels; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_util::SetLabelWidth(description_label, label_width); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string description(UTF16ToUTF8(shortcut_info_.description)); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string title(UTF16ToUTF8(shortcut_info_.title)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_label_set_text(GTK_LABEL(description_label), 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (description.empty() ? title : description).c_str()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Label on top of the checkboxes. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* checkboxes_label = gtk_label_new( 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_LABEL).c_str()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_misc_set_alignment(GTK_MISC(checkboxes_label), 0, 0); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(vbox), checkboxes_label, FALSE, FALSE, 0); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Desktop checkbox. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desktop_checkbox_ = gtk_check_button_new_with_label( 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_DESKTOP_CHKBOX).c_str()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(vbox), desktop_checkbox_, FALSE, FALSE, 0); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(desktop_checkbox_), true); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_signal_connect(desktop_checkbox_, "toggled", 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnToggleCheckboxThunk), this); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Menu checkbox. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu_checkbox_ = gtk_check_button_new_with_label( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_MENU_CHKBOX).c_str()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(vbox), menu_checkbox_, FALSE, FALSE, 0); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(menu_checkbox_), false); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_signal_connect(menu_checkbox_, "toggled", 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnToggleCheckboxThunk), this); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_signal_connect(create_dialog_, "response", 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnCreateDialogResponseThunk), this); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_show_all(create_dialog_); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreateApplicationShortcutsDialogGtk::~CreateApplicationShortcutsDialogGtk() { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_destroy(create_dialog_); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_dialog_) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_destroy(error_dialog_); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_object_unref(favicon_pixbuf_); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::OnCreateDialogResponse( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* widget, int response) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response == GTK_RESPONSE_ACCEPT) { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellIntegration::ShortcutLocations creation_locations; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) creation_locations.on_desktop = 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_)); 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_))) { 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) creation_locations.applications_menu_location = 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) create_in_chrome_apps_subdir_ ? 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShellIntegration::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS : 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShellIntegration::APP_MENU_LOCATION_ROOT; 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut, 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, shortcut_info_, creation_locations)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnCreatedShortcut(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::OnErrorDialogResponse( 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* widget, int response) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::CreateDesktopShortcut( 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info, 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutLocations& creation_locations) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ShellIntegrationLinux::CreateDesktopShortcut(shortcut_info, 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) creation_locations); 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Release(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::ShowErrorDialog() { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hide the create dialog so that the user can no longer interact with it. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_hide(create_dialog_); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_dialog_ = gtk_dialog_new_with_buttons( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_ERROR_TITLE).c_str(), 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (GtkDialogFlags) (GTK_DIALOG_NO_SEPARATOR), 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_STOCK_OK, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_RESPONSE_ACCEPT, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_realize(error_dialog_); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_util::SetWindowSizeFromResources( 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_WINDOW(error_dialog_), 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_CREATE_SHORTCUTS_ERROR_DIALOG_WIDTH_CHARS, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_CREATE_SHORTCUTS_ERROR_DIALOG_HEIGHT_LINES, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); // resizable 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* content_area = 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_dialog_get_content_area(GTK_DIALOG(error_dialog_)); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_set_spacing(GTK_BOX(content_area), ui::kContentAreaSpacing); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* vbox = gtk_vbox_new(FALSE, ui::kControlSpacing); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_container_add(GTK_CONTAINER(content_area), vbox); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Label on top of the checkboxes. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* description = gtk_label_new( 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF8(IDS_CREATE_SHORTCUTS_ERROR_LABEL).c_str()); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_label_set_line_wrap(GTK_LABEL(description), TRUE); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_misc_set_alignment(GTK_MISC(description), 0, 0); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(vbox), description, FALSE, FALSE, 0); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_signal_connect(error_dialog_, "response", 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnErrorDialogResponseThunk), this); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_show_all(error_dialog_); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateApplicationShortcutsDialogGtk::OnToggleCheckbox(GtkWidget* sender) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gboolean can_accept = FALSE; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(desktop_checkbox_)) || 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(menu_checkbox_))) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_accept = TRUE; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_dialog_set_response_sensitive(GTK_DIALOG(create_dialog_), 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_RESPONSE_ACCEPT, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_accept); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreateWebApplicationShortcutsDialogGtk::CreateWebApplicationShortcutsDialogGtk( 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWindow* parent, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : CreateApplicationShortcutsDialogGtk(parent), 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_(web_contents) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get shortcut information now, it's needed for our UI. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_app::GetShortcutInfoForTab(web_contents, &shortcut_info_); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconPixBuf(shortcut_info_.favicon); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Create URL app shortcuts in the top-level menu. 307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) create_in_chrome_apps_subdir_ = false; 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateDialogBox(parent); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateWebApplicationShortcutsDialogGtk::OnCreatedShortcut() { 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindBrowserWithWebContents(web_contents_); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::ConvertTabToAppWindow(browser, web_contents_); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CreateChromeApplicationShortcutsDialogGtk:: 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateChromeApplicationShortcutsDialogGtk( 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWindow* parent, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const Extension* app, 3238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const base::Closure& close_callback) 3248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : CreateApplicationShortcutsDialogGtk(parent), 3258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) app_(app), 3268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) profile_path_(profile->GetPath()), 3278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) close_callback_(close_callback) { 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Place Chrome app shortcuts in the "Chrome Apps" submenu. 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) create_in_chrome_apps_subdir_ = true; 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get shortcut information and icon now; they are needed for our UI. 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_app::UpdateShortcutInfoAndIconForApp( 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *app, profile, 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind( 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &CreateChromeApplicationShortcutsDialogGtk::OnShortcutInfoLoaded, 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this)); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CreateChromeApplicationShortcutsDialogGtk:: 3418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ~CreateChromeApplicationShortcutsDialogGtk() { 3428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!close_callback_.is_null()) 3438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) close_callback_.Run(); 3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called when the app's ShortcutInfo (with icon) is loaded. 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CreateChromeApplicationShortcutsDialogGtk::OnShortcutInfoLoaded( 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info) { 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info_ = shortcut_info; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconPixBuf(shortcut_info_.favicon); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateDialogBox(parent_); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateChromeApplicationShortcutsDialogGtk::CreateDesktopShortcut( 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info, 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutLocations& creation_locations) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (web_app::CreateShortcutsOnFileThread( 361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch shortcut_info, creation_locations, 362558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch web_app::SHORTCUT_CREATION_BY_USER)) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CreateChromeApplicationShortcutsDialogGtk::ShowErrorDialog, 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 370