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 |