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
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/external_protocol_dialog_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/metrics/histogram.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/external_protocol_handler.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_util.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/text/text_elider.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kMessageWidth = 400;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ExternalProtocolHandler
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExternalProtocolHandler::RunExternalProtocolDialog(
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url, int render_process_host_id, int routing_id) {
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new ExternalProtocolDialogGtk(url);
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ExternalProtocolDialogGtk
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochExternalProtocolDialogGtk::ExternalProtocolDialogGtk(const GURL& url)
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : url_(url),
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      creation_time_(base::TimeTicks::Now()) {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dialog_ = gtk_dialog_new_with_buttons(
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_TITLE).c_str(),
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_DIALOG_NO_SEPARATOR,
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL);
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add the response buttons.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::AddButtonToDialog(dialog_,
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          IDS_EXTERNAL_PROTOCOL_CANCEL_BUTTON_TEXT).c_str(),
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::AddButtonToDialog(dialog_,
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT).c_str(),
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the message text.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kMaxUrlWithoutSchemeSize = 256;
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kMaxCommandSize = 256;
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  string16 elided_url_without_scheme;
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  string16 elided_command;
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ui::ElideString(ASCIIToUTF16(url.possibly_invalid_spec()),
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kMaxUrlWithoutSchemeSize, &elided_url_without_scheme);
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ui::ElideString(ASCIIToUTF16(std::string("xdg-open ") + url.spec()),
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kMaxCommandSize, &elided_command);
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string message_text = l10n_util::GetStringFUTF8(
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDS_EXTERNAL_PROTOCOL_INFORMATION,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASCIIToUTF16(url.scheme() + ":"),
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      elided_url_without_scheme) + "\n\n";
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  message_text += l10n_util::GetStringFUTF8(
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      IDS_EXTERNAL_PROTOCOL_APPLICATION_TO_LAUNCH, elided_command) + "\n\n";
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  message_text += l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_WARNING);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create the content-holding vbox.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_set_border_width(GTK_CONTAINER(vbox),
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 gtk_util::kContentAreaBorder);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add the message text.
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* label = gtk_label_new(message_text.c_str());
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  gtk_util::SetLabelWidth(label, kMessageWidth);
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add the checkbox.
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  checkbox_ = gtk_check_button_new_with_label(
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT).c_str());
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(vbox), checkbox_,
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add our vbox to the dialog.
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), vbox,
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE);
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(dialog_);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenExternalProtocolDialogGtk::~ExternalProtocolDialogGtk() {
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ExternalProtocolDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox_))) {
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (response_id == GTK_RESPONSE_ACCEPT) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ExternalProtocolHandler::SetBlockState(
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          url_.scheme(), ExternalProtocolHandler::DONT_BLOCK);
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (response_id == GTK_RESPONSE_REJECT) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ExternalProtocolHandler::SetBlockState(
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          url_.scheme(), ExternalProtocolHandler::BLOCK);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // If the response is GTK_RESPONSE_DELETE, triggered by the user closing
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the dialog, do nothing.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (response_id == GTK_RESPONSE_ACCEPT) {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url",
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             base::TimeTicks::Now() - creation_time_);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_destroy(dialog_);
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
133