普通文本  |  132行  |  4.09 KB

// 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/memory/scoped_ptr.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 "content/browser/child_process_security_policy.h"
#include "net/base/network_delegate.h"
#include "net/url_request/url_request_redirect_job.h"


// 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);
  }
}

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::CanSchemeBeOverridden(
    const std::string& scheme) const {
  return GetHandlerFor(scheme) != NULL ||
    !net::URLRequest::IsHandledProtocol(scheme);
}

bool ProtocolHandlerRegistry::IsAlreadyRegistered(
    const ProtocolHandler* handler) const {
  ProtocolHandler* currentHandler = GetHandlerFor(handler->protocol());
  return currentHandler && *currentHandler == *handler;
}

net::URLRequestJob* ProtocolHandlerRegistry::Factory(net::URLRequest* request,
    const std::string& scheme) {
  return request->context()->network_delegate()->MaybeCreateURLRequestJob(
      request);
}


net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
    net::URLRequest* request) const {
  ProtocolHandler* handler = GetHandlerFor(request->url().scheme());

  if (!handler) {
    return NULL;
  }

  GURL translated_url(handler->TranslateUrl(request->url()));

  if (!translated_url.is_valid()) {
    return NULL;
  }

  return new net::URLRequestRedirectJob(request, translated_url);
}

ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {}

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);
}