172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/process_util.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/process_watcher.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/native_widget_types.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetDialogTitle(GtkWidget* dialog, const string16& title) { 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_window_set_title(GTK_WINDOW(dialog), UTF16ToUTF8(title).c_str()); 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(OS_CHROMEOS) 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The following code requires the dialog to be realized. However, we host 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // dialog's content in a Chrome window without really realize the dialog 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on ChromeOS. Thus, skip the following code for ChromeOS. 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_realize(dialog); 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure it's big enough to show the title. 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkRequisition req; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_size_request(dialog, &req); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int width; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::GetWidgetSizeFromCharacters(dialog, title.length(), 0, 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &width, NULL); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The fudge factor accounts for extra space needed by the frame 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // decorations as well as width differences between average text and the 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // actual title text. 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width = width * 1.2 + 50; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (width > req.width) 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(dialog, width, -1); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // !defined(OS_CHROMEOS) 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint g_dialog_response; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HandleOnResponseDialog(GtkWidget* widget, 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response, 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* user_data) { 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_dialog_response = response; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_destroy(widget); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->QuitNow(); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace platform_util { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::NativeWindow GetTopLevel(gfx::NativeView view) { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A detached widget won't have a toplevel window as an ancestor, so we can't 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // assume that the query for toplevel will return a window. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* toplevel = gtk_widget_get_ancestor(view, GTK_TYPE_WINDOW); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GTK_IS_WINDOW(toplevel) ? GTK_WINDOW(toplevel) : NULL; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdochgfx::NativeView GetParent(gfx::NativeView view) { 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return gtk_widget_get_parent(view); 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsWindowActive(gfx::NativeWindow window) { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gtk_window_is_active(window); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ActivateWindow(gfx::NativeWindow window) { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_window_present(window); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsVisible(gfx::NativeView view) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GTK_WIDGET_VISIBLE(view); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SimpleErrorBox(gfx::NativeWindow parent, 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& title, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& message) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* dialog = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", UTF16ToUTF8(message).c_str()); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ApplyMessageDialogQuirks(dialog); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetDialogTitle(dialog, title); 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ShowDialog(dialog); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SimpleYesNoBox(gfx::NativeWindow parent, 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& title, 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& message) { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* dialog = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF16ToUTF8(message).c_str()); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ApplyMessageDialogQuirks(dialog); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetDialogTitle(dialog, title); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(dialog, 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "response", 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(HandleOnResponseDialog), 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::ShowDialog(dialog); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Not gtk_dialog_run as it prevents timers from running in the unit tests. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Run(); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return g_dialog_response == GTK_RESPONSE_YES; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Warning: this may be either Linux or ChromeOS. 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string GetVersionStringModifier() { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char* env = getenv("CHROME_VERSION_EXTRA"); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!env) 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return std::string(); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string modifier(env); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(GOOGLE_CHROME_BUILD) 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only ever return "", "unknown", "dev" or "beta" in a branded build. 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (modifier == "unstable") // linux version of "dev" 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modifier = "dev"; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (modifier == "stable") { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modifier = ""; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if ((modifier == "dev") || (modifier == "beta")) { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // do nothing. 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modifier = "unknown"; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return modifier; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CanSetAsDefaultBrowser() { 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace platform_util 142