Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1792)

Unified Diff: chrome/browser/custom_handlers/protocol_handler_registry.cc

Issue 10071036: RefCounted types should not have public destructors, chrome/browser/ part 6 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Implementation fixes Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
index d81af988fc58af5d2e7f30e6b30679ff451d30bf..ab8753a58b5fab79be1633c088a6bdec5088e091 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -27,172 +27,224 @@
using content::BrowserThread;
using content::ChildProcessSecurityPolicy;
-// ProtocolHandlerRegistry -----------------------------------------------------
+namespace {
-ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile,
- Delegate* delegate)
- : profile_(profile),
- delegate_(delegate),
- enabled_(true),
- enabled_io_(enabled_),
- is_loading_(false) {
+// If true default protocol handlers will be removed if the OS level
+// registration for a protocol is no longer Chrome.
+bool ShouldRemoveHandlersNotInOS() {
+#if defined(OS_LINUX)
+ // We don't do this on Linux as the OS registration there is not reliable,
+ // and Chrome OS doesn't have any notion of OS registration.
+ // TODO(benwells): When Linux support is more reliable remove this
+ // difference (http://crbug.com/88255).
+ return false;
+#else
+ return ShellIntegration::CanSetAsDefaultProtocolClient();
+#endif
}
-ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(default_client_observers_.empty());
-}
+} // namespace
-void ProtocolHandlerRegistry::Finalize() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- delegate_.reset(NULL);
- // We free these now in case there are any outstanding workers running. If
- // we didn't free them they could respond to workers and try to update the
- // protocol handler registry after it was deleted.
- // Observers remove themselves from this list when they are deleted; so
- // we delete the last item until none are left in the list.
- while (!default_client_observers_.empty()) {
- delete default_client_observers_.back();
+static const ProtocolHandler& LookupHandler(
+ const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
+ const std::string& scheme) {
+ ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p =
+ handler_map.find(scheme);
+ if (p != handler_map.end()) {
+ return p->second;
}
+ return ProtocolHandler::EmptyProtocolHandler();
}
-const ProtocolHandlerRegistry::ProtocolHandlerList*
-ProtocolHandlerRegistry::GetHandlerList(
- const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
- if (p == protocol_handlers_.end()) {
- return NULL;
- }
- return &p->second;
+// DefaultClientObserver ------------------------------------------------------
+
+ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver(
+ ProtocolHandlerRegistry* registry)
+ : worker_(NULL),
+ registry_(registry) {
+ DCHECK(registry_);
}
-ProtocolHandlerRegistry::ProtocolHandlerList
-ProtocolHandlerRegistry::GetHandlersFor(
- const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
- if (p == protocol_handlers_.end()) {
- return ProtocolHandlerList();
+ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() {
+ if (worker_)
+ worker_->ObserverDestroyed();
+
+ DefaultClientObserverList::iterator iter = std::find(
+ registry_->default_client_observers_.begin(),
+ registry_->default_client_observers_.end(), this);
+ registry_->default_client_observers_.erase(iter);
+}
+
+void
+ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
+ ShellIntegration::DefaultWebClientUIState state) {
+ if (worker_) {
+ if (ShouldRemoveHandlersNotInOS() &&
+ (state == ShellIntegration::STATE_NOT_DEFAULT)) {
+ registry_->ClearDefault(worker_->protocol());
+ }
+ } else {
+ NOTREACHED();
}
- return p->second;
}
-ProtocolHandlerRegistry::ProtocolHandlerList
-ProtocolHandlerRegistry::GetIgnoredHandlers() {
- return ignored_protocol_handlers_;
+void ProtocolHandlerRegistry::DefaultClientObserver::SetWorker(
+ ShellIntegration::DefaultProtocolClientWorker* worker) {
+ worker_ = worker;
}
-void ProtocolHandlerRegistry::RegisterProtocolHandler(
- const ProtocolHandler& handler) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(CanSchemeBeOverridden(handler.protocol()));
- DCHECK(!handler.IsEmpty());
- if (IsRegistered(handler)) {
- return;
+// Delegate --------------------------------------------------------------------
+
+ProtocolHandlerRegistry::Delegate::~Delegate() {}
+
+void ProtocolHandlerRegistry::Delegate::RegisterExternalHandler(
+ const std::string& protocol) {
+ ChildProcessSecurityPolicy* policy =
+ ChildProcessSecurityPolicy::GetInstance();
+ if (!policy->IsWebSafeScheme(protocol)) {
+ policy->RegisterWebSafeScheme(protocol);
}
- if (enabled_ && !delegate_->IsExternalHandlerRegistered(handler.protocol()))
- delegate_->RegisterExternalHandler(handler.protocol());
- InsertHandler(handler);
}
-void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProtocolHandlerMultiMap::iterator p =
- protocol_handlers_.find(handler.protocol());
+void ProtocolHandlerRegistry::Delegate::DeregisterExternalHandler(
+ const std::string& protocol) {
+}
- if (p != protocol_handlers_.end()) {
- p->second.push_back(handler);
- return;
- }
+bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered(
+ const std::string& protocol) {
+ // NOTE(koz): This function is safe to call from any thread, despite living
+ // in ProfileIOData.
+ return ProfileIOData::IsHandledProtocol(protocol);
+}
- ProtocolHandlerList new_list;
- new_list.push_back(handler);
- protocol_handlers_[handler.protocol()] = new_list;
+ShellIntegration::DefaultProtocolClientWorker*
+ProtocolHandlerRegistry::Delegate::CreateShellWorker(
+ ShellIntegration::DefaultWebClientObserver* observer,
+ const std::string& protocol) {
+ return new ShellIntegration::DefaultProtocolClientWorker(observer, protocol);
}
-void ProtocolHandlerRegistry::IgnoreProtocolHandler(
+ProtocolHandlerRegistry::DefaultClientObserver*
+ProtocolHandlerRegistry::Delegate::CreateShellObserver(
+ ProtocolHandlerRegistry* registry) {
+ return new DefaultClientObserver(registry);
+}
+
+void ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(
+ const std::string& protocol, ProtocolHandlerRegistry* registry) {
+ DefaultClientObserver* observer = CreateShellObserver(registry);
+ // The worker pointer is reference counted. While it is running the
+ // message loops of the FILE and UI thread will hold references to it
+ // and it will be automatically freed once all its tasks have finished.
+ scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker;
+ worker = CreateShellWorker(observer, protocol);
+ observer->SetWorker(worker);
+ registry->default_client_observers_.push_back(observer);
+ worker->StartSetAsDefault();
+}
+
+// ProtocolHandlerRegistry -----------------------------------------------------
+
+ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile,
+ Delegate* delegate)
+ : profile_(profile),
+ delegate_(delegate),
+ enabled_(true),
+ enabled_io_(enabled_),
+ is_loading_(false) {
+}
+
+bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest(
+ const ProtocolHandler& handler) {
+ if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol()))
+ return true;
+
+ if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler))
+ return true;
+
+ if (AttemptReplace(handler))
+ return true;
+
+ return false;
+}
+
+void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ignored_protocol_handlers_.push_back(handler);
+ RegisterProtocolHandler(handler);
+ SetDefault(handler);
+ Save();
+ NotifyChanged();
}
-void ProtocolHandlerRegistry::Enable() {
+void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(
+ const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (enabled_) {
- return;
- }
- enabled_ = true;
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ProtocolHandlerRegistry::EnableIO, this));
- ProtocolHandlerMap::const_iterator p;
- for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
- delegate_->RegisterExternalHandler(p->first);
- }
+ RegisterProtocolHandler(handler);
Save();
NotifyChanged();
}
-void ProtocolHandlerRegistry::Disable() {
+void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler(
+ const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!enabled_) {
- return;
- }
- enabled_ = false;
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ProtocolHandlerRegistry::DisableIO, this));
- ProtocolHandlerMap::const_iterator p;
- for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
- delegate_->DeregisterExternalHandler(p->first);
- }
+ IgnoreProtocolHandler(handler);
Save();
NotifyChanged();
}
-std::vector<const DictionaryValue*>
-ProtocolHandlerRegistry::GetHandlersFromPref(const char* pref_name) const {
+bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::vector<const DictionaryValue*> result;
- PrefService* prefs = profile_->GetPrefs();
- if (!prefs->HasPrefPath(pref_name)) {
- return result;
+ ProtocolHandler old_default = GetHandlerFor(handler.protocol());
+ bool make_new_handler_default = handler.IsSameOrigin(old_default);
+ ProtocolHandlerList to_replace(GetReplacedHandlers(handler));
+ if (to_replace.empty())
+ return false;
+ for (ProtocolHandlerList::iterator p = to_replace.begin();
+ p != to_replace.end(); ++p) {
+ RemoveHandler(*p);
}
+ if (make_new_handler_default) {
+ OnAcceptRegisterProtocolHandler(handler);
+ } else {
+ InsertHandler(handler);
+ NotifyChanged();
+ }
+ return true;
+}
- const ListValue* handlers = prefs->GetList(pref_name);
- if (handlers) {
- for (size_t i = 0; i < handlers->GetSize(); ++i) {
- DictionaryValue* dict;
- if (!handlers->GetDictionary(i, &dict))
- continue;
- if (ProtocolHandler::IsValidDict(dict)) {
- result.push_back(dict);
- }
+ProtocolHandlerRegistry::ProtocolHandlerList
+ProtocolHandlerRegistry::GetReplacedHandlers(
+ const ProtocolHandler& handler) const {
+ ProtocolHandlerList replaced_handlers;
+ const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
+ if (!handlers)
+ return replaced_handlers;
+ for (ProtocolHandlerList::const_iterator p = handlers->begin();
+ p != handlers->end(); p++) {
+ if (handler.IsSameOrigin(*p)) {
+ replaced_handlers.push_back(*p);
}
}
- return result;
+ return replaced_handlers;
}
-namespace {
-
-// If true default protocol handlers will be removed if the OS level
-// registration for a protocol is no longer Chrome.
-bool ShouldRemoveHandlersNotInOS() {
-#if defined(OS_LINUX)
- // We don't do this on Linux as the OS registration there is not reliable,
- // and Chrome OS doesn't have any notion of OS registration.
- // TODO(benwells): When Linux support is more reliable remove this
- // difference (http://crbug.com/88255).
- return false;
-#else
- return ShellIntegration::CanSetAsDefaultProtocolClient();
-#endif
+void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ default_handlers_.erase(scheme);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme));
+ Save();
+ NotifyChanged();
}
-} // namespace
+bool ProtocolHandlerRegistry::IsDefault(
+ const ProtocolHandler& handler) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return GetHandlerFor(handler.protocol()) == handler;
+}
void ProtocolHandlerRegistry::Load() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -243,30 +295,38 @@ void ProtocolHandlerRegistry::Load() {
}
}
-void ProtocolHandlerRegistry::Save() {
+int ProtocolHandlerRegistry::GetHandlerIndex(const std::string& scheme) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ const ProtocolHandler& handler = GetHandlerFor(scheme);
+ if (handler.IsEmpty())
+ return -1;
+ const ProtocolHandlerList* handlers = GetHandlerList(scheme);
+ if (!handlers)
+ return -1;
+
+ ProtocolHandlerList::const_iterator p;
+ int i;
+ for (i = 0, p = handlers->begin(); p != handlers->end(); ++p, ++i) {
+ if (*p == handler)
+ return i;
+ }
+ return -1;
+}
+
+ProtocolHandlerRegistry::ProtocolHandlerList
+ProtocolHandlerRegistry::GetHandlersFor(
+ const std::string& scheme) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (is_loading_) {
- return;
+ ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
+ if (p == protocol_handlers_.end()) {
+ return ProtocolHandlerList();
}
- scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers());
- scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers());
- scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_));
- profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers,
- *registered_protocol_handlers);
- profile_->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers,
- *ignored_protocol_handlers);
- profile_->GetPrefs()->Set(prefs::kCustomHandlersEnabled, *enabled);
+ return p->second;
}
-bool ProtocolHandlerRegistry::CanSchemeBeOverridden(
- const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- const ProtocolHandlerList* handlers = GetHandlerList(scheme);
- // If we already have a handler for this scheme, we can add more.
- if (handlers != NULL && !handlers->empty())
- return true;
- // Don't override a scheme if it already has an external handler.
- return !delegate_->IsExternalHandlerRegistered(scheme);
+ProtocolHandlerRegistry::ProtocolHandlerList
+ProtocolHandlerRegistry::GetIgnoredHandlers() {
+ return ignored_protocol_handlers_;
}
void ProtocolHandlerRegistry::GetRegisteredProtocols(
@@ -279,20 +339,15 @@ void ProtocolHandlerRegistry::GetRegisteredProtocols(
}
}
-void ProtocolHandlerRegistry::RemoveIgnoredHandler(
- const ProtocolHandler& handler) {
+bool ProtocolHandlerRegistry::CanSchemeBeOverridden(
+ const std::string& scheme) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- bool should_notify = false;
- ProtocolHandlerList::iterator p = std::find(
- ignored_protocol_handlers_.begin(), ignored_protocol_handlers_.end(),
- handler);
- if (p != ignored_protocol_handlers_.end()) {
- ignored_protocol_handlers_.erase(p);
- Save();
- should_notify = true;
- }
- if (should_notify)
- NotifyChanged();
+ const ProtocolHandlerList* handlers = GetHandlerList(scheme);
+ // If we already have a handler for this scheme, we can add more.
+ if (handlers != NULL && !handlers->empty())
+ return true;
+ // Don't override a scheme if it already has an external handler.
+ return !delegate_->IsExternalHandlerRegistered(scheme);
}
bool ProtocolHandlerRegistry::IsRegistered(
@@ -306,6 +361,18 @@ bool ProtocolHandlerRegistry::IsRegistered(
handlers->end();
}
+bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler& handler) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ProtocolHandlerList::const_iterator i;
+ for (i = ignored_protocol_handlers_.begin();
+ i != ignored_protocol_handlers_.end(); ++i) {
+ if (*i == handler) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool ProtocolHandlerRegistry::HasRegisteredEquivalent(
const ProtocolHandler& handler) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -322,29 +389,33 @@ bool ProtocolHandlerRegistry::HasRegisteredEquivalent(
return false;
}
-bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler& handler) const {
+bool ProtocolHandlerRegistry::HasIgnoredEquivalent(
+ const ProtocolHandler& handler) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ProtocolHandlerList::const_iterator i;
for (i = ignored_protocol_handlers_.begin();
i != ignored_protocol_handlers_.end(); ++i) {
- if (*i == handler) {
+ if (handler.IsEquivalent(*i)) {
return true;
}
}
return false;
}
-bool ProtocolHandlerRegistry::HasIgnoredEquivalent(
- const ProtocolHandler& handler) const {
+void ProtocolHandlerRegistry::RemoveIgnoredHandler(
+ const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProtocolHandlerList::const_iterator i;
- for (i = ignored_protocol_handlers_.begin();
- i != ignored_protocol_handlers_.end(); ++i) {
- if (handler.IsEquivalent(*i)) {
- return true;
- }
+ bool should_notify = false;
+ ProtocolHandlerList::iterator p = std::find(
+ ignored_protocol_handlers_.begin(), ignored_protocol_handlers_.end(),
+ handler);
+ if (p != ignored_protocol_handlers_.end()) {
+ ignored_protocol_handlers_.erase(p);
+ Save();
+ should_notify = true;
}
- return false;
+ if (should_notify)
+ NotifyChanged();
}
bool ProtocolHandlerRegistry::IsHandledProtocol(
@@ -353,6 +424,12 @@ bool ProtocolHandlerRegistry::IsHandledProtocol(
return enabled_ && !GetHandlerFor(scheme).IsEmpty();
}
+bool ProtocolHandlerRegistry::IsHandledProtocolIO(
+ const std::string& scheme) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return enabled_io_ && !LookupHandler(default_handlers_io_, scheme).IsEmpty();
+}
+
void ProtocolHandlerRegistry::RemoveHandler(
const ProtocolHandler& handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -391,186 +468,89 @@ void ProtocolHandlerRegistry::RemoveDefaultHandler(const std::string& scheme) {
RemoveHandler(current_default);
}
-static const ProtocolHandler& LookupHandler(
- const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
- const std::string& scheme) {
- ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p =
- handler_map.find(scheme);
- if (p != handler_map.end()) {
- return p->second;
- }
- return ProtocolHandler::EmptyProtocolHandler();
-}
-
-Value* ProtocolHandlerRegistry::EncodeRegisteredHandlers() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ListValue* protocol_handlers = new ListValue();
- for (ProtocolHandlerMultiMap::iterator i = protocol_handlers_.begin();
- i != protocol_handlers_.end(); ++i) {
- for (ProtocolHandlerList::iterator j = i->second.begin();
- j != i->second.end(); ++j) {
- DictionaryValue* encoded = j->Encode();
- if (IsDefault(*j)) {
- encoded->Set("default", Value::CreateBooleanValue(true));
- }
- protocol_handlers->Append(encoded);
- }
- }
- return protocol_handlers;
-}
-
-Value* ProtocolHandlerRegistry::EncodeIgnoredHandlers() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ListValue* handlers = new ListValue();
- for (ProtocolHandlerList::iterator i = ignored_protocol_handlers_.begin();
- i != ignored_protocol_handlers_.end(); ++i) {
- handlers->Append(i->Encode());
- }
- return handlers;
-}
-
-bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest(
- const ProtocolHandler& handler) {
- if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol()))
- return true;
-
- if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler))
- return true;
-
- if (AttemptReplace(handler))
- return true;
-
- return false;
-}
-
-void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
- const ProtocolHandler& handler) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RegisterProtocolHandler(handler);
- SetDefault(handler);
- Save();
- NotifyChanged();
-}
-
-void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(
- const ProtocolHandler& handler) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RegisterProtocolHandler(handler);
- Save();
- NotifyChanged();
-}
-
-void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler(
- const ProtocolHandler& handler) {
+const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor(
+ const std::string& scheme) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- IgnoreProtocolHandler(handler);
- Save();
- NotifyChanged();
+ return LookupHandler(default_handlers_, scheme);
}
-bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProtocolHandler old_default = GetHandlerFor(handler.protocol());
- bool make_new_handler_default = handler.IsSameOrigin(old_default);
- ProtocolHandlerList to_replace(GetReplacedHandlers(handler));
- if (to_replace.empty())
- return false;
- for (ProtocolHandlerList::iterator p = to_replace.begin();
- p != to_replace.end(); ++p) {
- RemoveHandler(*p);
- }
- if (make_new_handler_default) {
- OnAcceptRegisterProtocolHandler(handler);
- } else {
- InsertHandler(handler);
- NotifyChanged();
+net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
+ net::URLRequest* request) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ProtocolHandler handler = LookupHandler(default_handlers_io_,
+ request->url().scheme());
+ if (handler.IsEmpty()) {
+ return NULL;
}
- return true;
-}
-
-ProtocolHandlerRegistry::ProtocolHandlerList
-ProtocolHandlerRegistry::GetReplacedHandlers(
- const ProtocolHandler& handler) const {
- ProtocolHandlerList replaced_handlers;
- const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
- if (!handlers)
- return replaced_handlers;
- for (ProtocolHandlerList::const_iterator p = handlers->begin();
- p != handlers->end(); p++) {
- if (handler.IsSameOrigin(*p)) {
- replaced_handlers.push_back(*p);
- }
+ GURL translated_url(handler.TranslateUrl(request->url()));
+ if (!translated_url.is_valid()) {
+ return NULL;
}
- return replaced_handlers;
-}
-
-
-// static
-void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) {
- pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers,
- PrefService::UNSYNCABLE_PREF);
- pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers,
- PrefService::UNSYNCABLE_PREF);
- pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true,
- PrefService::UNSYNCABLE_PREF);
+ return new net::URLRequestRedirectJob(request, translated_url);
}
-void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) {
+void ProtocolHandlerRegistry::Enable() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ProtocolHandlerMap::const_iterator p = default_handlers_.find(
- handler.protocol());
- // If we're not loading, and we are setting a default for a new protocol,
- // register with the OS.
- if (!is_loading_ && p == default_handlers_.end())
- delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this);
- default_handlers_.erase(handler.protocol());
- default_handlers_.insert(std::make_pair(handler.protocol(), handler));
- PromoteHandler(handler);
+ if (enabled_) {
+ return;
+ }
+ enabled_ = true;
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler));
+ base::Bind(&ProtocolHandlerRegistry::EnableIO, this));
+ ProtocolHandlerMap::const_iterator p;
+ for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
+ delegate_->RegisterExternalHandler(p->first);
+ }
+ Save();
+ NotifyChanged();
}
-void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) {
+void ProtocolHandlerRegistry::Disable() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- default_handlers_.erase(scheme);
+ if (!enabled_) {
+ return;
+ }
+ enabled_ = false;
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme));
+ base::Bind(&ProtocolHandlerRegistry::DisableIO, this));
+ ProtocolHandlerMap::const_iterator p;
+ for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
+ delegate_->DeregisterExternalHandler(p->first);
+ }
Save();
NotifyChanged();
}
-bool ProtocolHandlerRegistry::IsDefault(
- const ProtocolHandler& handler) const {
+void ProtocolHandlerRegistry::Finalize() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return GetHandlerFor(handler.protocol()) == handler;
+ delegate_.reset(NULL);
+ // We free these now in case there are any outstanding workers running. If
+ // we didn't free them they could respond to workers and try to update the
+ // protocol handler registry after it was deleted.
+ // Observers remove themselves from this list when they are deleted; so
+ // we delete the last item until none are left in the list.
+ while (!default_client_observers_.empty()) {
+ delete default_client_observers_.back();
+ }
}
-const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor(
- const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return LookupHandler(default_handlers_, scheme);
+// static
+void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) {
+ pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers,
+ PrefService::UNSYNCABLE_PREF);
+ pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers,
+ PrefService::UNSYNCABLE_PREF);
+ pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true,
+ PrefService::UNSYNCABLE_PREF);
}
-int ProtocolHandlerRegistry::GetHandlerIndex(const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- const ProtocolHandler& handler = GetHandlerFor(scheme);
- if (handler.IsEmpty())
- return -1;
- const ProtocolHandlerList* handlers = GetHandlerList(scheme);
- if (!handlers)
- return -1;
-
- ProtocolHandlerList::const_iterator p;
- int i;
- for (i = 0, p = handlers->begin(); p != handlers->end(); ++p, ++i) {
- if (*p == handler)
- return i;
- }
- return -1;
+ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(default_client_observers_.empty());
}
void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) {
@@ -583,16 +563,6 @@ void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) {
list.insert(list.begin(), handler);
}
-void ProtocolHandlerRegistry::NotifyChanged() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
- content::Source<Profile>(profile_),
- content::NotificationService::NoDetails());
-}
-
-// IO thread methods -----------------------------------------------------------
-
void ProtocolHandlerRegistry::ClearDefaultIO(const std::string& scheme) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
default_handlers_io_.erase(scheme);
@@ -604,110 +574,137 @@ void ProtocolHandlerRegistry::SetDefaultIO(const ProtocolHandler& handler) {
default_handlers_io_.insert(std::make_pair(handler.protocol(), handler));
}
-bool ProtocolHandlerRegistry::IsHandledProtocolIO(
- const std::string& scheme) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return enabled_io_ && !LookupHandler(default_handlers_io_, scheme).IsEmpty();
+void ProtocolHandlerRegistry::Save() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (is_loading_) {
+ return;
+ }
+ scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers());
+ scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers());
+ scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_));
+ profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers,
+ *registered_protocol_handlers);
+ profile_->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers,
+ *ignored_protocol_handlers);
+ profile_->GetPrefs()->Set(prefs::kCustomHandlersEnabled, *enabled);
}
-net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
- net::URLRequest* request) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ProtocolHandler handler = LookupHandler(default_handlers_io_,
- request->url().scheme());
- if (handler.IsEmpty()) {
- return NULL;
- }
- GURL translated_url(handler.TranslateUrl(request->url()));
- if (!translated_url.is_valid()) {
+const ProtocolHandlerRegistry::ProtocolHandlerList*
+ProtocolHandlerRegistry::GetHandlerList(
+ const std::string& scheme) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
+ if (p == protocol_handlers_.end()) {
return NULL;
}
- return new net::URLRequestRedirectJob(request, translated_url);
+ return &p->second;
}
-// Delegate --------------------------------------------------------------------
-
-ProtocolHandlerRegistry::Delegate::~Delegate() {
+void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ProtocolHandlerMap::const_iterator p = default_handlers_.find(
+ handler.protocol());
+ // If we're not loading, and we are setting a default for a new protocol,
+ // register with the OS.
+ if (!is_loading_ && p == default_handlers_.end())
+ delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this);
+ default_handlers_.erase(handler.protocol());
+ default_handlers_.insert(std::make_pair(handler.protocol(), handler));
+ PromoteHandler(handler);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler));
}
-void ProtocolHandlerRegistry::Delegate::RegisterExternalHandler(
- const std::string& protocol) {
- ChildProcessSecurityPolicy* policy =
- ChildProcessSecurityPolicy::GetInstance();
- if (!policy->IsWebSafeScheme(protocol)) {
- policy->RegisterWebSafeScheme(protocol);
- }
-}
+void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ProtocolHandlerMultiMap::iterator p =
+ protocol_handlers_.find(handler.protocol());
-void ProtocolHandlerRegistry::Delegate::DeregisterExternalHandler(
- const std::string& protocol) {
-}
+ if (p != protocol_handlers_.end()) {
+ p->second.push_back(handler);
+ return;
+ }
-ShellIntegration::DefaultProtocolClientWorker*
-ProtocolHandlerRegistry::Delegate::CreateShellWorker(
- ShellIntegration::DefaultWebClientObserver* observer,
- const std::string& protocol) {
- return new ShellIntegration::DefaultProtocolClientWorker(observer, protocol);
+ ProtocolHandlerList new_list;
+ new_list.push_back(handler);
+ protocol_handlers_[handler.protocol()] = new_list;
}
-ProtocolHandlerRegistry::DefaultClientObserver*
-ProtocolHandlerRegistry::Delegate::CreateShellObserver(
- ProtocolHandlerRegistry* registry) {
- return new DefaultClientObserver(registry);
+Value* ProtocolHandlerRegistry::EncodeRegisteredHandlers() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ListValue* protocol_handlers = new ListValue();
+ for (ProtocolHandlerMultiMap::iterator i = protocol_handlers_.begin();
+ i != protocol_handlers_.end(); ++i) {
+ for (ProtocolHandlerList::iterator j = i->second.begin();
+ j != i->second.end(); ++j) {
+ DictionaryValue* encoded = j->Encode();
+ if (IsDefault(*j)) {
+ encoded->Set("default", Value::CreateBooleanValue(true));
+ }
+ protocol_handlers->Append(encoded);
+ }
+ }
+ return protocol_handlers;
}
-void ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(
- const std::string& protocol, ProtocolHandlerRegistry* registry) {
- DefaultClientObserver* observer = CreateShellObserver(registry);
- // The worker pointer is reference counted. While it is running the
- // message loops of the FILE and UI thread will hold references to it
- // and it will be automatically freed once all its tasks have finished.
- scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker;
- worker = CreateShellWorker(observer, protocol);
- observer->SetWorker(worker);
- registry->default_client_observers_.push_back(observer);
- worker->StartSetAsDefault();
+Value* ProtocolHandlerRegistry::EncodeIgnoredHandlers() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ListValue* handlers = new ListValue();
+ for (ProtocolHandlerList::iterator i = ignored_protocol_handlers_.begin();
+ i != ignored_protocol_handlers_.end(); ++i) {
+ handlers->Append(i->Encode());
+ }
+ return handlers;
}
-bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered(
- const std::string& protocol) {
- // NOTE(koz): This function is safe to call from any thread, despite living
- // in ProfileIOData.
- return ProfileIOData::IsHandledProtocol(protocol);
+void ProtocolHandlerRegistry::NotifyChanged() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
+ content::Source<Profile>(profile_),
+ content::NotificationService::NoDetails());
}
-// DefaultClientObserver ------------------------------------------------------
-
-ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver(
- ProtocolHandlerRegistry* registry)
- : worker_(NULL), registry_(registry) {
- DCHECK(registry_);
+void ProtocolHandlerRegistry::RegisterProtocolHandler(
+ const ProtocolHandler& handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(CanSchemeBeOverridden(handler.protocol()));
+ DCHECK(!handler.IsEmpty());
+ if (IsRegistered(handler)) {
+ return;
+ }
+ if (enabled_ && !delegate_->IsExternalHandlerRegistered(handler.protocol()))
+ delegate_->RegisterExternalHandler(handler.protocol());
+ InsertHandler(handler);
}
-ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() {
- if (worker_) {
- worker_->ObserverDestroyed();
- };
- DefaultClientObserverList::iterator iter = std::find(
- registry_->default_client_observers_.begin(),
- registry_->default_client_observers_.end(), this);
- registry_->default_client_observers_.erase(iter);
-}
+std::vector<const DictionaryValue*>
+ProtocolHandlerRegistry::GetHandlersFromPref(const char* pref_name) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ std::vector<const DictionaryValue*> result;
+ PrefService* prefs = profile_->GetPrefs();
+ if (!prefs->HasPrefPath(pref_name)) {
+ return result;
+ }
-void
-ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
- ShellIntegration::DefaultWebClientUIState state) {
- if (worker_) {
- if (ShouldRemoveHandlersNotInOS() &&
- (state == ShellIntegration::STATE_NOT_DEFAULT)) {
- registry_->ClearDefault(worker_->protocol());
+ const ListValue* handlers = prefs->GetList(pref_name);
+ if (handlers) {
+ for (size_t i = 0; i < handlers->GetSize(); ++i) {
+ DictionaryValue* dict;
+ if (!handlers->GetDictionary(i, &dict))
+ continue;
+ if (ProtocolHandler::IsValidDict(dict)) {
+ result.push_back(dict);
+ }
}
- } else {
- NOTREACHED();
}
+ return result;
}
-void ProtocolHandlerRegistry::DefaultClientObserver::SetWorker(
- ShellIntegration::DefaultProtocolClientWorker* worker) {
- worker_ = worker;
+void ProtocolHandlerRegistry::IgnoreProtocolHandler(
+ const ProtocolHandler& handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ignored_protocol_handlers_.push_back(handler);
}

Powered by Google App Engine
This is Rietveld 408576698