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