Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 // 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, |
| 37 // and Chrome OS doesn't have any notion of OS registration. | 37 // and Chrome OS doesn't have any notion of OS registration. |
| 38 // TODO(benwells): When Linux support is more reliable remove this | 38 // TODO(benwells): When Linux support is more reliable remove this |
| 39 // difference (http://crbug.com/88255). | 39 // difference (http://crbug.com/88255). |
| 40 return false; | 40 return false; |
| 41 #else | 41 #else |
| 42 return ShellIntegration::CanSetAsDefaultProtocolClient(); | 42 return ShellIntegration::CanSetAsDefaultProtocolClient(); |
| 43 #endif | 43 #endif |
| 44 } | 44 } |
| 45 | 45 |
| 46 void InstallDefaultProtocolHandlers(ProtocolHandlerRegistry* registry) { | |
| 47 // only chromeos has default protocol handlers at this point. | |
| 48 #if defined(OS_CHROMEOS) | |
| 49 registry->AddPredefinedHandler( | |
| 50 ProtocolHandler::CreateProtocolHandler( | |
| 51 "mailto", | |
| 52 GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_MAILTO_HANDLER_URL)), | |
| 53 l10n_util::GetStringUTF16(IDS_GOOGLE_MAILTO_HANDLER_NAME))); | |
| 54 registry->AddPredefinedHandler( | |
| 55 ProtocolHandler::CreateProtocolHandler( | |
| 56 "webcal", | |
| 57 GURL(l10n_util::GetStringUTF8(IDS_GOOGLE_WEBCAL_HANDLER_URL)), | |
| 58 l10n_util::GetStringUTF16(IDS_GOOGLE_WEBCAL_HANDLER_NAME))); | |
| 59 #endif | |
| 60 } | |
| 61 | |
| 46 } // namespace | 62 } // namespace |
| 47 | 63 |
| 48 static const ProtocolHandler& LookupHandler( | 64 static const ProtocolHandler& LookupHandler( |
| 49 const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map, | 65 const ProtocolHandlerRegistry::ProtocolHandlerMap& handler_map, |
| 50 const std::string& scheme) { | 66 const std::string& scheme) { |
| 51 ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p = | 67 ProtocolHandlerRegistry::ProtocolHandlerMap::const_iterator p = |
| 52 handler_map.find(scheme); | 68 handler_map.find(scheme); |
| 53 if (p != handler_map.end()) { | 69 if (p != handler_map.end()) { |
| 54 return p->second; | 70 return p->second; |
| 55 } | 71 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 // and it will be automatically freed once all its tasks have finished. | 154 // and it will be automatically freed once all its tasks have finished. |
| 139 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker; | 155 scoped_refptr<ShellIntegration::DefaultProtocolClientWorker> worker; |
| 140 worker = CreateShellWorker(observer, protocol); | 156 worker = CreateShellWorker(observer, protocol); |
| 141 observer->SetWorker(worker); | 157 observer->SetWorker(worker); |
| 142 registry->default_client_observers_.push_back(observer); | 158 registry->default_client_observers_.push_back(observer); |
| 143 worker->StartSetAsDefault(); | 159 worker->StartSetAsDefault(); |
| 144 } | 160 } |
| 145 | 161 |
| 146 // ProtocolHandlerRegistry ----------------------------------------------------- | 162 // ProtocolHandlerRegistry ----------------------------------------------------- |
| 147 | 163 |
| 148 ProtocolHandlerRegistry::ProtocolHandlerRegistry(Profile* profile, | 164 ProtocolHandlerRegistry::ProtocolHandlerRegistry( |
| 165 Profile* profile, | |
| 149 Delegate* delegate) | 166 Delegate* delegate) |
| 150 : profile_(profile), | 167 : profile_(profile), |
| 151 delegate_(delegate), | 168 delegate_(delegate), |
| 152 enabled_(true), | 169 enabled_(true), |
| 153 enabled_io_(enabled_), | 170 enabled_io_(enabled_), |
| 154 is_loading_(false), | 171 is_loading_(false), |
| 155 is_loaded_(false) { | 172 is_loaded_(false) { |
| 156 } | 173 } |
| 157 | 174 |
| 158 bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( | 175 bool ProtocolHandlerRegistry::SilentlyHandleRegisterHandlerRequest( |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 p != handlers->end(); p++) { | 242 p != handlers->end(); p++) { |
| 226 if (handler.IsSameOrigin(*p)) { | 243 if (handler.IsSameOrigin(*p)) { |
| 227 replaced_handlers.push_back(*p); | 244 replaced_handlers.push_back(*p); |
| 228 } | 245 } |
| 229 } | 246 } |
| 230 return replaced_handlers; | 247 return replaced_handlers; |
| 231 } | 248 } |
| 232 | 249 |
| 233 void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) { | 250 void ProtocolHandlerRegistry::ClearDefault(const std::string& scheme) { |
| 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 252 | |
| 235 default_handlers_.erase(scheme); | 253 default_handlers_.erase(scheme); |
| 236 BrowserThread::PostTask( | 254 BrowserThread::PostTask( |
| 237 BrowserThread::IO, | 255 BrowserThread::IO, |
| 238 FROM_HERE, | 256 FROM_HERE, |
| 239 base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, scheme)); | 257 base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, |
| 258 base::Unretained(this), | |
| 259 scheme)); | |
| 240 Save(); | 260 Save(); |
| 241 NotifyChanged(); | 261 NotifyChanged(); |
| 242 } | 262 } |
| 243 | 263 |
| 244 bool ProtocolHandlerRegistry::IsDefault( | 264 bool ProtocolHandlerRegistry::IsDefault( |
| 245 const ProtocolHandler& handler) const { | 265 const ProtocolHandler& handler) const { |
| 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 247 return GetHandlerFor(handler.protocol()) == handler; | 267 return GetHandlerFor(handler.protocol()) == handler; |
| 248 } | 268 } |
| 249 | 269 |
| 270 void ProtocolHandlerRegistry::InitProtocolSettings() { | |
| 271 | |
| 272 // Install predefined protocol handlers. | |
| 273 InstallDefaultProtocolHandlers(this); | |
| 274 Load(); | |
| 275 } | |
| 276 | |
| 277 // TODO(smckay): Can this be made anonymous and accessed | |
| 278 // via InitProtocolSettings? | |
| 250 void ProtocolHandlerRegistry::Load() { | 279 void ProtocolHandlerRegistry::Load() { |
| 251 // Any further default additions to the table will get rejected from now on. | 280 // Any further default additions to the table will get rejected from now on. |
| 252 is_loaded_ = true; | 281 is_loaded_ = true; |
| 253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 254 is_loading_ = true; | 283 is_loading_ = true; |
| 255 PrefService* prefs = profile_->GetPrefs(); | 284 PrefService* prefs = profile_->GetPrefs(); |
| 256 if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) { | 285 if (prefs->HasPrefPath(prefs::kCustomHandlersEnabled)) { |
| 257 enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled); | 286 enabled_ = prefs->GetBoolean(prefs::kCustomHandlersEnabled); |
| 258 BrowserThread::PostTask( | 287 BrowserThread::PostTask( |
| 259 BrowserThread::IO, | 288 BrowserThread::IO, |
| 260 FROM_HERE, | 289 FROM_HERE, |
| 261 base::Bind(enabled_ ? &ProtocolHandlerRegistry::EnableIO : | 290 base::Bind(enabled_ ? |
| 262 &ProtocolHandlerRegistry::DisableIO, this)); | 291 &ProtocolHandlerRegistry::EnableIO : |
| 292 &ProtocolHandlerRegistry::DisableIO, | |
| 293 base::Unretained(this))); | |
| 263 } | 294 } |
| 264 std::vector<const DictionaryValue*> registered_handlers = | 295 std::vector<const DictionaryValue*> registered_handlers = |
| 265 GetHandlersFromPref(prefs::kRegisteredProtocolHandlers); | 296 GetHandlersFromPref(prefs::kRegisteredProtocolHandlers); |
| 266 for (std::vector<const DictionaryValue*>::const_iterator p = | 297 for (std::vector<const DictionaryValue*>::const_iterator p = |
| 267 registered_handlers.begin(); | 298 registered_handlers.begin(); |
| 268 p != registered_handlers.end(); ++p) { | 299 p != registered_handlers.end(); ++p) { |
| 269 ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(*p); | 300 ProtocolHandler handler = ProtocolHandler::CreateProtocolHandler(*p); |
| 270 RegisterProtocolHandler(handler); | 301 RegisterProtocolHandler(handler); |
| 271 bool is_default = false; | 302 bool is_default = false; |
| 272 if ((*p)->GetBoolean("default", &is_default) && is_default) { | 303 if ((*p)->GetBoolean("default", &is_default) && is_default) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 } | 475 } |
| 445 ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol()); | 476 ProtocolHandlerMap::iterator q = default_handlers_.find(handler.protocol()); |
| 446 if (q != default_handlers_.end() && q->second == handler) { | 477 if (q != default_handlers_.end() && q->second == handler) { |
| 447 // Make the new top handler in the list the default. | 478 // Make the new top handler in the list the default. |
| 448 if (!handlers.empty()) { | 479 if (!handlers.empty()) { |
| 449 // NOTE We pass a copy because SetDefault() modifies handlers. | 480 // NOTE We pass a copy because SetDefault() modifies handlers. |
| 450 SetDefault(ProtocolHandler(handlers[0])); | 481 SetDefault(ProtocolHandler(handlers[0])); |
| 451 } else { | 482 } else { |
| 452 BrowserThread::PostTask( | 483 BrowserThread::PostTask( |
| 453 BrowserThread::IO, FROM_HERE, | 484 BrowserThread::IO, FROM_HERE, |
| 454 base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, this, | 485 base::Bind(&ProtocolHandlerRegistry::ClearDefaultIO, |
| 486 base::Unretained(this), | |
| 455 q->second.protocol())); | 487 q->second.protocol())); |
| 456 default_handlers_.erase(q); | 488 default_handlers_.erase(q); |
| 457 } | 489 } |
| 458 } | 490 } |
| 459 | 491 |
| 460 if (!IsHandledProtocol(handler.protocol())) { | 492 if (!IsHandledProtocol(handler.protocol())) { |
| 461 delegate_->DeregisterExternalHandler(handler.protocol()); | 493 delegate_->DeregisterExternalHandler(handler.protocol()); |
| 462 } | 494 } |
| 463 Save(); | 495 Save(); |
| 464 NotifyChanged(); | 496 NotifyChanged(); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 494 | 526 |
| 495 void ProtocolHandlerRegistry::Enable() { | 527 void ProtocolHandlerRegistry::Enable() { |
| 496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 497 if (enabled_) { | 529 if (enabled_) { |
| 498 return; | 530 return; |
| 499 } | 531 } |
| 500 enabled_ = true; | 532 enabled_ = true; |
| 501 BrowserThread::PostTask( | 533 BrowserThread::PostTask( |
| 502 BrowserThread::IO, | 534 BrowserThread::IO, |
| 503 FROM_HERE, | 535 FROM_HERE, |
| 504 base::Bind(&ProtocolHandlerRegistry::EnableIO, this)); | 536 base::Bind(&ProtocolHandlerRegistry::EnableIO, base::Unretained(this))); |
| 505 ProtocolHandlerMap::const_iterator p; | 537 ProtocolHandlerMap::const_iterator p; |
| 506 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { | 538 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { |
| 507 delegate_->RegisterExternalHandler(p->first); | 539 delegate_->RegisterExternalHandler(p->first); |
| 508 } | 540 } |
| 509 Save(); | 541 Save(); |
| 510 NotifyChanged(); | 542 NotifyChanged(); |
| 511 } | 543 } |
| 512 | 544 |
| 513 void ProtocolHandlerRegistry::Disable() { | 545 void ProtocolHandlerRegistry::Disable() { |
| 514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 515 if (!enabled_) { | 547 if (!enabled_) { |
| 516 return; | 548 return; |
| 517 } | 549 } |
| 518 enabled_ = false; | 550 enabled_ = false; |
| 519 BrowserThread::PostTask( | 551 BrowserThread::PostTask( |
| 520 BrowserThread::IO, | 552 BrowserThread::IO, |
| 521 FROM_HERE, | 553 FROM_HERE, |
| 522 base::Bind(&ProtocolHandlerRegistry::DisableIO, this)); | 554 base::Bind(&ProtocolHandlerRegistry::DisableIO, |
| 555 base::Unretained(this))); | |
| 523 ProtocolHandlerMap::const_iterator p; | 556 ProtocolHandlerMap::const_iterator p; |
| 524 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { | 557 for (p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { |
| 525 delegate_->DeregisterExternalHandler(p->first); | 558 delegate_->DeregisterExternalHandler(p->first); |
| 526 } | 559 } |
| 527 Save(); | 560 Save(); |
| 528 NotifyChanged(); | 561 NotifyChanged(); |
| 529 } | 562 } |
| 530 | 563 |
| 531 void ProtocolHandlerRegistry::Finalize() { | 564 void ProtocolHandlerRegistry::Finalize() { |
|
Elliot Glaysher
2012/06/11 19:43:16
Rename Finalize() to Shutdown(), which is part of
Steve McKay
2012/06/11 22:09:38
Done.
| |
| 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 533 delegate_.reset(NULL); | 566 delegate_.reset(NULL); |
| 534 // We free these now in case there are any outstanding workers running. If | 567 // We free these now in case there are any outstanding workers running. If |
| 535 // we didn't free them they could respond to workers and try to update the | 568 // we didn't free them they could respond to workers and try to update the |
| 536 // protocol handler registry after it was deleted. | 569 // protocol handler registry after it was deleted. |
| 537 // Observers remove themselves from this list when they are deleted; so | 570 // Observers remove themselves from this list when they are deleted; so |
| 538 // we delete the last item until none are left in the list. | 571 // we delete the last item until none are left in the list. |
| 539 while (!default_client_observers_.empty()) { | 572 while (!default_client_observers_.empty()) { |
| 540 delete default_client_observers_.back(); | 573 delete default_client_observers_.back(); |
| 541 } | 574 } |
| 542 } | 575 } |
| 543 | 576 |
| 544 // static | 577 // static |
| 545 void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) { | 578 void ProtocolHandlerRegistry::RegisterPrefs(PrefService* pref_service) { |
| 546 pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers, | 579 pref_service->RegisterListPref(prefs::kRegisteredProtocolHandlers, |
| 547 PrefService::UNSYNCABLE_PREF); | 580 PrefService::UNSYNCABLE_PREF); |
| 548 pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers, | 581 pref_service->RegisterListPref(prefs::kIgnoredProtocolHandlers, |
| 549 PrefService::UNSYNCABLE_PREF); | 582 PrefService::UNSYNCABLE_PREF); |
| 550 pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true, | 583 pref_service->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true, |
| 551 PrefService::UNSYNCABLE_PREF); | 584 PrefService::UNSYNCABLE_PREF); |
| 552 } | 585 } |
| 553 | 586 |
| 554 ProtocolHandlerRegistry::~ProtocolHandlerRegistry() { | 587 ProtocolHandlerRegistry::~ProtocolHandlerRegistry() { |
| 555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 588 Finalize(); |
|
Elliot Glaysher
2012/06/11 19:43:16
(And remove this call)
Steve McKay
2012/06/11 22:09:38
Done.
| |
| 589 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
|
willchan no longer on Chromium
2012/06/11 21:17:22
I think this class is used on both the UI and IO t
Steve McKay
2012/06/11 22:09:38
So what I need to tease apart here, for my underst
willchan no longer on Chromium
2012/06/12 02:09:56
The full answer is complicated :) But in short, th
| |
| 556 DCHECK(default_client_observers_.empty()); | 590 DCHECK(default_client_observers_.empty()); |
| 557 } | 591 } |
| 558 | 592 |
| 559 void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { | 593 void ProtocolHandlerRegistry::PromoteHandler(const ProtocolHandler& handler) { |
| 560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 594 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 561 DCHECK(IsRegistered(handler)); | 595 DCHECK(IsRegistered(handler)); |
| 562 ProtocolHandlerMultiMap::iterator p = | 596 ProtocolHandlerMultiMap::iterator p = |
| 563 protocol_handlers_.find(handler.protocol()); | 597 protocol_handlers_.find(handler.protocol()); |
| 564 ProtocolHandlerList& list = p->second; | 598 ProtocolHandlerList& list = p->second; |
| 565 list.erase(std::find(list.begin(), list.end(), handler)); | 599 list.erase(std::find(list.begin(), list.end(), handler)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 610 // If we're not loading, and we are setting a default for a new protocol, | 644 // If we're not loading, and we are setting a default for a new protocol, |
| 611 // register with the OS. | 645 // register with the OS. |
| 612 if (!is_loading_ && p == default_handlers_.end()) | 646 if (!is_loading_ && p == default_handlers_.end()) |
| 613 delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this); | 647 delegate_->RegisterWithOSAsDefaultClient(handler.protocol(), this); |
| 614 default_handlers_.erase(handler.protocol()); | 648 default_handlers_.erase(handler.protocol()); |
| 615 default_handlers_.insert(std::make_pair(handler.protocol(), handler)); | 649 default_handlers_.insert(std::make_pair(handler.protocol(), handler)); |
| 616 PromoteHandler(handler); | 650 PromoteHandler(handler); |
| 617 BrowserThread::PostTask( | 651 BrowserThread::PostTask( |
| 618 BrowserThread::IO, | 652 BrowserThread::IO, |
| 619 FROM_HERE, | 653 FROM_HERE, |
| 620 base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, this, handler)); | 654 base::Bind(&ProtocolHandlerRegistry::SetDefaultIO, |
| 655 base::Unretained(this), | |
| 656 handler)); | |
| 621 } | 657 } |
| 622 | 658 |
| 623 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) { | 659 void ProtocolHandlerRegistry::InsertHandler(const ProtocolHandler& handler) { |
| 624 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 660 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 625 ProtocolHandlerMultiMap::iterator p = | 661 ProtocolHandlerMultiMap::iterator p = |
| 626 protocol_handlers_.find(handler.protocol()); | 662 protocol_handlers_.find(handler.protocol()); |
| 627 | 663 |
| 628 if (p != protocol_handlers_.end()) { | 664 if (p != protocol_handlers_.end()) { |
| 629 p->second.push_back(handler); | 665 p->second.push_back(handler); |
| 630 return; | 666 return; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 712 ignored_protocol_handlers_.push_back(handler); | 748 ignored_protocol_handlers_.push_back(handler); |
| 713 } | 749 } |
| 714 | 750 |
| 715 void ProtocolHandlerRegistry::AddPredefinedHandler( | 751 void ProtocolHandlerRegistry::AddPredefinedHandler( |
| 716 const ProtocolHandler& handler) { | 752 const ProtocolHandler& handler) { |
| 717 // If called after the load command was issued this function will fail. | 753 // If called after the load command was issued this function will fail. |
| 718 DCHECK(!is_loaded_); | 754 DCHECK(!is_loaded_); |
| 719 RegisterProtocolHandler(handler); | 755 RegisterProtocolHandler(handler); |
| 720 SetDefault(handler); | 756 SetDefault(handler); |
| 721 } | 757 } |
| 722 | |
| 723 | |
| OLD | NEW |