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 { return block_state_; }
55
56  virtual void BlockRequest() OVERRIDE {
57    ASSERT_TRUE(block_state_ == ExternalProtocolHandler::BLOCK ||
58                os_state_ == ShellIntegration::IS_DEFAULT);
59    has_blocked_ = true;
60  }
61
62  virtual void RunExternalProtocolDialog(const GURL& url,
63                                         int render_process_host_id,
64                                         int routing_id) OVERRIDE {
65    ASSERT_EQ(block_state_, ExternalProtocolHandler::UNKNOWN);
66    ASSERT_NE(os_state_, ShellIntegration::IS_DEFAULT);
67    has_prompted_ = true;
68  }
69
70  virtual void LaunchUrlWithoutSecurityCheck(const GURL& url) OVERRIDE {
71    ASSERT_EQ(block_state_, ExternalProtocolHandler::DONT_BLOCK);
72    ASSERT_NE(os_state_, ShellIntegration::IS_DEFAULT);
73    has_launched_ = true;
74  }
75
76  virtual void FinishedProcessingCheck() OVERRIDE {
77    base::MessageLoop::current()->Quit();
78  }
79
80  void set_os_state(ShellIntegration::DefaultWebClientState value) {
81    os_state_ = value;
82  }
83
84  void set_block_state(ExternalProtocolHandler::BlockState value) {
85    block_state_ = value;
86  }
87
88  bool has_launched() { return has_launched_; }
89  bool has_prompted() { return has_prompted_; }
90  bool has_blocked() { return has_blocked_; }
91
92 private:
93  ExternalProtocolHandler::BlockState block_state_;
94  ShellIntegration::DefaultWebClientState os_state_;
95  bool has_launched_;
96  bool has_prompted_;
97  bool has_blocked_;
98};
99
100class ExternalProtocolHandlerTest : public testing::Test {
101 protected:
102  ExternalProtocolHandlerTest()
103      : ui_thread_(BrowserThread::UI, base::MessageLoop::current()),
104        file_thread_(BrowserThread::FILE) {}
105
106  virtual void SetUp() {
107    file_thread_.Start();
108  }
109
110  virtual void TearDown() {
111    // Ensure that g_accept_requests gets set back to true after test execution.
112    ExternalProtocolHandler::PermitLaunchUrl();
113  }
114
115  void DoTest(ExternalProtocolHandler::BlockState block_state,
116              ShellIntegration::DefaultWebClientState os_state,
117              bool should_prompt, bool should_launch, bool should_block) {
118    GURL url("mailto:test@test.com");
119    ASSERT_FALSE(delegate_.has_prompted());
120    ASSERT_FALSE(delegate_.has_launched());
121    ASSERT_FALSE(delegate_.has_blocked());
122
123    delegate_.set_block_state(block_state);
124    delegate_.set_os_state(os_state);
125    ExternalProtocolHandler::LaunchUrlWithDelegate(url, 0, 0, &delegate_);
126    if (block_state != ExternalProtocolHandler::BLOCK)
127      base::MessageLoop::current()->Run();
128
129    ASSERT_EQ(should_prompt, delegate_.has_prompted());
130    ASSERT_EQ(should_launch, delegate_.has_launched());
131    ASSERT_EQ(should_block, delegate_.has_blocked());
132  }
133
134  base::MessageLoopForUI ui_message_loop_;
135  content::TestBrowserThread ui_thread_;
136  content::TestBrowserThread file_thread_;
137
138  FakeExternalProtocolHandlerDelegate delegate_;
139};
140
141TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeBlockedChromeDefault) {
142  DoTest(ExternalProtocolHandler::BLOCK,
143         ShellIntegration::IS_DEFAULT,
144         false, false, true);
145}
146
147TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeBlockedChromeNotDefault) {
148  DoTest(ExternalProtocolHandler::BLOCK,
149         ShellIntegration::NOT_DEFAULT,
150         false, false, true);
151}
152
153TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeBlockedChromeUnknown) {
154  DoTest(ExternalProtocolHandler::BLOCK,
155         ShellIntegration::UNKNOWN_DEFAULT,
156         false, false, true);
157}
158
159TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnBlockedChromeDefault) {
160  DoTest(ExternalProtocolHandler::DONT_BLOCK,
161         ShellIntegration::IS_DEFAULT,
162         false, false, true);
163}
164
165TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnBlockedChromeNotDefault) {
166  DoTest(ExternalProtocolHandler::DONT_BLOCK,
167         ShellIntegration::NOT_DEFAULT,
168         false, true, false);
169}
170
171TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnBlockedChromeUnknown) {
172  DoTest(ExternalProtocolHandler::DONT_BLOCK,
173         ShellIntegration::UNKNOWN_DEFAULT,
174         false, true, false);
175}
176
177TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeDefault) {
178  DoTest(ExternalProtocolHandler::UNKNOWN,
179         ShellIntegration::IS_DEFAULT,
180         false, false, true);
181}
182
183TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeNotDefault) {
184  DoTest(ExternalProtocolHandler::UNKNOWN,
185         ShellIntegration::NOT_DEFAULT,
186         true, false, false);
187}
188
189TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeUnknown) {
190  DoTest(ExternalProtocolHandler::UNKNOWN,
191         ShellIntegration::UNKNOWN_DEFAULT,
192         true, false, false);
193}
194