| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/external_protocol_handler.h" | 5 #include "chrome/browser/external_protocol_handler.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "base/thread.h" | 14 #include "base/thread.h" |
| 15 #include "chrome/browser/browser.h" | 15 #include "chrome/browser/browser.h" |
| 16 #include "chrome/browser/browser_process_impl.h" | 16 #include "chrome/browser/browser_process_impl.h" |
| 17 #include "chrome/common/platform_util.h" | 17 #include "chrome/common/platform_util.h" |
| 18 #include "chrome/common/pref_service.h" | 18 #include "chrome/common/pref_service.h" |
| 19 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 20 #include "googleurl/src/gurl.h" | 20 #include "googleurl/src/gurl.h" |
| 21 #include "net/base/escape.h" | 21 #include "net/base/escape.h" |
| 22 | 22 |
| 23 // Whether we accept requests for launching external protocols. This is set to |
| 24 // false every time an external protocol is requested, and set back to true on |
| 25 // each user gesture. This variable should only be accessed from the UI thread. |
| 26 static bool g_accept_requests = true; |
| 27 |
| 23 // static | 28 // static |
| 24 void ExternalProtocolHandler::PrepopulateDictionary(DictionaryValue* win_pref) { | 29 void ExternalProtocolHandler::PrepopulateDictionary(DictionaryValue* win_pref) { |
| 25 static bool is_warm = false; | 30 static bool is_warm = false; |
| 26 if (is_warm) | 31 if (is_warm) |
| 27 return; | 32 return; |
| 28 is_warm = true; | 33 is_warm = true; |
| 29 | 34 |
| 30 static const wchar_t* const denied_schemes[] = { | 35 static const wchar_t* const denied_schemes[] = { |
| 31 L"afp", | 36 L"afp", |
| 32 L"data", | 37 L"data", |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 for (size_t i = 0; i < arraysize(allowed_schemes); ++i) { | 71 for (size_t i = 0; i < arraysize(allowed_schemes); ++i) { |
| 67 if (!win_pref->GetBoolean(allowed_schemes[i], &should_block)) { | 72 if (!win_pref->GetBoolean(allowed_schemes[i], &should_block)) { |
| 68 win_pref->SetBoolean(allowed_schemes[i], false); | 73 win_pref->SetBoolean(allowed_schemes[i], false); |
| 69 } | 74 } |
| 70 } | 75 } |
| 71 } | 76 } |
| 72 | 77 |
| 73 // static | 78 // static |
| 74 ExternalProtocolHandler::BlockState ExternalProtocolHandler::GetBlockState( | 79 ExternalProtocolHandler::BlockState ExternalProtocolHandler::GetBlockState( |
| 75 const std::wstring& scheme) { | 80 const std::wstring& scheme) { |
| 81 // If we are being carpet bombed, block the request. |
| 82 if (!g_accept_requests) |
| 83 return BLOCK; |
| 84 |
| 76 if (scheme.length() == 1) { | 85 if (scheme.length() == 1) { |
| 77 // We have a URL that looks something like: | 86 // We have a URL that looks something like: |
| 78 // C:/WINDOWS/system32/notepad.exe | 87 // C:/WINDOWS/system32/notepad.exe |
| 79 // ShellExecuting this URL will cause the specified program to be executed. | 88 // ShellExecuting this URL will cause the specified program to be executed. |
| 80 return BLOCK; | 89 return BLOCK; |
| 81 } | 90 } |
| 82 | 91 |
| 83 // Check the stored prefs. | 92 // Check the stored prefs. |
| 84 // TODO(pkasting): http://b/119651 This kind of thing should go in the | 93 // TODO(pkasting): http://b/119651 This kind of thing should go in the |
| 85 // preferences on the profile, not in the local state. | 94 // preferences on the profile, not in the local state. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 97 return should_block ? BLOCK : DONT_BLOCK; | 106 return should_block ? BLOCK : DONT_BLOCK; |
| 98 } | 107 } |
| 99 | 108 |
| 100 return UNKNOWN; | 109 return UNKNOWN; |
| 101 } | 110 } |
| 102 | 111 |
| 103 // static | 112 // static |
| 104 void ExternalProtocolHandler::LaunchUrl(const GURL& url, | 113 void ExternalProtocolHandler::LaunchUrl(const GURL& url, |
| 105 int render_process_host_id, | 114 int render_process_host_id, |
| 106 int tab_contents_id) { | 115 int tab_contents_id) { |
| 116 DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()); |
| 117 |
| 107 // Escape the input scheme to be sure that the command does not | 118 // Escape the input scheme to be sure that the command does not |
| 108 // have parameters unexpected by the external program. | 119 // have parameters unexpected by the external program. |
| 109 std::string escaped_url_string = EscapeExternalHandlerValue(url.spec()); | 120 std::string escaped_url_string = EscapeExternalHandlerValue(url.spec()); |
| 110 GURL escaped_url(escaped_url_string); | 121 GURL escaped_url(escaped_url_string); |
| 111 BlockState block_state = GetBlockState(ASCIIToWide(escaped_url.scheme())); | 122 BlockState block_state = GetBlockState(ASCIIToWide(escaped_url.scheme())); |
| 112 if (block_state == BLOCK) | 123 if (block_state == BLOCK) |
| 113 return; | 124 return; |
| 114 | 125 |
| 115 if (block_state == UNKNOWN) { | 126 if (block_state == UNKNOWN) { |
| 116 #if defined(OS_WIN) || defined(TOOLKIT_GTK) | 127 #if defined(OS_WIN) || defined(TOOLKIT_GTK) |
| 128 g_accept_requests = false; |
| 117 // Ask the user if they want to allow the protocol. This will call | 129 // Ask the user if they want to allow the protocol. This will call |
| 118 // LaunchUrlWithoutSecurityCheck if the user decides to accept the protocol. | 130 // LaunchUrlWithoutSecurityCheck if the user decides to accept the protocol. |
| 119 RunExternalProtocolDialog(escaped_url, | 131 RunExternalProtocolDialog(escaped_url, |
| 120 render_process_host_id, | 132 render_process_host_id, |
| 121 tab_contents_id); | 133 tab_contents_id); |
| 122 #endif | 134 #endif |
| 123 // For now, allow only whitelisted protocols to fire on Mac and Linux/Views. | 135 // For now, allow only whitelisted protocols to fire on Mac and Linux/Views. |
| 124 // See http://crbug.com/15546. | 136 // See http://crbug.com/15546. |
| 125 return; | 137 return; |
| 126 } | 138 } |
| 127 | 139 |
| 128 LaunchUrlWithoutSecurityCheck(escaped_url); | 140 LaunchUrlWithoutSecurityCheck(escaped_url); |
| 129 } | 141 } |
| 130 | 142 |
| 131 // static | 143 // static |
| 132 void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(const GURL& url) { | 144 void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(const GURL& url) { |
| 133 #if defined(OS_MACOSX) | 145 #if defined(OS_MACOSX) |
| 134 // This must run on the main thread on OS X. | 146 // This must run on the UI thread on OS X. |
| 135 platform_util::OpenExternal(url); | 147 platform_util::OpenExternal(url); |
| 136 #else | 148 #else |
| 137 // Otherwise put this work on the file thread. On Windows ShellExecute may | 149 // Otherwise put this work on the file thread. On Windows ShellExecute may |
| 138 // block for a significant amount of time, and it shouldn't hurt on Linux. | 150 // block for a significant amount of time, and it shouldn't hurt on Linux. |
| 139 MessageLoop* loop = g_browser_process->file_thread()->message_loop(); | 151 MessageLoop* loop = g_browser_process->file_thread()->message_loop(); |
| 140 if (loop == NULL) { | 152 if (loop == NULL) { |
| 141 return; | 153 return; |
| 142 } | 154 } |
| 143 | 155 |
| 144 loop->PostTask(FROM_HERE, | 156 loop->PostTask(FROM_HERE, |
| 145 NewRunnableFunction(&platform_util::OpenExternal, url)); | 157 NewRunnableFunction(&platform_util::OpenExternal, url)); |
| 146 #endif | 158 #endif |
| 147 } | 159 } |
| 148 | 160 |
| 149 // static | 161 // static |
| 150 void ExternalProtocolHandler::RegisterPrefs(PrefService* prefs) { | 162 void ExternalProtocolHandler::RegisterPrefs(PrefService* prefs) { |
| 151 prefs->RegisterDictionaryPref(prefs::kExcludedSchemes); | 163 prefs->RegisterDictionaryPref(prefs::kExcludedSchemes); |
| 152 } | 164 } |
| 165 |
| 166 // static |
| 167 void ExternalProtocolHandler::OnUserGesture() { |
| 168 DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()); |
| 169 g_accept_requests = true; |
| 170 } |
| OLD | NEW |