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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/webui/sync_internals_message_handler.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "chrome/browser/sync/profile_sync_service_factory.h"
13 #include "chrome/browser/sync/user_event_service_factory.h"
14 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
15 #include "chrome/test/base/testing_profile.h"
16 #include "components/sync/driver/about_sync_util.h"
17 #include "components/sync/driver/fake_sync_service.h"
18 #include "components/sync/driver/sync_service.h"
19 #include "components/sync/js/js_test_util.h"
20 #include "components/sync_user_events/fake_user_event_service.h"
21 #include "content/public/browser/site_instance.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/test/test_web_ui.h"
24 
25 using base::DictionaryValue;
26 using base::ListValue;
27 using base::Value;
28 using sync_pb::UserEventSpecifics;
29 using syncer::FakeUserEventService;
30 using syncer::SyncService;
31 using syncer::SyncServiceObserver;
32 using syncer::TypeDebugInfoObserver;
33 
34 namespace {
35 
36 class TestableSyncInternalsMessageHandler : public SyncInternalsMessageHandler {
37  public:
TestableSyncInternalsMessageHandler(content::WebUI * web_ui,AboutSyncDataDelegate about_sync_data_delegate)38   TestableSyncInternalsMessageHandler(
39       content::WebUI* web_ui,
40       AboutSyncDataDelegate about_sync_data_delegate)
41       : SyncInternalsMessageHandler(std::move(about_sync_data_delegate)) {
42     set_web_ui(web_ui);
43   }
44 };
45 
46 class TestSyncService : public syncer::FakeSyncService {
47  public:
AddObserver(SyncServiceObserver * observer)48   void AddObserver(SyncServiceObserver* observer) override {
49     ++add_observer_count_;
50   }
51 
RemoveObserver(SyncServiceObserver * observer)52   void RemoveObserver(SyncServiceObserver* observer) override {
53     ++remove_observer_count_;
54   }
55 
AddTypeDebugInfoObserver(TypeDebugInfoObserver * observer)56   void AddTypeDebugInfoObserver(TypeDebugInfoObserver* observer) override {
57     ++add_type_debug_info_observer_count_;
58   }
59 
RemoveTypeDebugInfoObserver(TypeDebugInfoObserver * observer)60   void RemoveTypeDebugInfoObserver(TypeDebugInfoObserver* observer) override {
61     ++remove_type_debug_info_observer_count_;
62   }
63 
GetJsController()64   base::WeakPtr<syncer::JsController> GetJsController() override {
65     return js_controller_.AsWeakPtr();
66   }
67 
GetAllNodesForDebugging(base::OnceCallback<void (std::unique_ptr<base::ListValue>)> callback)68   void GetAllNodesForDebugging(
69       base::OnceCallback<void(std::unique_ptr<base::ListValue>)> callback)
70       override {
71     get_all_nodes_callback_ = std::move(callback);
72   }
73 
add_observer_count() const74   int add_observer_count() const { return add_observer_count_; }
remove_observer_count() const75   int remove_observer_count() const { return remove_observer_count_; }
add_type_debug_info_observer_count() const76   int add_type_debug_info_observer_count() const {
77     return add_type_debug_info_observer_count_;
78   }
remove_type_debug_info_observer_count() const79   int remove_type_debug_info_observer_count() const {
80     return remove_type_debug_info_observer_count_;
81   }
82   base::OnceCallback<void(std::unique_ptr<base::ListValue>)>
get_all_nodes_callback()83   get_all_nodes_callback() {
84     return std::move(get_all_nodes_callback_);
85   }
86 
87  private:
88   int add_observer_count_ = 0;
89   int remove_observer_count_ = 0;
90   int add_type_debug_info_observer_count_ = 0;
91   int remove_type_debug_info_observer_count_ = 0;
92   syncer::MockJsController js_controller_;
93   base::OnceCallback<void(std::unique_ptr<base::ListValue>)>
94       get_all_nodes_callback_;
95 };
96 
BuildTestSyncService(content::BrowserContext * context)97 static std::unique_ptr<KeyedService> BuildTestSyncService(
98     content::BrowserContext* context) {
99   return std::make_unique<TestSyncService>();
100 }
101 
BuildFakeUserEventService(content::BrowserContext * context)102 static std::unique_ptr<KeyedService> BuildFakeUserEventService(
103     content::BrowserContext* context) {
104   return std::make_unique<FakeUserEventService>();
105 }
106 
107 class SyncInternalsMessageHandlerTest : public ChromeRenderViewHostTestHarness {
108  protected:
109   SyncInternalsMessageHandlerTest() = default;
110   ~SyncInternalsMessageHandlerTest() override = default;
111 
SetUp()112   void SetUp() override {
113     ChromeRenderViewHostTestHarness::SetUp();
114 
115     web_ui_.set_web_contents(web_contents());
116     test_sync_service_ = static_cast<TestSyncService*>(
117         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
118             profile(), base::BindRepeating(&BuildTestSyncService)));
119     fake_user_event_service_ = static_cast<FakeUserEventService*>(
120         browser_sync::UserEventServiceFactory::GetInstance()
121             ->SetTestingFactoryAndUse(
122                 profile(), base::BindRepeating(&BuildFakeUserEventService)));
123     handler_ = std::make_unique<TestableSyncInternalsMessageHandler>(
124         &web_ui_,
125         base::BindRepeating(
126             &SyncInternalsMessageHandlerTest::ConstructAboutInformation,
127             base::Unretained(this)));
128   }
129 
TearDown()130   void TearDown() override {
131     // Destroy |handler_| before |web_contents()|.
132     handler_ = nullptr;
133     ChromeRenderViewHostTestHarness::TearDown();
134   }
135 
ConstructAboutInformation(SyncService * service,version_info::Channel channel)136   std::unique_ptr<DictionaryValue> ConstructAboutInformation(
137       SyncService* service,
138       version_info::Channel channel) {
139     ++about_sync_data_delegate_call_count_;
140     last_delegate_sync_service_ = service;
141     auto dictionary = std::make_unique<DictionaryValue>();
142     dictionary->SetString("fake_key", "fake_value");
143     return dictionary;
144   }
145 
ValidateAboutInfoCall()146   void ValidateAboutInfoCall() {
147     const auto& data_vector = web_ui_.call_data();
148     ASSERT_FALSE(data_vector.empty());
149     EXPECT_EQ(1u, data_vector.size());
150 
151     const content::TestWebUI::CallData& call_data = *data_vector[0];
152 
153     EXPECT_EQ(syncer::sync_ui_util::kDispatchEvent, call_data.function_name());
154 
155     const Value* arg1 = call_data.arg1();
156     ASSERT_TRUE(arg1);
157     std::string event_type;
158     EXPECT_TRUE(arg1->GetAsString(&event_type));
159     EXPECT_EQ(syncer::sync_ui_util::kOnAboutInfoUpdated, event_type);
160 
161     const Value* arg2 = call_data.arg2();
162     ASSERT_TRUE(arg2);
163 
164     const DictionaryValue* root_dictionary = nullptr;
165     ASSERT_TRUE(arg2->GetAsDictionary(&root_dictionary));
166 
167     std::string fake_value;
168     EXPECT_TRUE(root_dictionary->GetString("fake_key", &fake_value));
169     EXPECT_EQ("fake_value", fake_value);
170   }
171 
ValidateEmptyAboutInfoCall()172   void ValidateEmptyAboutInfoCall() {
173     EXPECT_TRUE(web_ui_.call_data().empty());
174   }
175 
test_sync_service()176   TestSyncService* test_sync_service() { return test_sync_service_; }
177 
fake_user_event_service()178   FakeUserEventService* fake_user_event_service() {
179     return fake_user_event_service_;
180   }
181 
handler()182   TestableSyncInternalsMessageHandler* handler() { return handler_.get(); }
183 
CallCountWithName(const std::string & function_name)184   int CallCountWithName(const std::string& function_name) {
185     int count = 0;
186     for (const auto& call_data : web_ui_.call_data()) {
187       if (call_data->function_name() == function_name) {
188         count++;
189       }
190     }
191     return count;
192   }
193 
about_sync_data_delegate_call_count() const194   int about_sync_data_delegate_call_count() const {
195     return about_sync_data_delegate_call_count_;
196   }
197 
last_delegate_sync_service() const198   const SyncService* last_delegate_sync_service() const {
199     return last_delegate_sync_service_;
200   }
201 
ResetHandler()202   void ResetHandler() { handler_.reset(); }
203 
204  private:
205   content::TestWebUI web_ui_;
206   TestSyncService* test_sync_service_;
207   FakeUserEventService* fake_user_event_service_;
208   std::unique_ptr<TestableSyncInternalsMessageHandler> handler_;
209   int about_sync_data_delegate_call_count_ = 0;
210   SyncService* last_delegate_sync_service_ = nullptr;
211 
212   DISALLOW_COPY_AND_ASSIGN(SyncInternalsMessageHandlerTest);
213 };
214 
TEST_F(SyncInternalsMessageHandlerTest,AddRemoveObservers)215 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObservers) {
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   ResetHandler();
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   // Add calls should never have increased since the initial subscription.
233   EXPECT_EQ(1, test_sync_service()->add_observer_count());
234   EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count());
235 }
236 
TEST_F(SyncInternalsMessageHandlerTest,AddRemoveObserversDisallowJavascript)237 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversDisallowJavascript) {
238   ListValue empty_list;
239 
240   EXPECT_EQ(0, test_sync_service()->add_observer_count());
241   handler()->HandleRegisterForEvents(&empty_list);
242   EXPECT_EQ(1, test_sync_service()->add_observer_count());
243 
244   EXPECT_EQ(0, test_sync_service()->add_type_debug_info_observer_count());
245   handler()->HandleRegisterForPerTypeCounters(&empty_list);
246   EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count());
247 
248   EXPECT_EQ(0, test_sync_service()->remove_observer_count());
249   EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count());
250   handler()->DisallowJavascript();
251   EXPECT_EQ(1, test_sync_service()->remove_observer_count());
252   EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count());
253 
254   // Deregistration should not repeat, no counts should increase.
255   ResetHandler();
256   EXPECT_EQ(1, test_sync_service()->add_observer_count());
257   EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count());
258   EXPECT_EQ(1, test_sync_service()->remove_observer_count());
259   EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count());
260 }
261 
TEST_F(SyncInternalsMessageHandlerTest,AddRemoveObserversSyncDisabled)262 TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversSyncDisabled) {
263   // Simulate completely disabling sync by flag or other mechanism.
264   ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
265       profile(), BrowserContextKeyedServiceFactory::TestingFactory());
266 
267   ListValue empty_list;
268   handler()->HandleRegisterForEvents(&empty_list);
269   handler()->HandleRegisterForPerTypeCounters(&empty_list);
270   handler()->DisallowJavascript();
271   // Cannot verify observer methods on sync services were not called, because
272   // there is no sync service. Rather, we're just making sure the handler hasn't
273   // performed any invalid operations when the sync service is missing.
274 }
275 
TEST_F(SyncInternalsMessageHandlerTest,RepeatedHandleRegisterForPerTypeCounters)276 TEST_F(SyncInternalsMessageHandlerTest,
277        RepeatedHandleRegisterForPerTypeCounters) {
278   ListValue empty_list;
279   handler()->HandleRegisterForPerTypeCounters(&empty_list);
280   EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count());
281   EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count());
282 
283   handler()->HandleRegisterForPerTypeCounters(&empty_list);
284   EXPECT_EQ(2, test_sync_service()->add_type_debug_info_observer_count());
285   EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count());
286 
287   handler()->HandleRegisterForPerTypeCounters(&empty_list);
288   EXPECT_EQ(3, test_sync_service()->add_type_debug_info_observer_count());
289   EXPECT_EQ(2, test_sync_service()->remove_type_debug_info_observer_count());
290 
291   ResetHandler();
292   EXPECT_EQ(3, test_sync_service()->add_type_debug_info_observer_count());
293   EXPECT_EQ(3, test_sync_service()->remove_type_debug_info_observer_count());
294 }
295 
TEST_F(SyncInternalsMessageHandlerTest,HandleGetAllNodes)296 TEST_F(SyncInternalsMessageHandlerTest, HandleGetAllNodes) {
297   ListValue args;
298   args.AppendInteger(0);
299   handler()->HandleGetAllNodes(&args);
300   test_sync_service()->get_all_nodes_callback().Run(
301       std::make_unique<ListValue>());
302   EXPECT_EQ(1, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback));
303 
304   handler()->HandleGetAllNodes(&args);
305   // This  breaks the weak ref the callback is hanging onto. Which results in
306   // the call count not incrementing.
307   handler()->DisallowJavascript();
308   test_sync_service()->get_all_nodes_callback().Run(
309       std::make_unique<ListValue>());
310   EXPECT_EQ(1, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback));
311 
312   handler()->HandleGetAllNodes(&args);
313   test_sync_service()->get_all_nodes_callback().Run(
314       std::make_unique<ListValue>());
315   EXPECT_EQ(2, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback));
316 }
317 
TEST_F(SyncInternalsMessageHandlerTest,SendAboutInfo)318 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfo) {
319   handler()->AllowJavascriptForTesting();
320   handler()->OnStateChanged(nullptr);
321   EXPECT_EQ(1, about_sync_data_delegate_call_count());
322   EXPECT_NE(nullptr, last_delegate_sync_service());
323   ValidateAboutInfoCall();
324 }
325 
TEST_F(SyncInternalsMessageHandlerTest,SendAboutInfoSyncDisabled)326 TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoSyncDisabled) {
327   // Simulate completely disabling sync by flag or other mechanism.
328   ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
329       profile(), BrowserContextKeyedServiceFactory::TestingFactory());
330 
331   handler()->AllowJavascriptForTesting();
332   handler()->OnStateChanged(nullptr);
333   EXPECT_EQ(1, about_sync_data_delegate_call_count());
334   EXPECT_EQ(nullptr, last_delegate_sync_service());
335   ValidateAboutInfoCall();
336 }
337 
TEST_F(SyncInternalsMessageHandlerTest,WriteUserEvent)338 TEST_F(SyncInternalsMessageHandlerTest, WriteUserEvent) {
339   ListValue args;
340   args.AppendString("1000000000000000000");
341   args.AppendString("-1");
342   handler()->HandleWriteUserEvent(&args);
343 
344   ASSERT_EQ(1u, fake_user_event_service()->GetRecordedUserEvents().size());
345   const UserEventSpecifics& event =
346       *fake_user_event_service()->GetRecordedUserEvents().begin();
347   EXPECT_EQ(UserEventSpecifics::kTestEvent, event.event_case());
348   EXPECT_EQ(1000000000000000000, event.event_time_usec());
349   EXPECT_EQ(-1, event.navigation_id());
350 }
351 
TEST_F(SyncInternalsMessageHandlerTest,WriteUserEventBadParse)352 TEST_F(SyncInternalsMessageHandlerTest, WriteUserEventBadParse) {
353   ListValue args;
354   args.AppendString("123abc");
355   args.AppendString("abcdefghijklmnopqrstuvwxyz");
356   handler()->HandleWriteUserEvent(&args);
357 
358   ASSERT_EQ(1u, fake_user_event_service()->GetRecordedUserEvents().size());
359   const UserEventSpecifics& event =
360       *fake_user_event_service()->GetRecordedUserEvents().begin();
361   EXPECT_EQ(UserEventSpecifics::kTestEvent, event.event_case());
362   EXPECT_EQ(0, event.event_time_usec());
363   EXPECT_EQ(0, event.navigation_id());
364 }
365 
TEST_F(SyncInternalsMessageHandlerTest,WriteUserEventBlank)366 TEST_F(SyncInternalsMessageHandlerTest, WriteUserEventBlank) {
367   ListValue args;
368   args.AppendString("");
369   args.AppendString("");
370   handler()->HandleWriteUserEvent(&args);
371 
372   ASSERT_EQ(1u, fake_user_event_service()->GetRecordedUserEvents().size());
373   const UserEventSpecifics& event =
374       *fake_user_event_service()->GetRecordedUserEvents().begin();
375   EXPECT_EQ(UserEventSpecifics::kTestEvent, event.event_case());
376   EXPECT_TRUE(event.has_event_time_usec());
377   EXPECT_EQ(0, event.event_time_usec());
378   // Should not have a navigation_id because that means something different to
379   // the UserEvents logic.
380   EXPECT_FALSE(event.has_navigation_id());
381 }
382 
TEST_F(SyncInternalsMessageHandlerTest,WriteUserEventZero)383 TEST_F(SyncInternalsMessageHandlerTest, WriteUserEventZero) {
384   ListValue args;
385   args.AppendString("0");
386   args.AppendString("0");
387   handler()->HandleWriteUserEvent(&args);
388 
389   ASSERT_EQ(1u, fake_user_event_service()->GetRecordedUserEvents().size());
390   const UserEventSpecifics& event =
391       *fake_user_event_service()->GetRecordedUserEvents().begin();
392   EXPECT_EQ(UserEventSpecifics::kTestEvent, event.event_case());
393   EXPECT_TRUE(event.has_event_time_usec());
394   EXPECT_EQ(0, event.event_time_usec());
395   // Should have a navigation_id, even though the value is 0.
396   EXPECT_TRUE(event.has_navigation_id());
397   EXPECT_EQ(0, event.navigation_id());
398 }
399 
400 }  // namespace
401