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