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_CUSTOM: 300 case base::MessageLoop::TYPE_DEFAULT: 301 return !BrowserThread::CurrentlyOn(BrowserThread::UI) && 302 !BrowserThread::CurrentlyOn(BrowserThread::IO); 303 } 304 return false; 305 } 306}; 307 308} // namespace 309 310class ProtocolHandlerRegistryTest : public testing::Test { 311 protected: 312 ProtocolHandlerRegistryTest() 313 : ui_thread_(BrowserThread::UI, &loop_), 314 file_thread_(BrowserThread::FILE, &loop_), 315 io_thread_(BrowserThread::IO, &loop_), 316 test_protocol_handler_(CreateProtocolHandler("test", "test")) {} 317 318 FakeDelegate* delegate() const { return delegate_; } 319 ProtocolHandlerRegistry* registry() { return registry_.get(); } 320 TestingProfile* profile() const { return profile_.get(); } 321 const ProtocolHandler& test_protocol_handler() const { 322 return test_protocol_handler_; 323 } 324 325 ProtocolHandler CreateProtocolHandler(const std::string& protocol, 326 const GURL& url, 327 const std::string& title) { 328 return ProtocolHandler::CreateProtocolHandler(protocol, url, 329 UTF8ToUTF16(title)); 330 } 331 332 ProtocolHandler CreateProtocolHandler(const std::string& protocol, 333 const std::string& name) { 334 return CreateProtocolHandler(protocol, GURL("http://" + name + "/%s"), 335 name); 336 } 337 338 void RecreateRegistry(bool initialize) { 339 TeadDownRegistry(); 340 SetUpRegistry(initialize); 341 } 342 343 // Returns a new registry, initializing it if |initialize| is true. 344 // Caller assumes ownership for the object 345 void SetUpRegistry(bool initialize) { 346 delegate_ = new FakeDelegate(); 347 registry_.reset(new ProtocolHandlerRegistry(profile(), delegate())); 348 if (initialize) registry_->InitProtocolSettings(); 349 } 350 351 void TeadDownRegistry() { 352 registry_->Shutdown(); 353 registry_.reset(); 354 // Registry owns the delegate_ it handles deletion of that object. 355 } 356 357 virtual void SetUp() { 358 profile_.reset(new TestingProfile()); 359 CHECK(profile_->GetPrefs()); 360 SetUpRegistry(true); 361 test_protocol_handler_ = 362 CreateProtocolHandler("test", GURL("http://test.com/%s"), "Test"); 363 } 364 365 virtual void TearDown() { 366 TeadDownRegistry(); 367 } 368 369 TestMessageLoop loop_; 370 371 private: 372 content::TestBrowserThread ui_thread_; 373 content::TestBrowserThread file_thread_; 374 content::TestBrowserThread io_thread_; 375 376 scoped_ptr<TestingProfile> profile_; 377 FakeDelegate* delegate_; // Registry assumes ownership of delegate_. 378 scoped_ptr<ProtocolHandlerRegistry> registry_; 379 ProtocolHandler test_protocol_handler_; 380}; 381 382// ProtocolHandlerRegistryTest tests are flaky on Linux & ChromeOS. 383// http://crbug.com/133023 384#if defined(OS_LINUX) || defined(OS_CHROMEOS) 385#define MAYBE_AcceptProtocolHandlerHandlesProtocol \ 386 DISABLED_AcceptProtocolHandlerHandlesProtocol 387#define MAYBE_DeniedProtocolIsntHandledUntilAccepted \ 388 DISABLED_DeniedProtocolIsntHandledUntilAccepted 389#define MAYBE_TestStartsAsDefault DISABLED_TestStartsAsDefault 390#define MAYBE_TestRemoveHandlerRemovesDefault \ 391 DISABLED_TestRemoveHandlerRemovesDefault 392#define MAYBE_TestClearDefaultGetsPropagatedToIO \ 393 DISABLED_TestClearDefaultGetsPropagatedToIO 394#define MAYBE_TestIsHandledProtocolWorksOnIOThread \ 395 DISABLED_TestIsHandledProtocolWorksOnIOThread 396#define MAYBE_TestInstallDefaultHandler \ 397 DISABLED_TestInstallDefaultHandler 398#else 399#define MAYBE_AcceptProtocolHandlerHandlesProtocol \ 400 AcceptProtocolHandlerHandlesProtocol 401#define MAYBE_DeniedProtocolIsntHandledUntilAccepted \ 402 DeniedProtocolIsntHandledUntilAccepted 403#define MAYBE_TestStartsAsDefault TestStartsAsDefault 404#define MAYBE_TestRemoveHandlerRemovesDefault TestRemoveHandlerRemovesDefault 405#define MAYBE_TestClearDefaultGetsPropagatedToIO \ 406 TestClearDefaultGetsPropagatedToIO 407#define MAYBE_TestIsHandledProtocolWorksOnIOThread \ 408 TestIsHandledProtocolWorksOnIOThread 409#define MAYBE_TestInstallDefaultHandler TestInstallDefaultHandler 410#endif // defined(OS_CHROMEOS) 411 412TEST_F(ProtocolHandlerRegistryTest, 413 MAYBE_AcceptProtocolHandlerHandlesProtocol) { 414 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 415 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 416 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 417} 418 419TEST_F(ProtocolHandlerRegistryTest, 420 MAYBE_DeniedProtocolIsntHandledUntilAccepted) { 421 registry()->OnDenyRegisterProtocolHandler(test_protocol_handler()); 422 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 423 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 424 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 425} 426 427TEST_F(ProtocolHandlerRegistryTest, ClearDefaultMakesProtocolNotHandled) { 428 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 429 registry()->ClearDefault("test"); 430 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 431 ASSERT_TRUE(registry()->GetHandlerFor("test").IsEmpty()); 432} 433 434TEST_F(ProtocolHandlerRegistryTest, DisableDeregistersProtocolHandlers) { 435 ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test")); 436 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 437 ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test")); 438 439 registry()->Disable(); 440 ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test")); 441 registry()->Enable(); 442 ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test")); 443} 444 445TEST_F(ProtocolHandlerRegistryTest, IgnoreProtocolHandler) { 446 registry()->OnIgnoreRegisterProtocolHandler(test_protocol_handler()); 447 ASSERT_TRUE(registry()->IsIgnored(test_protocol_handler())); 448 449 registry()->RemoveIgnoredHandler(test_protocol_handler()); 450 ASSERT_FALSE(registry()->IsIgnored(test_protocol_handler())); 451} 452 453TEST_F(ProtocolHandlerRegistryTest, IgnoreEquivalentProtocolHandler) { 454 ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"), 455 "test1"); 456 ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"), 457 "test2"); 458 459 registry()->OnIgnoreRegisterProtocolHandler(ph1); 460 ASSERT_TRUE(registry()->IsIgnored(ph1)); 461 ASSERT_TRUE(registry()->HasIgnoredEquivalent(ph2)); 462 463 registry()->RemoveIgnoredHandler(ph1); 464 ASSERT_FALSE(registry()->IsIgnored(ph1)); 465 ASSERT_FALSE(registry()->HasIgnoredEquivalent(ph2)); 466} 467 468TEST_F(ProtocolHandlerRegistryTest, SaveAndLoad) { 469 ProtocolHandler stuff_protocol_handler( 470 CreateProtocolHandler("stuff", "stuff")); 471 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 472 registry()->OnIgnoreRegisterProtocolHandler(stuff_protocol_handler); 473 474 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 475 ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler)); 476 delegate()->Reset(); 477 RecreateRegistry(true); 478 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 479 ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler)); 480} 481 482TEST_F(ProtocolHandlerRegistryTest, TestEnabledDisabled) { 483 registry()->Disable(); 484 ASSERT_FALSE(registry()->enabled()); 485 registry()->Enable(); 486 ASSERT_TRUE(registry()->enabled()); 487} 488 489TEST_F(ProtocolHandlerRegistryTest, 490 DisallowRegisteringExternallyHandledProtocols) { 491 delegate()->RegisterExternalHandler("test"); 492 ASSERT_FALSE(registry()->CanSchemeBeOverridden("test")); 493} 494 495TEST_F(ProtocolHandlerRegistryTest, RemovingHandlerMeansItCanBeAddedAgain) { 496 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 497 ASSERT_TRUE(registry()->CanSchemeBeOverridden("test")); 498 registry()->RemoveHandler(test_protocol_handler()); 499 ASSERT_TRUE(registry()->CanSchemeBeOverridden("test")); 500} 501 502TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestStartsAsDefault) { 503 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 504 ASSERT_TRUE(registry()->IsDefault(test_protocol_handler())); 505} 506 507TEST_F(ProtocolHandlerRegistryTest, TestClearDefault) { 508 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 509 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 510 registry()->OnAcceptRegisterProtocolHandler(ph1); 511 registry()->OnAcceptRegisterProtocolHandler(ph2); 512 513 registry()->OnAcceptRegisterProtocolHandler(ph1); 514 registry()->ClearDefault("test"); 515 ASSERT_FALSE(registry()->IsDefault(ph1)); 516 ASSERT_FALSE(registry()->IsDefault(ph2)); 517} 518 519TEST_F(ProtocolHandlerRegistryTest, TestGetHandlerFor) { 520 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 521 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 522 registry()->OnAcceptRegisterProtocolHandler(ph1); 523 registry()->OnAcceptRegisterProtocolHandler(ph2); 524 525 registry()->OnAcceptRegisterProtocolHandler(ph2); 526 ASSERT_EQ(ph2, registry()->GetHandlerFor("test")); 527 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 528} 529 530TEST_F(ProtocolHandlerRegistryTest, TestMostRecentHandlerIsDefault) { 531 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 532 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 533 registry()->OnAcceptRegisterProtocolHandler(ph1); 534 registry()->OnAcceptRegisterProtocolHandler(ph2); 535 ASSERT_FALSE(registry()->IsDefault(ph1)); 536 ASSERT_TRUE(registry()->IsDefault(ph2)); 537} 538 539TEST_F(ProtocolHandlerRegistryTest, TestOnAcceptRegisterProtocolHandler) { 540 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 541 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 542 registry()->OnAcceptRegisterProtocolHandler(ph1); 543 registry()->OnAcceptRegisterProtocolHandler(ph2); 544 545 registry()->OnAcceptRegisterProtocolHandler(ph1); 546 ASSERT_TRUE(registry()->IsDefault(ph1)); 547 ASSERT_FALSE(registry()->IsDefault(ph2)); 548 549 registry()->OnAcceptRegisterProtocolHandler(ph2); 550 ASSERT_FALSE(registry()->IsDefault(ph1)); 551 ASSERT_TRUE(registry()->IsDefault(ph2)); 552} 553 554TEST_F(ProtocolHandlerRegistryTest, TestDefaultSaveLoad) { 555 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 556 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 557 registry()->OnDenyRegisterProtocolHandler(ph1); 558 registry()->OnDenyRegisterProtocolHandler(ph2); 559 560 registry()->OnAcceptRegisterProtocolHandler(ph2); 561 registry()->Disable(); 562 563 RecreateRegistry(true); 564 565 ASSERT_FALSE(registry()->enabled()); 566 registry()->Enable(); 567 ASSERT_FALSE(registry()->IsDefault(ph1)); 568 ASSERT_TRUE(registry()->IsDefault(ph2)); 569 570 RecreateRegistry(true); 571 ASSERT_TRUE(registry()->enabled()); 572} 573 574TEST_F(ProtocolHandlerRegistryTest, TestRemoveHandler) { 575 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 576 registry()->OnAcceptRegisterProtocolHandler(ph1); 577 registry()->OnAcceptRegisterProtocolHandler(ph1); 578 579 registry()->RemoveHandler(ph1); 580 ASSERT_FALSE(registry()->IsRegistered(ph1)); 581 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 582} 583 584TEST_F(ProtocolHandlerRegistryTest, TestIsRegistered) { 585 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 586 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 587 registry()->OnAcceptRegisterProtocolHandler(ph1); 588 registry()->OnAcceptRegisterProtocolHandler(ph2); 589 590 ASSERT_TRUE(registry()->IsRegistered(ph1)); 591} 592 593TEST_F(ProtocolHandlerRegistryTest, TestIsEquivalentRegistered) { 594 ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"), 595 "test1"); 596 ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"), 597 "test2"); 598 registry()->OnAcceptRegisterProtocolHandler(ph1); 599 600 ASSERT_TRUE(registry()->IsRegistered(ph1)); 601 ASSERT_TRUE(registry()->HasRegisteredEquivalent(ph2)); 602} 603 604TEST_F(ProtocolHandlerRegistryTest, TestSilentlyRegisterHandler) { 605 ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"), 606 "test1"); 607 ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"), 608 "test2"); 609 ProtocolHandler ph3 = CreateProtocolHandler("ignore", GURL("http://test/%s"), 610 "ignore1"); 611 ProtocolHandler ph4 = CreateProtocolHandler("ignore", GURL("http://test/%s"), 612 "ignore2"); 613 614 ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph1)); 615 ASSERT_FALSE(registry()->IsRegistered(ph1)); 616 617 registry()->OnAcceptRegisterProtocolHandler(ph1); 618 ASSERT_TRUE(registry()->IsRegistered(ph1)); 619 620 ASSERT_TRUE(registry()->SilentlyHandleRegisterHandlerRequest(ph2)); 621 ASSERT_FALSE(registry()->IsRegistered(ph1)); 622 ASSERT_TRUE(registry()->IsRegistered(ph2)); 623 624 ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph3)); 625 ASSERT_FALSE(registry()->IsRegistered(ph3)); 626 627 registry()->OnIgnoreRegisterProtocolHandler(ph3); 628 ASSERT_FALSE(registry()->IsRegistered(ph3)); 629 ASSERT_TRUE(registry()->IsIgnored(ph3)); 630 631 ASSERT_TRUE(registry()->SilentlyHandleRegisterHandlerRequest(ph4)); 632 ASSERT_FALSE(registry()->IsRegistered(ph4)); 633 ASSERT_TRUE(registry()->HasIgnoredEquivalent(ph4)); 634} 635 636TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestRemoveHandlerRemovesDefault) { 637 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 638 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 639 ProtocolHandler ph3 = CreateProtocolHandler("test", "test3"); 640 641 registry()->OnAcceptRegisterProtocolHandler(ph1); 642 registry()->OnAcceptRegisterProtocolHandler(ph2); 643 registry()->OnAcceptRegisterProtocolHandler(ph3); 644 645 registry()->OnAcceptRegisterProtocolHandler(ph1); 646 registry()->RemoveHandler(ph1); 647 ASSERT_FALSE(registry()->IsDefault(ph1)); 648} 649 650TEST_F(ProtocolHandlerRegistryTest, TestGetHandlersFor) { 651 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 652 ProtocolHandler ph2 = CreateProtocolHandler("test", "test2"); 653 ProtocolHandler ph3 = CreateProtocolHandler("test", "test3"); 654 registry()->OnAcceptRegisterProtocolHandler(ph1); 655 registry()->OnAcceptRegisterProtocolHandler(ph2); 656 registry()->OnAcceptRegisterProtocolHandler(ph3); 657 658 ProtocolHandlerRegistry::ProtocolHandlerList handlers = 659 registry()->GetHandlersFor("test"); 660 ASSERT_EQ(static_cast<size_t>(3), handlers.size()); 661 662 ASSERT_EQ(ph3, handlers[0]); 663 ASSERT_EQ(ph2, handlers[1]); 664 ASSERT_EQ(ph1, handlers[2]); 665} 666 667TEST_F(ProtocolHandlerRegistryTest, TestGetRegisteredProtocols) { 668 std::vector<std::string> protocols; 669 registry()->GetRegisteredProtocols(&protocols); 670 ASSERT_EQ(static_cast<size_t>(0), protocols.size()); 671 672 registry()->GetHandlersFor("test"); 673 674 protocols.clear(); 675 registry()->GetRegisteredProtocols(&protocols); 676 ASSERT_EQ(static_cast<size_t>(0), protocols.size()); 677} 678 679TEST_F(ProtocolHandlerRegistryTest, TestIsHandledProtocol) { 680 registry()->GetHandlersFor("test"); 681 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 682} 683 684TEST_F(ProtocolHandlerRegistryTest, TestNotifications) { 685 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 686 NotificationCounter counter(profile()); 687 688 registry()->OnAcceptRegisterProtocolHandler(ph1); 689 ASSERT_TRUE(counter.notified()); 690 counter.Clear(); 691 692 registry()->Disable(); 693 ASSERT_TRUE(counter.notified()); 694 counter.Clear(); 695 696 registry()->Enable(); 697 ASSERT_TRUE(counter.notified()); 698 counter.Clear(); 699 700 registry()->RemoveHandler(ph1); 701 ASSERT_TRUE(counter.notified()); 702 counter.Clear(); 703} 704 705TEST_F(ProtocolHandlerRegistryTest, TestReentrantNotifications) { 706 QueryProtocolHandlerOnChange queryer(profile(), registry()); 707 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 708 registry()->OnAcceptRegisterProtocolHandler(ph1); 709 ASSERT_TRUE(queryer.called_); 710} 711 712TEST_F(ProtocolHandlerRegistryTest, TestProtocolsWithNoDefaultAreHandled) { 713 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 714 registry()->OnAcceptRegisterProtocolHandler(ph1); 715 registry()->ClearDefault("test"); 716 std::vector<std::string> handled_protocols; 717 registry()->GetRegisteredProtocols(&handled_protocols); 718 ASSERT_EQ(static_cast<size_t>(1), handled_protocols.size()); 719 ASSERT_EQ("test", handled_protocols[0]); 720} 721 722TEST_F(ProtocolHandlerRegistryTest, TestDisablePreventsHandling) { 723 ProtocolHandler ph1 = CreateProtocolHandler("test", "test1"); 724 registry()->OnAcceptRegisterProtocolHandler(ph1); 725 ASSERT_TRUE(registry()->IsHandledProtocol("test")); 726 registry()->Disable(); 727 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 728} 729 730// TODO(smckay): This is much more appropriately an integration 731// test. Make that so, then update the 732// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully 733// isolate this test from the FILE thread. 734TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) { 735 ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1"); 736 ProtocolHandler ph_do2 = CreateProtocolHandler("do", "test2"); 737 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test"); 738 739 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("do")); 740 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont")); 741 742 registry()->OnAcceptRegisterProtocolHandler(ph_do1); 743 registry()->OnDenyRegisterProtocolHandler(ph_dont); 744 base::MessageLoop::current()->Run(); // FILE thread needs to run. 745 ASSERT_TRUE(delegate()->IsFakeRegisteredWithOS("do")); 746 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont")); 747 748 // This should not register with the OS, if it does the delegate 749 // will assert for us. We don't need to wait for the message loop 750 // as it should not go through to the shell worker. 751 registry()->OnAcceptRegisterProtocolHandler(ph_do2); 752} 753 754#if defined(OS_LINUX) 755// TODO(benwells): When Linux support is more reliable and 756// http://crbut.com/88255 is fixed this test will pass. 757#define MAYBE_TestOSRegistrationFailure DISABLED_TestOSRegistrationFailure 758#else 759#define MAYBE_TestOSRegistrationFailure TestOSRegistrationFailure 760#endif 761 762// TODO(smckay): This is much more appropriately an integration 763// test. Make that so, then update the 764// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully 765// isolate this test from the FILE thread. 766TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) { 767 ProtocolHandler ph_do = CreateProtocolHandler("do", "test1"); 768 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test"); 769 770 ASSERT_FALSE(registry()->IsHandledProtocol("do")); 771 ASSERT_FALSE(registry()->IsHandledProtocol("dont")); 772 773 registry()->OnAcceptRegisterProtocolHandler(ph_do); 774 base::MessageLoop::current()->Run(); // FILE thread needs to run. 775 delegate()->set_force_os_failure(true); 776 registry()->OnAcceptRegisterProtocolHandler(ph_dont); 777 base::MessageLoop::current()->Run(); // FILE thread needs to run. 778 ASSERT_TRUE(registry()->IsHandledProtocol("do")); 779 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("do").size()); 780 ASSERT_FALSE(registry()->IsHandledProtocol("dont")); 781 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("dont").size()); 782} 783 784TEST_F(ProtocolHandlerRegistryTest, TestMaybeCreateTaskWorksFromIOThread) { 785 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 786 registry()->OnAcceptRegisterProtocolHandler(ph1); 787 GURL url("mailto:someone@something.com"); 788 789 scoped_ptr<net::URLRequestJobFactory> interceptor( 790 registry()->CreateJobInterceptorFactory()); 791 AssertIntercepted(url, interceptor.get()); 792} 793 794TEST_F(ProtocolHandlerRegistryTest, 795 MAYBE_TestIsHandledProtocolWorksOnIOThread) { 796 std::string scheme("mailto"); 797 ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1"); 798 registry()->OnAcceptRegisterProtocolHandler(ph1); 799 800 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor( 801 registry()->CreateJobInterceptorFactory()); 802 AssertWillHandle(scheme, true, interceptor.get()); 803} 804 805TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultFallsBackToOldDefault) { 806 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 807 ProtocolHandler ph2 = CreateProtocolHandler("mailto", "test2"); 808 ProtocolHandler ph3 = CreateProtocolHandler("mailto", "test3"); 809 registry()->OnAcceptRegisterProtocolHandler(ph1); 810 registry()->OnAcceptRegisterProtocolHandler(ph2); 811 registry()->OnAcceptRegisterProtocolHandler(ph3); 812 813 ASSERT_TRUE(registry()->IsDefault(ph3)); 814 registry()->RemoveHandler(ph3); 815 ASSERT_TRUE(registry()->IsDefault(ph2)); 816 registry()->OnAcceptRegisterProtocolHandler(ph3); 817 ASSERT_TRUE(registry()->IsDefault(ph3)); 818 registry()->RemoveHandler(ph2); 819 ASSERT_TRUE(registry()->IsDefault(ph3)); 820 registry()->RemoveHandler(ph3); 821 ASSERT_TRUE(registry()->IsDefault(ph1)); 822} 823 824TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultDoesntChangeHandlers) { 825 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 826 ProtocolHandler ph2 = CreateProtocolHandler("mailto", "test2"); 827 ProtocolHandler ph3 = CreateProtocolHandler("mailto", "test3"); 828 registry()->OnAcceptRegisterProtocolHandler(ph1); 829 registry()->OnAcceptRegisterProtocolHandler(ph2); 830 registry()->OnAcceptRegisterProtocolHandler(ph3); 831 registry()->RemoveHandler(ph3); 832 833 ProtocolHandlerRegistry::ProtocolHandlerList handlers = 834 registry()->GetHandlersFor("mailto"); 835 ASSERT_EQ(static_cast<size_t>(2), handlers.size()); 836 837 ASSERT_EQ(ph2, handlers[0]); 838 ASSERT_EQ(ph1, handlers[1]); 839} 840 841TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestClearDefaultGetsPropagatedToIO) { 842 std::string scheme("mailto"); 843 ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1"); 844 registry()->OnAcceptRegisterProtocolHandler(ph1); 845 registry()->ClearDefault(scheme); 846 847 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor( 848 registry()->CreateJobInterceptorFactory()); 849 AssertWillHandle(scheme, false, interceptor.get()); 850} 851 852TEST_F(ProtocolHandlerRegistryTest, TestLoadEnabledGetsPropogatedToIO) { 853 std::string mailto("mailto"); 854 ProtocolHandler ph1 = CreateProtocolHandler(mailto, "MailtoHandler"); 855 registry()->OnAcceptRegisterProtocolHandler(ph1); 856 857 scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor( 858 registry()->CreateJobInterceptorFactory()); 859 AssertWillHandle(mailto, true, interceptor.get()); 860 registry()->Disable(); 861 AssertWillHandle(mailto, false, interceptor.get()); 862} 863 864TEST_F(ProtocolHandlerRegistryTest, TestReplaceHandler) { 865 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 866 GURL("http://test.com/%s"), "test1"); 867 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 868 GURL("http://test.com/updated-url/%s"), "test2"); 869 registry()->OnAcceptRegisterProtocolHandler(ph1); 870 ASSERT_TRUE(registry()->AttemptReplace(ph2)); 871 const ProtocolHandler& handler(registry()->GetHandlerFor("mailto")); 872 ASSERT_EQ(handler.url(), ph2.url()); 873} 874 875TEST_F(ProtocolHandlerRegistryTest, TestReplaceNonDefaultHandler) { 876 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 877 GURL("http://test.com/%s"), "test1"); 878 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 879 GURL("http://test.com/updated-url/%s"), "test2"); 880 ProtocolHandler ph3 = CreateProtocolHandler("mailto", 881 GURL("http://else.com/%s"), "test3"); 882 registry()->OnAcceptRegisterProtocolHandler(ph1); 883 registry()->OnAcceptRegisterProtocolHandler(ph3); 884 ASSERT_TRUE(registry()->AttemptReplace(ph2)); 885 const ProtocolHandler& handler(registry()->GetHandlerFor("mailto")); 886 ASSERT_EQ(handler.url(), ph3.url()); 887} 888 889TEST_F(ProtocolHandlerRegistryTest, TestReplaceRemovesStaleHandlers) { 890 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 891 GURL("http://test.com/%s"), "test1"); 892 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 893 GURL("http://test.com/updated-url/%s"), "test2"); 894 ProtocolHandler ph3 = CreateProtocolHandler("mailto", 895 GURL("http://test.com/third/%s"), "test"); 896 registry()->OnAcceptRegisterProtocolHandler(ph1); 897 registry()->OnAcceptRegisterProtocolHandler(ph2); 898 899 // This should replace the previous two handlers. 900 ASSERT_TRUE(registry()->AttemptReplace(ph3)); 901 const ProtocolHandler& handler(registry()->GetHandlerFor("mailto")); 902 ASSERT_EQ(handler.url(), ph3.url()); 903 registry()->RemoveHandler(ph3); 904 ASSERT_TRUE(registry()->GetHandlerFor("mailto").IsEmpty()); 905} 906 907TEST_F(ProtocolHandlerRegistryTest, TestIsSameOrigin) { 908 ProtocolHandler ph1 = CreateProtocolHandler("mailto", 909 GURL("http://test.com/%s"), "test1"); 910 ProtocolHandler ph2 = CreateProtocolHandler("mailto", 911 GURL("http://test.com/updated-url/%s"), "test2"); 912 ProtocolHandler ph3 = CreateProtocolHandler("mailto", 913 GURL("http://other.com/%s"), "test"); 914 ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(), 915 ph1.IsSameOrigin(ph2)); 916 ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(), 917 ph2.IsSameOrigin(ph1)); 918 ASSERT_EQ(ph2.url().GetOrigin() == ph3.url().GetOrigin(), 919 ph2.IsSameOrigin(ph3)); 920 ASSERT_EQ(ph3.url().GetOrigin() == ph2.url().GetOrigin(), 921 ph3.IsSameOrigin(ph2)); 922} 923 924TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestInstallDefaultHandler) { 925 RecreateRegistry(false); 926 registry()->AddPredefinedHandler(CreateProtocolHandler( 927 "test", GURL("http://test.com/%s"), "Test")); 928 registry()->InitProtocolSettings(); 929 std::vector<std::string> protocols; 930 registry()->GetRegisteredProtocols(&protocols); 931 ASSERT_EQ(static_cast<size_t>(1), protocols.size()); 932} 933