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