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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 5 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg ate.h" 13 #include "chrome/browser/custom_handlers/register_protocol_handler_infobar_deleg ate.h"
14 #include "chrome/browser/net/chrome_url_request_context.h" 14 #include "chrome/browser/net/chrome_url_request_context.h"
15 #include "chrome/browser/prefs/pref_service.h" 15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/profiles/profile_io_data.h" 16 #include "chrome/browser/profiles/profile_io_data.h"
17 #include "chrome/common/chrome_notification_types.h" 17 #include "chrome/common/chrome_notification_types.h"
18 #include "chrome/common/chrome_switches.h" 18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/custom_handlers/protocol_handler.h" 19 #include "chrome/common/custom_handlers/protocol_handler.h"
20 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
21 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/child_process_security_policy.h" 22 #include "content/public/browser/child_process_security_policy.h"
23 #include "content/public/browser/notification_service.h" 23 #include "content/public/browser/notification_service.h"
24 #include "net/base/network_delegate.h" 24 #include "net/base/network_delegate.h"
25 #include "net/url_request/url_request_redirect_job.h" 25 #include "net/url_request/url_request_redirect_job.h"
26 26
27 using content::BrowserThread; 27 using content::BrowserThread;
28 using content::ChildProcessSecurityPolicy; 28 using content::ChildProcessSecurityPolicy;
29 29
30 // ProtocolHandlerRegistry -----------------------------------------------------
31
32 ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile,
33 Delegate* delegate)
34 : profile_(profile),
35 delegate_(delegate),
36 enabled_(true),
37 enabled_io_(enabled_),
38 is_loading_(false) {
39 }
40
41 ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
43 DCHECK(default_client_observers_.empty());
44 }
45
46 void ProtocolHandlerRegistry::Finalize() {
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48 delegate_.reset(NULL);
49 // We free these now in case there are any outstanding workers running. If
50 // we didn't free them they could respond to workers and try to update the
51 // protocol handler registry after it was deleted.
52 // Observers remove themselves from this list when they are deleted; so
53 // we delete the last item until none are left in the list.
54 while (!default_client_observers_.empty()) {
55 delete default_client_observers_.back();
56 }
57 }
58
59 const ProtocolHandlerRegistry::ProtocolHandlerList*
60 ProtocolHandlerRegistry::GetHandlerList(
61 const std::string& scheme) const {
62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
63 ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
64 if (p == protocol_handlers_.end()) {
65 return NULL;
66 }
67 return &p->second;
68 }
69
70 ProtocolHandlerRegistry::ProtocolHandlerList
71 ProtocolHandlerRegistry::GetHandlersFor(
72 const std::string& scheme) const {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74 ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
75 if (p == protocol_handlers_.end()) {
76 return ProtocolHandlerList();
77 }
78 return p->second;
79 }
80
81 ProtocolHandlerRegistry::ProtocolHandlerList
82 ProtocolHandlerRegistry::GetIgnoredHandlers() {
83 return ignored_protocol_handlers_;
84 }
85
86 void ProtocolHandlerRegistry::RegisterProtocolHandler(
87 const ProtocolHandler& handler) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
89 DCHECK(CanSchemeBeOverridden(handler.protocol()));
90 DCHECK(!handler.IsEmpty());
91 if (IsRegistered(handler)) {
92 return;
93 }
94 if (enabled_ && !delegate_->IsExternalHandlerRegistered(handler.protocol()))
95 delegate_->RegisterExternalHandler(handler.protocol());
96 InsertHandler(handler);
97 }
98
99 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
101 ProtocolHandlerMultiMap::iterator p =
102 protocol_handlers_.find(handler.protocol());
103
104 if (p != protocol_handlers_.end()) {
105 p->second.push_back(handler);
106 return;
107 }
108
109 ProtocolHandlerList new_list;
110 new_list.push_back(handler);
111 protocol_handlers_[handler.protocol()] = new_list;
112 }
113
114 void ProtocolHandlerRegistry::IgnoreProtocolHandler(
115 const ProtocolHandler& handler) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117 ignored_protocol_handlers_.push_back(handler);
118 }
119
120 void ProtocolHandlerRegistry::Enable() {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122 if (enabled_) {
123 return;
124 }
125 enabled_ = true;
126 BrowserThread::PostTask(
127 BrowserThread::IO,
128 FROM_HERE,
129 base::Bind(&ProtocolHandlerRegistry::EnableIO, this));
130 ProtocolHandlerMap::const_iterator p;
131 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
132 delegate_->RegisterExternalHandler(p->first);
133 }
134 Save();
135 NotifyChanged();
136 }
137
138 void ProtocolHandlerRegistry::Disable() {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 if (!enabled_) {
141 return;
142 }
143 enabled_ = false;
144 BrowserThread::PostTask(
145 BrowserThread::IO,
146 FROM_HERE,
147 base::Bind(&ProtocolHandlerRegistry::DisableIO, this));
148 ProtocolHandlerMap::const_iterator p;
149 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
150 delegate_->DeregisterExternalHandler(p->first);
151 }
152 Save();
153 NotifyChanged();
154 }
155
156 std::vector<const DictionaryValue*>
157 ProtocolHandlerRegistry::GetHandlersFromPref(const char* pref_name) const {
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
159 std::vector<const DictionaryValue*> result;
160 PrefService* prefs = profile_->GetPrefs();
161 if (!prefs->HasPrefPath(pref_name)) {
162 return result;
163 }
164
165 const ListValue* handlers = prefs->GetList(pref_name);
166 if (handlers) {
167 for (size_t i = 0; i < handlers->GetSize(); ++i) {
168 DictionaryValue* dict;
169 if (!handlers->GetDictionary(i, &dict))
170 continue;
171 if (ProtocolHandler::IsValidDict(dict)) {
172 result.push_back(dict);
173 }
174 }
175 }
176 return result;
177 }
178
179 namespace { 30 namespace {
180 31
181 // If true default protocol handlers will be removed if the OS level 32 // If true default protocol handlers will be removed if the OS level
182 // registration for a protocol is no longer Chrome. 33 // registration for a protocol is no longer Chrome.
183 bool ShouldRemoveHandlersNotInOS() { 34 bool ShouldRemoveHandlersNotInOS() {
184 #if defined(OS_LINUX) 35 #if defined(OS_LINUX)
185 // We don't do this on Linux as the OS registration there is not reliable, 36 // We don't do this on Linux as the OS registration there is not reliable,
186 // and Chrome OS doesn't have any notion of OS registration. 37 // and Chrome OS doesn't have any notion of OS registration.
187 // TODO(benwells): When Linux support is more reliable remove this 38 // TODO(benwells): When Linux support is more reliable remove this
188 // difference (http://crbug.com/88255). 39 // difference (http://crbug.com/88255).
189 return false; 40 return false;
190 #else 41 #else
191 return ShellIntegration::CanSetAsDefaultProtocolClient(); 42 return ShellIntegration::CanSetAsDefaultProtocolClient();
192 #endif 43 #endif
193 } 44 }
194 45
195 } // namespace 46 } // namespace
196 47
48 static const ProtocolHandler& LookupHandler(
49 const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map,
50 const std::string& scheme) {
51 ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p =
52 handler_map.find(scheme);
53 if (p != handler_map.end()) {
54 return p->second;
55 }
56 return ProtocolHandler::EmptyProtocolHandler();
57 }
58
59 // DefaultClientObserver ------------------------------------------------------
60
61 ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver(
62 ProtocolHandlerRegistry* registry)
63 : worker_(NULL),
64 registry_(registry) {
65 DCHECK(registry_);
66 }
67
68 ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() {
69 if (worker_)
70 worker_->ObserverDestroyed();
71
72 DefaultClientObserverList::iterator iter = std::find(
73 registry_->default_client_observers_.begin(),
74 registry_->default_client_observers_.end(), this);
75 registry_->default_client_observers_.erase(iter);
76 }
77
78 void
79 ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
80 ShellIntegration::DefaultWebClientUIState state) {
81 if (worker_) {
82 if (ShouldRemoveHandlersNotInOS() &&
83 (state == ShellIntegration::STATE_NOT_DEFAULT)) {
84 registry_->ClearDefault(worker_->protocol());
85 }
86 } else {
87 NOTREACHED();
88 }
89 }
90
91 void ProtocolHandlerRegistry::DefaultClientObserver::SetWorker(
92 ShellIntegration::DefaultProtocolClientWorker* worker) {
93 worker_ = worker;
94 }
95
96 // Delegate --------------------------------------------------------------------
97
98 ProtocolHandlerRegistry::Delegate::~Delegate() {}
99
100 void ProtocolHandlerRegistry::Delegate::RegisterExternalHandler(
101 const std::string& protocol) {
102 ChildProcessSecurityPolicy* policy =
103 ChildProcessSecurityPolicy::GetInstance();
104 if (!policy->IsWebSafeScheme(protocol)) {
105 policy->RegisterWebSafeScheme(protocol);
106 }
107 }
108
109 void ProtocolHandlerRegistry::Delegate::DeregisterExternalHandler(
110 const std::string& protocol) {
111 }
112
113 bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered(
114 const std::string& protocol) {
115 // NOTE(koz): This function is safe to call from any thread, despite living
116 // in ProfileIOData.
117 return ProfileIOData::IsHandledProtocol(protocol);
118 }
119
120 ShellIntegration::DefaultProtocolClientWorker*
121 ProtocolHandlerRegistry::Delegate::CreateShellWorker(
122 ShellIntegration::DefaultWebClientObserver* observer,
123 const std::string& protocol) {
124 return new ShellIntegration::DefaultProtocolClientWorker(observer, protocol);
125 }
126
127 ProtocolHandlerRegistry::DefaultClientObserver*
128 ProtocolHandlerRegistry::Delegate::CreateShellObserver(
129 ProtocolHandlerRegistry* registry) {
130 return new DefaultClientObserver(registry);
131 }
132
133 void ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(
134 const std::string& protocol, ProtocolHandlerRegistry* registry) {
135 DefaultClientObserver* observer = CreateShellObserver(registry);
136 // The worker pointer is reference counted. While it is running the
137 // message loops of the FILE and UI thread will hold references to it
138 // and it will be automatically freed once all its tasks have finished.
139 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker;
140 worker = CreateShellWorker(observer, protocol);
141 observer->SetWorker(worker);
142 registry->default_client_observers_.push_back(observer);
143 worker->StartSetAsDefault();
144 }
145
146 // ProtocolHandlerRegistry -----------------------------------------------------
147
148 ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile,
149 Delegate* delegate)
150 : profile_(profile),
151 delegate_(delegate),
152 enabled_(true),
153 enabled_io_(enabled_),
154 is_loading_(false) {
155 }
156
157 bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest(
158 const ProtocolHandler& handler) {
159 if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol()))
160 return true;
161
162 if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler))
163 return true;
164
165 if (AttemptReplace(handler))
166 return true;
167
168 return false;
169 }
170
171 void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
172 const ProtocolHandler& handler) {
173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
174 RegisterProtocolHandler(handler);
175 SetDefault(handler);
176 Save();
177 NotifyChanged();
178 }
179
180 void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler(
181 const ProtocolHandler& handler) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 RegisterProtocolHandler(handler);
184 Save();
185 NotifyChanged();
186 }
187
188 void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler(
189 const ProtocolHandler& handler) {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191 IgnoreProtocolHandler(handler);
192 Save();
193 NotifyChanged();
194 }
195
196 bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198 ProtocolHandler old_default = GetHandlerFor(handler.protocol());
199 bool make_new_handler_default = handler.IsSameOrigin(old_default);
200 ProtocolHandlerList to_replace(GetReplacedHandlers(handler));
201 if (to_replace.empty())
202 return false;
203 for (ProtocolHandlerList::iterator p = to_replace.begin();
204 p != to_replace.end(); ++p) {
205 RemoveHandler(*p);
206 }
207 if (make_new_handler_default) {
208 OnAcceptRegisterProtocolHandler(handler);
209 } else {
210 InsertHandler(handler);
211 NotifyChanged();
212 }
213 return true;
214 }
215
216 ProtocolHandlerRegistry::ProtocolHandlerList
217 ProtocolHandlerRegistry::GetReplacedHandlers(
218 const ProtocolHandler& handler) const {
219 ProtocolHandlerList replaced_handlers;
220 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
221 if (!handlers)
222 return replaced_handlers;
223 for (ProtocolHandlerList::const_iterator p = handlers->begin();
224 p != handlers->end(); p++) {
225 if (handler.IsSameOrigin(*p)) {
226 replaced_handlers.push_back(*p);
227 }
228 }
229 return replaced_handlers;
230 }
231
232 void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
234 default_handlers_.erase(scheme);
235 BrowserThread::PostTask(
236 BrowserThread::IO,
237 FROM_HERE,
238 base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme));
239 Save();
240 NotifyChanged();
241 }
242
243 bool ProtocolHandlerRegistry::IsDefault(
244 const ProtocolHandler& handler) const {
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
246 return GetHandlerFor(handler.protocol()) == handler;
247 }
248
197 void ProtocolHandlerRegistry::Load() { 249 void ProtocolHandlerRegistry::Load() {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
199 is_loading_ = true; 251 is_loading_ = true;
200 PrefService* prefs = profile_->GetPrefs(); 252 PrefService* prefs = profile_->GetPrefs();
201 if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) { 253 if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) {
202 enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled); 254 enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled);
203 BrowserThread::PostTask( 255 BrowserThread::PostTask(
204 BrowserThread::IO, 256 BrowserThread::IO,
205 FROM_HERE, 257 FROM_HERE,
206 base::Bind(enabled_ ? &ProtocolHandlerRegistry::EnableIO : 258 base::Bind(enabled_ ? &ProtocolHandlerRegistry::EnableIO :
(...skipping 29 matching lines...) Expand all
236 DefaultClientObserver* observer = delegate_->CreateShellObserver(this); 288 DefaultClientObserver* observer = delegate_->CreateShellObserver(this);
237 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker; 289 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker;
238 worker = delegate_->CreateShellWorker(observer, handler.protocol()); 290 worker = delegate_->CreateShellWorker(observer, handler.protocol());
239 observer->SetWorker(worker); 291 observer->SetWorker(worker);
240 default_client_observers_.push_back(observer); 292 default_client_observers_.push_back(observer);
241 worker->StartCheckIsDefault(); 293 worker->StartCheckIsDefault();
242 } 294 }
243 } 295 }
244 } 296 }
245 297
246 void ProtocolHandlerRegistry::Save() { 298 int ProtocolHandlerRegistry::GetHandlerIndex(const std::string& scheme) const {
247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
248 if (is_loading_) { 300 const ProtocolHandler& handler = GetHandlerFor(scheme);
249 return; 301 if (handler.IsEmpty())
302 return -1;
303 const ProtocolHandlerList* handlers = GetHandlerList(scheme);
304 if (!handlers)
305 return -1;
306
307 ProtocolHandlerList::const_iterator p;
308 int i;
309 for (i = 0, p = handlers->begin(); p != handlers->end(); ++p, ++i) {
310 if (*p == handler)
311 return i;
250 } 312 }
251 scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers()); 313 return -1;
252 scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers());
253 scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_));
254 profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers,
255 *registered_protocol_handlers);
256 profile_->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers,
257 *ignored_protocol_handlers);
258 profile_->GetPrefs()->Set(prefs::kCustomHandlersEnabled, *enabled);
259 } 314 }
260 315
261 bool ProtocolHandlerRegistry::CanSchemeBeOverridden( 316 ProtocolHandlerRegistry::ProtocolHandlerList
317 ProtocolHandlerRegistry::GetHandlersFor(
262 const std::string& scheme) const { 318 const std::string& scheme) const {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264 const ProtocolHandlerList* handlers = GetHandlerList(scheme); 320 ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
265 // If we already have a handler for this scheme, we can add more. 321 if (p == protocol_handlers_.end()) {
266 if (handlers != NULL && !handlers->empty()) 322 return ProtocolHandlerList();
267 return true; 323 }
268 // Don't override a scheme if it already has an external handler. 324 return p->second;
269 return !delegate_->IsExternalHandlerRegistered(scheme); 325 }
326
327 ProtocolHandlerRegistry::ProtocolHandlerList
328 ProtocolHandlerRegistry::GetIgnoredHandlers() {
329 return ignored_protocol_handlers_;
270 } 330 }
271 331
272 void ProtocolHandlerRegistry::GetRegisteredProtocols( 332 void ProtocolHandlerRegistry::GetRegisteredProtocols(
273 std::vector<std::string>* output) const { 333 std::vector<std::string>* output) const {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275 ProtocolHandlerMultiMap::const_iterator p; 335 ProtocolHandlerMultiMap::const_iterator p;
276 for (p = protocol_handlers_.begin(); p != protocol_handlers_.end(); ++p) { 336 for (p = protocol_handlers_.begin(); p != protocol_handlers_.end(); ++p) {
277 if (!p->second.empty()) 337 if (!p->second.empty())
278 output->push_back(p->first); 338 output->push_back(p->first);
279 } 339 }
280 } 340 }
281 341
282 void ProtocolHandlerRegistry::RemoveIgnoredHandler( 342 bool ProtocolHandlerRegistry::CanSchemeBeOverridden(
283 const ProtocolHandler& handler) { 343 const std::string& scheme) const {
284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
285 bool should_notify = false; 345 const ProtocolHandlerList* handlers = GetHandlerList(scheme);
286 ProtocolHandlerList::iterator p = std::find( 346 // If we already have a handler for this scheme, we can add more.
287 ignored_protocol_handlers_.begin(), ignored_protocol_handlers_.end(), 347 if (handlers != NULL && !handlers->empty())
288 handler); 348 return true;
289 if (p != ignored_protocol_handlers_.end()) { 349 // Don't override a scheme if it already has an external handler.
290 ignored_protocol_handlers_.erase(p); 350 return !delegate_->IsExternalHandlerRegistered(scheme);
291 Save();
292 should_notify = true;
293 }
294 if (should_notify)
295 NotifyChanged();
296 } 351 }
297 352
298 bool ProtocolHandlerRegistry::IsRegistered( 353 bool ProtocolHandlerRegistry::IsRegistered(
299 const ProtocolHandler& handler) const { 354 const ProtocolHandler& handler) const {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
301 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol()); 356 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
302 if (!handlers) { 357 if (!handlers) {
303 return false; 358 return false;
304 } 359 }
305 return std::find(handlers->begin(), handlers->end(), handler) != 360 return std::find(handlers->begin(), handlers->end(), handler) !=
306 handlers->end(); 361 handlers->end();
307 } 362 }
308 363
364 bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler& handler) const {
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
366 ProtocolHandlerList::const_iterator i;
367 for (i = ignored_protocol_handlers_.begin();
368 i != ignored_protocol_handlers_.end(); ++i) {
369 if (*i == handler) {
370 return true;
371 }
372 }
373 return false;
374 }
375
309 bool ProtocolHandlerRegistry::HasRegisteredEquivalent( 376 bool ProtocolHandlerRegistry::HasRegisteredEquivalent(
310 const ProtocolHandler& handler) const { 377 const ProtocolHandler& handler) const {
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol()); 379 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
313 if (!handlers) { 380 if (!handlers) {
314 return false; 381 return false;
315 } 382 }
316 ProtocolHandlerList::const_iterator i; 383 ProtocolHandlerList::const_iterator i;
317 for (i = handlers->begin(); i != handlers->end(); ++i) { 384 for (i = handlers->begin(); i != handlers->end(); ++i) {
318 if (handler.IsEquivalent(*i)) { 385 if (handler.IsEquivalent(*i)) {
319 return true; 386 return true;
320 } 387 }
321 } 388 }
322 return false; 389 return false;
323 } 390 }
324 391
325 bool ProtocolHandlerRegistry::IsIgnored(const ProtocolHandler& handler) const {
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
327 ProtocolHandlerList::const_iterator i;
328 for (i = ignored_protocol_handlers_.begin();
329 i != ignored_protocol_handlers_.end(); ++i) {
330 if (*i == handler) {
331 return true;
332 }
333 }
334 return false;
335 }
336
337 bool ProtocolHandlerRegistry::HasIgnoredEquivalent( 392 bool ProtocolHandlerRegistry::HasIgnoredEquivalent(
338 const ProtocolHandler& handler) const { 393 const ProtocolHandler& handler) const {
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
340 ProtocolHandlerList::const_iterator i; 395 ProtocolHandlerList::const_iterator i;
341 for (i = ignored_protocol_handlers_.begin(); 396 for (i = ignored_protocol_handlers_.begin();
342 i != ignored_protocol_handlers_.end(); ++i) { 397 i != ignored_protocol_handlers_.end(); ++i) {
343 if (handler.IsEquivalent(*i)) { 398 if (handler.IsEquivalent(*i)) {
344 return true; 399 return true;
345 } 400 }
346 } 401 }
347 return false; 402 return false;
348 } 403 }
349 404
405 void ProtocolHandlerRegistry::RemoveIgnoredHandler(
406 const ProtocolHandler& handler) {
407 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
408 bool should_notify = false;
409 ProtocolHandlerList::iterator p = std::find(
410 ignored_protocol_handlers_.begin(), ignored_protocol_handlers_.end(),
411 handler);
412 if (p != ignored_protocol_handlers_.end()) {
413 ignored_protocol_handlers_.erase(p);
414 Save();
415 should_notify = true;
416 }
417 if (should_notify)
418 NotifyChanged();
419 }
420
350 bool ProtocolHandlerRegistry::IsHandledProtocol( 421 bool ProtocolHandlerRegistry::IsHandledProtocol(
351 const std::string& scheme) const { 422 const std::string& scheme) const {
352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
353 return enabled_ && !GetHandlerFor(scheme).IsEmpty(); 424 return enabled_ && !GetHandlerFor(scheme).IsEmpty();
354 } 425 }
355 426
427 bool ProtocolHandlerRegistry::IsHandledProtocolIO(
428 const std::string& scheme) const {
429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
430 return enabled_io_ && !LookupHandler(default_handlers_io_, scheme).IsEmpty();
431 }
432
356 void ProtocolHandlerRegistry::RemoveHandler( 433 void ProtocolHandlerRegistry::RemoveHandler(
357 const ProtocolHandler& handler) { 434 const ProtocolHandler& handler) {
358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
359 ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()]; 436 ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()];
360 ProtocolHandlerList::iterator p = 437 ProtocolHandlerList::iterator p =
361 std::find(handlers.begin(), handlers.end(), handler); 438 std::find(handlers.begin(), handlers.end(), handler);
362 if (p != handlers.end()) { 439 if (p != handlers.end()) {
363 handlers.erase(p); 440 handlers.erase(p);
364 } 441 }
365 ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol()); 442 ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol());
(...skipping 18 matching lines...) Expand all
384 NotifyChanged(); 461 NotifyChanged();
385 } 462 }
386 463
387 void ProtocolHandlerRegistry::RemoveDefaultHandler(const std::string& scheme) { 464 void ProtocolHandlerRegistry::RemoveDefaultHandler(const std::string& scheme) {
388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 465 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
389 ProtocolHandler current_default = GetHandlerFor(scheme); 466 ProtocolHandler current_default = GetHandlerFor(scheme);
390 if (!current_default.IsEmpty()) 467 if (!current_default.IsEmpty())
391 RemoveHandler(current_default); 468 RemoveHandler(current_default);
392 } 469 }
393 470
394 static const ProtocolHandler& LookupHandler( 471 const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor(
395 const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map, 472 const std::string& scheme) const {
396 const std::string& scheme) { 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
397 ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p = 474 return LookupHandler(default_handlers_, scheme);
398 handler_map.find(scheme);
399 if (p != handler_map.end()) {
400 return p->second;
401 }
402 return ProtocolHandler::EmptyProtocolHandler();
403 } 475 }
404 476
405 Value* ProtocolHandlerRegistry::EncodeRegisteredHandlers() { 477 net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob(
406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 478 net::URLRequest* request) const {
407 ListValue* protocol_handlers = new ListValue(); 479 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
408 for (ProtocolHandlerMultiMap::iterator i = protocol_handlers_.begin(); 480 ProtocolHandler handler = LookupHandler(default_handlers_io_,
409 i != protocol_handlers_.end(); ++i) { 481 request->url().scheme());
410 for (ProtocolHandlerList::iterator j = i->second.begin(); 482 if (handler.IsEmpty()) {
411 j != i->second.end(); ++j) { 483 return NULL;
412 DictionaryValue* encoded = j->Encode();
413 if (IsDefault(*j)) {
414 encoded->Set("default", Value::CreateBooleanValue(true));
415 }
416 protocol_handlers->Append(encoded);
417 }
418 } 484 }
419 return protocol_handlers; 485 GURL translated_url(handler.TranslateUrl(request->url()));
486 if (!translated_url.is_valid()) {
487 return NULL;
488 }
489 return new net::URLRequestRedirectJob(request, translated_url);
420 } 490 }
421 491
422 Value* ProtocolHandlerRegistry::EncodeIgnoredHandlers() { 492 void ProtocolHandlerRegistry::Enable() {
423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
424 ListValue* handlers = new ListValue(); 494 if (enabled_) {
425 for (ProtocolHandlerList::iterator i = ignored_protocol_handlers_.begin(); 495 return;
426 i != ignored_protocol_handlers_.end(); ++i) {
427 handlers->Append(i->Encode());
428 } 496 }
429 return handlers; 497 enabled_ = true;
430 } 498 BrowserThread::PostTask(
431 499 BrowserThread::IO,
432 bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( 500 FROM_HERE,
433 const ProtocolHandler& handler) { 501 base::Bind(&ProtocolHandlerRegistry::EnableIO, this));
434 if (handler.IsEmpty() || !CanSchemeBeOverridden(handler.protocol())) 502 ProtocolHandlerMap::const_iterator p;
435 return true; 503 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
436 504 delegate_->RegisterExternalHandler(p->first);
437 if (!enabled() || IsRegistered(handler) || HasIgnoredEquivalent(handler)) 505 }
438 return true;
439
440 if (AttemptReplace(handler))
441 return true;
442
443 return false;
444 }
445
446 void ProtocolHandlerRegistry::OnAcceptRegisterProtocolHandler(
447 const ProtocolHandler& handler) {
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
449 RegisterProtocolHandler(handler);
450 SetDefault(handler);
451 Save(); 506 Save();
452 NotifyChanged(); 507 NotifyChanged();
453 } 508 }
454 509
455 void ProtocolHandlerRegistry::OnDenyRegisterProtocolHandler( 510 void ProtocolHandlerRegistry::Disable() {
456 const ProtocolHandler& handler) {
457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
458 RegisterProtocolHandler(handler); 512 if (!enabled_) {
513 return;
514 }
515 enabled_ = false;
516 BrowserThread::PostTask(
517 BrowserThread::IO,
518 FROM_HERE,
519 base::Bind(&ProtocolHandlerRegistry::DisableIO, this));
520 ProtocolHandlerMap::const_iterator p;
521 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) {
522 delegate_->DeregisterExternalHandler(p->first);
523 }
459 Save(); 524 Save();
460 NotifyChanged(); 525 NotifyChanged();
461 } 526 }
462 527
463 void ProtocolHandlerRegistry::OnIgnoreRegisterProtocolHandler( 528 void ProtocolHandlerRegistry::Finalize() {
464 const ProtocolHandler& handler) {
465 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
466 IgnoreProtocolHandler(handler); 530 delegate_.reset(NULL);
467 Save(); 531 // We free these now in case there are any outstanding workers running. If
468 NotifyChanged(); 532 // we didn't free them they could respond to workers and try to update the
533 // protocol handler registry after it was deleted.
534 // Observers remove themselves from this list when they are deleted; so
535 // we delete the last item until none are left in the list.
536 while (!default_client_observers_.empty()) {
537 delete default_client_observers_.back();
538 }
469 } 539 }
470 540
471 bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) {
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
473 ProtocolHandler old_default = GetHandlerFor(handler.protocol());
474 bool make_new_handler_default = handler.IsSameOrigin(old_default);
475 ProtocolHandlerList to_replace(GetReplacedHandlers(handler));
476 if (to_replace.empty())
477 return false;
478 for (ProtocolHandlerList::iterator p = to_replace.begin();
479 p != to_replace.end(); ++p) {
480 RemoveHandler(*p);
481 }
482 if (make_new_handler_default) {
483 OnAcceptRegisterProtocolHandler(handler);
484 } else {
485 InsertHandler(handler);
486 NotifyChanged();
487 }
488 return true;
489 }
490
491 ProtocolHandlerRegistry::ProtocolHandlerList
492 ProtocolHandlerRegistry::GetReplacedHandlers(
493 const ProtocolHandler& handler) const {
494 ProtocolHandlerList replaced_handlers;
495 const ProtocolHandlerList* handlers = GetHandlerList(handler.protocol());
496 if (!handlers)
497 return replaced_handlers;
498 for (ProtocolHandlerList::const_iterator p = handlers->begin();
499 p != handlers->end(); p++) {
500 if (handler.IsSameOrigin(*p)) {
501 replaced_handlers.push_back(*p);
502 }
503 }
504 return replaced_handlers;
505 }
506
507
508 // static 541 // static
509 void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) { 542 void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) {
510 pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers, 543 pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers,
511 PrefService::UNSYNCABLE_PREF); 544 PrefService::UNSYNCABLE_PREF);
512 pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers, 545 pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers,
513 PrefService::UNSYNCABLE_PREF); 546 PrefService::UNSYNCABLE_PREF);
514 pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true, 547 pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true,
515 PrefService::UNSYNCABLE_PREF); 548 PrefService::UNSYNCABLE_PREF);
516 } 549 }
517 550
518 void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) { 551 ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
520 ProtocolHandlerMap::const_iterator p = default_handlers_.find( 553 DCHECK(default_client_observers_.empty());
521 handler.protocol());
522 // If we're not loading, and we are setting a default for a new protocol,
523 // register with the OS.
524 if (!is_loading_ && p == default_handlers_.end())
525 delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this);
526 default_handlers_.erase(handler.protocol());
527 default_handlers_.insert(std::make_pair(handler.protocol(), handler));
528 PromoteHandler(handler);
529 BrowserThread::PostTask(
530 BrowserThread::IO,
531 FROM_HERE,
532 base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler));
533 }
534
535 void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) {
536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
537 default_handlers_.erase(scheme);
538 BrowserThread::PostTask(
539 BrowserThread::IO,
540 FROM_HERE,
541 base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme));
542 Save();
543 NotifyChanged();
544 }
545
546 bool ProtocolHandlerRegistry::IsDefault(
547 const ProtocolHandler& handler) const {
548 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
549 return GetHandlerFor(handler.protocol()) == handler;
550 }
551
552 const ProtocolHandler& ProtocolHandlerRegistry::GetHandlerFor(
553 const std::string& scheme) const {
554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
555 return LookupHandler(default_handlers_, scheme);
556 }
557
558 int ProtocolHandlerRegistry::GetHandlerIndex(const std::string& scheme) const {
559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
560 const ProtocolHandler& handler = GetHandlerFor(scheme);
561 if (handler.IsEmpty())
562 return -1;
563 const ProtocolHandlerList* handlers = GetHandlerList(scheme);
564 if (!handlers)
565 return -1;
566
567 ProtocolHandlerList::const_iterator p;
568 int i;
569 for (i = 0, p = handlers->begin(); p != handlers->end(); ++p, ++i) {
570 if (*p == handler)
571 return i;
572 }
573 return -1;
574 } 554 }
575 555
576 void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { 556 void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) {
577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578 DCHECK(IsRegistered(handler)); 558 DCHECK(IsRegistered(handler));
579 ProtocolHandlerMultiMap::iterator p = 559 ProtocolHandlerMultiMap::iterator p =
580 protocol_handlers_.find(handler.protocol()); 560 protocol_handlers_.find(handler.protocol());
581 ProtocolHandlerList& list = p->second; 561 ProtocolHandlerList& list = p->second;
582 list.erase(std::find(list.begin(), list.end(), handler)); 562 list.erase(std::find(list.begin(), list.end(), handler));
583 list.insert(list.begin(), handler); 563 list.insert(list.begin(), handler);
584 } 564 }
585 565
586 void ProtocolHandlerRegistry::NotifyChanged() {
587 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
588 content::NotificationService::current()->Notify(
589 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
590 content::Source<Profile>(profile_),
591 content::NotificationService::NoDetails());
592 }
593
594 // IO thread methods -----------------------------------------------------------
595
596 void ProtocolHandlerRegistry::ClearDefaultIO(const std::string& scheme) { 566 void ProtocolHandlerRegistry::ClearDefaultIO(const std::string& scheme) {
597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
598 default_handlers_io_.erase(scheme); 568 default_handlers_io_.erase(scheme);
599 } 569 }
600 570
601 void ProtocolHandlerRegistry::SetDefaultIO(const ProtocolHandler& handler) { 571 void ProtocolHandlerRegistry::SetDefaultIO(const ProtocolHandler& handler) {
602 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 572 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
603 ClearDefaultIO(handler.protocol()); 573 ClearDefaultIO(handler.protocol());
604 default_handlers_io_.insert(std::make_pair(handler.protocol(), handler)); 574 default_handlers_io_.insert(std::make_pair(handler.protocol(), handler));
605 } 575 }
606 576
607 bool ProtocolHandlerRegistry::IsHandledProtocolIO( 577 void ProtocolHandlerRegistry::Save() {
608 const std::string& scheme) const { 578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 579 if (is_loading_) {
610 return enabled_io_ && !LookupHandler(default_handlers_io_, scheme).IsEmpty(); 580 return;
581 }
582 scoped_ptr<Value> registered_protocol_handlers(EncodeRegisteredHandlers());
583 scoped_ptr<Value> ignored_protocol_handlers(EncodeIgnoredHandlers());
584 scoped_ptr<Value> enabled(Value::CreateBooleanValue(enabled_));
585 profile_->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers,
586 *registered_protocol_handlers);
587 profile_->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers,
588 *ignored_protocol_handlers);
589 profile_->GetPrefs()->Set(prefs::kCustomHandlersEnabled, *enabled);
611 } 590 }
612 591
613 net::URLRequestJob* ProtocolHandlerRegistry::MaybeCreateJob( 592 const ProtocolHandlerRegistry::ProtocolHandlerList*
614 net::URLRequest* request) const { 593 ProtocolHandlerRegistry::GetHandlerList(
615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 594 const std::string& scheme) const {
616 ProtocolHandler handler = LookupHandler(default_handlers_io_, 595 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
617 request->url().scheme()); 596 ProtocolHandlerMultiMap::const_iterator p = protocol_handlers_.find(scheme);
618 if (handler.IsEmpty()) { 597 if (p == protocol_handlers_.end()) {
619 return NULL; 598 return NULL;
620 } 599 }
621 GURL translated_url(handler.TranslateUrl(request->url())); 600 return &p->second;
622 if (!translated_url.is_valid()) {
623 return NULL;
624 }
625 return new net::URLRequestRedirectJob(request, translated_url);
626 } 601 }
627 602
628 // Delegate -------------------------------------------------------------------- 603 void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) {
629 604 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
630 ProtocolHandlerRegistry::Delegate::~Delegate() { 605 ProtocolHandlerMap::const_iterator p = default_handlers_.find(
606 handler.protocol());
607 // If we're not loading, and we are setting a default for a new protocol,
608 // register with the OS.
609 if (!is_loading_ && p == default_handlers_.end())
610 delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this);
611 default_handlers_.erase(handler.protocol());
612 default_handlers_.insert(std::make_pair(handler.protocol(), handler));
613 PromoteHandler(handler);
614 BrowserThread::PostTask(
615 BrowserThread::IO,
616 FROM_HERE,
617 base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler));
631 } 618 }
632 619
633 void ProtocolHandlerRegistry::Delegate::RegisterExternalHandler( 620 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) {
634 const std::string& protocol) { 621 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
635 ChildProcessSecurityPolicy* policy = 622 ProtocolHandlerMultiMap::iterator p =
636 ChildProcessSecurityPolicy::GetInstance(); 623 protocol_handlers_.find(handler.protocol());
637 if (!policy->IsWebSafeScheme(protocol)) { 624
638 policy->RegisterWebSafeScheme(protocol); 625 if (p != protocol_handlers_.end()) {
626 p->second.push_back(handler);
627 return;
639 } 628 }
629
630 ProtocolHandlerList new_list;
631 new_list.push_back(handler);
632 protocol_handlers_[handler.protocol()] = new_list;
640 } 633 }
641 634
642 void ProtocolHandlerRegistry::Delegate::DeregisterExternalHandler( 635 Value* ProtocolHandlerRegistry::EncodeRegisteredHandlers() {
643 const std::string& protocol) { 636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
637 ListValue* protocol_handlers = new ListValue();
638 for (ProtocolHandlerMultiMap::iterator i = protocol_handlers_.begin();
639 i != protocol_handlers_.end(); ++i) {
640 for (ProtocolHandlerList::iterator j = i->second.begin();
641 j != i->second.end(); ++j) {
642 DictionaryValue* encoded = j->Encode();
643 if (IsDefault(*j)) {
644 encoded->Set("default", Value::CreateBooleanValue(true));
645 }
646 protocol_handlers->Append(encoded);
647 }
648 }
649 return protocol_handlers;
644 } 650 }
645 651
646 ShellIntegration::DefaultProtocolClientWorker* 652 Value* ProtocolHandlerRegistry::EncodeIgnoredHandlers() {
647 ProtocolHandlerRegistry::Delegate::CreateShellWorker( 653 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
648 ShellIntegration::DefaultWebClientObserver* observer, 654 ListValue* handlers = new ListValue();
649 const std::string& protocol) { 655 for (ProtocolHandlerList::iterator i = ignored_protocol_handlers_.begin();
650 return new ShellIntegration::DefaultProtocolClientWorker(observer, protocol); 656 i != ignored_protocol_handlers_.end(); ++i) {
657 handlers->Append(i->Encode());
658 }
659 return handlers;
651 } 660 }
652 661
653 ProtocolHandlerRegistry::DefaultClientObserver* 662 void ProtocolHandlerRegistry::NotifyChanged() {
654 ProtocolHandlerRegistry::Delegate::CreateShellObserver( 663 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
655 ProtocolHandlerRegistry* registry) { 664 content::NotificationService::current()->Notify(
656 return new DefaultClientObserver(registry); 665 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
666 content::Source<Profile>(profile_),
667 content::NotificationService::NoDetails());
657 } 668 }
658 669
659 void ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient( 670 void ProtocolHandlerRegistry::RegisterProtocolHandler(
660 const std::string& protocol, ProtocolHandlerRegistry* registry) { 671 const ProtocolHandler& handler) {
661 DefaultClientObserver* observer = CreateShellObserver(registry); 672 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
662 // The worker pointer is reference counted. While it is running the 673 DCHECK(CanSchemeBeOverridden(handler.protocol()));
663 // message loops of the FILE and UI thread will hold references to it 674 DCHECK(!handler.IsEmpty());
664 // and it will be automatically freed once all its tasks have finished. 675 if (IsRegistered(handler)) {
665 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker; 676 return;
666 worker = CreateShellWorker(observer, protocol); 677 }
667 observer->SetWorker(worker); 678 if (enabled_ && !delegate_->IsExternalHandlerRegistered(handler.protocol()))
668 registry->default_client_observers_.push_back(observer); 679 delegate_->RegisterExternalHandler(handler.protocol());
669 worker->StartSetAsDefault(); 680 InsertHandler(handler);
670 } 681 }
671 682
672 bool ProtocolHandlerRegistry::Delegate::IsExternalHandlerRegistered( 683 std::vector<const DictionaryValue*>
673 const std::string& protocol) { 684 ProtocolHandlerRegistry::GetHandlersFromPref(const char* pref_name) const {
674 // NOTE(koz): This function is safe to call from any thread, despite living 685 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
675 // in ProfileIOData. 686 std::vector<const DictionaryValue*> result;
676 return ProfileIOData::IsHandledProtocol(protocol); 687 PrefService* prefs = profile_->GetPrefs();
688 if (!prefs->HasPrefPath(pref_name)) {
689 return result;
690 }
691
692 const ListValue* handlers = prefs->GetList(pref_name);
693 if (handlers) {
694 for (size_t i = 0; i < handlers->GetSize(); ++i) {
695 DictionaryValue* dict;
696 if (!handlers->GetDictionary(i, &dict))
697 continue;
698 if (ProtocolHandler::IsValidDict(dict)) {
699 result.push_back(dict);
700 }
701 }
702 }
703 return result;
677 } 704 }
678 705
679 // DefaultClientObserver ------------------------------------------------------ 706 void ProtocolHandlerRegistry::IgnoreProtocolHandler(
680 707 const ProtocolHandler& handler) {
681 ProtocolHandlerRegistry::DefaultClientObserver::DefaultClientObserver( 708 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
682 ProtocolHandlerRegistry* registry) 709 ignored_protocol_handlers_.push_back(handler);
683 : worker_(NULL), registry_(registry) {
684 DCHECK(registry_);
685 } 710 }
686
687 ProtocolHandlerRegistry::DefaultClientObserver::~DefaultClientObserver() {
688 if (worker_) {
689 worker_->ObserverDestroyed();
690 };
691 DefaultClientObserverList::iterator iter = std::find(
692 registry_->default_client_observers_.begin(),
693 registry_->default_client_observers_.end(), this);
694 registry_->default_client_observers_.erase(iter);
695 }
696
697 void
698 ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
699 ShellIntegration::DefaultWebClientUIState state) {
700 if (worker_) {
701 if (ShouldRemoveHandlersNotInOS() &&
702 (state == ShellIntegration::STATE_NOT_DEFAULT)) {
703 registry_->ClearDefault(worker_->protocol());
704 }
705 } else {
706 NOTREACHED();
707 }
708 }
709
710 void ProtocolHandlerRegistry::DefaultClientObserver::SetWorker(
711 ShellIntegration::DefaultProtocolClientWorker* worker) {
712 worker_ = worker;
713 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698