Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc

Issue 2896473002: Remove FILE thread dependency in protocol_handler_registry_unittest.cc (Closed)
Patch Set: MakeShared to MakeRefCounted Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" 5 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
11 11
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h" 13 #include "base/run_loop.h"
15 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
16 #include "base/synchronization/waitable_event.h" 15 #include "base/threading/thread_task_runner_handle.h"
17 #include "build/build_config.h" 16 #include "build/build_config.h"
18 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/common/custom_handlers/protocol_handler.h" 18 #include "chrome/common/custom_handlers/protocol_handler.h"
20 #include "chrome/common/pref_names.h" 19 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_browser_process.h" 20 #include "chrome/test/base/testing_browser_process.h"
22 #include "chrome/test/base/testing_profile.h" 21 #include "chrome/test/base/testing_profile.h"
23 #include "components/pref_registry/pref_registry_syncable.h" 22 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "components/sync_preferences/pref_service_syncable.h" 23 #include "components/sync_preferences/pref_service_syncable.h"
25 #include "content/public/browser/notification_observer.h" 24 #include "content/public/browser/notification_observer.h"
26 #include "content/public/browser/notification_registrar.h" 25 #include "content/public/browser/notification_registrar.h"
27 #include "content/public/browser/notification_source.h" 26 #include "content/public/browser/notification_source.h"
28 #include "content/public/test/test_browser_thread.h" 27 #include "content/public/test/test_browser_thread_bundle.h"
29 #include "content/public/test/test_renderer_host.h" 28 #include "content/public/test/test_renderer_host.h"
30 #include "net/base/request_priority.h" 29 #include "net/base/request_priority.h"
31 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" 30 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
32 #include "net/url_request/url_request.h" 31 #include "net/url_request/url_request.h"
33 #include "net/url_request/url_request_context.h" 32 #include "net/url_request/url_request_context.h"
34 #include "testing/gtest/include/gtest/gtest.h" 33 #include "testing/gtest/include/gtest/gtest.h"
35 34
36 using content::BrowserThread; 35 using content::BrowserThread;
37 36
38 namespace { 37 namespace {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 std::unique_ptr<base::DictionaryValue> GetProtocolHandlerValueWithDefault( 128 std::unique_ptr<base::DictionaryValue> GetProtocolHandlerValueWithDefault(
130 const std::string& protocol, 129 const std::string& protocol,
131 const std::string& url, 130 const std::string& url,
132 bool is_default) { 131 bool is_default) {
133 std::unique_ptr<base::DictionaryValue> value = 132 std::unique_ptr<base::DictionaryValue> value =
134 GetProtocolHandlerValue(protocol, url); 133 GetProtocolHandlerValue(protocol, url);
135 value->SetBoolean("default", is_default); 134 value->SetBoolean("default", is_default);
136 return value; 135 return value;
137 } 136 }
138 137
139 class FakeProtocolClientWorker
140 : public shell_integration::DefaultProtocolClientWorker {
141 public:
142 FakeProtocolClientWorker(
143 const shell_integration::DefaultWebClientWorkerCallback& callback,
144 const std::string& protocol,
145 bool force_failure)
146 : shell_integration::DefaultProtocolClientWorker(callback, protocol),
147 force_failure_(force_failure) {}
148
149 private:
150 ~FakeProtocolClientWorker() override = default;
151
152 shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
153 return force_failure_ ? shell_integration::NOT_DEFAULT
154 : shell_integration::IS_DEFAULT;
155 }
156
157 void SetAsDefaultImpl(const base::Closure& on_finished_callback) override {
158 on_finished_callback.Run();
159 }
160
161 private:
162 bool force_failure_;
163 };
164
165 class FakeDelegate : public ProtocolHandlerRegistry::Delegate { 138 class FakeDelegate : public ProtocolHandlerRegistry::Delegate {
166 public: 139 public:
167 FakeDelegate() : force_os_failure_(false) {} 140 FakeDelegate() : force_os_failure_(false) {}
168 ~FakeDelegate() override {} 141 ~FakeDelegate() override {}
169 void RegisterExternalHandler(const std::string& protocol) override { 142 void RegisterExternalHandler(const std::string& protocol) override {
170 ASSERT_TRUE( 143 ASSERT_TRUE(
171 registered_protocols_.find(protocol) == registered_protocols_.end()); 144 registered_protocols_.find(protocol) == registered_protocols_.end());
172 registered_protocols_.insert(protocol); 145 registered_protocols_.insert(protocol);
173 } 146 }
174 147
175 void DeregisterExternalHandler(const std::string& protocol) override { 148 void DeregisterExternalHandler(const std::string& protocol) override {
176 registered_protocols_.erase(protocol); 149 registered_protocols_.erase(protocol);
177 } 150 }
178 151
179 scoped_refptr<shell_integration::DefaultProtocolClientWorker>
180 CreateShellWorker(
181 const shell_integration::DefaultWebClientWorkerCallback& callback,
182 const std::string& protocol) override {
183 return new FakeProtocolClientWorker(callback, protocol, force_os_failure_);
184 }
185
186 void RegisterWithOSAsDefaultClient( 152 void RegisterWithOSAsDefaultClient(
187 const std::string& protocol, 153 const std::string& protocol,
188 ProtocolHandlerRegistry* registry) override; 154 ProtocolHandlerRegistry* registry) override {
155 // Do as-if the registration has to run on another sequence and post back
156 // the result with a task to the current thread.
157 base::ThreadTaskRunnerHandle::Get()->PostTask(
158 FROM_HERE,
159 base::Bind(registry->GetDefaultWebClientCallback(protocol),
160 force_os_failure_ ? shell_integration::NOT_DEFAULT
161 : shell_integration::IS_DEFAULT));
162
163 if (!force_os_failure_)
164 os_registered_protocols_.insert(protocol);
165 }
189 166
190 bool IsExternalHandlerRegistered(const std::string& protocol) override { 167 bool IsExternalHandlerRegistered(const std::string& protocol) override {
191 return registered_protocols_.find(protocol) != registered_protocols_.end(); 168 return registered_protocols_.find(protocol) != registered_protocols_.end();
192 } 169 }
193 170
194 bool IsFakeRegisteredWithOS(const std::string& protocol) { 171 bool IsFakeRegisteredWithOS(const std::string& protocol) {
195 return os_registered_protocols_.find(protocol) != 172 return os_registered_protocols_.find(protocol) !=
196 os_registered_protocols_.end(); 173 os_registered_protocols_.end();
197 } 174 }
198 175
199 void FakeRegisterWithOS(const std::string& protocol) {
200 os_registered_protocols_.insert(protocol);
201 }
202
203 void Reset() { 176 void Reset() {
204 registered_protocols_.clear(); 177 registered_protocols_.clear();
205 os_registered_protocols_.clear(); 178 os_registered_protocols_.clear();
206 force_os_failure_ = false; 179 force_os_failure_ = false;
207 } 180 }
208 181
209 void set_force_os_failure(bool force) { force_os_failure_ = force; } 182 void set_force_os_failure(bool force) { force_os_failure_ = force; }
210 183
211 bool force_os_failure() { return force_os_failure_; } 184 bool force_os_failure() { return force_os_failure_; }
212 185
213 private: 186 private:
214 std::set<std::string> registered_protocols_; 187 std::set<std::string> registered_protocols_;
215 std::set<std::string> os_registered_protocols_; 188 std::set<std::string> os_registered_protocols_;
216 bool force_os_failure_; 189 bool force_os_failure_;
217 }; 190 };
218 191
219 void OnShellWorkerFinished(ProtocolHandlerRegistry* registry,
220 FakeDelegate* delegate,
221 const std::string& protocol,
222 shell_integration::DefaultWebClientState state) {
223 registry->GetDefaultWebClientCallback(protocol).Run(state);
224 if (state == shell_integration::IS_DEFAULT) {
225 delegate->FakeRegisterWithOS(protocol);
226 }
227
228 base::MessageLoop::current()->QuitWhenIdle();
229 }
230
231 void FakeDelegate::RegisterWithOSAsDefaultClient(
232 const std::string& protocol,
233 ProtocolHandlerRegistry* registry) {
234 // The worker pointer is reference counted. While it is running, the
235 // message loops of the FILE and UI thread will hold references to it
236 // and it will be automatically freed once all its tasks have finished.
237 CreateShellWorker(base::Bind(OnShellWorkerFinished, registry, this, protocol),
238 protocol)
239 ->StartSetAsDefault();
240 ASSERT_FALSE(IsFakeRegisteredWithOS(protocol));
241 }
242
243 class NotificationCounter : public content::NotificationObserver { 192 class NotificationCounter : public content::NotificationObserver {
244 public: 193 public:
245 explicit NotificationCounter(content::BrowserContext* context) 194 explicit NotificationCounter(content::BrowserContext* context)
246 : events_(0), 195 : events_(0),
247 notification_registrar_() { 196 notification_registrar_() {
248 notification_registrar_.Add(this, 197 notification_registrar_.Add(this,
249 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, 198 chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
250 content::Source<content::BrowserContext>(context)); 199 content::Source<content::BrowserContext>(context));
251 } 200 }
252 201
(...skipping 29 matching lines...) Expand all
282 std::vector<std::string> output; 231 std::vector<std::string> output;
283 local_registry_->GetRegisteredProtocols(&output); 232 local_registry_->GetRegisteredProtocols(&output);
284 called_ = true; 233 called_ = true;
285 } 234 }
286 235
287 ProtocolHandlerRegistry* local_registry_; 236 ProtocolHandlerRegistry* local_registry_;
288 bool called_; 237 bool called_;
289 content::NotificationRegistrar notification_registrar_; 238 content::NotificationRegistrar notification_registrar_;
290 }; 239 };
291 240
292 // URLRequest DCHECKS that the current MessageLoop is IO. It does this because
293 // it can't check the thread id (since net can't depend on content.) We want
294 // to harness our tests so all threads use the same loop allowing us to
295 // guarantee all messages are processed.) By overriding the IsType method
296 // we basically ignore the supplied message loop type, and instead infer
297 // our type based on the current thread. GO DEPENDENCY INJECTION!
298 class TestMessageLoop : public base::MessageLoop {
299 public:
300 TestMessageLoop() {}
301 ~TestMessageLoop() override {}
302 bool IsType(base::MessageLoop::Type type) const override {
303 switch (type) {
304 case base::MessageLoop::TYPE_UI:
305 return BrowserThread::CurrentlyOn(BrowserThread::UI);
306 case base::MessageLoop::TYPE_IO:
307 return BrowserThread::CurrentlyOn(BrowserThread::IO);
308 #if defined(OS_ANDROID)
309 case base::MessageLoop::TYPE_JAVA: // fall-through
310 #endif // defined(OS_ANDROID)
311 case base::MessageLoop::TYPE_CUSTOM:
312 case base::MessageLoop::TYPE_DEFAULT:
313 return !BrowserThread::CurrentlyOn(BrowserThread::UI) &&
314 !BrowserThread::CurrentlyOn(BrowserThread::IO);
315 }
316 return false;
317 }
318 };
319
320 } // namespace 241 } // namespace
321 242
322 class ProtocolHandlerRegistryTest : public testing::Test { 243 class ProtocolHandlerRegistryTest : public testing::Test {
323 protected: 244 protected:
324 ProtocolHandlerRegistryTest() 245 ProtocolHandlerRegistryTest()
325 : ui_thread_(BrowserThread::UI, &loop_), 246 : test_protocol_handler_(CreateProtocolHandler("test", "test")) {}
326 file_thread_(BrowserThread::FILE, &loop_),
327 io_thread_(BrowserThread::IO, &loop_),
328 test_protocol_handler_(CreateProtocolHandler("test", "test")) {}
329 247
330 FakeDelegate* delegate() const { return delegate_; } 248 FakeDelegate* delegate() const { return delegate_; }
331 ProtocolHandlerRegistry* registry() { return registry_.get(); } 249 ProtocolHandlerRegistry* registry() { return registry_.get(); }
332 TestingProfile* profile() const { return profile_.get(); } 250 TestingProfile* profile() const { return profile_.get(); }
333 const ProtocolHandler& test_protocol_handler() const { 251 const ProtocolHandler& test_protocol_handler() const {
334 return test_protocol_handler_; 252 return test_protocol_handler_;
335 } 253 }
336 254
337 ProtocolHandler CreateProtocolHandler(const std::string& protocol, 255 ProtocolHandler CreateProtocolHandler(const std::string& protocol,
338 const GURL& url) { 256 const GURL& url) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 void SetUp() override { 314 void SetUp() override {
397 profile_.reset(new TestingProfile()); 315 profile_.reset(new TestingProfile());
398 CHECK(profile_->GetPrefs()); 316 CHECK(profile_->GetPrefs());
399 SetUpRegistry(true); 317 SetUpRegistry(true);
400 test_protocol_handler_ = 318 test_protocol_handler_ =
401 CreateProtocolHandler("test", GURL("http://test.com/%s")); 319 CreateProtocolHandler("test", GURL("http://test.com/%s"));
402 } 320 }
403 321
404 void TearDown() override { TeadDownRegistry(); } 322 void TearDown() override { TeadDownRegistry(); }
405 323
406 TestMessageLoop loop_;
407
408 private: 324 private:
409 content::TestBrowserThread ui_thread_; 325 content::TestBrowserThreadBundle test_browser_thread_bundle_;
410 content::TestBrowserThread file_thread_;
411 content::TestBrowserThread io_thread_;
412 326
413 std::unique_ptr<TestingProfile> profile_; 327 std::unique_ptr<TestingProfile> profile_;
414 FakeDelegate* delegate_; // Registry assumes ownership of delegate_. 328 FakeDelegate* delegate_; // Registry assumes ownership of delegate_.
415 std::unique_ptr<ProtocolHandlerRegistry> registry_; 329 std::unique_ptr<ProtocolHandlerRegistry> registry_;
416 ProtocolHandler test_protocol_handler_; 330 ProtocolHandler test_protocol_handler_;
417 }; 331 };
418 332
419 TEST_F(ProtocolHandlerRegistryTest, AcceptProtocolHandlerHandlesProtocol) { 333 TEST_F(ProtocolHandlerRegistryTest, AcceptProtocolHandlerHandlesProtocol) {
420 ASSERT_FALSE(registry()->IsHandledProtocol("test")); 334 ASSERT_FALSE(registry()->IsHandledProtocol("test"));
421 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler()); 335 registry()->OnAcceptRegisterProtocolHandler(test_protocol_handler());
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) { 645 TEST_F(ProtocolHandlerRegistryTest, TestOSRegistration) {
732 ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1"); 646 ProtocolHandler ph_do1 = CreateProtocolHandler("do", "test1");
733 ProtocolHandler ph_do2 = CreateProtocolHandler("do", "test2"); 647 ProtocolHandler ph_do2 = CreateProtocolHandler("do", "test2");
734 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test"); 648 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test");
735 649
736 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("do")); 650 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("do"));
737 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont")); 651 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont"));
738 652
739 registry()->OnAcceptRegisterProtocolHandler(ph_do1); 653 registry()->OnAcceptRegisterProtocolHandler(ph_do1);
740 registry()->OnDenyRegisterProtocolHandler(ph_dont); 654 registry()->OnDenyRegisterProtocolHandler(ph_dont);
741 base::RunLoop().Run(); // FILE thread needs to run. 655 base::RunLoop().RunUntilIdle();
656
742 ASSERT_TRUE(delegate()->IsFakeRegisteredWithOS("do")); 657 ASSERT_TRUE(delegate()->IsFakeRegisteredWithOS("do"));
743 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont")); 658 ASSERT_FALSE(delegate()->IsFakeRegisteredWithOS("dont"));
744 659
745 // This should not register with the OS, if it does the delegate 660 // This should not register with the OS, if it does the delegate
746 // will assert for us. We don't need to wait for the message loop 661 // will assert for us. We don't need to wait for the message loop
747 // as it should not go through to the shell worker. 662 // as it should not go through to the shell worker.
748 registry()->OnAcceptRegisterProtocolHandler(ph_do2); 663 registry()->OnAcceptRegisterProtocolHandler(ph_do2);
749 } 664 }
750 665
751 #if defined(OS_LINUX) 666 #if defined(OS_LINUX)
752 // TODO(benwells): When Linux support is more reliable and 667 // TODO(benwells): When Linux support is more reliable and
753 // http://crbug.com/88255 is fixed this test will pass. 668 // http://crbug.com/88255 is fixed this test will pass.
754 #define MAYBE_TestOSRegistrationFailure DISABLED_TestOSRegistrationFailure 669 #define MAYBE_TestOSRegistrationFailure DISABLED_TestOSRegistrationFailure
755 #else 670 #else
756 #define MAYBE_TestOSRegistrationFailure TestOSRegistrationFailure 671 #define MAYBE_TestOSRegistrationFailure TestOSRegistrationFailure
757 #endif 672 #endif
758 673
759 // TODO(smckay): This is much more appropriately an integration 674 // TODO(smckay): This is much more appropriately an integration
760 // test. Make that so, then update the 675 // test. Make that so, then update the
761 // ShellIntegretion{Delegate,Callback,Worker} test classes we use to fully 676 // ShellIntegretion{Delegate,Callback,Worker} test classes we use to fully
762 // isolate this test from the FILE thread. 677 // isolate this test from the FILE thread.
763 TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) { 678 TEST_F(ProtocolHandlerRegistryTest, MAYBE_TestOSRegistrationFailure) {
764 ProtocolHandler ph_do = CreateProtocolHandler("do", "test1"); 679 ProtocolHandler ph_do = CreateProtocolHandler("do", "test1");
765 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test"); 680 ProtocolHandler ph_dont = CreateProtocolHandler("dont", "test");
766 681
767 ASSERT_FALSE(registry()->IsHandledProtocol("do")); 682 ASSERT_FALSE(registry()->IsHandledProtocol("do"));
768 ASSERT_FALSE(registry()->IsHandledProtocol("dont")); 683 ASSERT_FALSE(registry()->IsHandledProtocol("dont"));
769 684
770 registry()->OnAcceptRegisterProtocolHandler(ph_do); 685 registry()->OnAcceptRegisterProtocolHandler(ph_do);
771 base::RunLoop().Run(); // FILE thread needs to run. 686 base::RunLoop().RunUntilIdle();
687
772 delegate()->set_force_os_failure(true); 688 delegate()->set_force_os_failure(true);
773 registry()->OnAcceptRegisterProtocolHandler(ph_dont); 689 registry()->OnAcceptRegisterProtocolHandler(ph_dont);
774 base::RunLoop().Run(); // FILE thread needs to run. 690 base::RunLoop().RunUntilIdle();
691
775 ASSERT_TRUE(registry()->IsHandledProtocol("do")); 692 ASSERT_TRUE(registry()->IsHandledProtocol("do"));
776 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("do").size()); 693 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("do").size());
777 ASSERT_FALSE(registry()->IsHandledProtocol("dont")); 694 ASSERT_FALSE(registry()->IsHandledProtocol("dont"));
778 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("dont").size()); 695 ASSERT_EQ(static_cast<size_t>(1), registry()->GetHandlersFor("dont").size());
779 } 696 }
780 697
781 TEST_F(ProtocolHandlerRegistryTest, TestMaybeCreateTaskWorksFromIOThread) { 698 TEST_F(ProtocolHandlerRegistryTest, TestMaybeCreateTaskWorksFromIOThread) {
782 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1"); 699 ProtocolHandler ph1 = CreateProtocolHandler("mailto", "test1");
783 registry()->OnAcceptRegisterProtocolHandler(ph1); 700 registry()->OnAcceptRegisterProtocolHandler(ph1);
784 GURL url("mailto:someone@something.com"); 701 GURL url("mailto:someone@something.com");
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 // added to pref. 996 // added to pref.
1080 ASSERT_EQ(InPrefIgnoredHandlerCount(), 2); 997 ASSERT_EQ(InPrefIgnoredHandlerCount(), 2);
1081 ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4); 998 ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4);
1082 999
1083 registry()->RemoveIgnoredHandler(p2u1); 1000 registry()->RemoveIgnoredHandler(p2u1);
1084 1001
1085 // p2u1 installed by user and policy, so it is removed from pref alone. 1002 // p2u1 installed by user and policy, so it is removed from pref alone.
1086 ASSERT_EQ(InPrefIgnoredHandlerCount(), 1); 1003 ASSERT_EQ(InPrefIgnoredHandlerCount(), 1);
1087 ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4); 1004 ASSERT_EQ(InMemoryIgnoredHandlerCount(), 4);
1088 } 1005 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698