1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/net/chrome_url_request_context.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/common/pref_names.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/child_process_security_policy.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/network_delegate.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/url_request/url_request_redirect_job.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// ProtocolHandlerRegistry -----------------------------------------------------
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
18dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile)
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  :profile_(profile) {
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::RegisterProtocolHandler(
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ProtocolHandler* handler) {
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (protocolHandlers_.find(handler->protocol()) == protocolHandlers_.end()) {
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ChildProcessSecurityPolicy* policy =
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ChildProcessSecurityPolicy::GetInstance();
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!policy->IsWebSafeScheme(handler->protocol())) {
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      policy->RegisterWebSafeScheme(handler->protocol());
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    net::URLRequest::RegisterProtocolFactory(handler->protocol(),
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        &ProtocolHandlerRegistry::Factory);
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  protocolHandlers_[handler->protocol()] = handler;
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::Load() {
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PrefService* prefs = profile_->GetPrefs();
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!prefs->HasPrefPath(prefs::kRegisteredProtocolHandlers)) {
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const ListValue* protocolHandlers =
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    prefs->GetList(prefs::kRegisteredProtocolHandlers);
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (size_t i = 0; i < protocolHandlers->GetSize(); i++) {
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DictionaryValue* dict;
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    protocolHandlers->GetDictionary(i, &dict);
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    RegisterHandlerFromValue(dict);
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::RegisterHandlerFromValue(
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const DictionaryValue* value) {
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ProtocolHandler* handler = ProtocolHandler::CreateProtocolHandler(value);
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (handler) {
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    RegisterProtocolHandler(handler);
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::Save() {
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<Value> value(Encode());
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers, *value);
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  profile_->GetPrefs()->ScheduleSavePersistentPrefs();
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
65dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenProtocolHandler* ProtocolHandlerRegistry::GetHandlerFor(
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& scheme) const {
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ProtocolHandlerMap::const_iterator i = protocolHandlers_.find(scheme);
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return i == protocolHandlers_.end() ? NULL : i->second;
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool ProtocolHandlerRegistry::CanSchemeBeOverridden(
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& scheme) const {
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return GetHandlerFor(scheme) != NULL ||
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    !net::URLRequest::IsHandledProtocol(scheme);
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool ProtocolHandlerRegistry::IsAlreadyRegistered(
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const ProtocolHandler* handler) const {
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ProtocolHandler* currentHandler = GetHandlerFor(handler->protocol());
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return currentHandler && *currentHandler == *handler;
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennet::URLRequestJob* ProtocolHandlerRegistry::Factory(net::URLRequest* request,
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& scheme) {
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return request->context()->network_delegate()->MaybeCreateURLRequestJob(
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      request);
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennet::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    net::URLRequest* request) const {
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProtocolHandler* handler = GetHandlerFor(request->url().scheme());
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!handler) {
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return NULL;
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL translated_url(handler->TranslateUrl(request->url()));
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!translated_url.is_valid()) {
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return NULL;
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return new net::URLRequestRedirectJob(request, translated_url);
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
107dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenProtocolHandlerRegistry::~ProtocolHandlerRegistry() {}
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenValue* ProtocolHandlerRegistry::Encode() {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ListValue* protocolHandlers = new ListValue();
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (ProtocolHandlerMap::iterator i = protocolHandlers_.begin();
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      i != protocolHandlers_.end(); ++i) {
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    protocolHandlers->Append(i->second->Encode());
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return protocolHandlers;
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ProtocolHandler* handler) {
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RegisterProtocolHandler(handler);
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Save();
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ProtocolHandler* handler) {
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ProtocolHandlerRegistry::RegisterPrefs(PrefService* prefService) {
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  prefService->RegisterListPref(prefs::kRegisteredProtocolHandlers);
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
132