protocol_handler_registry_unittest.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 3// found in the LICENSE file. 4 5#include "chrome/browser/custom_handlers/protocol_handler_registry.h" 6 7#include <set> 8 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "base/strings/utf_string_conversions.h" 12#include "base/synchronization/waitable_event.h" 13#include "chrome/browser/chrome_notification_types.h" 14#include "chrome/browser/prefs/pref_service_syncable.h" 15#include "chrome/common/custom_handlers/protocol_handler.h" 16#include "chrome/test/base/testing_browser_process.h" 17#include "chrome/test/base/testing_profile.h" 18#include "components/user_prefs/pref_registry_syncable.h" 19#include "content/public/browser/notification_observer.h" 20#include "content/public/browser/notification_registrar.h" 21#include "content/public/browser/notification_source.h" 22#include "content/public/test/test_browser_thread.h" 23#include "content/public/test/test_renderer_host.h" 24#include "net/base/request_priority.h" 25#include "net/url_request/url_request.h" 26#include "net/url_request/url_request_context.h" 27#include "testing/gtest/include/gtest/gtest.h" 28 29using content::BrowserThread; 30 31namespace { 32 33void AssertInterceptedIO( 34 const GURL& url, 35 net::URLRequestJobFactory* interceptor) { 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 37 net::URLRequestContext context; 38 net::URLRequest request(url, net::DEFAULT_PRIORITY, NULL, &context); 39 scoped_refptr<net::URLRequestJob> job = 40 interceptor->MaybeCreateJobWithProtocolHandler( 41 url.scheme(), &request, context.network_delegate()); 42 ASSERT_TRUE(job.get() != NULL); 43} 44 45void AssertIntercepted( 46 const GURL& url, 47 net::URLRequestJobFactory* interceptor) { 48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 49 BrowserThread::PostTask(BrowserThread::IO, 50 FROM_HERE, 51 base::Bind(AssertInterceptedIO, 52 url, 53 base::Unretained(interceptor))); 54 base::MessageLoop::current()->RunUntilIdle(); 55} 56 57// FakeURLRequestJobFactory returns NULL for all job creation requests and false 58// for all IsHandled*() requests. FakeURLRequestJobFactory can be chained to 59// ProtocolHandlerRegistry::JobInterceptorFactory so the result of 60// MaybeCreateJobWithProtocolHandler() indicates whether the 61// ProtocolHandlerRegistry properly handled a job creation request. 62class FakeURLRequestJobFactory : public net::URLRequestJobFactory { 63 // net::URLRequestJobFactory implementation: 64 virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler( 65 const std::string& scheme, 66 net::URLRequest* request, 67 net::NetworkDelegate* network_delegate) const OVERRIDE { 68 return NULL; 69 } 70 virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE { 71 return false; 72 } 73 virtual bool IsHandledURL(const GURL& url) const OVERRIDE { 74 return false; 75 } 76 virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE { 77 return true; 78 } 79}; 80 81void AssertWillHandleIO( 82 const std::string& scheme, 83 bool expected, 84 ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) { 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 86 interceptor->Chain(scoped_ptr<net::URLRequestJobFactory>( 87 new FakeURLRequestJobFactory())); 88 ASSERT_EQ(expected, interceptor->IsHandledProtocol(scheme)); 89 interceptor->Chain(scoped_ptr<net::URLRequestJobFactory>()); 90} 91 92void AssertWillHandle( 93 const std::string& scheme, 94 bool expected, 95 ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) { 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 97 BrowserThread::PostTask(BrowserThread::IO, 98 FROM_HERE, 99 base::Bind(AssertWillHandleIO, 100 scheme, 101 expected, 102 base::Unretained(interceptor))); 103 base::MessageLoop::current()->RunUntilIdle(); 104} 105 106class FakeDelegate : public ProtocolHandlerRegistry::Delegate { 107 public: 108 FakeDelegate() : force_os_failure_(false) {} 109 virtual ~FakeDelegate() { } 110 virtual void RegisterExternalHandler(const std::string& protocol) OVERRIDE { 111 ASSERT_TRUE( 112 registered_protocols_.find(protocol) == registered_protocols_.end()); 113 registered_protocols_.insert(protocol); 114 } 115 116 virtual void DeregisterExternalHandler(const std::string& protocol) OVERRIDE { 117 registered_protocols_.erase(protocol); 118 } 119 120 virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker( 121 ShellIntegration::DefaultWebClientObserver* observer, 122 const std::string& protocol) OVERRIDE; 123 124 virtual ProtocolHandlerRegistry::DefaultClientObserver* CreateShellObserver( 125 ProtocolHandlerRegistry* registry) OVERRIDE; 126 127 virtual void RegisterWithOSAsDefaultClient( 128 const std::string& protocol, 129 ProtocolHandlerRegistry* reg) OVERRIDE { 130 ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(protocol, 131 reg); 132 ASSERT_FALSE(IsFakeRegisteredWithOS(protocol)); 133 } 134 135 virtual bool IsExternalHandlerRegistered( 136 const std::string& protocol) OVERRIDE { 137 return registered_protocols_.find(protocol) != registered_protocols_.end(); 138 } 139 140 bool IsFakeRegisteredWithOS(const std::string& protocol) { 141 return os_registered_protocols_.find(protocol) != 142 os_registered_protocols_.end(); 143 } 144 145 void FakeRegisterWithOS(const std::string& protocol) { 146 os_registered_protocols_.insert(protocol); 147 } 148 149 void Reset() { 150 registered_protocols_.clear(); 151 os_registered_protocols_.clear(); 152 force_os_failure_ = false; 153 } 154 155 void set_force_os_failure(bool force) { force_os_failure_ = force; } 156 157 bool force_os_failure() { return force_os_failure_; } 158 159 private: 160 std::set<std::string> registered_protocols_; 161 std::set<std::string> os_registered_protocols_; 162 bool force_os_failure_; 163}; 164 165class FakeClientObserver 166 : public ProtocolHandlerRegistry::DefaultClientObserver { 167 public: 168 FakeClientObserver(ProtocolHandlerRegistry* registry, 169 FakeDelegate* registry_delegate) 170 : ProtocolHandlerRegistry::DefaultClientObserver(registry), 171 delegate_(registry_delegate) {} 172 173 virtual void SetDefaultWebClientUIState( 174 ShellIntegration::DefaultWebClientUIState state) OVERRIDE { 175 ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState( 176 state); 177 if (state == ShellIntegration::STATE_IS_DEFAULT) { 178 delegate_->FakeRegisterWithOS(worker_->protocol()); 179 } 180 if (state != ShellIntegration::STATE_PROCESSING) { 181 base::MessageLoop::current()->Quit(); 182 } 183 } 184 185 private: 186 FakeDelegate* delegate_; 187}; 188 189class FakeProtocolClientWorker 190 : public ShellIntegration::DefaultProtocolClientWorker { 191 public: 192 FakeProtocolClientWorker(ShellIntegration::DefaultWebClientObserver* observer, 193 const std::string& protocol, 194 bool force_failure) 195 : ShellIntegration::DefaultProtocolClientWorker(observer, protocol), 196 force_failure_(force_failure) {} 197 198 private: 199 virtual ~FakeProtocolClientWorker() {} 200 201 virtual ShellIntegration::DefaultWebClientState CheckIsDefault() OVERRIDE { 202 if (force_failure_) { 203 return ShellIntegration::NOT_DEFAULT; 204 } else { 205 return ShellIntegration::IS_DEFAULT; 206 } 207 } 208 209 virtual bool SetAsDefault(bool interactive_permitted) OVERRIDE { 210 return true; 211 } 212 213 private: 214 bool force_failure_; 215}; 216 217ProtocolHandlerRegistry::DefaultClientObserver* 218 FakeDelegate::CreateShellObserver(ProtocolHandlerRegistry* registry) { 219 return new FakeClientObserver(registry, this); 220} 221 222ShellIntegration::DefaultProtocolClientWorker* FakeDelegate::CreateShellWorker( 223 ShellIntegration::DefaultWebClientObserver* observer, 224 const std::string& protocol) { 225 return new FakeProtocolClientWorker(observer, protocol, force_os_failure_); 226} 227 228class NotificationCounter : public content::NotificationObserver { 229 public: 230 explicit NotificationCounter(Profile* profile) 231 : events_(0), 232 notification_registrar_() { 233 notification_registrar_.Add(this, 234 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, 235 content::Source<Profile>(profile)); 236 } 237 238 int events() { return events_; } 239 bool notified() { return events_ > 0; } 240 void Clear() { events_ = 0; } 241 virtual void Observe(int type, 242 const content::NotificationSource& source, 243 const content::NotificationDetails& details) OVERRIDE { 244 ++events_; 245 } 246 247 int events_; 248 content::NotificationRegistrar notification_registrar_; 249}; 250 251class QueryProtocolHandlerOnChange 252 : public content::NotificationObserver { 253 public: 254 QueryProtocolHandlerOnChange(Profile* profile, 255 ProtocolHandlerRegistry* registry) 256 : local_registry_(registry), 257 called_(false), 258 notification_registrar_() { 259 notification_registrar_.Add(this, 260 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, 261 content::Source<Profile>(profile)); 262 } 263 264 virtual void Observe(int type, 265 const content::NotificationSource& source, 266 const content::NotificationDetails& details) OVERRIDE { 267 std::vector<std::string> output; 268 local_registry_->GetRegisteredProtocols(&output); 269 called_ = true; 270 } 271 272 ProtocolHandlerRegistry* local_registry_; 273 bool called_; 274 content::NotificationRegistrar notification_registrar_; 275}; 276 277// URLRequest DCHECKS that the current MessageLoop is IO. It does this because 278// it can't check the thread id (since net can't depend on content.) We want 279// to harness our tests so all threads use the same loop allowing us to 280// guarantee all messages are processed.) By overriding the IsType method 281// we basically ignore the supplied message loop type, and instead infer 282// our type based on the current thread. GO DEPENDENCY INJECTION! 283class TestMessageLoop : public base::MessageLoop { 284 public: 285 TestMessageLoop() : base::MessageLoop(base::MessageLoop::TYPE_DEFAULT) {} 286 virtual ~TestMessageLoop() {} 287 virtual bool IsType(base::MessageLoop::Type type) const OVERRIDE { 288 switch (type) { 289#if defined(TOOLKIT_GTK) 290 case base::MessageLoop::TYPE_GPU: 291#endif 292 case base::MessageLoop::TYPE_UI: 293 return BrowserThread::CurrentlyOn(BrowserThread::UI); 294 case base::MessageLoop::TYPE_IO: 295 return BrowserThread::CurrentlyOn(BrowserThread::IO); 296#if defined(OS_ANDROID) 297 case base::MessageLoop::TYPE_JAVA: // fall-through 298#endif // defined(OS_ANDROID) 299 case base::MessageLoop::TYPE_DEFAULT: 300 return !BrowserThread::CurrentlyOn(BrowserThread::UI) && 301 !BrowserThread::CurrentlyOn(BrowserThread::IO); 302 } 303 return false; 304 } 305}; 306 307} // namespace 308 309class ProtocolHandlerRegistryTest : public testing::Test { 310 protected: 311 ProtocolHandlerRegistryTest() 312 : ui_thread_(BrowserThread::UI, &loop_), 313 file_thread_(BrowserThread::FILE, &loop_), 314 io_thread_(BrowserThread::IO, &loop_), 315 test_protocol_handler_(CreateProtocolHandler("test", "test")) {} 316 317 FakeDelegate* delegate() const { return delegate_; } 318 ProtocolHandlerRegistry* registry() { return registry_.get(); } 319 TestingProfile* profile() const { return profile_.get(); } 320 const ProtocolHandler& test_protocol_handler() const { 321 return test_protocol_handler_; 322 } 323 324 ProtocolHandler CreateProtocolHandler(const std::string& protocol, 325 const GURL& url, 326 const std::string& title) { 327 return ProtocolHandler::CreateProtocolHandler(protocol, url, 328 UTF8ToUTF16(title)); 329 } 330 331 ProtocolHandler CreateProtocolHandler(const std::string& protocol, 332 const std::string& name) { 333 return CreateProtocolHandler(protocol, GURL("http://" + name + "/%s"), 334 name); 335 } 336 337 void RecreateRegistry(bool initialize) { 338 TeadDownRegistry(); 339 SetUpRegistry(initialize); 340 } 341 342 // Returns a new registry, initializing it if |initialize| is true. 343 // Caller assumes ownership for the object 344 void SetUpRegistry(bool initialize) { 345 delegate_ = new FakeDelegate(); 346 registry_.reset(new ProtocolHandlerRegistry(profile(), delegate())); 347 if (initialize) registry_->InitProtocolSettings(); 348 } 349 350 void TeadDownRegistry() { 351 registry_->Shutdown(); 352 registry_.reset(); 353 // Registry owns the delegate_ it handles deletion of that object. 354 } 355 356 virtual void SetUp() { 357 profile_.reset(new TestingProfile()); 358 CHECK(profile_->GetPrefs()); 359 SetUpRegistry(true); 360 test_protocol_handler_ = 361 CreateProtocolHandler("test", GURL("http://test.com/%s"), "Test"); 362 } 363 364 virtual void TearDown() { 365 TeadDownRegistry(); 366 } 367 368 TestMessageLoop loop_; 369 370 private: 371 content::TestBrowserThread ui_thread_; 372 content::TestBrowserThread file_thread_; 373 content::TestBrowserThread io_thread_; 374 375 scoped_ptr<TestingProfile> profile_; 376 FakeDelegate* delegate_; // Registry assumes ownership of delegate_. 377 scoped_ptr<ProtocolHandlerRegistry> registry_; 378 ProtocolHandler test_protocol_handler_; 379}; 380 381// ProtocolHandlerRegistryTest tests are flaky on Linux & ChromeOS. 382// http://crbug.com/133023 383#if defined(OS_LINUX) || defined(OS_CHROMEOS) 384#define MAYBE_AcceptProtocolHandlerHandlesProtocol \ 385 DISABLED_AcceptProtocolHandlerHandlesProtocol 386#define MAYBE_DeniedProtocolIsntHandledUntilAccepted \ 387 DISABLED_DeniedProtocolIsntHandledUntilAccepted 388#define MAYBE_TestStartsAsDefault DISABLED_TestStartsAsDefault 389#define MAYBE_TestRemoveHandlerRemovesDefault \ 390 DISABLED_TestRemoveHandlerRemovesDefault 391#define MAYBE_TestClearDefaultGetsPropagatedToIO \ 392 DISABLED_TestClearDefaultGetsPropagatedToIO 393#define MAYBE_TestIsHandledProtocolWorksOnIOThread \ 394 DISABLED_TestIsHandledProtocolWorksOnIOThread 395#define MAYBE_TestInstallDefaultHandler \ 396 DISABLED_TestInstallDefaultHandler 397#else 398#define MAYBE_AcceptProtocolHandlerHandlesProtocol \ 399 AcceptProtocolHandlerHandlesProtocol 400#define MAYBE_DeniedProtocolIsntHandledUntilAccepted \ 401 DeniedProtocolIsntHandledUntilAccepted 402#define MAYBE_TestStartsAsDefault TestStartsAsDefault 403#define MAYBE_TestRemoveHandlerRemovesDefault TestRemoveHandlerRemovesDefault 404#define MAYBE_TestClearDefaultGetsPropagatedToIO \ 405 TestClearDefaultGetsPropagatedToIO 406#define MAYBE_TestIsHandledProtocolWorksOnIOThread \ 407 TestIsHandledProtocolWorksOnIOThread 408#define MAYBE_TestInstallDefaultHandler TestInstallDefaultHandler 409#endif // defined(OS_CHROMEOS) 410 411TEST_F(ProtocolHandlerRegistryTest, 412 MAYBE_AcceptProtocolHandlerHandlesProtocol) { 413 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 414 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 415 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 416} 417 418TEST_F(ProtocolHandlerRegistryTest, 419 MAYBE_DeniedProtocolIsntHandledUntilAccepted) { 420 registry()->OnDenyRegisterProtocolHandler(test_protocol_handler()); 421 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 422 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 423 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 424} 425 426TEST_F(ProtocolHandlerRegistryTest, ClearDefaultMakesProtocolNotHandled) { 427 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 428 registry()->ClearDefault("test"); 429 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 430 ASSERT_TRUE(registry()->GetHandlerFor("test").IsEmpty()); 431} 432 433TEST_F(ProtocolHandlerRegistryTest, DisableDeregistersProtocolHandlers) { 434 ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test")); 435 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 436 ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test")); 437 438 registry()->Disable(); 439 ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test")); 440 registry()->Enable(); 441 ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test")); 442} 443 444TEST_F(ProtocolHandlerRegistryTest, IgnoreProtocolHandler) { 445 registry()->OnIgnoreRegisterProtocolHandler(test_protocol_handler()); 446 ASSERT_TRUE(registry()->IsIgnored(test_protocol_handler())); 447 448 registry()->RemoveIgnoredHandler(test_protocol_handler()); 449 ASSERT_FALSE(registry()->IsIgnored(test_protocol_handler())); 450} 451 452TEST_F(ProtocolHandlerRegistryTest, IgnoreEquivalentProtocolHandler) { 453 ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"), 454 "test1"); 455 ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"), 456 "test2"); 457 458 registry()->OnIgnoreRegisterProtocolHandler(ph1); 459 ASSERT_TRUE(registry()->IsIgnored(ph1)); 460 ASSERT_TRUE(registry()->HasIgnoredEquivalent(ph2)); 461 462 registry()->RemoveIgnoredHandler(ph1); 463 ASSERT_FALSE(registry()->IsIgnored(ph1)); 464 ASSERT_FALSE(registry()->HasIgnoredEquivalent(ph2)); 465} 466 467TEST_F(ProtocolHandlerRegistryTest, SaveAndLoad) { 468 ProtocolHandler stuff_protocol_handler( 469 CreateProtocolHandler("stuff", "stuff")); 470 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 471 registry()->OnIgnoreRegisterProtocolHandler(stuff_protocol_handler); 472 473 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 474 ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler)); 475 delegate()->Reset(); 476 RecreateRegistry(true); 477 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 478 ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler)); 479} 480 481TEST_F(ProtocolHandlerRegistryTest, TestEnabledDisabled) { 482 registry()->Disable(); 483 ASSERT_FALSE(registry()->enabled()); 484 registry()->Enable(); 485 ASSERT_TRUE(registry()->enabled()); 486} 487 488TEST_F(ProtocolHandlerRegistryTest, 489 DisallowRegisteringExternallyHandledProtocols) { 490 delegate()->RegisterExternalHandler("test"); 491 ASSERT_FALSE(registry()->CanSchemeBeOverridden("test")); 492} 493 494TEST_F(ProtocolHandlerRegistryTest, RemovingHandlerMeansItCanBeAddedAgain) { 495 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 496 ASSERT_TRUE(registry()->CanSchemeBeOverridden("test")); 497 registry()->RemoveHandler(test_protocol_handler()); 498 ASSERT_TRUE(registry()->CanSchemeBeOverridden("test")); 499} 500 501TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestStartsAsDefault) { 502 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 503 ASSERT_TRUE(registry()->IsDefault(test_protocol_handler())); 504} 505 506TEST_F(ProtocolHandlerRegistryTest, TestClearDefault) { 507 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 508 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 509 registry()->OnAcceptRegisterProtocolHandler(ph1); 510 registry()->OnAcceptRegisterProtocolHandler(ph2); 511 512 registry()->OnAcceptRegisterProtocolHandler(ph1); 513 registry()->ClearDefault("test"); 514 ASSERT_FALSE(registry()->IsDefault(ph1)); 515 ASSERT_FALSE(registry()->IsDefault(ph2)); 516} 517 518TEST_F(ProtocolHandlerRegistryTest, TestGetHandlerFor) { 519 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 520 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 521 registry()->OnAcceptRegisterProtocolHandler(ph1); 522 registry()->OnAcceptRegisterProtocolHandler(ph2); 523 524 registry()->OnAcceptRegisterProtocolHandler(ph2); 525 ASSERT_EQ(ph2, registry()->GetHandlerFor("test")); 526 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 527} 528 529TEST_F(ProtocolHandlerRegistryTest, TestMostRecentHandlerIsDefault) { 530 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 531 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 532 registry()->OnAcceptRegisterProtocolHandler(ph1); 533 registry()->OnAcceptRegisterProtocolHandler(ph2); 534 ASSERT_FALSE(registry()->IsDefault(ph1)); 535 ASSERT_TRUE(registry()->IsDefault(ph2)); 536} 537 538TEST_F(ProtocolHandlerRegistryTest, TestOnAcceptRegisterProtocolHandler) { 539 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 540 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 541 registry()->OnAcceptRegisterProtocolHandler(ph1); 542 registry()->OnAcceptRegisterProtocolHandler(ph2); 543 544 registry()->OnAcceptRegisterProtocolHandler(ph1); 545 ASSERT_TRUE(registry()->IsDefault(ph1)); 546 ASSERT_FALSE(registry()->IsDefault(ph2)); 547 548 registry()->OnAcceptRegisterProtocolHandler(ph2); 549 ASSERT_FALSE(registry()->IsDefault(ph1)); 550 ASSERT_TRUE(registry()->IsDefault(ph2)); 551} 552 553TEST_F(ProtocolHandlerRegistryTest, TestDefaultSaveLoad) { 554 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 555 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 556 registry()->OnDenyRegisterProtocolHandler(ph1); 557 registry()->OnDenyRegisterProtocolHandler(ph2); 558 559 registry()->OnAcceptRegisterProtocolHandler(ph2); 560 registry()->Disable(); 561 562 RecreateRegistry(true); 563 564 ASSERT_FALSE(registry()->enabled()); 565 registry()->Enable(); 566 ASSERT_FALSE(registry()->IsDefault(ph1)); 567 ASSERT_TRUE(registry()->IsDefault(ph2)); 568 569 RecreateRegistry(true); 570 ASSERT_TRUE(registry()->enabled()); 571} 572 573TEST_F(ProtocolHandlerRegistryTest, TestRemoveHandler) { 574 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 575 registry()->OnAcceptRegisterProtocolHandler(ph1); 576 registry()->OnAcceptRegisterProtocolHandler(ph1); 577 578 registry()->RemoveHandler(ph1); 579 ASSERT_FALSE(registry()->IsRegistered(ph1)); 580 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 581} 582 583TEST_F(ProtocolHandlerRegistryTest, TestIsRegistered) { 584 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 585 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 586 registry()->OnAcceptRegisterProtocolHandler(ph1); 587 registry()->OnAcceptRegisterProtocolHandler(ph2); 588 589 ASSERT_TRUE(registry()->IsRegistered(ph1)); 590} 591 592TEST_F(ProtocolHandlerRegistryTest, TestIsEquivalentRegistered) { 593 ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"), 594 "test1"); 595 ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"), 596 "test2"); 597 registry()->OnAcceptRegisterProtocolHandler(ph1); 598 599 ASSERT_TRUE(registry()->IsRegistered(ph1)); 600 ASSERT_TRUE(registry()->HasRegisteredEquivalent(ph2)); 601} 602 603TEST_F(ProtocolHandlerRegistryTest, TestSilentlyRegisterHandler) { 604 ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"), 605 "test1"); 606 ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"), 607 "test2"); 608 ProtocolHandler ph3 = CreateProtocolHandler("ignore", GURL("http://test/%s"), 609 "ignore1"); 610 ProtocolHandler ph4 = CreateProtocolHandler("ignore", GURL("http://test/%s"), 611 "ignore2"); 612 613 ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph1)); 614 ASSERT_FALSE(registry()->IsRegistered(ph1)); 615 616 registry()->OnAcceptRegisterProtocolHandler(ph1); 617 ASSERT_TRUE(registry()->IsRegistered(ph1)); 618 619 ASSERT_TRUE(registry()->SilentlyHandleRegisterHandlerRequest(ph2)); 620 ASSERT_FALSE(registry()->IsRegistered(ph1)); 621 ASSERT_TRUE(registry()->IsRegistered(ph2)); 622 623 ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph3)); 624 ASSERT_FALSE(registry()->IsRegistered(ph3)); 625 626 registry()->OnIgnoreRegisterProtocolHandler(ph3); 627 ASSERT_FALSE(registry()->IsRegistered(ph3)); 628 ASSERT_TRUE(registry()->IsIgnored(ph3)); 629 630 ASSERT_TRUE(registry()->SilentlyHandleRegisterHandlerRequest(ph4)); 631 ASSERT_FALSE(registry()->IsRegistered(ph4)); 632 ASSERT_TRUE(registry()->HasIgnoredEquivalent(ph4)); 633} 634 635TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestRemoveHandlerRemovesDefault) { 636 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 637 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 638 ProtocolHandler ph3 = CreateProtocolHandler("test", "test3"); 639 640 registry()->OnAcceptRegisterProtocolHandler(ph1); 641 registry()->OnAcceptRegisterProtocolHandler(ph2); 642 registry()->OnAcceptRegisterProtocolHandler(ph3); 643 644 registry()->OnAcceptRegisterProtocolHandler(ph1); 645 registry()->RemoveHandler(ph1); 646 ASSERT_FALSE(registry()->IsDefault(ph1)); 647} 648 649TEST_F(ProtocolHandlerRegistryTest, TestGetHandlersFor) { 650 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 651 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 652 ProtocolHandler ph3 = CreateProtocolHandler("test", "test3"); 653 registry()->OnAcceptRegisterProtocolHandler(ph1); 654 registry()->OnAcceptRegisterProtocolHandler(ph2); 655 registry()->OnAcceptRegisterProtocolHandler(ph3); 656 657 ProtocolHandlerRegistry::ProtocolHandlerList handlers = 658 registry()->GetHandlersFor("test"); 659 ASSERT_EQ(static_cast<size_t>(3), handlers.size()); 660 661 ASSERT_EQ(ph3, handlers[0]); 662 ASSERT_EQ(ph2, handlers[1]); 663 ASSERT_EQ(ph1, handlers[2]); 664} 665 666TEST_F(ProtocolHandlerRegistryTest, TestGetRegisteredProtocols) { 667 std::vector<std::string> protocols; 668 registry()->GetRegisteredProtocols(&protocols); 669 ASSERT_EQ(static_cast<size_t>(0), protocols.size()); 670 671 registry()->GetHandlersFor("test"); 672 673 protocols.clear(); 674 registry()->GetRegisteredProtocols(&protocols); 675 ASSERT_EQ(static_cast<size_t>(0), protocols.size()); 676} 677 678TEST_F(ProtocolHandlerRegistryTest, TestIsHandledProtocol) { 679 registry()->GetHandlersFor("test"); 680 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 681} 682 683TEST_F(ProtocolHandlerRegistryTest, TestNotifications) { 684 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 685 NotificationCounter counter(profile()); 686 687 registry()->OnAcceptRegisterProtocolHandler(ph1); 688 ASSERT_TRUE(counter.notified()); 689 counter.Clear(); 690 691 registry()->Disable(); 692 ASSERT_TRUE(counter.notified()); 693 counter.Clear(); 694 695 registry()->Enable(); 696 ASSERT_TRUE(counter.notified()); 697 counter.Clear(); 698 699 registry()->RemoveHandler(ph1); 700 ASSERT_TRUE(counter.notified()); 701 counter.Clear(); 702} 703 704TEST_F(ProtocolHandlerRegistryTest, TestReentrantNotifications) { 705 QueryProtocolHandlerOnChange queryer(profile(), registry()); 706 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 707 registry()->OnAcceptRegisterProtocolHandler(ph1); 708 ASSERT_TRUE(queryer.called_); 709} 710 711TEST_F(ProtocolHandlerRegistryTest, TestProtocolsWithNoDefaultAreHandled) { 712 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 713 registry()->OnAcceptRegisterProtocolHandler(ph1); 714 registry()->ClearDefault("test"); 715 std::vector<std::string> handled_protocols; 716 registry()->GetRegisteredProtocols(&handled_protocols); 717 ASSERT_EQ(static_cast<size_t>(1), handled_protocols.size()); 718 ASSERT_EQ("test", handled_protocols[0]); 719} 720 721TEST_F(ProtocolHandlerRegistryTest, TestDisablePreventsHandling) { 722 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 723 registry()->OnAcceptRegisterProtocolHandler(ph1); 724 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 725 registry()->Disable(); 726 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 727} 728 729// TODO(smckay): This is much more appropriately an integration 730// test. Make that so, then update the 731// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully 732// isolate this test from the FILE thread. 733TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) { 734 ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1"); 735 ProtocolHandler ph_do2 = CreateProtocolHandler("do", "test2"); 736 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test"); 737 738 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("do")); 739 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont")); 740 741 registry()->OnAcceptRegisterProtocolHandler(ph_do1); 742 registry()->OnDenyRegisterProtocolHandler(ph_dont); 743 base::MessageLoop::current()->Run(); // FILE thread needs to run. 744 ASSERT_TRUE(delegate()->IsFakeRegisteredWithOS("do")); 745 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont")); 746 747 // This should not register with the OS, if it does the delegate 748 // will assert for us. We don't need to wait for the message loop 749 // as it should not go through to the shell worker. 750 registry()->OnAcceptRegisterProtocolHandler(ph_do2); 751} 752 753#if defined(OS_LINUX) 754// TODO(benwells): When Linux support is more reliable and 755// http://crbut.com/88255 is fixed this test will pass. 756#define MAYBE_TestOSRegistrationFailure DISABLED_TestOSRegistrationFailure 757#else 758#define MAYBE_TestOSRegistrationFailure TestOSRegistrationFailure 759#endif 760 761// TODO(smckay): This is much more appropriately an integration 762// test. Make that so, then update the 763// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully 764// isolate this test from the FILE thread. 765TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) { 766 ProtocolHandler ph_do = CreateProtocolHandler("do", "test1"); 767 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test"); 768 769 ASSERT_FALSE(registry()->IsHandledProtocol("do")); 770 ASSERT_FALSE(registry()->IsHandledProtocol("dont")); 771 772 registry()->OnAcceptRegisterProtocolHandler(ph_do); 773 base::MessageLoop::current()->Run(); // FILE thread needs to run. 774 delegate()->set_force_os_failure(true); 775 registry()->OnAcceptRegisterProtocolHandler(ph_dont); 776 base::MessageLoop::current()->Run(); // FILE thread needs to run. 777 ASSERT_TRUE(registry()->IsHandledProtocol("do")); 778 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("do").size()); 779 ASSERT_FALSE(registry()->IsHandledProtocol("dont")); 780 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("dont").size()); 781} 782 783TEST_F(ProtocolHandlerRegistryTest, TestMaybeCreateTaskWorksFromIOThread) { 784 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 785 registry()->OnAcceptRegisterProtocolHandler(ph1); 786 GURL url("mailto:someone@something.com"); 787 788 scoped_ptr<net::URLRequestJobFactory> interceptor( 789 registry()->CreateJobInterceptorFactory()); 790 AssertIntercepted(url, interceptor.get()); 791} 792 793TEST_F(ProtocolHandlerRegistryTest, 794 MAYBE_TestIsHandledProtocolWorksOnIOThread) { 795 std::string scheme("mailto"); 796 ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1"); 797 registry()->OnAcceptRegisterProtocolHandler(ph1); 798 799 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor( 800 registry()->CreateJobInterceptorFactory()); 801 AssertWillHandle(scheme, true, interceptor.get()); 802} 803 804TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultFallsBackToOldDefault) { 805 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 806 ProtocolHandler ph2 = CreateProtocolHandler("mailto", "test2"); 807 ProtocolHandler ph3 = CreateProtocolHandler("mailto", "test3"); 808 registry()->OnAcceptRegisterProtocolHandler(ph1); 809 registry()->OnAcceptRegisterProtocolHandler(ph2); 810 registry()->OnAcceptRegisterProtocolHandler(ph3); 811 812 ASSERT_TRUE(registry()->IsDefault(ph3)); 813 registry()->RemoveHandler(ph3); 814 ASSERT_TRUE(registry()->IsDefault(ph2)); 815 registry()->OnAcceptRegisterProtocolHandler(ph3); 816 ASSERT_TRUE(registry()->IsDefault(ph3)); 817 registry()->RemoveHandler(ph2); 818 ASSERT_TRUE(registry()->IsDefault(ph3)); 819 registry()->RemoveHandler(ph3); 820 ASSERT_TRUE(registry()->IsDefault(ph1)); 821} 822 823TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultDoesntChangeHandlers) { 824 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 825 ProtocolHandler ph2 = CreateProtocolHandler("mailto", "test2"); 826 ProtocolHandler ph3 = CreateProtocolHandler("mailto", "test3"); 827 registry()->OnAcceptRegisterProtocolHandler(ph1); 828 registry()->OnAcceptRegisterProtocolHandler(ph2); 829 registry()->OnAcceptRegisterProtocolHandler(ph3); 830 registry()->RemoveHandler(ph3); 831 832 ProtocolHandlerRegistry::ProtocolHandlerList handlers = 833 registry()->GetHandlersFor("mailto"); 834 ASSERT_EQ(static_cast<size_t>(2), handlers.size()); 835 836 ASSERT_EQ(ph2, handlers[0]); 837 ASSERT_EQ(ph1, handlers[1]); 838} 839 840TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestClearDefaultGetsPropagatedToIO) { 841 std::string scheme("mailto"); 842 ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1"); 843 registry()->OnAcceptRegisterProtocolHandler(ph1); 844 registry()->ClearDefault(scheme); 845 846 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor( 847 registry()->CreateJobInterceptorFactory()); 848 AssertWillHandle(scheme, false, interceptor.get()); 849} 850 851TEST_F(ProtocolHandlerRegistryTest, TestLoadEnabledGetsPropogatedToIO) { 852 std::string mailto("mailto"); 853 ProtocolHandler ph1 = CreateProtocolHandler(mailto, "MailtoHandler"); 854 registry()->OnAcceptRegisterProtocolHandler(ph1); 855 856 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor( 857 registry()->CreateJobInterceptorFactory()); 858 AssertWillHandle(mailto, true, interceptor.get()); 859 registry()->Disable(); 860 AssertWillHandle(mailto, false, interceptor.get()); 861} 862 863TEST_F(ProtocolHandlerRegistryTest, TestReplaceHandler) { 864 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 865 GURL("http://test.com/%s"), "test1"); 866 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 867 GURL("http://test.com/updated-url/%s"), "test2"); 868 registry()->OnAcceptRegisterProtocolHandler(ph1); 869 ASSERT_TRUE(registry()->AttemptReplace(ph2)); 870 const ProtocolHandler& handler(registry()->GetHandlerFor("mailto")); 871 ASSERT_EQ(handler.url(), ph2.url()); 872} 873 874TEST_F(ProtocolHandlerRegistryTest, TestReplaceNonDefaultHandler) { 875 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 876 GURL("http://test.com/%s"), "test1"); 877 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 878 GURL("http://test.com/updated-url/%s"), "test2"); 879 ProtocolHandler ph3 = CreateProtocolHandler("mailto", 880 GURL("http://else.com/%s"), "test3"); 881 registry()->OnAcceptRegisterProtocolHandler(ph1); 882 registry()->OnAcceptRegisterProtocolHandler(ph3); 883 ASSERT_TRUE(registry()->AttemptReplace(ph2)); 884 const ProtocolHandler& handler(registry()->GetHandlerFor("mailto")); 885 ASSERT_EQ(handler.url(), ph3.url()); 886} 887 888TEST_F(ProtocolHandlerRegistryTest, TestReplaceRemovesStaleHandlers) { 889 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 890 GURL("http://test.com/%s"), "test1"); 891 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 892 GURL("http://test.com/updated-url/%s"), "test2"); 893 ProtocolHandler ph3 = CreateProtocolHandler("mailto", 894 GURL("http://test.com/third/%s"), "test"); 895 registry()->OnAcceptRegisterProtocolHandler(ph1); 896 registry()->OnAcceptRegisterProtocolHandler(ph2); 897 898 // This should replace the previous two handlers. 899 ASSERT_TRUE(registry()->AttemptReplace(ph3)); 900 const ProtocolHandler& handler(registry()->GetHandlerFor("mailto")); 901 ASSERT_EQ(handler.url(), ph3.url()); 902 registry()->RemoveHandler(ph3); 903 ASSERT_TRUE(registry()->GetHandlerFor("mailto").IsEmpty()); 904} 905 906TEST_F(ProtocolHandlerRegistryTest, TestIsSameOrigin) { 907 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 908 GURL("http://test.com/%s"), "test1"); 909 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 910 GURL("http://test.com/updated-url/%s"), "test2"); 911 ProtocolHandler ph3 = CreateProtocolHandler("mailto", 912 GURL("http://other.com/%s"), "test"); 913 ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(), 914 ph1.IsSameOrigin(ph2)); 915 ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(), 916 ph2.IsSameOrigin(ph1)); 917 ASSERT_EQ(ph2.url().GetOrigin() == ph3.url().GetOrigin(), 918 ph2.IsSameOrigin(ph3)); 919 ASSERT_EQ(ph3.url().GetOrigin() == ph2.url().GetOrigin(), 920 ph3.IsSameOrigin(ph2)); 921} 922 923TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestInstallDefaultHandler) { 924 RecreateRegistry(false); 925 registry()->AddPredefinedHandler(CreateProtocolHandler( 926 "test", GURL("http://test.com/%s"), "Test")); 927 registry()->InitProtocolSettings(); 928 std::vector<std::string> protocols; 929 registry()->GetRegisteredProtocols(&protocols); 930 ASSERT_EQ(static_cast<size_t>(1), protocols.size()); 931} 932