Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / custom_handlers / protocol_handler_registry_unittest.cc
index a3783da..7a1f09e 100644 (file)
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/common/custom_handlers/protocol_handler.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/user_prefs/pref_registry_syncable.h"
+#include "components/pref_registry/pref_registry_syncable.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_source.h"
@@ -35,10 +36,11 @@ void AssertInterceptedIO(
     net::URLRequestJobFactory* interceptor) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   net::URLRequestContext context;
-  net::URLRequest request(url, net::DEFAULT_PRIORITY, NULL, &context);
+  scoped_ptr<net::URLRequest> request(context.CreateRequest(
+      url, net::DEFAULT_PRIORITY, NULL, NULL));
   scoped_refptr<net::URLRequestJob> job =
       interceptor->MaybeCreateJobWithProtocolHandler(
-          url.scheme(), &request, context.network_delegate());
+          url.scheme(), request.get(), context.network_delegate());
   ASSERT_TRUE(job.get() != NULL);
 }
 
@@ -61,19 +63,31 @@ void AssertIntercepted(
 // ProtocolHandlerRegistry properly handled a job creation request.
 class FakeURLRequestJobFactory : public net::URLRequestJobFactory {
   // net::URLRequestJobFactory implementation:
-  virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+  net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
       const std::string& scheme,
       net::URLRequest* request,
-      net::NetworkDelegate* network_delegate) const OVERRIDE {
+      net::NetworkDelegate* network_delegate) const override {
     return NULL;
   }
-  virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
-    return false;
+
+  net::URLRequestJob* MaybeInterceptRedirect(
+      net::URLRequest* request,
+      net::NetworkDelegate* network_delegate,
+      const GURL& location) const override {
+    return nullptr;
   }
-  virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+
+  net::URLRequestJob* MaybeInterceptResponse(
+      net::URLRequest* request,
+      net::NetworkDelegate* network_delegate) const override {
+    return nullptr;
+  }
+
+  bool IsHandledProtocol(const std::string& scheme) const override {
     return false;
   }
-  virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+  bool IsHandledURL(const GURL& url) const override { return false; }
+  bool IsSafeRedirectTarget(const GURL& location) const override {
     return true;
   }
 };
@@ -103,37 +117,51 @@ void AssertWillHandle(
   base::MessageLoop::current()->RunUntilIdle();
 }
 
+base::DictionaryValue* GetProtocolHandlerValue(std::string protocol,
+                                               std::string url) {
+  base::DictionaryValue* value = new base::DictionaryValue();
+  value->SetString("protocol", protocol);
+  value->SetString("url", url);
+  return value;
+}
+
+base::DictionaryValue* GetProtocolHandlerValueWithDefault(std::string protocol,
+                                                          std::string url,
+                                                          bool is_default) {
+  base::DictionaryValue* value = GetProtocolHandlerValue(protocol, url);
+  value->SetBoolean("default", is_default);
+  return value;
+}
+
 class FakeDelegate : public ProtocolHandlerRegistry::Delegate {
  public:
   FakeDelegate() : force_os_failure_(false) {}
-  virtual ~FakeDelegate() { }
-  virtual void RegisterExternalHandler(const std::string& protocol) OVERRIDE {
+  ~FakeDelegate() override {}
+  void RegisterExternalHandler(const std::string& protocol) override {
     ASSERT_TRUE(
         registered_protocols_.find(protocol) == registered_protocols_.end());
     registered_protocols_.insert(protocol);
   }
 
-  virtual void DeregisterExternalHandler(const std::string& protocol) OVERRIDE {
+  void DeregisterExternalHandler(const std::string& protocol) override {
     registered_protocols_.erase(protocol);
   }
 
-  virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker(
-    ShellIntegration::DefaultWebClientObserver* observer,
-    const std::string& protocol) OVERRIDE;
+  ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker(
+      ShellIntegration::DefaultWebClientObserver* observer,
+      const std::string& protocol) override;
 
-  virtual ProtocolHandlerRegistry::DefaultClientObserver* CreateShellObserver(
-      ProtocolHandlerRegistry* registry) OVERRIDE;
+  ProtocolHandlerRegistry::DefaultClientObserver* CreateShellObserver(
+      ProtocolHandlerRegistry* registry) override;
 
-  virtual void RegisterWithOSAsDefaultClient(
-      const std::string& protocol,
-      ProtocolHandlerRegistry* reg) OVERRIDE {
+  void RegisterWithOSAsDefaultClient(const std::string& protocol,
+                                     ProtocolHandlerRegistry* reg) override {
     ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(protocol,
                                                                      reg);
     ASSERT_FALSE(IsFakeRegisteredWithOS(protocol));
   }
 
-  virtual bool IsExternalHandlerRegistered(
-      const std::string& protocol) OVERRIDE {
+  bool IsExternalHandlerRegistered(const std::string& protocol) override {
     return registered_protocols_.find(protocol) != registered_protocols_.end();
   }
 
@@ -170,8 +198,8 @@ class FakeClientObserver
       : ProtocolHandlerRegistry::DefaultClientObserver(registry),
         delegate_(registry_delegate) {}
 
-  virtual void SetDefaultWebClientUIState(
-      ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
+  void SetDefaultWebClientUIState(
+      ShellIntegration::DefaultWebClientUIState state) override {
     ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
         state);
     if (state == ShellIntegration::STATE_IS_DEFAULT) {
@@ -196,9 +224,9 @@ class FakeProtocolClientWorker
         force_failure_(force_failure) {}
 
  private:
-  virtual ~FakeProtocolClientWorker() {}
+  ~FakeProtocolClientWorker() override {}
 
-  virtual ShellIntegration::DefaultWebClientState CheckIsDefault() OVERRIDE {
+  ShellIntegration::DefaultWebClientState CheckIsDefault() override {
     if (force_failure_) {
       return ShellIntegration::NOT_DEFAULT;
     } else {
@@ -206,9 +234,7 @@ class FakeProtocolClientWorker
     }
   }
 
-  virtual bool SetAsDefault(bool interactive_permitted) OVERRIDE {
-    return true;
-  }
+  bool SetAsDefault(bool interactive_permitted) override { return true; }
 
  private:
   bool force_failure_;
@@ -227,20 +253,20 @@ ShellIntegration::DefaultProtocolClientWorker* FakeDelegate::CreateShellWorker(
 
 class NotificationCounter : public content::NotificationObserver {
  public:
-  explicit NotificationCounter(Profile* profile)
+  explicit NotificationCounter(content::BrowserContext* context)
       : events_(0),
         notification_registrar_() {
     notification_registrar_.Add(this,
         chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
-        content::Source<Profile>(profile));
+            content::Source<content::BrowserContext>(context));
   }
 
   int events() { return events_; }
   bool notified() { return events_ > 0; }
   void Clear() { events_ = 0; }
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE {
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override {
     ++events_;
   }
 
@@ -251,19 +277,19 @@ class NotificationCounter : public content::NotificationObserver {
 class QueryProtocolHandlerOnChange
     : public content::NotificationObserver {
  public:
-  QueryProtocolHandlerOnChange(Profile* profile,
+  QueryProtocolHandlerOnChange(content::BrowserContext* context,
                                ProtocolHandlerRegistry* registry)
     : local_registry_(registry),
       called_(false),
       notification_registrar_() {
     notification_registrar_.Add(this,
         chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
-        content::Source<Profile>(profile));
+            content::Source<content::BrowserContext>(context));
   }
 
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE {
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override {
     std::vector<std::string> output;
     local_registry_->GetRegisteredProtocols(&output);
     called_ = true;
@@ -283,8 +309,8 @@ class QueryProtocolHandlerOnChange
 class TestMessageLoop : public base::MessageLoop {
  public:
   TestMessageLoop() {}
-  virtual ~TestMessageLoop() {}
-  virtual bool IsType(base::MessageLoop::Type type) const OVERRIDE {
+  ~TestMessageLoop() override {}
+  bool IsType(base::MessageLoop::Type type) const override {
     switch (type) {
       case base::MessageLoop::TYPE_UI:
         return BrowserThread::CurrentlyOn(BrowserThread::UI);
@@ -320,16 +346,13 @@ class ProtocolHandlerRegistryTest : public testing::Test {
   }
 
   ProtocolHandler CreateProtocolHandler(const std::string& protocol,
-                                        const GURL& url,
-                                        const std::string& title) {
-    return ProtocolHandler::CreateProtocolHandler(protocol, url,
-        base::UTF8ToUTF16(title));
+                                        const GURL& url) {
+    return ProtocolHandler::CreateProtocolHandler(protocol, url);
   }
 
   ProtocolHandler CreateProtocolHandler(const std::string& protocol,
-      const std::string& name) {
-    return CreateProtocolHandler(protocol, GURL("http://" + name + "/%s"),
-        name);
+                                        const std::string& name) {
+    return CreateProtocolHandler(protocol, GURL("http://" + name + "/%s"));
   }
 
   void RecreateRegistry(bool initialize) {
@@ -337,6 +360,36 @@ class ProtocolHandlerRegistryTest : public testing::Test {
     SetUpRegistry(initialize);
   }
 
+  int InPrefHandlerCount() {
+    const base::ListValue* in_pref_handlers =
+        profile()->GetPrefs()->GetList(prefs::kRegisteredProtocolHandlers);
+    return static_cast<int>(in_pref_handlers->GetSize());
+  }
+
+  int InMemoryHandlerCount() {
+    int in_memory_handler_count = 0;
+    ProtocolHandlerRegistry::ProtocolHandlerMultiMap::iterator it =
+        registry()->protocol_handlers_.begin();
+    for (; it != registry()->protocol_handlers_.end(); ++it)
+      in_memory_handler_count += it->second.size();
+    return in_memory_handler_count;
+  }
+
+  int InPrefIgnoredHandlerCount() {
+    const base::ListValue* in_pref_ignored_handlers =
+        profile()->GetPrefs()->GetList(prefs::kIgnoredProtocolHandlers);
+    return static_cast<int>(in_pref_ignored_handlers->GetSize());
+  }
+
+  int InMemoryIgnoredHandlerCount() {
+    int in_memory_ignored_handler_count = 0;
+    ProtocolHandlerRegistry::ProtocolHandlerList::iterator it =
+        registry()->ignored_protocol_handlers_.begin();
+    for (; it != registry()->ignored_protocol_handlers_.end(); ++it)
+      in_memory_ignored_handler_count++;
+    return in_memory_ignored_handler_count;
+  }
+
   // Returns a new registry, initializing it if |initialize| is true.
   // Caller assumes ownership for the object
   void SetUpRegistry(bool initialize) {
@@ -351,17 +404,15 @@ class ProtocolHandlerRegistryTest : public testing::Test {
     // Registry owns the delegate_ it handles deletion of that object.
   }
 
-  virtual void SetUp() {
+  void SetUp() override {
     profile_.reset(new TestingProfile());
     CHECK(profile_->GetPrefs());
     SetUpRegistry(true);
     test_protocol_handler_ =
-        CreateProtocolHandler("test", GURL("http://test.com/%s"), "Test");
+        CreateProtocolHandler("test", GURL("http://test.com/%s"));
   }
 
-  virtual void TearDown() {
-    TeadDownRegistry();
-  }
+  void TearDown() override { TeadDownRegistry(); }
 
   TestMessageLoop loop_;
 
@@ -448,10 +499,8 @@ TEST_F(ProtocolHandlerRegistryTest, IgnoreProtocolHandler) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, IgnoreEquivalentProtocolHandler) {
-  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"),
-                                              "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"),
-                                              "test2");
+  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"));
+  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"));
 
   registry()->OnIgnoreRegisterProtocolHandler(ph1);
   ASSERT_TRUE(registry()->IsIgnored(ph1));
@@ -588,10 +637,8 @@ TEST_F(ProtocolHandlerRegistryTest, TestIsRegistered) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, TestIsEquivalentRegistered) {
-  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"),
-                                              "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"),
-                                              "test2");
+  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"));
+  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"));
   registry()->OnAcceptRegisterProtocolHandler(ph1);
 
   ASSERT_TRUE(registry()->IsRegistered(ph1));
@@ -599,14 +646,10 @@ TEST_F(ProtocolHandlerRegistryTest, TestIsEquivalentRegistered) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, TestSilentlyRegisterHandler) {
-  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"),
-                                              "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"),
-                                              "test2");
-  ProtocolHandler ph3 = CreateProtocolHandler("ignore", GURL("http://test/%s"),
-                                              "ignore1");
-  ProtocolHandler ph4 = CreateProtocolHandler("ignore", GURL("http://test/%s"),
-                                              "ignore2");
+  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/1/%s"));
+  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/2/%s"));
+  ProtocolHandler ph3 = CreateProtocolHandler("ignore", GURL("http://test/%s"));
+  ProtocolHandler ph4 = CreateProtocolHandler("ignore", GURL("http://test/%s"));
 
   ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph1));
   ASSERT_FALSE(registry()->IsRegistered(ph1));
@@ -859,10 +902,10 @@ TEST_F(ProtocolHandlerRegistryTest, TestLoadEnabledGetsPropogatedToIO) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, TestReplaceHandler) {
-  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/%s"), "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/updated-url/%s"), "test2");
+  ProtocolHandler ph1 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/%s"));
+  ProtocolHandler ph2 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/updated-url/%s"));
   registry()->OnAcceptRegisterProtocolHandler(ph1);
   ASSERT_TRUE(registry()->AttemptReplace(ph2));
   const ProtocolHandler& handler(registry()->GetHandlerFor("mailto"));
@@ -870,12 +913,12 @@ TEST_F(ProtocolHandlerRegistryTest, TestReplaceHandler) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, TestReplaceNonDefaultHandler) {
-  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/%s"), "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/updated-url/%s"), "test2");
-  ProtocolHandler ph3 = CreateProtocolHandler("mailto",
-      GURL("http://else.com/%s"), "test3");
+  ProtocolHandler ph1 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/%s"));
+  ProtocolHandler ph2 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/updated-url/%s"));
+  ProtocolHandler ph3 =
+      CreateProtocolHandler("mailto", GURL("http://else.com/%s"));
   registry()->OnAcceptRegisterProtocolHandler(ph1);
   registry()->OnAcceptRegisterProtocolHandler(ph3);
   ASSERT_TRUE(registry()->AttemptReplace(ph2));
@@ -884,12 +927,12 @@ TEST_F(ProtocolHandlerRegistryTest, TestReplaceNonDefaultHandler) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, TestReplaceRemovesStaleHandlers) {
-  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/%s"), "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/updated-url/%s"), "test2");
-  ProtocolHandler ph3 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/third/%s"), "test");
+  ProtocolHandler ph1 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/%s"));
+  ProtocolHandler ph2 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/updated-url/%s"));
+  ProtocolHandler ph3 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/third/%s"));
   registry()->OnAcceptRegisterProtocolHandler(ph1);
   registry()->OnAcceptRegisterProtocolHandler(ph2);
 
@@ -902,12 +945,12 @@ TEST_F(ProtocolHandlerRegistryTest, TestReplaceRemovesStaleHandlers) {
 }
 
 TEST_F(ProtocolHandlerRegistryTest, TestIsSameOrigin) {
-  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/%s"), "test1");
-  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
-      GURL("http://test.com/updated-url/%s"), "test2");
-  ProtocolHandler ph3 = CreateProtocolHandler("mailto",
-      GURL("http://other.com/%s"), "test");
+  ProtocolHandler ph1 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/%s"));
+  ProtocolHandler ph2 =
+      CreateProtocolHandler("mailto", GURL("http://test.com/updated-url/%s"));
+  ProtocolHandler ph3 =
+      CreateProtocolHandler("mailto", GURL("http://other.com/%s"));
   ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(),
       ph1.IsSameOrigin(ph2));
   ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(),
@@ -920,10 +963,169 @@ TEST_F(ProtocolHandlerRegistryTest, TestIsSameOrigin) {
 
 TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestInstallDefaultHandler) {
   RecreateRegistry(false);
-  registry()->AddPredefinedHandler(CreateProtocolHandler(
-      "test", GURL("http://test.com/%s"), "Test"));
+  registry()->AddPredefinedHandler(
+      CreateProtocolHandler("test", GURL("http://test.com/%s")));
   registry()->InitProtocolSettings();
   std::vector<std::string> protocols;
   registry()->GetRegisteredProtocols(&protocols);
   ASSERT_EQ(static_cast<size_t>(1), protocols.size());
 }
+
+#define URL_p1u1 "http://p1u1.com/%s"
+#define URL_p1u2 "http://p1u2.com/%s"
+#define URL_p1u3 "http://p1u3.com/%s"
+#define URL_p2u1 "http://p2u1.com/%s"
+#define URL_p2u2 "http://p2u2.com/%s"
+#define URL_p3u1 "http://p3u1.com/%s"
+
+TEST_F(ProtocolHandlerRegistryTest, TestPrefPolicyOverlapRegister) {
+  base::ListValue handlers_registered_by_pref;
+  base::ListValue handlers_registered_by_policy;
+
+  handlers_registered_by_pref.Append(
+      GetProtocolHandlerValueWithDefault("p1", URL_p1u2, true));
+  handlers_registered_by_pref.Append(
+      GetProtocolHandlerValueWithDefault("p1", URL_p1u1, true));
+  handlers_registered_by_pref.Append(
+      GetProtocolHandlerValueWithDefault("p1", URL_p1u2, false));
+
+  handlers_registered_by_policy.Append(
+      GetProtocolHandlerValueWithDefault("p1", URL_p1u1, false));
+  handlers_registered_by_policy.Append(
+      GetProtocolHandlerValueWithDefault("p3", URL_p3u1, true));
+
+  profile()->GetPrefs()->Set(prefs::kRegisteredProtocolHandlers,
+                             handlers_registered_by_pref);
+  profile()->GetPrefs()->Set(prefs::kPolicyRegisteredProtocolHandlers,
+                             handlers_registered_by_policy);
+  registry()->InitProtocolSettings();
+
+  // Duplicate p1u2 eliminated in memory but not yet saved in pref
+  ProtocolHandler p1u1 = CreateProtocolHandler("p1", GURL(URL_p1u1));
+  ProtocolHandler p1u2 = CreateProtocolHandler("p1", GURL(URL_p1u2));
+  ASSERT_EQ(InPrefHandlerCount(), 3);
+  ASSERT_EQ(InMemoryHandlerCount(), 3);
+  ASSERT_TRUE(registry()->IsDefault(p1u1));
+  ASSERT_FALSE(registry()->IsDefault(p1u2));
+
+  ProtocolHandler p2u1 = CreateProtocolHandler("p2", GURL(URL_p2u1));
+  registry()->OnDenyRegisterProtocolHandler(p2u1);
+
+  // Duplicate p1u2 saved in pref and a new handler added to pref and memory
+  ASSERT_EQ(InPrefHandlerCount(), 3);
+  ASSERT_EQ(InMemoryHandlerCount(), 4);
+  ASSERT_FALSE(registry()->IsDefault(p2u1));
+
+  registry()->RemoveHandler(p1u1);
+
+  // p1u1 removed from user pref but not from memory due to policy.
+  ASSERT_EQ(InPrefHandlerCount(), 2);
+  ASSERT_EQ(InMemoryHandlerCount(), 4);
+  ASSERT_TRUE(registry()->IsDefault(p1u1));
+
+  ProtocolHandler p3u1 = CreateProtocolHandler("p3", GURL(URL_p3u1));
+  registry()->RemoveHandler(p3u1);
+
+  // p3u1 not removed from memory due to policy and it was never in pref.
+  ASSERT_EQ(InPrefHandlerCount(), 2);
+  ASSERT_EQ(InMemoryHandlerCount(), 4);
+  ASSERT_TRUE(registry()->IsDefault(p3u1));
+
+  registry()->RemoveHandler(p1u2);
+
+  // p1u2 removed from user pref and memory.
+  ASSERT_EQ(InPrefHandlerCount(), 1);
+  ASSERT_EQ(InMemoryHandlerCount(), 3);
+  ASSERT_TRUE(registry()->IsDefault(p1u1));
+
+  ProtocolHandler p1u3 = CreateProtocolHandler("p1", GURL(URL_p1u3));
+  registry()->OnAcceptRegisterProtocolHandler(p1u3);
+
+  // p1u3 added to pref and memory.
+  ASSERT_EQ(InPrefHandlerCount(), 2);
+  ASSERT_EQ(InMemoryHandlerCount(), 4);
+  ASSERT_FALSE(registry()->IsDefault(p1u1));
+  ASSERT_TRUE(registry()->IsDefault(p1u3));
+
+  registry()->RemoveHandler(p1u3);
+
+  // p1u3 the default handler for p1 removed from user pref and memory.
+  ASSERT_EQ(InPrefHandlerCount(), 1);
+  ASSERT_EQ(InMemoryHandlerCount(), 3);
+  ASSERT_FALSE(registry()->IsDefault(p1u3));
+  ASSERT_TRUE(registry()->IsDefault(p1u1));
+  ASSERT_TRUE(registry()->IsDefault(p3u1));
+  ASSERT_FALSE(registry()->IsDefault(p2u1));
+}
+
+TEST_F(ProtocolHandlerRegistryTest, TestPrefPolicyOverlapIgnore) {
+  base::ListValue handlers_ignored_by_pref;
+  base::ListValue handlers_ignored_by_policy;
+
+  handlers_ignored_by_pref.Append(GetProtocolHandlerValue("p1", URL_p1u1));
+  handlers_ignored_by_pref.Append(GetProtocolHandlerValue("p1", URL_p1u2));
+  handlers_ignored_by_pref.Append(GetProtocolHandlerValue("p1", URL_p1u2));
+  handlers_ignored_by_pref.Append(GetProtocolHandlerValue("p3", URL_p3u1));
+
+  handlers_ignored_by_policy.Append(GetProtocolHandlerValue("p1", URL_p1u2));
+  handlers_ignored_by_policy.Append(GetProtocolHandlerValue("p1", URL_p1u3));
+  handlers_ignored_by_policy.Append(GetProtocolHandlerValue("p2", URL_p2u1));
+
+  profile()->GetPrefs()->Set(prefs::kIgnoredProtocolHandlers,
+                             handlers_ignored_by_pref);
+  profile()->GetPrefs()->Set(prefs::kPolicyIgnoredProtocolHandlers,
+                             handlers_ignored_by_policy);
+  registry()->InitProtocolSettings();
+
+  // Duplicate p1u2 eliminated in memory but not yet saved in pref
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 4);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 5);
+
+  ProtocolHandler p2u2 = CreateProtocolHandler("p2", GURL(URL_p2u2));
+  registry()->OnIgnoreRegisterProtocolHandler(p2u2);
+
+  // Duplicate p1u2 eliminated in pref, p2u2 added to pref and memory.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 4);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 6);
+
+  ProtocolHandler p2u1 = CreateProtocolHandler("p2", GURL(URL_p2u1));
+  registry()->RemoveIgnoredHandler(p2u1);
+
+  // p2u1 installed by policy so cant be removed.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 4);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 6);
+
+  ProtocolHandler p1u2 = CreateProtocolHandler("p1", GURL(URL_p1u2));
+  registry()->RemoveIgnoredHandler(p1u2);
+
+  // p1u2 installed by policy and pref so it is removed from pref and not from
+  // memory.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 3);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 6);
+
+  ProtocolHandler p1u1 = CreateProtocolHandler("p1", GURL(URL_p1u1));
+  registry()->RemoveIgnoredHandler(p1u1);
+
+  // p1u1 installed by pref so it is removed from pref and memory.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 2);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 5);
+
+  registry()->RemoveIgnoredHandler(p2u2);
+
+  // p2u2 installed by user so it is removed from pref and memory.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 1);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4);
+
+  registry()->OnIgnoreRegisterProtocolHandler(p2u1);
+
+  // p2u1 installed by user but it is already installed by policy, so it is
+  // added to pref.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 2);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4);
+
+  registry()->RemoveIgnoredHandler(p2u1);
+
+  // p2u1 installed by user and policy, so it is removed from pref alone.
+  ASSERT_EQ(InPrefIgnoredHandlerCount(), 1);
+  ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4);
+}