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