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/external_protocol/external_protocol_handler.h"
6
7#include "base/message_loop/message_loop.h"
8#include "content/public/test/test_browser_thread.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11using content::BrowserThread;
12
13class FakeExternalProtocolHandlerWorker
14    : public ShellIntegration::DefaultProtocolClientWorker {
15 public:
16  FakeExternalProtocolHandlerWorker(
17      ShellIntegration::DefaultWebClientObserver* observer,
18      const std::string& protocol,
19      ShellIntegration::DefaultWebClientState os_state)
20      : ShellIntegration::DefaultProtocolClientWorker(observer, protocol),
21        os_state_(os_state) {}
22
23 private:
24  virtual ~FakeExternalProtocolHandlerWorker() {}
25
26  virtual ShellIntegration::DefaultWebClientState CheckIsDefault() OVERRIDE {
27    return os_state_;
28  }
29
30  virtual bool SetAsDefault(bool interactive_permitted) OVERRIDE {
31    return true;
32  }
33
34  ShellIntegration::DefaultWebClientState os_state_;
35};
36
37class FakeExternalProtocolHandlerDelegate
38    : public ExternalProtocolHandler::Delegate {
39 public:
40  FakeExternalProtocolHandlerDelegate()
41      : block_state_(ExternalProtocolHandler::BLOCK),
42        os_state_(ShellIntegration::UNKNOWN_DEFAULT),
43        has_launched_(false),
44        has_prompted_(false),
45        has_blocked_ (false) {}
46
47  virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker(
48      ShellIntegration::DefaultWebClientObserver* observer,
49      const std::string& protocol) OVERRIDE {
50    return new FakeExternalProtocolHandlerWorker(observer, protocol, os_state_);
51  }
52
53  virtual ExternalProtocolHandler::BlockState GetBlockState(
54      const std::string& scheme) OVERRIDE {
55    return block_state_;
56  }
57
58  virtual void BlockRequest() OVERRIDE {
59    ASSERT_TRUE(block_state_ == ExternalProtocolHandler::BLOCK ||
60                os_state_ == ShellIntegration::IS_DEFAULT);
61    has_blocked_ = true;
62  }
63
64  virtual void RunExternalProtocolDialog(const GURL& url,
65                                         int render_process_host_id,
66                                         int routing_id) OVERRIDE {
67    ASSERT_EQ(block_state_, ExternalProtocolHandler::UNKNOWN);
68    ASSERT_NE(os_state_, ShellIntegration::IS_DEFAULT);
69    has_prompted_ = true;
70  }
71
72  virtual void LaunchUrlWithoutSecurityCheck(const GURL& url) OVERRIDE {
73    ASSERT_EQ(block_state_, ExternalProtocolHandler::DONT_BLOCK);
74    ASSERT_NE(os_state_, ShellIntegration::IS_DEFAULT);
75    has_launched_ = true;
76  }
77
78  virtual void FinishedProcessingCheck() OVERRIDE {
79    base::MessageLoop::current()->Quit();
80  }
81
82  void set_os_state(ShellIntegration::DefaultWebClientState value) {
83    os_state_ = value;
84  }
85
86  void set_block_state(ExternalProtocolHandler::BlockState value) {
87    block_state_ = value;
88  }
89
90  bool has_launched() { return has_launched_; }
91  bool has_prompted() { return has_prompted_; }
92  bool has_blocked() { return has_blocked_; }
93
94 private:
95  ExternalProtocolHandler::BlockState block_state_;
96  ShellIntegration::DefaultWebClientState os_state_;
97  bool has_launched_;
98  bool has_prompted_;
99  bool has_blocked_;
100};
101
102class ExternalProtocolHandlerTest : public testing::Test {
103 protected:
104  ExternalProtocolHandlerTest()
105      : ui_thread_(BrowserThread::UI, base::MessageLoop::current()),
106        file_thread_(BrowserThread::FILE) {}
107
108  virtual void SetUp() {
109    file_thread_.Start();
110  }
111
112  virtual void TearDown() {
113    // Ensure that g_accept_requests gets set back to true after test execution.
114    ExternalProtocolHandler::PermitLaunchUrl();
115  }
116
117  void DoTest(ExternalProtocolHandler::BlockState block_state,
118              ShellIntegration::DefaultWebClientState os_state,
119              bool should_prompt, bool should_launch, bool should_block) {
120    GURL url("mailto:test@test.com");
121    ASSERT_FALSE(delegate_.has_prompted());
122    ASSERT_FALSE(delegate_.has_launched());
123    ASSERT_FALSE(delegate_.has_blocked());
124
125    delegate_.set_block_state(block_state);
126    delegate_.set_os_state(os_state);
127    ExternalProtocolHandler::LaunchUrlWithDelegate(url, 0, 0, &delegate_);
128    if (block_state != ExternalProtocolHandler::BLOCK)
129      base::MessageLoop::current()->Run();
130
131    ASSERT_EQ(should_prompt, delegate_.has_prompted());
132    ASSERT_EQ(should_launch, delegate_.has_launched());
133    ASSERT_EQ(should_block, delegate_.has_blocked());
134  }
135
136  base::MessageLoopForUI ui_message_loop_;
137  content::TestBrowserThread ui_thread_;
138  content::TestBrowserThread file_thread_;
139
140  FakeExternalProtocolHandlerDelegate delegate_;
141};
142
143TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeBlockedChromeDefault) {
144  DoTest(ExternalProtocolHandler::BLOCK,
145         ShellIntegration::IS_DEFAULT,
146         false, false, true);
147}
148
149TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeBlockedChromeNotDefault) {
150  DoTest(ExternalProtocolHandler::BLOCK,
151         ShellIntegration::NOT_DEFAULT,
152         false, false, true);
153}
154
155TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeBlockedChromeUnknown) {
156  DoTest(ExternalProtocolHandler::BLOCK,
157         ShellIntegration::UNKNOWN_DEFAULT,
158         false, false, true);
159}
160
161TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnBlockedChromeDefault) {
162  DoTest(ExternalProtocolHandler::DONT_BLOCK,
163         ShellIntegration::IS_DEFAULT,
164         false, false, true);
165}
166
167TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnBlockedChromeNotDefault) {
168  DoTest(ExternalProtocolHandler::DONT_BLOCK,
169         ShellIntegration::NOT_DEFAULT,
170         false, true, false);
171}
172
173TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnBlockedChromeUnknown) {
174  DoTest(ExternalProtocolHandler::DONT_BLOCK,
175         ShellIntegration::UNKNOWN_DEFAULT,
176         false, true, false);
177}
178
179TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeDefault) {
180  DoTest(ExternalProtocolHandler::UNKNOWN,
181         ShellIntegration::IS_DEFAULT,
182         false, false, true);
183}
184
185TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeNotDefault) {
186  DoTest(ExternalProtocolHandler::UNKNOWN,
187         ShellIntegration::NOT_DEFAULT,
188         true, false, false);
189}
190
191TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeUnknown) {
192  DoTest(ExternalProtocolHandler::UNKNOWN,
193         ShellIntegration::UNKNOWN_DEFAULT,
194         true, false, false);
195}
196