diff options
-rw-r--r-- | chrome/browser/external_protocol_handler.cc | 89 | ||||
-rw-r--r-- | chrome/common/platform_util.h | 5 | ||||
-rw-r--r-- | chrome/common/platform_util_linux.cc | 13 | ||||
-rw-r--r-- | chrome/common/platform_util_mac.mm | 8 | ||||
-rw-r--r-- | chrome/common/platform_util_win.cc | 46 |
5 files changed, 80 insertions, 81 deletions
diff --git a/chrome/browser/external_protocol_handler.cc b/chrome/browser/external_protocol_handler.cc index a8ebeb2..59f7a23 100644 --- a/chrome/browser/external_protocol_handler.cc +++ b/chrome/browser/external_protocol_handler.cc @@ -6,11 +6,6 @@ #include "build/build_config.h" -#if defined(OS_WIN) -#include <windows.h> -#include <shellapi.h> -#endif - #include <set> #include "base/logging.h" @@ -19,18 +14,14 @@ #include "base/thread.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_process_impl.h" +#include "chrome/common/platform_util.h" #include "chrome/common/pref_service.h" #include "chrome/common/pref_names.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" #if defined(OS_WIN) -#include "base/registry.h" #include "chrome/browser/views/external_protocol_dialog.h" -#elif defined(OS_MACOSX) -#include <ApplicationServices/ApplicationServices.h> -#include "base/scoped_cftyperef.h" -#include "base/sys_string_conversions.h" #endif // static @@ -117,7 +108,6 @@ ExternalProtocolHandler::BlockState ExternalProtocolHandler::GetBlockState( void ExternalProtocolHandler::LaunchUrl(const GURL& url, int render_process_host_id, int tab_contents_id) { -#if !defined(OS_LINUX) // Escape the input scheme to be sure that the command does not // have parameters unexpected by the external program. std::string escaped_url_string = EscapeExternalHandlerValue(url.spec()); @@ -145,90 +135,35 @@ void ExternalProtocolHandler::LaunchUrl(const GURL& url, } #else // For now, allow only whitelisted protocols to fire. - // TODO(port): implement dialog for Mac + // 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 - // Put this work on the file thread since ShellExecute may block for a - // significant amount of time. + // Otherwise the protocol is white-listed, so go ahead and launch. +#if defined(OS_MACOSX) + // This must run on the main thread on OS X. + LaunchUrlWithoutSecurityCheck(escaped_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. MessageLoop* loop = g_browser_process->file_thread()->message_loop(); if (loop == NULL) { return; } - // Otherwise the protocol is white-listed, so go ahead and launch. loop->PostTask(FROM_HERE, NewRunnableFunction( &ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck, escaped_url)); -#else - // TODO(port): Implement launching external handler. - NOTIMPLEMENTED(); #endif } // static void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(const GURL& url) { -#if defined(OS_WIN) - // Quote the input scheme to be sure that the command does not have - // parameters unexpected by the external program. This url should already - // have been escaped. - std::string escaped_url = url.spec(); - escaped_url.insert(0, "\""); - escaped_url += "\""; - - // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp: - // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in - // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 - // support URLS of 2083 chars in length, 2K is safe." - const size_t kMaxUrlLength = 2048; - if (escaped_url.length() > kMaxUrlLength) { - NOTREACHED(); - return; - } - - RegKey key; - std::wstring registry_path = ASCIIToWide(url.scheme()) + - L"\\shell\\open\\command"; - key.Open(HKEY_CLASSES_ROOT, registry_path.c_str()); - if (key.Valid()) { - DWORD size = 0; - key.ReadValue(NULL, NULL, &size); - if (size <= 2) { - // ShellExecute crashes the process when the command is empty. - // We check for "2" because it always returns the trailing NULL. - // TODO(nsylvain): we should also add a dialog to warn on errors. See - // bug 1136923. - return; - } - } - - if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open", - escaped_url.c_str(), NULL, NULL, - SW_SHOWNORMAL)) <= 32) { - // We fail to execute the call. We could display a message to the user. - // TODO(nsylvain): we should also add a dialog to warn on errors. See - // bug 1136923. - return; - } -#elif defined(OS_MACOSX) - scoped_cftyperef<CFStringRef> string_ref( - base::SysUTF8ToCFStringRef(url.spec())); - if (!string_ref) - return; - - scoped_cftyperef<CFURLRef> url_ref(CFURLCreateWithString(kCFAllocatorDefault, - string_ref, - NULL)); - if (!url_ref) - return; - - LSOpenCFURLRef(url_ref, NULL); -#elif defined(OS_LINUX) - // TODO(port): Implement launching external handler. - NOTIMPLEMENTED(); -#endif + platform_util::OpenExternal(url); } // static diff --git a/chrome/common/platform_util.h b/chrome/common/platform_util.h index 54e7487..cb3c5e0 100644 --- a/chrome/common/platform_util.h +++ b/chrome/common/platform_util.h @@ -9,6 +9,7 @@ #include "base/string16.h" class FilePath; +class GURL; namespace platform_util { @@ -18,6 +19,10 @@ void ShowItemInFolder(const FilePath& full_path); // Open the given file in the desktop's default manner. void OpenItem(const FilePath& full_path); +// Open the given external protocol URL in the desktop's default manner. +// (For example, mailto: URLs in the default mail user agent.) +void OpenExternal(const GURL& url); + // Get the top level window for the native view. This can return NULL. gfx::NativeWindow GetTopLevel(gfx::NativeView view); diff --git a/chrome/common/platform_util_linux.cc b/chrome/common/platform_util_linux.cc index 778e046..b211898 100644 --- a/chrome/common/platform_util_linux.cc +++ b/chrome/common/platform_util_linux.cc @@ -10,13 +10,14 @@ #include "base/process_util.h" #include "base/string_util.h" #include "chrome/common/process_watcher.h" +#include "googleurl/src/gurl.h" namespace { -void XDGOpen(const FilePath& path) { +void XDGOpen(const std::string& path) { std::vector<std::string> argv; argv.push_back("xdg-open"); - argv.push_back(path.value()); + argv.push_back(path); base::environment_vector env; // xdg-open can fall back on mailcap which eventually might plumb through @@ -43,11 +44,15 @@ void ShowItemInFolder(const FilePath& full_path) { if (!file_util::DirectoryExists(dir)) return; - XDGOpen(dir); + XDGOpen(dir.value()); } void OpenItem(const FilePath& full_path) { - XDGOpen(full_path); + XDGOpen(full_path.value()); +} + +void OpenExternal(const GURL& url) { + XDGOpen(url.spec()); } gfx::NativeWindow GetTopLevel(gfx::NativeView view) { diff --git a/chrome/common/platform_util_mac.mm b/chrome/common/platform_util_mac.mm index b8787ea8..9c4cbe2 100644 --- a/chrome/common/platform_util_mac.mm +++ b/chrome/common/platform_util_mac.mm @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/sys_string_conversions.h" #include "chrome/browser/cocoa/tab_window_controller.h" +#include "googleurl/src/gurl.h" #include "grit/generated_resources.h" namespace platform_util { @@ -28,6 +29,13 @@ void OpenItem(const FilePath& full_path) { [[NSWorkspace sharedWorkspace] openFile:path_string]; } +void OpenExternal(const GURL& url) { + DCHECK_EQ([NSThread currentThread], [NSThread mainThread]); + NSString* url_string = base::SysUTF8ToNSString(url.spec()); + NSURL* ns_url = [NSURL URLWithString:url_string]; + [[NSWorkspace sharedWorkspace] openURL:ns_url]; +} + gfx::NativeWindow GetTopLevel(gfx::NativeView view) { return [view window]; } diff --git a/chrome/common/platform_util_win.cc b/chrome/common/platform_util_win.cc index e3cd5db..b602388 100644 --- a/chrome/common/platform_util_win.cc +++ b/chrome/common/platform_util_win.cc @@ -16,7 +16,9 @@ #include "base/file_util.h" #include "base/gfx/native_widget_types.h" #include "base/logging.h" +#include "base/registry.h" #include "base/string_util.h" +#include "googleurl/src/gurl.h" namespace platform_util { @@ -86,6 +88,50 @@ void OpenItem(const FilePath& full_path) { win_util::OpenItemViaShell(full_path); } +void OpenExternal(const GURL& url) { + // Quote the input scheme to be sure that the command does not have + // parameters unexpected by the external program. This url should already + // have been escaped. + std::string escaped_url = url.spec(); + escaped_url.insert(0, "\""); + escaped_url += "\""; + + // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp: + // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in + // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 + // support URLS of 2083 chars in length, 2K is safe." + const size_t kMaxUrlLength = 2048; + if (escaped_url.length() > kMaxUrlLength) { + NOTREACHED(); + return; + } + + RegKey key; + std::wstring registry_path = ASCIIToWide(url.scheme()) + + L"\\shell\\open\\command"; + key.Open(HKEY_CLASSES_ROOT, registry_path.c_str()); + if (key.Valid()) { + DWORD size = 0; + key.ReadValue(NULL, NULL, &size); + if (size <= 2) { + // ShellExecute crashes the process when the command is empty. + // We check for "2" because it always returns the trailing NULL. + // TODO(nsylvain): we should also add a dialog to warn on errors. See + // bug 1136923. + return; + } + } + + if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open", + escaped_url.c_str(), NULL, NULL, + SW_SHOWNORMAL)) <= 32) { + // We fail to execute the call. We could display a message to the user. + // TODO(nsylvain): we should also add a dialog to warn on errors. See + // bug 1136923. + return; + } +} + gfx::NativeWindow GetTopLevel(gfx::NativeView view) { return GetAncestor(view, GA_ROOT); } |