diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-03 21:33:21 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-03 21:33:21 +0000 |
commit | 10f57b9be42b705fd1bed1a97acd90c8c885c396 (patch) | |
tree | 77d5fbbace6a41dc28ace3b4f573fc917aae61da /chrome | |
parent | df891031f2d5bd26eccd180fea4deb4797dd7a60 (diff) | |
download | chromium_src-10f57b9be42b705fd1bed1a97acd90c8c885c396.zip chromium_src-10f57b9be42b705fd1bed1a97acd90c8c885c396.tar.gz chromium_src-10f57b9be42b705fd1bed1a97acd90c8c885c396.tar.bz2 |
Add external protocol dialog for Linux.
This exposes a bug where \n in a string resource is rendered literally when it is displayed. I don't know at what point on Windows the '\' + 'n' is translated to a line return, I have filed crbug.com/20943
BUG=20731
Review URL: http://codereview.chromium.org/194002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25373 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/external_protocol_handler.cc | 48 | ||||
-rw-r--r-- | chrome/browser/external_protocol_handler.h | 24 | ||||
-rw-r--r-- | chrome/browser/gtk/external_protocol_dialog_gtk.cc | 92 | ||||
-rw-r--r-- | chrome/browser/gtk/external_protocol_dialog_gtk.h | 29 | ||||
-rw-r--r-- | chrome/browser/views/external_protocol_dialog.cc | 34 | ||||
-rw-r--r-- | chrome/browser/views/external_protocol_dialog.h | 33 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
7 files changed, 182 insertions, 80 deletions
diff --git a/chrome/browser/external_protocol_handler.cc b/chrome/browser/external_protocol_handler.cc index 59f7a23..3bfbb6e6 100644 --- a/chrome/browser/external_protocol_handler.cc +++ b/chrome/browser/external_protocol_handler.cc @@ -20,10 +20,6 @@ #include "googleurl/src/gurl.h" #include "net/base/escape.h" -#if defined(OS_WIN) -#include "chrome/browser/views/external_protocol_dialog.h" -#endif - // static void ExternalProtocolHandler::PrepopulateDictionary(DictionaryValue* win_pref) { static bool is_warm = false; @@ -116,36 +112,27 @@ void ExternalProtocolHandler::LaunchUrl(const GURL& url, if (block_state == BLOCK) return; -#if defined(OS_WIN) if (block_state == UNKNOWN) { - std::wstring command = ExternalProtocolDialog::GetApplicationForProtocol( - escaped_url); - if (command.empty()) { - // ShellExecute won't do anything. Don't bother warning the user. - return; - } - +#if !defined(OS_MACOSX) // Ask the user if they want to allow the protocol. This will call // LaunchUrlWithoutSecurityCheck if the user decides to accept the protocol. - ExternalProtocolDialog::RunExternalProtocolDialog(escaped_url, - command, - render_process_host_id, - tab_contents_id); + RunExternalProtocolDialog(escaped_url, + render_process_host_id, + tab_contents_id); +#endif + // For now, allow only whitelisted protocols to fire on Mac. + // See http://crbug.com/15546. return; } -#else - // For now, allow only whitelisted protocols to fire. - // TODO(port): implement dialog for Mac/Linux. - // See http://code.google.com/p/chromium/issues/detail?id=20731 - // and http://code.google.com/p/chromium/issues/detail?id=15546. - if (block_state == UNKNOWN) - return; -#endif - // Otherwise the protocol is white-listed, so go ahead and launch. + LaunchUrlWithoutSecurityCheck(escaped_url); +} + +// static +void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(const GURL& url) { #if defined(OS_MACOSX) // This must run on the main thread on OS X. - LaunchUrlWithoutSecurityCheck(escaped_url); + platform_util::OpenExternal(url); #else // Otherwise put this work on the file thread. On Windows ShellExecute may // block for a significant amount of time, and it shouldn't hurt on Linux. @@ -155,18 +142,11 @@ void ExternalProtocolHandler::LaunchUrl(const GURL& url, } loop->PostTask(FROM_HERE, - NewRunnableFunction( - &ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck, - escaped_url)); + NewRunnableFunction(&platform_util::OpenExternal, url)); #endif } // static -void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(const GURL& url) { - platform_util::OpenExternal(url); -} - -// static void ExternalProtocolHandler::RegisterPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(prefs::kExcludedSchemes); } diff --git a/chrome/browser/external_protocol_handler.h b/chrome/browser/external_protocol_handler.h index 20a1375..5089d2c0 100644 --- a/chrome/browser/external_protocol_handler.h +++ b/chrome/browser/external_protocol_handler.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_EXTERNAL_PROTOCOL_HANDLER_H__ -#define CHROME_BROWSER_EXTERNAL_PROTOCOL_HANDLER_H__ +#ifndef CHROME_BROWSER_EXTERNAL_PROTOCOL_HANDLER_H_ +#define CHROME_BROWSER_EXTERNAL_PROTOCOL_HANDLER_H_ #include <string> @@ -33,6 +33,20 @@ class ExternalProtocolHandler { static void LaunchUrl(const GURL& url, int render_process_host_id, int tab_contents_id); + // Creates and runs a External Protocol dialog box. + // |url| - The url of the request. + // |render_process_host_id| and |routing_id| are used by + // tab_util::GetTabContentsByID to aquire the tab contents associated with + // this dialog. + // NOTE: There is a race between the Time of Check and the Time Of Use for + // the command line. Since the caller (web page) does not have access + // to change the command line by itself, we do not do anything special + // to protect against this scenario. + // This is implemented separately on each platform. + static void RunExternalProtocolDialog(const GURL& url, + int render_process_host_id, + int routing_id); + // Register the ExcludedSchemes preference. static void RegisterPrefs(PrefService* prefs); @@ -44,7 +58,7 @@ class ExternalProtocolHandler { // NOTE: You should Not call this function directly unless you are sure the // url you have has been checked against the blacklist, and has been escaped. // All calls to this function should originate in some way from LaunchUrl. - // Must run on the file thread. + // This will execute on the file thread. static void LaunchUrlWithoutSecurityCheck(const GURL& url); // Prepopulates the dictionary with known protocols to deny or allow, if @@ -52,4 +66,4 @@ class ExternalProtocolHandler { static void PrepopulateDictionary(DictionaryValue* win_pref); }; -#endif // CHROME_BROWSER_EXTERNAL_PROTOCOL_HANDLER_H__ +#endif // CHROME_BROWSER_EXTERNAL_PROTOCOL_HANDLER_H_ diff --git a/chrome/browser/gtk/external_protocol_dialog_gtk.cc b/chrome/browser/gtk/external_protocol_dialog_gtk.cc new file mode 100644 index 0000000..538579e --- /dev/null +++ b/chrome/browser/gtk/external_protocol_dialog_gtk.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/external_protocol_dialog_gtk.h" + +#include <gtk/gtk.h> + +#include "app/l10n_util.h" +#include "base/histogram.h" +#include "chrome/browser/external_protocol_handler.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/common/gtk_util.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" + +namespace { + +const int kMessageWidth = 400; + +} // namespace + +/////////////////////////////////////////////////////////////////////////////// +// ExternalProtocolHandler + +// static +void ExternalProtocolHandler::RunExternalProtocolDialog( + const GURL& url, int render_process_host_id, int routing_id) { + TabContents* tab_contents = tab_util::GetTabContentsByID( + render_process_host_id, routing_id); + new ExternalProtocolDialogGtk(url, tab_contents); +} + +/////////////////////////////////////////////////////////////////////////////// +// ExternalProtocolDialogGtk + +ExternalProtocolDialogGtk::ExternalProtocolDialogGtk( + const GURL& url, TabContents* tab_contents) + : url_(url), + creation_time_(base::Time::Now()) { + GtkWindow* parent = tab_contents ? + tab_contents->view()->GetTopLevelNativeWindow() : NULL; + + dialog_ = gtk_dialog_new_with_buttons( + l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_TITLE).c_str(), + parent, + (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + NULL); + + gtk_util::AddButtonToDialog(dialog_, + l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT).c_str(), + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT); + + std::string message_text = l10n_util::GetStringFUTF8( + IDS_EXTERNAL_PROTOCOL_INFORMATION, + ASCIIToUTF16(url.scheme() + ":"), + ASCIIToUTF16(url.possibly_invalid_spec())) + "\n\n"; + + message_text += l10n_util::GetStringFUTF8( + IDS_EXTERNAL_PROTOCOL_APPLICATION_TO_LAUNCH, + ASCIIToUTF16(std::string("xdg-open ") + url.spec())) + "\n\n"; + + message_text += l10n_util::GetStringUTF8(IDS_EXTERNAL_PROTOCOL_WARNING); + + GtkWidget* label = gtk_label_new(message_text.c_str()); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_widget_set_size_request(label, kMessageWidth, -1); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), label, TRUE, TRUE, 0); + + g_signal_connect(dialog_, "response", + G_CALLBACK(OnDialogResponse), this); + + gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE); + gtk_widget_show_all(dialog_); +} + +void ExternalProtocolDialogGtk::OnDialogResponse(GtkWidget* widget, + int response, ExternalProtocolDialogGtk* dialog) { + if (response == GTK_RESPONSE_ACCEPT) { + UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url", + base::Time::Now() - dialog->creation_time_); + + ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(dialog->url_); + } + + gtk_widget_destroy(widget); + delete dialog; +} diff --git a/chrome/browser/gtk/external_protocol_dialog_gtk.h b/chrome/browser/gtk/external_protocol_dialog_gtk.h new file mode 100644 index 0000000..17d9e61 --- /dev/null +++ b/chrome/browser/gtk/external_protocol_dialog_gtk.h @@ -0,0 +1,29 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_ +#define CHROME_BROWSER_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_ + +#include "base/time.h" +#include "googleurl/src/gurl.h" + +class TabContents; + +typedef struct _GtkWidget GtkWidget; + +class ExternalProtocolDialogGtk { + public: + ExternalProtocolDialogGtk(const GURL& url, TabContents* tab_contents); + + private: + static void OnDialogResponse(GtkWidget* widget, + int response, + ExternalProtocolDialogGtk* dialog); + + GtkWidget* dialog_; + GURL url_; + base::Time creation_time_; +}; + +#endif // CHROME_BROWSER_GTK_EXTERNAL_PROTOCOL_DIALOG_GTK_H_ diff --git a/chrome/browser/views/external_protocol_dialog.cc b/chrome/browser/views/external_protocol_dialog.cc index 2feb0d7..4240e21 100644 --- a/chrome/browser/views/external_protocol_dialog.cc +++ b/chrome/browser/views/external_protocol_dialog.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,8 +12,8 @@ #include "base/thread.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/external_protocol_handler.h" -#include "chrome/browser/tab_contents/tab_util.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "views/controls/message_box_view.h" @@ -26,18 +26,26 @@ const int kMessageWidth = 400; } // namespace /////////////////////////////////////////////////////////////////////////////// -// ExternalProtocolDialog, public: +// ExternalProtocolHandler // static -void ExternalProtocolDialog::RunExternalProtocolDialog( - const GURL& url, const std::wstring& command, int render_process_host_id, - int routing_id) { +void ExternalProtocolHandler::RunExternalProtocolDialog( + const GURL& url, int render_process_host_id, int routing_id) { + std::wstring command = + ExternalProtocolDialog::GetApplicationForProtocol(url); + if (command.empty()) { + // ShellExecute won't do anything. Don't bother warning the user. + return; + } TabContents* tab_contents = tab_util::GetTabContentsByID( render_process_host_id, routing_id); ExternalProtocolDialog* handler = new ExternalProtocolDialog(tab_contents, url, command); } +/////////////////////////////////////////////////////////////////////////////// +// ExternalProtocolDialog + ExternalProtocolDialog::~ExternalProtocolDialog() { } @@ -72,16 +80,8 @@ bool ExternalProtocolDialog::Accept() { UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url", base::Time::Now() - creation_time_); - MessageLoop* io_loop = g_browser_process->io_thread()->message_loop(); - if (io_loop == NULL) { - // Returning true closes the dialog. - return true; - } - - // Attempt to launch the application on the IO loop. - io_loop->PostTask(FROM_HERE, - NewRunnableFunction( - &ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck, url_)); + ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_); + // Returning true closes the dialog. return true; } @@ -123,7 +123,7 @@ ExternalProtocolDialog::ExternalProtocolDialog(TabContents* tab_contents, views::Window::CreateChromeWindow(root_hwnd, gfx::Rect(), this)->Show(); } -/* static */ +// static std::wstring ExternalProtocolDialog::GetApplicationForProtocol( const GURL& url) { std::wstring url_spec = ASCIIToWide(url.possibly_invalid_spec()); diff --git a/chrome/browser/views/external_protocol_dialog.h b/chrome/browser/views/external_protocol_dialog.h index d74df51..c9e5199 100644 --- a/chrome/browser/views/external_protocol_dialog.h +++ b/chrome/browser/views/external_protocol_dialog.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_EXTERNAL_PROTOCOL_DIALOG_H__ -#define CHROME_BROWSER_EXTERNAL_PROTOCOL_DIALOG_H__ +#ifndef CHROME_BROWSER_EXTERNAL_PROTOCOL_DIALOG_H_ +#define CHROME_BROWSER_EXTERNAL_PROTOCOL_DIALOG_H_ #include "base/time.h" #include "googleurl/src/gurl.h" @@ -14,20 +14,10 @@ class TabContents; class ExternalProtocolDialog : public views::DialogDelegate { public: - // Creates and runs a External Protocol dialog box. - // |url| - The url of the request. - // |command| - the command that ShellExecute will run. - // |render_process_host_id| and |routing_id| are used by - // tab_util::GetTabContentsByID to aquire the tab contents associated with - // this dialog. - // NOTE: There is a race between the Time of Check and the Time Of Use for - // the command line. Since the caller (web page) does not have access - // to change the command line by itself, we do not do anything special - // to protect against this scenario. - static void RunExternalProtocolDialog(const GURL& url, - const std::wstring& command, - int render_process_host_id, - int routing_id); + // RunExternalProtocolDialog calls this private constructor. + ExternalProtocolDialog(TabContents* tab_contents, + const GURL& url, + const std::wstring& command); // Returns the path of the application to be launched given the protocol // of the requested url. Returns an empty string on failure. @@ -49,11 +39,6 @@ class ExternalProtocolDialog : public views::DialogDelegate { virtual bool IsModal() const { return false; } private: - // RunExternalProtocolDialog calls this private constructor. - ExternalProtocolDialog(TabContents* tab_contents, - const GURL& url, - const std::wstring& command); - // The message box view whose commands we handle. MessageBoxView* message_box_view_; @@ -66,7 +51,7 @@ class ExternalProtocolDialog : public views::DialogDelegate { // The time at which this dialog was created. base::Time creation_time_; - DISALLOW_EVIL_CONSTRUCTORS(ExternalProtocolDialog); + DISALLOW_COPY_AND_ASSIGN(ExternalProtocolDialog); }; -#endif // CHROME_BROWSER_EXTERNAL_PROTOCOL_DIALOG_H__ +#endif // CHROME_BROWSER_EXTERNAL_PROTOCOL_DIALOG_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index c7e50f3..6563807 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1246,6 +1246,8 @@ 'browser/gtk/extension_shelf_gtk.h', 'browser/gtk/extension_view_gtk.cc', 'browser/gtk/extension_view_gtk.h', + 'browser/gtk/external_protocol_dialog_gtk.cc', + 'browser/gtk/external_protocol_dialog_gtk.h', 'browser/gtk/find_bar_gtk.cc', 'browser/gtk/find_bar_gtk.h', 'browser/gtk/first_run_bubble.cc', |