| Index: chrome/browser/external_protocol/external_protocol_handler.cc
|
| diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
|
| index 7388dd94b1337446098063e7f742f9f0a6c88aeb..a6dd49b33790b1b4ac511252f610158174a8781b 100644
|
| --- a/chrome/browser/external_protocol/external_protocol_handler.cc
|
| +++ b/chrome/browser/external_protocol/external_protocol_handler.cc
|
| @@ -24,6 +24,116 @@
|
| // each user gesture. This variable should only be accessed from the UI thread.
|
| static bool g_accept_requests = true;
|
|
|
| +namespace {
|
| +
|
| +// Functions enabling unit testing. Using a NULL delegate will use the default
|
| +// behavior; if a delegate is provided it will be used instead.
|
| +ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker(
|
| + ShellIntegration::DefaultWebClientObserver* observer,
|
| + const std::string& protocol,
|
| + ExternalProtocolHandler::Delegate* delegate) {
|
| + if (!delegate)
|
| + return new ShellIntegration::DefaultProtocolClientWorker(observer,
|
| + protocol);
|
| +
|
| + return delegate->CreateShellWorker(observer, protocol);
|
| +}
|
| +
|
| +ExternalProtocolHandler::BlockState GetBlockStateWithDelegate(
|
| + const std::string& scheme,
|
| + ExternalProtocolHandler::Delegate* delegate) {
|
| + if (!delegate)
|
| + return ExternalProtocolHandler::GetBlockState(scheme);
|
| +
|
| + return delegate->GetBlockState(scheme);
|
| +}
|
| +
|
| +void RunExternalProtocolDialogWithDelegate(
|
| + const GURL& url,
|
| + int render_process_host_id,
|
| + int routing_id,
|
| + ExternalProtocolHandler::Delegate* delegate) {
|
| + if (!delegate) {
|
| + ExternalProtocolHandler::RunExternalProtocolDialog(url,
|
| + render_process_host_id,
|
| + routing_id);
|
| + } else {
|
| + delegate->RunExternalProtocolDialog(url, render_process_host_id,
|
| + routing_id);
|
| + }
|
| +}
|
| +
|
| +void LaunchUrlWithoutSecurityCheckWithDelegate(
|
| + const GURL& url,
|
| + ExternalProtocolHandler::Delegate* delegate) {
|
| + if (!delegate)
|
| + ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url);
|
| + else
|
| + delegate->LaunchUrlWithoutSecurityCheck(url);
|
| +}
|
| +
|
| +// When we are about to launch a URL with the default OS level application,
|
| +// we check if that external application will be us. If it is we just ignore
|
| +// the request.
|
| +class ExternalDefaultProtocolObserver
|
| + : public ShellIntegration::DefaultWebClientObserver {
|
| + public:
|
| + ExternalDefaultProtocolObserver(const GURL& escaped_url,
|
| + int render_process_host_id,
|
| + int tab_contents_id,
|
| + bool prompt_user,
|
| + ExternalProtocolHandler::Delegate* delegate)
|
| + : delegate_(delegate),
|
| + escaped_url_(escaped_url),
|
| + render_process_host_id_(render_process_host_id),
|
| + tab_contents_id_(tab_contents_id),
|
| + prompt_user_(prompt_user) {}
|
| +
|
| + virtual void SetDefaultWebClientUIState(
|
| + ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
|
| + DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
|
| +
|
| + // If we are still working out if we're the default, or we've found
|
| + // out we definately are the default, we end here.
|
| + if (state == ShellIntegration::STATE_PROCESSING) {
|
| + return;
|
| + }
|
| +
|
| + if (delegate_)
|
| + delegate_->FinishedProcessingCheck();
|
| +
|
| + if (state == ShellIntegration::STATE_IS_DEFAULT) {
|
| + if (delegate_)
|
| + delegate_->BlockRequest();
|
| + return;
|
| + }
|
| +
|
| + // If we get here, either we are not the default or we cannot work out
|
| + // what the default is, so we proceed.
|
| + if (prompt_user_) {
|
| + // Ask the user if they want to allow the protocol. This will call
|
| + // LaunchUrlWithoutSecurityCheck if the user decides to accept the
|
| + // protocol.
|
| + RunExternalProtocolDialogWithDelegate(escaped_url_,
|
| + render_process_host_id_, tab_contents_id_, delegate_);
|
| + return;
|
| + }
|
| +
|
| + LaunchUrlWithoutSecurityCheckWithDelegate(escaped_url_, delegate_);
|
| + }
|
| +
|
| + virtual bool IsOwnedByWorker() OVERRIDE { return true; }
|
| +
|
| + private:
|
| + ExternalProtocolHandler::Delegate* delegate_;
|
| + GURL escaped_url_;
|
| + int render_process_host_id_;
|
| + int tab_contents_id_;
|
| + bool prompt_user_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| // static
|
| void ExternalProtocolHandler::PrepopulateDictionary(DictionaryValue* win_pref) {
|
| static bool is_warm = false;
|
| @@ -126,31 +236,42 @@ void ExternalProtocolHandler::SetBlockState(const std::string& scheme,
|
| }
|
|
|
| // static
|
| -void ExternalProtocolHandler::LaunchUrl(const GURL& url,
|
| - int render_process_host_id,
|
| - int tab_contents_id) {
|
| +void ExternalProtocolHandler::LaunchUrlWithDelegate(const GURL& url,
|
| + int render_process_host_id,
|
| + int tab_contents_id,
|
| + Delegate* delegate) {
|
| DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
|
|
|
| // 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());
|
| GURL escaped_url(escaped_url_string);
|
| - BlockState block_state = GetBlockState(escaped_url.scheme());
|
| - if (block_state == BLOCK)
|
| + BlockState block_state = GetBlockStateWithDelegate(escaped_url.scheme(),
|
| + delegate);
|
| + if (block_state == BLOCK) {
|
| + if (delegate)
|
| + delegate->BlockRequest();
|
| return;
|
| + }
|
|
|
| g_accept_requests = false;
|
|
|
| - if (block_state == UNKNOWN) {
|
| - // Ask the user if they want to allow the protocol. This will call
|
| - // LaunchUrlWithoutSecurityCheck if the user decides to accept the protocol.
|
| - RunExternalProtocolDialog(escaped_url,
|
| - render_process_host_id,
|
| - tab_contents_id);
|
| - return;
|
| - }
|
| + // The worker creates tasks with references to itself and puts them into
|
| + // message loops. When no tasks are left it will delete the observer and
|
| + // eventually be deleted itself.
|
| + ShellIntegration::DefaultWebClientObserver* observer =
|
| + new ExternalDefaultProtocolObserver(url,
|
| + render_process_host_id,
|
| + tab_contents_id,
|
| + block_state == UNKNOWN,
|
| + delegate);
|
| + scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker =
|
| + CreateShellWorker(observer, escaped_url.scheme(), delegate);
|
|
|
| - LaunchUrlWithoutSecurityCheck(escaped_url);
|
| + // Start the check process running. This will send tasks to the FILE thread
|
| + // and when the answer is known will send the result back to the observer on
|
| + // the UI thread.
|
| + worker->StartCheckIsDefault();
|
| }
|
|
|
| // static
|
|
|