protocol_handler_registry_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
1c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// Use of this source code is governed by a BSD-style license that can be
3c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// found in the LICENSE file.
4c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
5c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
6c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
7c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include <set>
8c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
9c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "base/memory/scoped_ptr.h"
10c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "base/message_loop/message_loop.h"
11c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "base/strings/utf_string_conversions.h"
12c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "base/synchronization/waitable_event.h"
13770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com#include "chrome/browser/chrome_notification_types.h"
14c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "chrome/browser/prefs/pref_service_syncable.h"
15c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "chrome/common/custom_handlers/protocol_handler.h"
16c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "chrome/test/base/testing_browser_process.h"
17c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "chrome/test/base/testing_profile.h"
18c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "components/user_prefs/pref_registry_syncable.h"
19c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "content/public/browser/notification_observer.h"
20c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "content/public/browser/notification_registrar.h"
21c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "content/public/browser/notification_source.h"
22c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "content/public/test/test_browser_thread.h"
23c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "content/public/test/test_renderer_host.h"
24c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "net/base/request_priority.h"
2574b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org#include "net/url_request/url_request.h"
26c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "net/url_request/url_request_context.h"
27c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "testing/gtest/include/gtest/gtest.h"
28c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
29c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgusing content::BrowserThread;
30c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
31c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgnamespace {
3284b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com
3384b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.comvoid AssertInterceptedIO(
345fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    const GURL& url,
355fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org    net::URLRequestJobFactory* interceptor) {
36c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
3774b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  net::URLRequestContext context;
38c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  net::URLRequest request(url, net::DEFAULT_PRIORITY, NULL, &context);
39c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  scoped_refptr<net::URLRequestJob> job =
4074b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org      interceptor->MaybeCreateJobWithProtocolHandler(
4174b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org          url.scheme(), &request, context.network_delegate());
4274b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  ASSERT_TRUE(job.get() != NULL);
43c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
44c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
45c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgvoid AssertIntercepted(
46c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    const GURL& url,
47a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org    net::URLRequestJobFactory* interceptor) {
48a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
49a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org  BrowserThread::PostTask(BrowserThread::IO,
50a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org                          FROM_HERE,
51c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                          base::Bind(AssertInterceptedIO,
52c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                                     url,
53c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                                     base::Unretained(interceptor)));
54c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  base::MessageLoop::current()->RunUntilIdle();
55c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
56c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
57c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// FakeURLRequestJobFactory returns NULL for all job creation requests and false
58c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// for all IsHandled*() requests. FakeURLRequestJobFactory can be chained to
59c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// ProtocolHandlerRegistry::JobInterceptorFactory so the result of
60c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// MaybeCreateJobWithProtocolHandler() indicates whether the
61c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org// ProtocolHandlerRegistry properly handled a job creation request.
62c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgclass FakeURLRequestJobFactory : public net::URLRequestJobFactory {
63c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  // net::URLRequestJobFactory implementation:
64c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
65c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      const std::string& scheme,
66c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      net::URLRequest* request,
67c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      net::NetworkDelegate* network_delegate) const OVERRIDE {
68c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    return NULL;
69c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
70c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
71c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    return false;
72c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
73c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
74c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    return false;
75c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
76c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
77c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    return true;
78c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
79c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org};
80c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
81c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgvoid AssertWillHandleIO(
82c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    const std::string& scheme,
83c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    bool expected,
84c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) {
85c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
86c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  interceptor->Chain(scoped_ptr<net::URLRequestJobFactory>(
87c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      new FakeURLRequestJobFactory()));
88c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  ASSERT_EQ(expected, interceptor->IsHandledProtocol(scheme));
89c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  interceptor->Chain(scoped_ptr<net::URLRequestJobFactory>());
90c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
91c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
92c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgvoid AssertWillHandle(
93c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    const std::string& scheme,
94c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    bool expected,
95c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    ProtocolHandlerRegistry::JobInterceptorFactory* interceptor) {
96c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
97c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  BrowserThread::PostTask(BrowserThread::IO,
98c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                          FROM_HERE,
99c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                          base::Bind(AssertWillHandleIO,
100c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                                     scheme,
101c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                                     expected,
102c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                                     base::Unretained(interceptor)));
103c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  base::MessageLoop::current()->RunUntilIdle();
104c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
105c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
106c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgclass FakeDelegate : public ProtocolHandlerRegistry::Delegate {
107c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org public:
108c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  FakeDelegate() : force_os_failure_(false) {}
109c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual ~FakeDelegate() { }
110c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual void RegisterExternalHandler(const std::string& protocol) OVERRIDE {
111c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    ASSERT_TRUE(
112c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        registered_protocols_.find(protocol) == registered_protocols_.end());
113c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    registered_protocols_.insert(protocol);
114c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
115c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
116c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual void DeregisterExternalHandler(const std::string& protocol) OVERRIDE {
117c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    registered_protocols_.erase(protocol);
118c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
119c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
120c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker(
121c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    ShellIntegration::DefaultWebClientObserver* observer,
122c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    const std::string& protocol) OVERRIDE;
123c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
124c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual ProtocolHandlerRegistry::DefaultClientObserver* CreateShellObserver(
125c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      ProtocolHandlerRegistry* registry) OVERRIDE;
126c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
127c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  virtual void RegisterWithOSAsDefaultClient(
128c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      const std::string& protocol,
129c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org      ProtocolHandlerRegistry* reg) OVERRIDE {
130c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    ProtocolHandlerRegistry::Delegate::RegisterWithOSAsDefaultClient(protocol,
131c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                                                                     reg);
132c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    ASSERT_FALSE(IsFakeRegisteredWithOS(protocol));
133c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
13474b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org
13574b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  virtual bool IsExternalHandlerRegistered(
13674b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org      const std::string& protocol) OVERRIDE {
13774b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org    return registered_protocols_.find(protocol) != registered_protocols_.end();
13874b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  }
13974b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org
140c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  bool IsFakeRegisteredWithOS(const std::string& protocol) {
141c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    return os_registered_protocols_.find(protocol) !=
142c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        os_registered_protocols_.end();
143c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
14474b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org
14574b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  void FakeRegisterWithOS(const std::string& protocol) {
14674b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org    os_registered_protocols_.insert(protocol);
14774b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  }
14874b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org
14974b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org  void Reset() {
150c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    registered_protocols_.clear();
151c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    os_registered_protocols_.clear();
152c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    force_os_failure_ = false;
153c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  }
154c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
155c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  void set_force_os_failure(bool force) { force_os_failure_ = force; }
156c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
157c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  bool force_os_failure() { return force_os_failure_; }
15874b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org
15974b8cb15e4fb330e8d10856f6620e8b92b39a9cecommit-bot@chromium.org private:
160c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  std::set<std::string> registered_protocols_;
161c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  std::set<std::string> os_registered_protocols_;
162c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org  bool force_os_failure_;
163c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org};
164c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
165class FakeClientObserver
166    : public ProtocolHandlerRegistry::DefaultClientObserver {
167 public:
168  FakeClientObserver(ProtocolHandlerRegistry* registry,
169                     FakeDelegate* registry_delegate)
170      : ProtocolHandlerRegistry::DefaultClientObserver(registry),
171        delegate_(registry_delegate) {}
172
173  virtual void SetDefaultWebClientUIState(
174      ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
175    ProtocolHandlerRegistry::DefaultClientObserver::SetDefaultWebClientUIState(
176        state);
177    if (state == ShellIntegration::STATE_IS_DEFAULT) {
178      delegate_->FakeRegisterWithOS(worker_->protocol());
179    }
180    if (state != ShellIntegration::STATE_PROCESSING) {
181      base::MessageLoop::current()->Quit();
182    }
183  }
184
185 private:
186  FakeDelegate* delegate_;
187};
188
189class FakeProtocolClientWorker
190    : public ShellIntegration::DefaultProtocolClientWorker {
191 public:
192  FakeProtocolClientWorker(ShellIntegration::DefaultWebClientObserver* observer,
193                           const std::string& protocol,
194                           bool force_failure)
195      : ShellIntegration::DefaultProtocolClientWorker(observer, protocol),
196        force_failure_(force_failure) {}
197
198 private:
199  virtual ~FakeProtocolClientWorker() {}
200
201  virtual ShellIntegration::DefaultWebClientState CheckIsDefault() OVERRIDE {
202    if (force_failure_) {
203      return ShellIntegration::NOT_DEFAULT;
204    } else {
205      return ShellIntegration::IS_DEFAULT;
206    }
207  }
208
209  virtual bool SetAsDefault(bool interactive_permitted) OVERRIDE {
210    return true;
211  }
212
213 private:
214  bool force_failure_;
215};
216
217ProtocolHandlerRegistry::DefaultClientObserver*
218    FakeDelegate::CreateShellObserver(ProtocolHandlerRegistry* registry) {
219  return new FakeClientObserver(registry, this);
220}
221
222ShellIntegration::DefaultProtocolClientWorker* FakeDelegate::CreateShellWorker(
223    ShellIntegration::DefaultWebClientObserver* observer,
224    const std::string& protocol) {
225  return new FakeProtocolClientWorker(observer, protocol, force_os_failure_);
226}
227
228class NotificationCounter : public content::NotificationObserver {
229 public:
230  explicit NotificationCounter(Profile* profile)
231      : events_(0),
232        notification_registrar_() {
233    notification_registrar_.Add(this,
234        chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
235        content::Source<Profile>(profile));
236  }
237
238  int events() { return events_; }
239  bool notified() { return events_ > 0; }
240  void Clear() { events_ = 0; }
241  virtual void Observe(int type,
242                       const content::NotificationSource& source,
243                       const content::NotificationDetails& details) OVERRIDE {
244    ++events_;
245  }
246
247  int events_;
248  content::NotificationRegistrar notification_registrar_;
249};
250
251class QueryProtocolHandlerOnChange
252    : public content::NotificationObserver {
253 public:
254  QueryProtocolHandlerOnChange(Profile* profile,
255                               ProtocolHandlerRegistry* registry)
256    : local_registry_(registry),
257      called_(false),
258      notification_registrar_() {
259    notification_registrar_.Add(this,
260        chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
261        content::Source<Profile>(profile));
262  }
263
264  virtual void Observe(int type,
265                       const content::NotificationSource& source,
266                       const content::NotificationDetails& details) OVERRIDE {
267    std::vector<std::string> output;
268    local_registry_->GetRegisteredProtocols(&output);
269    called_ = true;
270  }
271
272  ProtocolHandlerRegistry* local_registry_;
273  bool called_;
274  content::NotificationRegistrar notification_registrar_;
275};
276
277// URLRequest DCHECKS that the current MessageLoop is IO. It does this because
278// it can't check the thread id (since net can't depend on content.) We want
279// to harness our tests so all threads use the same loop allowing us to
280// guarantee all messages are processed.) By overriding the IsType method
281// we basically ignore the supplied message loop type, and instead infer
282// our type based on the current thread. GO DEPENDENCY INJECTION!
283class TestMessageLoop : public base::MessageLoop {
284 public:
285  TestMessageLoop() : base::MessageLoop(base::MessageLoop::TYPE_DEFAULT) {}
286  virtual ~TestMessageLoop() {}
287  virtual bool IsType(base::MessageLoop::Type type) const OVERRIDE {
288    switch (type) {
289#if defined(TOOLKIT_GTK)
290      case base::MessageLoop::TYPE_GPU:
291#endif
292      case base::MessageLoop::TYPE_UI:
293        return BrowserThread::CurrentlyOn(BrowserThread::UI);
294      case base::MessageLoop::TYPE_IO:
295        return BrowserThread::CurrentlyOn(BrowserThread::IO);
296#if defined(OS_ANDROID)
297      case base::MessageLoop::TYPE_JAVA: // fall-through
298#endif // defined(OS_ANDROID)
299      case base::MessageLoop::TYPE_CUSTOM:
300      case base::MessageLoop::TYPE_DEFAULT:
301        return !BrowserThread::CurrentlyOn(BrowserThread::UI) &&
302               !BrowserThread::CurrentlyOn(BrowserThread::IO);
303    }
304    return false;
305  }
306};
307
308}  // namespace
309
310class ProtocolHandlerRegistryTest : public testing::Test {
311 protected:
312  ProtocolHandlerRegistryTest()
313  : ui_thread_(BrowserThread::UI, &loop_),
314    file_thread_(BrowserThread::FILE, &loop_),
315    io_thread_(BrowserThread::IO, &loop_),
316    test_protocol_handler_(CreateProtocolHandler("test", "test")) {}
317
318  FakeDelegate* delegate() const { return delegate_; }
319  ProtocolHandlerRegistry* registry() { return registry_.get(); }
320  TestingProfile* profile() const { return profile_.get(); }
321  const ProtocolHandler& test_protocol_handler() const {
322    return test_protocol_handler_;
323  }
324
325  ProtocolHandler CreateProtocolHandler(const std::string& protocol,
326                                        const GURL& url,
327                                        const std::string& title) {
328    return ProtocolHandler::CreateProtocolHandler(protocol, url,
329        UTF8ToUTF16(title));
330  }
331
332  ProtocolHandler CreateProtocolHandler(const std::string& protocol,
333      const std::string& name) {
334    return CreateProtocolHandler(protocol, GURL("http://" + name + "/%s"),
335        name);
336  }
337
338  void RecreateRegistry(bool initialize) {
339    TeadDownRegistry();
340    SetUpRegistry(initialize);
341  }
342
343  // Returns a new registry, initializing it if |initialize| is true.
344  // Caller assumes ownership for the object
345  void SetUpRegistry(bool initialize) {
346    delegate_ = new FakeDelegate();
347    registry_.reset(new ProtocolHandlerRegistry(profile(), delegate()));
348    if (initialize) registry_->InitProtocolSettings();
349  }
350
351  void TeadDownRegistry() {
352    registry_->Shutdown();
353    registry_.reset();
354    // Registry owns the delegate_ it handles deletion of that object.
355  }
356
357  virtual void SetUp() {
358    profile_.reset(new TestingProfile());
359    CHECK(profile_->GetPrefs());
360    SetUpRegistry(true);
361    test_protocol_handler_ =
362        CreateProtocolHandler("test", GURL("http://test.com/%s"), "Test");
363  }
364
365  virtual void TearDown() {
366    TeadDownRegistry();
367  }
368
369  TestMessageLoop loop_;
370
371 private:
372  content::TestBrowserThread ui_thread_;
373  content::TestBrowserThread file_thread_;
374  content::TestBrowserThread io_thread_;
375
376  scoped_ptr<TestingProfile> profile_;
377  FakeDelegate* delegate_;  // Registry assumes ownership of delegate_.
378  scoped_ptr<ProtocolHandlerRegistry> registry_;
379  ProtocolHandler test_protocol_handler_;
380};
381
382// ProtocolHandlerRegistryTest tests are flaky on Linux & ChromeOS.
383// http://crbug.com/133023
384#if defined(OS_LINUX) || defined(OS_CHROMEOS)
385#define MAYBE_AcceptProtocolHandlerHandlesProtocol \
386    DISABLED_AcceptProtocolHandlerHandlesProtocol
387#define MAYBE_DeniedProtocolIsntHandledUntilAccepted \
388    DISABLED_DeniedProtocolIsntHandledUntilAccepted
389#define MAYBE_TestStartsAsDefault DISABLED_TestStartsAsDefault
390#define MAYBE_TestRemoveHandlerRemovesDefault \
391    DISABLED_TestRemoveHandlerRemovesDefault
392#define MAYBE_TestClearDefaultGetsPropagatedToIO \
393    DISABLED_TestClearDefaultGetsPropagatedToIO
394#define MAYBE_TestIsHandledProtocolWorksOnIOThread \
395    DISABLED_TestIsHandledProtocolWorksOnIOThread
396#define MAYBE_TestInstallDefaultHandler \
397    DISABLED_TestInstallDefaultHandler
398#else
399#define MAYBE_AcceptProtocolHandlerHandlesProtocol \
400    AcceptProtocolHandlerHandlesProtocol
401#define MAYBE_DeniedProtocolIsntHandledUntilAccepted \
402    DeniedProtocolIsntHandledUntilAccepted
403#define MAYBE_TestStartsAsDefault TestStartsAsDefault
404#define MAYBE_TestRemoveHandlerRemovesDefault TestRemoveHandlerRemovesDefault
405#define MAYBE_TestClearDefaultGetsPropagatedToIO \
406    TestClearDefaultGetsPropagatedToIO
407#define MAYBE_TestIsHandledProtocolWorksOnIOThread \
408    TestIsHandledProtocolWorksOnIOThread
409#define MAYBE_TestInstallDefaultHandler TestInstallDefaultHandler
410#endif  // defined(OS_CHROMEOS)
411
412TEST_F(ProtocolHandlerRegistryTest,
413       MAYBE_AcceptProtocolHandlerHandlesProtocol) {
414  ASSERT_FALSE(registry()->IsHandledProtocol("test"));
415  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
416  ASSERT_TRUE(registry()->IsHandledProtocol("test"));
417}
418
419TEST_F(ProtocolHandlerRegistryTest,
420       MAYBE_DeniedProtocolIsntHandledUntilAccepted) {
421  registry()->OnDenyRegisterProtocolHandler(test_protocol_handler());
422  ASSERT_FALSE(registry()->IsHandledProtocol("test"));
423  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
424  ASSERT_TRUE(registry()->IsHandledProtocol("test"));
425}
426
427TEST_F(ProtocolHandlerRegistryTest, ClearDefaultMakesProtocolNotHandled) {
428  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
429  registry()->ClearDefault("test");
430  ASSERT_FALSE(registry()->IsHandledProtocol("test"));
431  ASSERT_TRUE(registry()->GetHandlerFor("test").IsEmpty());
432}
433
434TEST_F(ProtocolHandlerRegistryTest, DisableDeregistersProtocolHandlers) {
435  ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test"));
436  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
437  ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test"));
438
439  registry()->Disable();
440  ASSERT_FALSE(delegate()->IsExternalHandlerRegistered("test"));
441  registry()->Enable();
442  ASSERT_TRUE(delegate()->IsExternalHandlerRegistered("test"));
443}
444
445TEST_F(ProtocolHandlerRegistryTest, IgnoreProtocolHandler) {
446  registry()->OnIgnoreRegisterProtocolHandler(test_protocol_handler());
447  ASSERT_TRUE(registry()->IsIgnored(test_protocol_handler()));
448
449  registry()->RemoveIgnoredHandler(test_protocol_handler());
450  ASSERT_FALSE(registry()->IsIgnored(test_protocol_handler()));
451}
452
453TEST_F(ProtocolHandlerRegistryTest, IgnoreEquivalentProtocolHandler) {
454  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"),
455                                              "test1");
456  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"),
457                                              "test2");
458
459  registry()->OnIgnoreRegisterProtocolHandler(ph1);
460  ASSERT_TRUE(registry()->IsIgnored(ph1));
461  ASSERT_TRUE(registry()->HasIgnoredEquivalent(ph2));
462
463  registry()->RemoveIgnoredHandler(ph1);
464  ASSERT_FALSE(registry()->IsIgnored(ph1));
465  ASSERT_FALSE(registry()->HasIgnoredEquivalent(ph2));
466}
467
468TEST_F(ProtocolHandlerRegistryTest, SaveAndLoad) {
469  ProtocolHandler stuff_protocol_handler(
470      CreateProtocolHandler("stuff", "stuff"));
471  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
472  registry()->OnIgnoreRegisterProtocolHandler(stuff_protocol_handler);
473
474  ASSERT_TRUE(registry()->IsHandledProtocol("test"));
475  ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler));
476  delegate()->Reset();
477  RecreateRegistry(true);
478  ASSERT_TRUE(registry()->IsHandledProtocol("test"));
479  ASSERT_TRUE(registry()->IsIgnored(stuff_protocol_handler));
480}
481
482TEST_F(ProtocolHandlerRegistryTest, TestEnabledDisabled) {
483  registry()->Disable();
484  ASSERT_FALSE(registry()->enabled());
485  registry()->Enable();
486  ASSERT_TRUE(registry()->enabled());
487}
488
489TEST_F(ProtocolHandlerRegistryTest,
490    DisallowRegisteringExternallyHandledProtocols) {
491  delegate()->RegisterExternalHandler("test");
492  ASSERT_FALSE(registry()->CanSchemeBeOverridden("test"));
493}
494
495TEST_F(ProtocolHandlerRegistryTest, RemovingHandlerMeansItCanBeAddedAgain) {
496  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
497  ASSERT_TRUE(registry()->CanSchemeBeOverridden("test"));
498  registry()->RemoveHandler(test_protocol_handler());
499  ASSERT_TRUE(registry()->CanSchemeBeOverridden("test"));
500}
501
502TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestStartsAsDefault) {
503  registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
504  ASSERT_TRUE(registry()->IsDefault(test_protocol_handler()));
505}
506
507TEST_F(ProtocolHandlerRegistryTest, TestClearDefault) {
508  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
509  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
510  registry()->OnAcceptRegisterProtocolHandler(ph1);
511  registry()->OnAcceptRegisterProtocolHandler(ph2);
512
513  registry()->OnAcceptRegisterProtocolHandler(ph1);
514  registry()->ClearDefault("test");
515  ASSERT_FALSE(registry()->IsDefault(ph1));
516  ASSERT_FALSE(registry()->IsDefault(ph2));
517}
518
519TEST_F(ProtocolHandlerRegistryTest, TestGetHandlerFor) {
520  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
521  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
522  registry()->OnAcceptRegisterProtocolHandler(ph1);
523  registry()->OnAcceptRegisterProtocolHandler(ph2);
524
525  registry()->OnAcceptRegisterProtocolHandler(ph2);
526  ASSERT_EQ(ph2, registry()->GetHandlerFor("test"));
527  ASSERT_TRUE(registry()->IsHandledProtocol("test"));
528}
529
530TEST_F(ProtocolHandlerRegistryTest, TestMostRecentHandlerIsDefault) {
531  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
532  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
533  registry()->OnAcceptRegisterProtocolHandler(ph1);
534  registry()->OnAcceptRegisterProtocolHandler(ph2);
535  ASSERT_FALSE(registry()->IsDefault(ph1));
536  ASSERT_TRUE(registry()->IsDefault(ph2));
537}
538
539TEST_F(ProtocolHandlerRegistryTest, TestOnAcceptRegisterProtocolHandler) {
540  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
541  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
542  registry()->OnAcceptRegisterProtocolHandler(ph1);
543  registry()->OnAcceptRegisterProtocolHandler(ph2);
544
545  registry()->OnAcceptRegisterProtocolHandler(ph1);
546  ASSERT_TRUE(registry()->IsDefault(ph1));
547  ASSERT_FALSE(registry()->IsDefault(ph2));
548
549  registry()->OnAcceptRegisterProtocolHandler(ph2);
550  ASSERT_FALSE(registry()->IsDefault(ph1));
551  ASSERT_TRUE(registry()->IsDefault(ph2));
552}
553
554TEST_F(ProtocolHandlerRegistryTest, TestDefaultSaveLoad) {
555  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
556  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
557  registry()->OnDenyRegisterProtocolHandler(ph1);
558  registry()->OnDenyRegisterProtocolHandler(ph2);
559
560  registry()->OnAcceptRegisterProtocolHandler(ph2);
561  registry()->Disable();
562
563  RecreateRegistry(true);
564
565  ASSERT_FALSE(registry()->enabled());
566  registry()->Enable();
567  ASSERT_FALSE(registry()->IsDefault(ph1));
568  ASSERT_TRUE(registry()->IsDefault(ph2));
569
570  RecreateRegistry(true);
571  ASSERT_TRUE(registry()->enabled());
572}
573
574TEST_F(ProtocolHandlerRegistryTest, TestRemoveHandler) {
575  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
576  registry()->OnAcceptRegisterProtocolHandler(ph1);
577  registry()->OnAcceptRegisterProtocolHandler(ph1);
578
579  registry()->RemoveHandler(ph1);
580  ASSERT_FALSE(registry()->IsRegistered(ph1));
581  ASSERT_FALSE(registry()->IsHandledProtocol("test"));
582}
583
584TEST_F(ProtocolHandlerRegistryTest, TestIsRegistered) {
585  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
586  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
587  registry()->OnAcceptRegisterProtocolHandler(ph1);
588  registry()->OnAcceptRegisterProtocolHandler(ph2);
589
590  ASSERT_TRUE(registry()->IsRegistered(ph1));
591}
592
593TEST_F(ProtocolHandlerRegistryTest, TestIsEquivalentRegistered) {
594  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"),
595                                              "test1");
596  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"),
597                                              "test2");
598  registry()->OnAcceptRegisterProtocolHandler(ph1);
599
600  ASSERT_TRUE(registry()->IsRegistered(ph1));
601  ASSERT_TRUE(registry()->HasRegisteredEquivalent(ph2));
602}
603
604TEST_F(ProtocolHandlerRegistryTest, TestSilentlyRegisterHandler) {
605  ProtocolHandler ph1 = CreateProtocolHandler("test", GURL("http://test/%s"),
606                                              "test1");
607  ProtocolHandler ph2 = CreateProtocolHandler("test", GURL("http://test/%s"),
608                                              "test2");
609  ProtocolHandler ph3 = CreateProtocolHandler("ignore", GURL("http://test/%s"),
610                                              "ignore1");
611  ProtocolHandler ph4 = CreateProtocolHandler("ignore", GURL("http://test/%s"),
612                                              "ignore2");
613
614  ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph1));
615  ASSERT_FALSE(registry()->IsRegistered(ph1));
616
617  registry()->OnAcceptRegisterProtocolHandler(ph1);
618  ASSERT_TRUE(registry()->IsRegistered(ph1));
619
620  ASSERT_TRUE(registry()->SilentlyHandleRegisterHandlerRequest(ph2));
621  ASSERT_FALSE(registry()->IsRegistered(ph1));
622  ASSERT_TRUE(registry()->IsRegistered(ph2));
623
624  ASSERT_FALSE(registry()->SilentlyHandleRegisterHandlerRequest(ph3));
625  ASSERT_FALSE(registry()->IsRegistered(ph3));
626
627  registry()->OnIgnoreRegisterProtocolHandler(ph3);
628  ASSERT_FALSE(registry()->IsRegistered(ph3));
629  ASSERT_TRUE(registry()->IsIgnored(ph3));
630
631  ASSERT_TRUE(registry()->SilentlyHandleRegisterHandlerRequest(ph4));
632  ASSERT_FALSE(registry()->IsRegistered(ph4));
633  ASSERT_TRUE(registry()->HasIgnoredEquivalent(ph4));
634}
635
636TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestRemoveHandlerRemovesDefault) {
637  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
638  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
639  ProtocolHandler ph3 = CreateProtocolHandler("test", "test3");
640
641  registry()->OnAcceptRegisterProtocolHandler(ph1);
642  registry()->OnAcceptRegisterProtocolHandler(ph2);
643  registry()->OnAcceptRegisterProtocolHandler(ph3);
644
645  registry()->OnAcceptRegisterProtocolHandler(ph1);
646  registry()->RemoveHandler(ph1);
647  ASSERT_FALSE(registry()->IsDefault(ph1));
648}
649
650TEST_F(ProtocolHandlerRegistryTest, TestGetHandlersFor) {
651  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
652  ProtocolHandler ph2 = CreateProtocolHandler("test", "test2");
653  ProtocolHandler ph3 = CreateProtocolHandler("test", "test3");
654  registry()->OnAcceptRegisterProtocolHandler(ph1);
655  registry()->OnAcceptRegisterProtocolHandler(ph2);
656  registry()->OnAcceptRegisterProtocolHandler(ph3);
657
658  ProtocolHandlerRegistry::ProtocolHandlerList handlers =
659      registry()->GetHandlersFor("test");
660  ASSERT_EQ(static_cast<size_t>(3), handlers.size());
661
662  ASSERT_EQ(ph3, handlers[0]);
663  ASSERT_EQ(ph2, handlers[1]);
664  ASSERT_EQ(ph1, handlers[2]);
665}
666
667TEST_F(ProtocolHandlerRegistryTest, TestGetRegisteredProtocols) {
668  std::vector<std::string> protocols;
669  registry()->GetRegisteredProtocols(&protocols);
670  ASSERT_EQ(static_cast<size_t>(0), protocols.size());
671
672  registry()->GetHandlersFor("test");
673
674  protocols.clear();
675  registry()->GetRegisteredProtocols(&protocols);
676  ASSERT_EQ(static_cast<size_t>(0), protocols.size());
677}
678
679TEST_F(ProtocolHandlerRegistryTest, TestIsHandledProtocol) {
680  registry()->GetHandlersFor("test");
681  ASSERT_FALSE(registry()->IsHandledProtocol("test"));
682}
683
684TEST_F(ProtocolHandlerRegistryTest, TestNotifications) {
685  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
686  NotificationCounter counter(profile());
687
688  registry()->OnAcceptRegisterProtocolHandler(ph1);
689  ASSERT_TRUE(counter.notified());
690  counter.Clear();
691
692  registry()->Disable();
693  ASSERT_TRUE(counter.notified());
694  counter.Clear();
695
696  registry()->Enable();
697  ASSERT_TRUE(counter.notified());
698  counter.Clear();
699
700  registry()->RemoveHandler(ph1);
701  ASSERT_TRUE(counter.notified());
702  counter.Clear();
703}
704
705TEST_F(ProtocolHandlerRegistryTest, TestReentrantNotifications) {
706  QueryProtocolHandlerOnChange queryer(profile(), registry());
707  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
708  registry()->OnAcceptRegisterProtocolHandler(ph1);
709  ASSERT_TRUE(queryer.called_);
710}
711
712TEST_F(ProtocolHandlerRegistryTest, TestProtocolsWithNoDefaultAreHandled) {
713  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
714  registry()->OnAcceptRegisterProtocolHandler(ph1);
715  registry()->ClearDefault("test");
716  std::vector<std::string> handled_protocols;
717  registry()->GetRegisteredProtocols(&handled_protocols);
718  ASSERT_EQ(static_cast<size_t>(1), handled_protocols.size());
719  ASSERT_EQ("test", handled_protocols[0]);
720}
721
722TEST_F(ProtocolHandlerRegistryTest, TestDisablePreventsHandling) {
723  ProtocolHandler ph1 = CreateProtocolHandler("test", "test1");
724  registry()->OnAcceptRegisterProtocolHandler(ph1);
725  ASSERT_TRUE(registry()->IsHandledProtocol("test"));
726  registry()->Disable();
727  ASSERT_FALSE(registry()->IsHandledProtocol("test"));
728}
729
730// TODO(smckay): This is much more appropriately an integration
731// test. Make that so, then update the
732// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully
733// isolate this test from the FILE thread.
734TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) {
735  ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1");
736  ProtocolHandler ph_do2 = CreateProtocolHandler("do", "test2");
737  ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test");
738
739  ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("do"));
740  ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont"));
741
742  registry()->OnAcceptRegisterProtocolHandler(ph_do1);
743  registry()->OnDenyRegisterProtocolHandler(ph_dont);
744  base::MessageLoop::current()->Run();  // FILE thread needs to run.
745  ASSERT_TRUE(delegate()->IsFakeRegisteredWithOS("do"));
746  ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont"));
747
748  // This should not register with the OS, if it does the delegate
749  // will assert for us. We don't need to wait for the message loop
750  // as it should not go through to the shell worker.
751  registry()->OnAcceptRegisterProtocolHandler(ph_do2);
752}
753
754#if defined(OS_LINUX)
755// TODO(benwells): When Linux support is more reliable and
756// http://crbut.com/88255 is fixed this test will pass.
757#define MAYBE_TestOSRegistrationFailure DISABLED_TestOSRegistrationFailure
758#else
759#define MAYBE_TestOSRegistrationFailure TestOSRegistrationFailure
760#endif
761
762// TODO(smckay): This is much more appropriately an integration
763// test. Make that so, then update the
764// ShellIntegretion{Delegate,Observer,Worker} test classes we use to fully
765// isolate this test from the FILE thread.
766TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) {
767  ProtocolHandler ph_do = CreateProtocolHandler("do", "test1");
768  ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test");
769
770  ASSERT_FALSE(registry()->IsHandledProtocol("do"));
771  ASSERT_FALSE(registry()->IsHandledProtocol("dont"));
772
773  registry()->OnAcceptRegisterProtocolHandler(ph_do);
774  base::MessageLoop::current()->Run();  // FILE thread needs to run.
775  delegate()->set_force_os_failure(true);
776  registry()->OnAcceptRegisterProtocolHandler(ph_dont);
777  base::MessageLoop::current()->Run();  // FILE thread needs to run.
778  ASSERT_TRUE(registry()->IsHandledProtocol("do"));
779  ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("do").size());
780  ASSERT_FALSE(registry()->IsHandledProtocol("dont"));
781  ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("dont").size());
782}
783
784TEST_F(ProtocolHandlerRegistryTest, TestMaybeCreateTaskWorksFromIOThread) {
785  ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1");
786  registry()->OnAcceptRegisterProtocolHandler(ph1);
787  GURL url("mailto:someone@something.com");
788
789  scoped_ptr<net::URLRequestJobFactory> interceptor(
790      registry()->CreateJobInterceptorFactory());
791  AssertIntercepted(url, interceptor.get());
792}
793
794TEST_F(ProtocolHandlerRegistryTest,
795       MAYBE_TestIsHandledProtocolWorksOnIOThread) {
796  std::string scheme("mailto");
797  ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1");
798  registry()->OnAcceptRegisterProtocolHandler(ph1);
799
800  scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor(
801      registry()->CreateJobInterceptorFactory());
802  AssertWillHandle(scheme, true, interceptor.get());
803}
804
805TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultFallsBackToOldDefault) {
806  ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1");
807  ProtocolHandler ph2 = CreateProtocolHandler("mailto", "test2");
808  ProtocolHandler ph3 = CreateProtocolHandler("mailto", "test3");
809  registry()->OnAcceptRegisterProtocolHandler(ph1);
810  registry()->OnAcceptRegisterProtocolHandler(ph2);
811  registry()->OnAcceptRegisterProtocolHandler(ph3);
812
813  ASSERT_TRUE(registry()->IsDefault(ph3));
814  registry()->RemoveHandler(ph3);
815  ASSERT_TRUE(registry()->IsDefault(ph2));
816  registry()->OnAcceptRegisterProtocolHandler(ph3);
817  ASSERT_TRUE(registry()->IsDefault(ph3));
818  registry()->RemoveHandler(ph2);
819  ASSERT_TRUE(registry()->IsDefault(ph3));
820  registry()->RemoveHandler(ph3);
821  ASSERT_TRUE(registry()->IsDefault(ph1));
822}
823
824TEST_F(ProtocolHandlerRegistryTest, TestRemovingDefaultDoesntChangeHandlers) {
825  ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1");
826  ProtocolHandler ph2 = CreateProtocolHandler("mailto", "test2");
827  ProtocolHandler ph3 = CreateProtocolHandler("mailto", "test3");
828  registry()->OnAcceptRegisterProtocolHandler(ph1);
829  registry()->OnAcceptRegisterProtocolHandler(ph2);
830  registry()->OnAcceptRegisterProtocolHandler(ph3);
831  registry()->RemoveHandler(ph3);
832
833  ProtocolHandlerRegistry::ProtocolHandlerList handlers =
834      registry()->GetHandlersFor("mailto");
835  ASSERT_EQ(static_cast<size_t>(2), handlers.size());
836
837  ASSERT_EQ(ph2, handlers[0]);
838  ASSERT_EQ(ph1, handlers[1]);
839}
840
841TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestClearDefaultGetsPropagatedToIO) {
842  std::string scheme("mailto");
843  ProtocolHandler ph1 = CreateProtocolHandler(scheme, "test1");
844  registry()->OnAcceptRegisterProtocolHandler(ph1);
845  registry()->ClearDefault(scheme);
846
847  scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor(
848      registry()->CreateJobInterceptorFactory());
849  AssertWillHandle(scheme, false, interceptor.get());
850}
851
852TEST_F(ProtocolHandlerRegistryTest, TestLoadEnabledGetsPropogatedToIO) {
853  std::string mailto("mailto");
854  ProtocolHandler ph1 = CreateProtocolHandler(mailto, "MailtoHandler");
855  registry()->OnAcceptRegisterProtocolHandler(ph1);
856
857  scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> interceptor(
858      registry()->CreateJobInterceptorFactory());
859  AssertWillHandle(mailto, true, interceptor.get());
860  registry()->Disable();
861  AssertWillHandle(mailto, false, interceptor.get());
862}
863
864TEST_F(ProtocolHandlerRegistryTest, TestReplaceHandler) {
865  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
866      GURL("http://test.com/%s"), "test1");
867  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
868      GURL("http://test.com/updated-url/%s"), "test2");
869  registry()->OnAcceptRegisterProtocolHandler(ph1);
870  ASSERT_TRUE(registry()->AttemptReplace(ph2));
871  const ProtocolHandler& handler(registry()->GetHandlerFor("mailto"));
872  ASSERT_EQ(handler.url(), ph2.url());
873}
874
875TEST_F(ProtocolHandlerRegistryTest, TestReplaceNonDefaultHandler) {
876  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
877      GURL("http://test.com/%s"), "test1");
878  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
879      GURL("http://test.com/updated-url/%s"), "test2");
880  ProtocolHandler ph3 = CreateProtocolHandler("mailto",
881      GURL("http://else.com/%s"), "test3");
882  registry()->OnAcceptRegisterProtocolHandler(ph1);
883  registry()->OnAcceptRegisterProtocolHandler(ph3);
884  ASSERT_TRUE(registry()->AttemptReplace(ph2));
885  const ProtocolHandler& handler(registry()->GetHandlerFor("mailto"));
886  ASSERT_EQ(handler.url(), ph3.url());
887}
888
889TEST_F(ProtocolHandlerRegistryTest, TestReplaceRemovesStaleHandlers) {
890  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
891      GURL("http://test.com/%s"), "test1");
892  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
893      GURL("http://test.com/updated-url/%s"), "test2");
894  ProtocolHandler ph3 = CreateProtocolHandler("mailto",
895      GURL("http://test.com/third/%s"), "test");
896  registry()->OnAcceptRegisterProtocolHandler(ph1);
897  registry()->OnAcceptRegisterProtocolHandler(ph2);
898
899  // This should replace the previous two handlers.
900  ASSERT_TRUE(registry()->AttemptReplace(ph3));
901  const ProtocolHandler& handler(registry()->GetHandlerFor("mailto"));
902  ASSERT_EQ(handler.url(), ph3.url());
903  registry()->RemoveHandler(ph3);
904  ASSERT_TRUE(registry()->GetHandlerFor("mailto").IsEmpty());
905}
906
907TEST_F(ProtocolHandlerRegistryTest, TestIsSameOrigin) {
908  ProtocolHandler ph1 = CreateProtocolHandler("mailto",
909      GURL("http://test.com/%s"), "test1");
910  ProtocolHandler ph2 = CreateProtocolHandler("mailto",
911      GURL("http://test.com/updated-url/%s"), "test2");
912  ProtocolHandler ph3 = CreateProtocolHandler("mailto",
913      GURL("http://other.com/%s"), "test");
914  ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(),
915      ph1.IsSameOrigin(ph2));
916  ASSERT_EQ(ph1.url().GetOrigin() == ph2.url().GetOrigin(),
917      ph2.IsSameOrigin(ph1));
918  ASSERT_EQ(ph2.url().GetOrigin() == ph3.url().GetOrigin(),
919      ph2.IsSameOrigin(ph3));
920  ASSERT_EQ(ph3.url().GetOrigin() == ph2.url().GetOrigin(),
921      ph3.IsSameOrigin(ph2));
922}
923
924TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestInstallDefaultHandler) {
925  RecreateRegistry(false);
926  registry()->AddPredefinedHandler(CreateProtocolHandler(
927      "test", GURL("http://test.com/%s"), "Test"));
928  registry()->InitProtocolSettings();
929  std::vector<std::string> protocols;
930  registry()->GetRegisteredProtocols(&protocols);
931  ASSERT_EQ(static_cast<size_t>(1), protocols.size());
932}
933