Chromium Code Reviews| Index: chrome/browser/custom_handlers/protocol_handler_registry.cc |
| diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1c20ffd690af3dba8699bfa77bcbdd030c61ef22 |
| --- /dev/null |
| +++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc |
| @@ -0,0 +1,167 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" |
| + |
| +#include "base/scoped_ptr.h" |
| +#include "base/string_util.h" |
| +#include "chrome/browser/child_process_security_policy.h" |
| +#include "chrome/browser/custom_handlers/register_protocol_handler_infobar_delegate.h" |
| +#include "chrome/browser/net/chrome_url_request_context.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "net/base/escape.h" |
| +#include "net/url_request/url_request_redirect_job.h" |
| + |
| +// ProtocolHandler ------------------------------------------------------------- |
| + |
| +ProtocolHandler::ProtocolHandler(const std::string& protocol, |
| + const GURL& url, |
| + const string16& title) |
| + :protocol_(protocol), |
| + url_(url), |
| + title_(title) { |
| +} |
| + |
| +ProtocolHandler* ProtocolHandler::CreateProtocolHandler( |
| + const std::string& protocol, |
| + const GURL& url, |
| + const string16& title) { |
| + // TODO(koz) Check for bad protocol and url here. |
|
tony
2011/02/14 23:40:07
We should probably make sure we have this check be
koz (OOO until 15th September)
2011/02/15 03:37:27
I talked with Ojan earlier about validating input
|
| + std::string lower_protocol(protocol); |
| + lower_protocol = StringToLowerASCII(protocol); |
| + return new ProtocolHandler(lower_protocol, url, title); |
| +} |
| + |
| +ProtocolHandler* ProtocolHandler::CreateProtocolHandler(const DictionaryValue* value) { |
|
tony
2011/02/14 23:40:07
80 cols here and in lots of other places. Please
koz (OOO until 15th September)
2011/02/15 03:37:27
Done.
|
| + std::string protocol, url; |
| + string16 title; |
| + value->GetString("protocol", &protocol); |
| + value->GetString("url", &url); |
| + value->GetString("title", &title); |
| + return ProtocolHandler::CreateProtocolHandler(protocol, GURL(url), title); |
| +} |
| + |
| +GURL ProtocolHandler::TranslateUrl(const GURL& url) { |
| + std::string translatedUrlSpec(url_.spec()); |
| + ReplaceSubstringsAfterOffset(&translatedUrlSpec, 0, "%s", |
| + EscapeQueryParamValue(url.spec(), true)); |
| + return GURL(translatedUrlSpec); |
| +} |
| + |
| +Value* ProtocolHandler::Encode() { |
| + DictionaryValue* d = new DictionaryValue(); |
| + d->Set("protocol", Value::CreateStringValue(protocol_)); |
| + d->Set("url", Value::CreateStringValue(url_.spec())); |
| + d->Set("title", Value::CreateStringValue(title_)); |
| + return d; |
| +} |
| + |
| +bool ProtocolHandler::operator==(const ProtocolHandler &other) const { |
| + return protocol_ == other.protocol_ && |
| + url_ == other.url_ && |
| + title_ == other.title_; |
| +} |
| + |
| +// ProtocolHandlerRegistry ------------------------------------------------------------- |
| + |
| +ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile) |
| + :profile_(profile) { |
| +} |
| + |
| +void ProtocolHandlerRegistry::RegisterProtocolHandler(ProtocolHandler* handler) { |
| + if (protocolHandlers_.find(handler->protocol()) == protocolHandlers_.end()) { |
| + ChildProcessSecurityPolicy* policy = ChildProcessSecurityPolicy::GetInstance(); |
| + if (!policy->IsWebSafeScheme(handler->protocol())) { |
| + policy->RegisterWebSafeScheme(handler->protocol()); |
| + } |
| + net::URLRequest::RegisterProtocolFactory(handler->protocol(), |
| + &ProtocolHandlerRegistry::Factory); |
| + } |
| + protocolHandlers_[handler->protocol()] = handler; |
| +} |
| + |
| +void ProtocolHandlerRegistry::Load() { |
| + PrefService* prefs = profile_->GetPrefs(); |
| + if (!prefs->HasPrefPath(prefs::kRegisteredProtocolHandlers)) { |
| + return; |
| + } |
| + const ListValue* protocolHandlers = prefs->GetList(prefs::kRegisteredProtocolHandlers); |
| + |
| + for (size_t i = 0; i < protocolHandlers->GetSize(); i++) { |
| + DictionaryValue* dict; |
| + protocolHandlers->GetDictionary(i, &dict); |
| + RegisterHandlerFromValue(dict); |
| + } |
| +} |
| + |
| +void ProtocolHandlerRegistry::RegisterHandlerFromValue(const DictionaryValue* value) { |
| + ProtocolHandler* handler = ProtocolHandler::CreateProtocolHandler(value); |
| + if (handler) { |
| + RegisterProtocolHandler(handler); |
| + } else { |
| + } |
|
tony
2011/02/14 23:40:07
Remove empty else?
koz (OOO until 15th September)
2011/02/15 03:37:27
Done.
|
| +} |
| + |
| +void ProtocolHandlerRegistry::Save() { |
| + scoped_ptr<Value> value(Encode()); |
| + profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers, *value); |
| + profile_->GetPrefs()->ScheduleSavePersistentPrefs(); |
| +} |
| + |
| +ProtocolHandler* ProtocolHandlerRegistry::GetHandlerFor(const std::string& scheme) const { |
| + ProtocolHandlerMap::const_iterator i = protocolHandlers_.find(scheme); |
| + return i == protocolHandlers_.end() ? NULL : i->second; |
| +} |
| + |
| +bool ProtocolHandlerRegistry::IsAlreadyRegistered(const ProtocolHandler* handler) const { |
| + ProtocolHandler* currentHandler = GetHandlerFor(handler->protocol()); |
| + return currentHandler && *currentHandler == *handler; |
| +} |
| + |
| +net::URLRequestJob* ProtocolHandlerRegistry::CreateJob(net::URLRequest* request, |
| + const std::string& scheme) const { |
| + ProtocolHandler* handler = GetHandlerFor(scheme); |
| + |
| + if (!handler) { |
| + return NULL; |
| + } |
| + |
| + GURL translatedUrl(handler->TranslateUrl(request->url())); |
| + |
| + if (!translatedUrl.is_valid()) { |
| + return NULL; |
| + } |
| + |
| + return new net::URLRequestRedirectJob(request, translatedUrl); |
| +} |
| + |
| +net::URLRequestJob* ProtocolHandlerRegistry::Factory(net::URLRequest* request, |
| + const std::string& scheme) { |
| + ChromeURLRequestContext* context = |
| + reinterpret_cast<ChromeURLRequestContext*>(request->context()); |
|
tony
2011/02/14 23:40:07
I think this should be a static_cast.
koz (OOO until 15th September)
2011/02/15 03:37:27
Done.
|
| + return context->protocol_handler_registry()->CreateJob(request, scheme); |
| +} |
| + |
| +Value* ProtocolHandlerRegistry::Encode() { |
| + ListValue* protocolHandlers = new ListValue(); |
| + |
| + for (ProtocolHandlerMap::iterator i = protocolHandlers_.begin(); |
| + i != protocolHandlers_.end(); ++i) { |
| + protocolHandlers->Append(i->second->Encode()); |
| + } |
| + return protocolHandlers; |
| +} |
| + |
| +void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(ProtocolHandler* handler) { |
| + RegisterProtocolHandler(handler); |
| + Save(); |
| +} |
| + |
| +void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(ProtocolHandler* handler) { |
| + |
| +} |
| + |
| +void ProtocolHandlerRegistry::RegisterPrefs(PrefService* prefService) { |
| + prefService->RegisterListPref(prefs::kRegisteredProtocolHandlers); |
| +} |