This source file includes following definitions.
- CreateShellWorker
 
- GetBlockStateWithDelegate
 
- RunExternalProtocolDialogWithDelegate
 
- LaunchUrlWithoutSecurityCheckWithDelegate
 
- prompt_user_
 
- SetDefaultWebClientUIState
 
- IsOwnedByWorker
 
- PrepopulateDictionary
 
- GetBlockState
 
- SetBlockState
 
- LaunchUrlWithDelegate
 
- LaunchUrlWithoutSecurityCheck
 
- RegisterPrefs
 
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include <set>
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/strings/string_util.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "net/base/escape.h"
#include "url/gurl.h"
using content::BrowserThread;
namespace {
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,
    bool initiated_by_user_gesture) {
  if (!delegate)
    return ExternalProtocolHandler::GetBlockState(scheme,
                                                  initiated_by_user_gesture);
  return delegate->GetBlockState(scheme, initiated_by_user_gesture);
}
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,
    int render_process_host_id,
    int tab_contents_id,
    ExternalProtocolHandler::Delegate* delegate) {
  if (!delegate) {
    ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(
        url, render_process_host_id, tab_contents_id);
  } else {
    delegate->LaunchUrlWithoutSecurityCheck(url);
  }
}
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(base::MessageLoopForUI::IsCurrent());
    
    
    if (state == ShellIntegration::STATE_PROCESSING) {
      return;
    }
    if (delegate_)
      delegate_->FinishedProcessingCheck();
    if (state == ShellIntegration::STATE_IS_DEFAULT) {
      if (delegate_)
        delegate_->BlockRequest();
      return;
    }
    
    
    if (prompt_user_) {
      
      
      
      RunExternalProtocolDialogWithDelegate(escaped_url_,
          render_process_host_id_, tab_contents_id_, delegate_);
      return;
    }
    LaunchUrlWithoutSecurityCheckWithDelegate(
        escaped_url_, render_process_host_id_, tab_contents_id_, 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_;
};
}  
void ExternalProtocolHandler::PrepopulateDictionary(
    base::DictionaryValue* win_pref) {
  static bool is_warm = false;
  if (is_warm)
    return;
  is_warm = true;
  static const char* const denied_schemes[] = {
    "afp",
    "data",
    "disk",
    "disks",
    
    
    
    
    "file",
    "hcp",
    "javascript",
    "ms-help",
    "nntp",
    "shell",
    "vbscript",
    
    
    
    "view-source",
    "vnd.ms.radio",
  };
  static const char* const allowed_schemes[] = {
    "mailto",
    "news",
    "snews",
#if defined(OS_WIN)
    "ms-windows-store",
#endif
  };
  bool should_block;
  for (size_t i = 0; i < arraysize(denied_schemes); ++i) {
    if (!win_pref->GetBoolean(denied_schemes[i], &should_block)) {
      win_pref->SetBoolean(denied_schemes[i], true);
    }
  }
  for (size_t i = 0; i < arraysize(allowed_schemes); ++i) {
    if (!win_pref->GetBoolean(allowed_schemes[i], &should_block)) {
      win_pref->SetBoolean(allowed_schemes[i], false);
    }
  }
}
ExternalProtocolHandler::BlockState ExternalProtocolHandler::GetBlockState(
    const std::string& scheme,
    bool initiated_by_user_gesture) {
  if (!initiated_by_user_gesture)
    return BLOCK;
  if (scheme.length() == 1) {
    
    
    
    return BLOCK;
  }
  
  
  
  PrefService* pref = g_browser_process->local_state();
  if (pref) {  
    DictionaryPrefUpdate update_excluded_schemas(pref, prefs::kExcludedSchemes);
    
    PrepopulateDictionary(update_excluded_schemas.Get());
    bool should_block;
    if (update_excluded_schemas->GetBoolean(scheme, &should_block))
      return should_block ? BLOCK : DONT_BLOCK;
  }
  return UNKNOWN;
}
void ExternalProtocolHandler::SetBlockState(const std::string& scheme,
                                            BlockState state) {
  
  
  
  PrefService* pref = g_browser_process->local_state();
  if (pref) {  
    DictionaryPrefUpdate update_excluded_schemas(pref, prefs::kExcludedSchemes);
    if (state == UNKNOWN) {
      update_excluded_schemas->Remove(scheme, NULL);
    } else {
      update_excluded_schemas->SetBoolean(scheme, (state == BLOCK));
    }
  }
}
void ExternalProtocolHandler::LaunchUrlWithDelegate(
    const GURL& url,
    int render_process_host_id,
    int tab_contents_id,
    Delegate* delegate,
    bool initiated_by_user_gesture) {
  DCHECK(base::MessageLoopForUI::IsCurrent());
  
  
  std::string escaped_url_string = net::EscapeExternalHandlerValue(url.spec());
  GURL escaped_url(escaped_url_string);
  BlockState block_state = GetBlockStateWithDelegate(escaped_url.scheme(),
                                                     delegate,
                                                     initiated_by_user_gesture);
  if (block_state == BLOCK) {
    if (delegate)
      delegate->BlockRequest();
    return;
  }
  
  
  
  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);
  
  
  
  worker->StartCheckIsDefault();
}
void ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(
    const GURL& url,
    int render_process_host_id,
    int tab_contents_id) {
  content::WebContents* web_contents = tab_util::GetWebContentsByID(
      render_process_host_id, tab_contents_id);
  if (!web_contents)
    return;
  platform_util::OpenExternal(
      Profile::FromBrowserContext(web_contents->GetBrowserContext()), url);
}
void ExternalProtocolHandler::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterDictionaryPref(prefs::kExcludedSchemes);
}