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