OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ui/webui/sync_internals_message_handler.h" | 5 #include "chrome/browser/ui/webui/sync_internals_message_handler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
12 #include "chrome/test/base/testing_profile.h" | 12 #include "chrome/test/base/testing_profile.h" |
13 #include "components/browser_sync/browser_sync_switches.h" | 13 #include "components/browser_sync/browser_sync_switches.h" |
14 #include "components/sync/driver/about_sync_util.h" | 14 #include "components/sync/driver/about_sync_util.h" |
| 15 #include "components/sync/driver/fake_sync_service.h" |
15 #include "components/sync/driver/sync_service.h" | 16 #include "components/sync/driver/sync_service.h" |
| 17 #include "components/sync/js/js_test_util.h" |
16 #include "content/public/browser/site_instance.h" | 18 #include "content/public/browser/site_instance.h" |
17 #include "content/public/browser/web_contents.h" | 19 #include "content/public/browser/web_contents.h" |
18 #include "content/public/test/test_browser_thread_bundle.h" | 20 #include "content/public/test/test_browser_thread_bundle.h" |
19 #include "content/public/test/test_web_ui.h" | 21 #include "content/public/test/test_web_ui.h" |
20 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
21 | 23 |
| 24 using base::DictionaryValue; |
| 25 using base::ListValue; |
| 26 using base::Value; |
| 27 using syncer::SyncService; |
| 28 using syncer::SyncServiceObserver; |
| 29 using syncer::TypeDebugInfoObserver; |
| 30 |
22 namespace { | 31 namespace { |
23 | 32 |
24 class TestableSyncInternalsMessageHandler : public SyncInternalsMessageHandler { | 33 class TestableSyncInternalsMessageHandler : public SyncInternalsMessageHandler { |
25 public: | 34 public: |
26 explicit TestableSyncInternalsMessageHandler( | 35 TestableSyncInternalsMessageHandler( |
27 content::WebUI* web_ui, | 36 content::WebUI* web_ui, |
28 std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor) | 37 SyncServiceProvider sync_service_provider, |
29 : SyncInternalsMessageHandler(std::move(about_sync_data_extractor)) { | 38 AboutSyncDataDelegate about_sync_data_delegate) |
| 39 : SyncInternalsMessageHandler(std::move(sync_service_provider), |
| 40 std::move(about_sync_data_delegate)) { |
30 set_web_ui(web_ui); | 41 set_web_ui(web_ui); |
31 } | 42 } |
32 }; | 43 }; |
33 | 44 |
34 class FakeExtractor : public AboutSyncDataExtractor { | 45 class TestSyncService : public syncer::FakeSyncService { |
35 public: | 46 public: |
36 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation( | 47 void AddObserver(SyncServiceObserver* observer) override { |
37 syncer::SyncService* service, | 48 ++add_observer_count_; |
38 SigninManagerBase* signin) override { | |
39 call_count_++; | |
40 last_service_ = service; | |
41 last_signin_ = signin; | |
42 std::unique_ptr<base::DictionaryValue> dictionary( | |
43 new base::DictionaryValue()); | |
44 dictionary->SetString("fake_key", "fake_value"); | |
45 return dictionary; | |
46 } | 49 } |
47 | 50 |
48 int call_count() const { return call_count_; } | 51 void RemoveObserver(SyncServiceObserver* observer) override { |
49 syncer::SyncService* last_service() const { return last_service_; } | 52 ++remove_observer_count_; |
50 SigninManagerBase* last_signin() const { return last_signin_; } | 53 } |
| 54 |
| 55 void AddTypeDebugInfoObserver(TypeDebugInfoObserver* observer) override { |
| 56 ++add_type_debug_info_observer_count_; |
| 57 } |
| 58 |
| 59 void RemoveTypeDebugInfoObserver(TypeDebugInfoObserver* observer) override { |
| 60 ++remove_type_debug_info_observer_count_; |
| 61 } |
| 62 |
| 63 base::WeakPtr<syncer::JsController> GetJsController() override { |
| 64 return js_controller_.AsWeakPtr(); |
| 65 } |
| 66 |
| 67 void GetAllNodes(const base::Callback<void(std::unique_ptr<base::ListValue>)>& |
| 68 callback) override { |
| 69 get_all_nodes_callback_ = std::move(callback); |
| 70 } |
| 71 |
| 72 int add_observer_count() const { return add_observer_count_; } |
| 73 int remove_observer_count() const { return remove_observer_count_; } |
| 74 int add_type_debug_info_observer_count() const { |
| 75 return add_type_debug_info_observer_count_; |
| 76 } |
| 77 int remove_type_debug_info_observer_count() const { |
| 78 return remove_type_debug_info_observer_count_; |
| 79 } |
| 80 base::Callback<void(std::unique_ptr<base::ListValue>)> |
| 81 get_all_nodes_callback() { |
| 82 return std::move(get_all_nodes_callback_); |
| 83 } |
51 | 84 |
52 private: | 85 private: |
53 int call_count_ = 0; | 86 int add_observer_count_ = 0; |
54 syncer::SyncService* last_service_ = nullptr; | 87 int remove_observer_count_ = 0; |
55 SigninManagerBase* last_signin_ = nullptr; | 88 int add_type_debug_info_observer_count_ = 0; |
| 89 int remove_type_debug_info_observer_count_ = 0; |
| 90 syncer::MockJsController js_controller_; |
| 91 base::Callback<void(std::unique_ptr<base::ListValue>)> |
| 92 get_all_nodes_callback_; |
56 }; | 93 }; |
57 | 94 |
58 class SyncInternalsMessageHandlerTest : public ::testing::Test { | 95 class SyncInternalsMessageHandlerTest : public ::testing::Test { |
59 protected: | 96 protected: |
60 SyncInternalsMessageHandlerTest() { | 97 SyncInternalsMessageHandlerTest() { |
61 site_instance_ = content::SiteInstance::Create(&profile_); | 98 site_instance_ = content::SiteInstance::Create(&profile_); |
62 web_contents_.reset(content::WebContents::Create( | 99 web_contents_.reset(content::WebContents::Create( |
63 content::WebContents::CreateParams(&profile_, site_instance_.get()))); | 100 content::WebContents::CreateParams(&profile_, site_instance_.get()))); |
64 web_ui_.set_web_contents(web_contents_.get()); | 101 web_ui_.set_web_contents(web_contents_.get()); |
65 fake_extractor_ = new FakeExtractor(); | 102 test_sync_service_ = base::MakeUnique<TestSyncService>(); |
66 handler_.reset(new TestableSyncInternalsMessageHandler( | 103 handler_.reset(new TestableSyncInternalsMessageHandler( |
67 &web_ui_, std::unique_ptr<FakeExtractor>(fake_extractor_))); | 104 &web_ui_, |
| 105 base::BindRepeating(&SyncInternalsMessageHandlerTest::sync_service, |
| 106 base::Unretained(this)), |
| 107 base::BindRepeating( |
| 108 &SyncInternalsMessageHandlerTest::ConstructAboutInformation, |
| 109 base::Unretained(this)))); |
| 110 } |
| 111 |
| 112 std::unique_ptr<DictionaryValue> ConstructAboutInformation( |
| 113 SyncService* service, |
| 114 version_info::Channel channel) { |
| 115 ++about_sync_data_delegate_call_count_; |
| 116 last_delegate_sync_service_ = service; |
| 117 auto dictionary = base::MakeUnique<DictionaryValue>(); |
| 118 dictionary->SetString("fake_key", "fake_value"); |
| 119 return dictionary; |
68 } | 120 } |
69 | 121 |
70 void ValidateAboutInfoCall() { | 122 void ValidateAboutInfoCall() { |
71 const auto& data_vector = web_ui_.call_data(); | 123 const auto& data_vector = web_ui_.call_data(); |
72 ASSERT_FALSE(data_vector.empty()); | 124 ASSERT_FALSE(data_vector.empty()); |
73 EXPECT_EQ(1u, data_vector.size()); | 125 EXPECT_EQ(1u, data_vector.size()); |
74 | 126 |
75 const content::TestWebUI::CallData& call_data = *data_vector[0]; | 127 const content::TestWebUI::CallData& call_data = *data_vector[0]; |
76 | 128 |
77 EXPECT_EQ(syncer::sync_ui_util::kDispatchEvent, call_data.function_name()); | 129 EXPECT_EQ(syncer::sync_ui_util::kDispatchEvent, call_data.function_name()); |
78 | 130 |
79 const base::Value* arg1 = call_data.arg1(); | 131 const Value* arg1 = call_data.arg1(); |
80 ASSERT_TRUE(arg1); | 132 ASSERT_TRUE(arg1); |
81 std::string event_type; | 133 std::string event_type; |
82 EXPECT_TRUE(arg1->GetAsString(&event_type)); | 134 EXPECT_TRUE(arg1->GetAsString(&event_type)); |
83 EXPECT_EQ(syncer::sync_ui_util::kOnAboutInfoUpdated, event_type); | 135 EXPECT_EQ(syncer::sync_ui_util::kOnAboutInfoUpdated, event_type); |
84 | 136 |
85 const base::Value* arg2 = call_data.arg2(); | 137 const Value* arg2 = call_data.arg2(); |
86 ASSERT_TRUE(arg2); | 138 ASSERT_TRUE(arg2); |
87 | 139 |
88 const base::DictionaryValue* root_dictionary = nullptr; | 140 const DictionaryValue* root_dictionary = nullptr; |
89 ASSERT_TRUE(arg2->GetAsDictionary(&root_dictionary)); | 141 ASSERT_TRUE(arg2->GetAsDictionary(&root_dictionary)); |
90 | 142 |
91 std::string fake_value; | 143 std::string fake_value; |
92 EXPECT_TRUE(root_dictionary->GetString("fake_key", &fake_value)); | 144 EXPECT_TRUE(root_dictionary->GetString("fake_key", &fake_value)); |
93 EXPECT_EQ("fake_value", fake_value); | 145 EXPECT_EQ("fake_value", fake_value); |
94 } | 146 } |
95 | 147 |
96 SyncInternalsMessageHandler* handler() { return handler_.get(); } | 148 void ValidateEmptyAboutInfoCall() { |
97 FakeExtractor* fake_extractor() { return fake_extractor_; } | 149 EXPECT_TRUE(web_ui_.call_data().empty()); |
| 150 } |
| 151 |
| 152 TestSyncService* test_sync_service() { return test_sync_service_.get(); } |
| 153 |
| 154 TestableSyncInternalsMessageHandler* handler() { return handler_.get(); } |
| 155 |
| 156 int CallCountWithName(const std::string& function_name) { |
| 157 int count = 0; |
| 158 for (const auto& call_data : web_ui_.call_data()) { |
| 159 if (call_data->function_name() == function_name) { |
| 160 count++; |
| 161 } |
| 162 } |
| 163 return count; |
| 164 } |
| 165 |
| 166 int about_sync_data_delegate_call_count() const { |
| 167 return about_sync_data_delegate_call_count_; |
| 168 } |
| 169 |
| 170 const SyncService* last_delegate_sync_service() const { |
| 171 return last_delegate_sync_service_; |
| 172 } |
| 173 |
| 174 void ResetSyncService() { test_sync_service_.reset(); } |
| 175 |
| 176 void ResetHandler() { handler_.reset(); } |
98 | 177 |
99 private: | 178 private: |
| 179 SyncService* sync_service() { return test_sync_service_.get(); } |
| 180 |
100 content::TestBrowserThreadBundle thread_bundle_; | 181 content::TestBrowserThreadBundle thread_bundle_; |
101 TestingProfile profile_; | 182 TestingProfile profile_; |
102 content::TestWebUI web_ui_; | 183 content::TestWebUI web_ui_; |
103 scoped_refptr<content::SiteInstance> site_instance_; | 184 scoped_refptr<content::SiteInstance> site_instance_; |
104 std::unique_ptr<content::WebContents> web_contents_; | 185 std::unique_ptr<content::WebContents> web_contents_; |
105 std::unique_ptr<SyncInternalsMessageHandler> handler_; | 186 std::unique_ptr<TestSyncService> test_sync_service_; |
| 187 std::unique_ptr<TestableSyncInternalsMessageHandler> handler_; |
106 | 188 |
107 // Non-owning pointer to the about information the handler uses. This | 189 int about_sync_data_delegate_call_count_ = 0; |
108 // extractor is owned by the handler. | 190 SyncService* last_delegate_sync_service_ = nullptr; |
109 FakeExtractor* fake_extractor_; | |
110 }; | 191 }; |
111 | 192 |
112 } // namespace | 193 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObservers) { |
| 194 ListValue empty_list; |
113 | 195 |
114 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoWithService) { | 196 EXPECT_EQ(0, test_sync_service()->add_observer_count()); |
| 197 handler()->HandleRegisterForEvents(&empty_list); |
| 198 EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| 199 |
| 200 EXPECT_EQ(0, test_sync_service()->add_type_debug_info_observer_count()); |
| 201 handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| 202 EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| 203 |
| 204 EXPECT_EQ(0, test_sync_service()->remove_observer_count()); |
| 205 EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count()); |
| 206 ResetHandler(); |
| 207 EXPECT_EQ(1, test_sync_service()->remove_observer_count()); |
| 208 EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| 209 |
| 210 // Add calls should never have increased since the initial subscription. |
| 211 EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| 212 EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| 213 } |
| 214 |
| 215 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversDisallowJavascript) { |
| 216 ListValue empty_list; |
| 217 |
| 218 EXPECT_EQ(0, test_sync_service()->add_observer_count()); |
| 219 handler()->HandleRegisterForEvents(&empty_list); |
| 220 EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| 221 |
| 222 EXPECT_EQ(0, test_sync_service()->add_type_debug_info_observer_count()); |
| 223 handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| 224 EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| 225 |
| 226 EXPECT_EQ(0, test_sync_service()->remove_observer_count()); |
| 227 EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count()); |
| 228 handler()->DisallowJavascript(); |
| 229 EXPECT_EQ(1, test_sync_service()->remove_observer_count()); |
| 230 EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| 231 |
| 232 // Deregistration should not repeat, no counts should increase. |
| 233 ResetHandler(); |
| 234 EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| 235 EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| 236 EXPECT_EQ(1, test_sync_service()->remove_observer_count()); |
| 237 EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| 238 } |
| 239 |
| 240 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversSyncDisabled) { |
| 241 // Simulate completely disabling sync by flag or other mechanism. |
| 242 ResetSyncService(); |
| 243 |
| 244 ListValue empty_list; |
| 245 handler()->HandleRegisterForEvents(&empty_list); |
| 246 handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| 247 handler()->DisallowJavascript(); |
| 248 // Cannot verify observer methods on sync services were not called, because |
| 249 // there is no sync service. Rather, we're just making sure the handler hasn't |
| 250 // performed any invalid operations when the sync service is missing. |
| 251 } |
| 252 |
| 253 TEST_F(SyncInternalsMessageHandlerTest, |
| 254 RepeatedHandleRegisterForPerTypeCounters) { |
| 255 ListValue empty_list; |
| 256 handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| 257 EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| 258 EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count()); |
| 259 |
| 260 handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| 261 EXPECT_EQ(2, test_sync_service()->add_type_debug_info_observer_count()); |
| 262 EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| 263 |
| 264 handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| 265 EXPECT_EQ(3, test_sync_service()->add_type_debug_info_observer_count()); |
| 266 EXPECT_EQ(2, test_sync_service()->remove_type_debug_info_observer_count()); |
| 267 |
| 268 ResetHandler(); |
| 269 EXPECT_EQ(3, test_sync_service()->add_type_debug_info_observer_count()); |
| 270 EXPECT_EQ(3, test_sync_service()->remove_type_debug_info_observer_count()); |
| 271 } |
| 272 |
| 273 TEST_F(SyncInternalsMessageHandlerTest, HandleGetAllNodes) { |
| 274 ListValue args; |
| 275 args.AppendInteger(0); |
| 276 handler()->HandleGetAllNodes(&args); |
| 277 test_sync_service()->get_all_nodes_callback().Run( |
| 278 base::MakeUnique<ListValue>()); |
| 279 EXPECT_EQ(1, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback)); |
| 280 |
| 281 handler()->HandleGetAllNodes(&args); |
| 282 // This breaks the weak ref the callback is hanging onto. Which results in |
| 283 // the call count not incrementing. |
| 284 handler()->DisallowJavascript(); |
| 285 test_sync_service()->get_all_nodes_callback().Run( |
| 286 base::MakeUnique<ListValue>()); |
| 287 EXPECT_EQ(1, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback)); |
| 288 |
| 289 handler()->HandleGetAllNodes(&args); |
| 290 test_sync_service()->get_all_nodes_callback().Run( |
| 291 base::MakeUnique<ListValue>()); |
| 292 EXPECT_EQ(2, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback)); |
| 293 } |
| 294 |
| 295 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfo) { |
| 296 handler()->AllowJavascriptForTesting(); |
115 handler()->OnStateChanged(nullptr); | 297 handler()->OnStateChanged(nullptr); |
116 EXPECT_EQ(1, fake_extractor()->call_count()); | 298 EXPECT_EQ(1, about_sync_data_delegate_call_count()); |
117 EXPECT_NE(nullptr, fake_extractor()->last_service()); | 299 EXPECT_NE(nullptr, last_delegate_sync_service()); |
118 EXPECT_NE(nullptr, fake_extractor()->last_signin()); | |
119 ValidateAboutInfoCall(); | 300 ValidateAboutInfoCall(); |
120 } | 301 } |
121 | 302 |
122 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoWithoutService) { | 303 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoSyncDisabled) { |
123 base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync); | 304 // Simulate completely disabling sync by flag or other mechanism. |
| 305 ResetSyncService(); |
| 306 |
| 307 handler()->AllowJavascriptForTesting(); |
124 handler()->OnStateChanged(nullptr); | 308 handler()->OnStateChanged(nullptr); |
125 EXPECT_EQ(1, fake_extractor()->call_count()); | 309 EXPECT_EQ(1, about_sync_data_delegate_call_count()); |
126 EXPECT_EQ(nullptr, fake_extractor()->last_service()); | 310 EXPECT_EQ(nullptr, last_delegate_sync_service()); |
127 EXPECT_EQ(nullptr, fake_extractor()->last_signin()); | |
128 ValidateAboutInfoCall(); | 311 ValidateAboutInfoCall(); |
129 } | 312 } |
| 313 |
| 314 } // namespace |
OLD | NEW |