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 <string>
6
7#include "base/command_line.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop/message_loop.h"
10#include "base/prefs/testing_pref_service.h"
11#include "base/run_loop.h"
12#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
13#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
14#include "chrome/browser/service_process/service_process_control.h"
15#include "chrome/browser/ui/startup/startup_browser_creator.h"
16#include "chrome/common/chrome_switches.h"
17#include "chrome/common/cloud_print/cloud_print_proxy_info.h"
18#include "chrome/common/pref_names.h"
19#include "chrome/common/service_messages.h"
20#include "chrome/test/base/testing_browser_process.h"
21#include "chrome/test/base/testing_pref_service_syncable.h"
22#include "chrome/test/base/testing_profile.h"
23#include "chrome/test/base/testing_profile_manager.h"
24#include "content/public/browser/browser_thread.h"
25#include "content/public/test/test_browser_thread.h"
26#include "testing/gmock/include/gmock/gmock.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29using ::testing::Assign;
30using ::testing::AtMost;
31using ::testing::DeleteArg;
32using ::testing::DoAll;
33using ::testing::Invoke;
34using ::testing::Property;
35using ::testing::Return;
36using ::testing::ReturnPointee;
37using ::testing::WithArgs;
38using ::testing::WithoutArgs;
39using ::testing::_;
40
41class MockServiceProcessControl : public ServiceProcessControl {
42 public:
43  static std::string EnabledUserId();
44
45  MockServiceProcessControl() : connected_(false) { }
46
47  MOCK_CONST_METHOD0(IsConnected, bool());
48
49  MOCK_METHOD2(Launch, void(const base::Closure&, const base::Closure&));
50  MOCK_METHOD0(Disconnect, void());
51
52  MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message&));
53  MOCK_METHOD1(OnChannelConnected, void(int32 peer_pid));
54  MOCK_METHOD0(OnChannelError, void());
55
56  MOCK_METHOD1(Send, bool(IPC::Message*));
57
58  typedef enum {
59    kServiceStateDisabled,
60    kServiceStateEnabled,
61    kServiceStateNone
62  } ServiceState;
63
64  void SetConnectSuccessMockExpectations(ServiceState state, bool post_task);
65
66  void SetServiceEnabledExpectations();
67  void SetServiceDisabledExpectations();
68  void SetWillBeEnabledExpectations();
69  void SetWillBeDisabledExpectations();
70
71  bool SendEnabledInfo();
72  bool SendDisabledInfo();
73
74 private:
75  bool connected_;
76  cloud_print::CloudPrintProxyInfo info_;
77};
78
79// static
80std::string MockServiceProcessControl::EnabledUserId() {
81  return std::string("dorothy@somewhere.otr");
82}
83
84void CallTask(const base::Closure& task) {
85  if (!task.is_null())
86    task.Run();
87}
88
89void PostTask(const base::Closure& task) {
90  if (!task.is_null())
91    base::MessageLoop::current()->PostTask(FROM_HERE, task);
92}
93
94void MockServiceProcessControl::SetConnectSuccessMockExpectations(
95    ServiceState service_state,
96    bool post_task) {
97  EXPECT_CALL(*this, IsConnected()).WillRepeatedly(ReturnPointee(&connected_));
98
99  EXPECT_CALL(*this, Launch(_, _))
100      .WillRepeatedly(
101          DoAll(Assign(&connected_, true),
102                WithArgs<0>(Invoke(post_task ? PostTask : CallTask))));
103
104  EXPECT_CALL(*this, Disconnect()).Times(AtMost(1))
105      .WillRepeatedly(Assign(&connected_, false));
106
107  EXPECT_CALL(*this, Send(_)).Times(0);
108
109  if (service_state == kServiceStateEnabled)
110    SetServiceEnabledExpectations();
111  else if (service_state == kServiceStateDisabled)
112    SetServiceDisabledExpectations();
113}
114
115void MockServiceProcessControl::SetServiceEnabledExpectations() {
116  EXPECT_CALL(
117      *this,
118      Send(Property(&IPC::Message::type,
119                    static_cast<int32>(ServiceMsg_GetCloudPrintProxyInfo::ID))))
120      .Times(1).WillOnce(
121          DoAll(
122              DeleteArg<0>(),
123              WithoutArgs(
124                  Invoke(this, &MockServiceProcessControl::SendEnabledInfo))));
125}
126
127void MockServiceProcessControl::SetServiceDisabledExpectations() {
128  EXPECT_CALL(
129      *this,
130      Send(Property(&IPC::Message::type,
131                    static_cast<int32>(ServiceMsg_GetCloudPrintProxyInfo::ID))))
132      .Times(1).WillOnce(
133          DoAll(
134              DeleteArg<0>(),
135              WithoutArgs(
136                  Invoke(this, &MockServiceProcessControl::SendDisabledInfo))));
137}
138
139void MockServiceProcessControl::SetWillBeEnabledExpectations() {
140  int32 message_id = ServiceMsg_EnableCloudPrintProxyWithRobot::ID;
141  EXPECT_CALL(
142      *this,
143      Send(Property(&IPC::Message::type, message_id)))
144      .Times(1).WillOnce(DoAll(DeleteArg<0>(), Return(true)));
145}
146
147void MockServiceProcessControl::SetWillBeDisabledExpectations() {
148  EXPECT_CALL(
149      *this,
150      Send(Property(&IPC::Message::type,
151                    static_cast<int32>(ServiceMsg_DisableCloudPrintProxy::ID))))
152      .Times(1).WillOnce(DoAll(DeleteArg<0>(), Return(true)));
153}
154
155bool MockServiceProcessControl::SendEnabledInfo() {
156  info_.enabled = true;
157  info_.email = EnabledUserId();
158  PostTask(base::Bind(&MockServiceProcessControl::OnCloudPrintProxyInfo,
159                      base::Unretained(this), info_));
160  return true;
161}
162
163bool MockServiceProcessControl::SendDisabledInfo() {
164  info_.enabled = false;
165  info_.email = std::string();
166  PostTask(base::Bind(&MockServiceProcessControl::OnCloudPrintProxyInfo,
167                      base::Unretained(this), info_));
168  return true;
169}
170
171class TestCloudPrintProxyService : public CloudPrintProxyService {
172 public:
173  explicit TestCloudPrintProxyService(Profile* profile)
174      : CloudPrintProxyService(profile) { }
175
176  void Initialize() {
177    CloudPrintProxyService::Initialize();
178    base::RunLoop().RunUntilIdle();
179  }
180
181  void RefreshStatusFromService() {
182    CloudPrintProxyService::RefreshStatusFromService();
183    base::RunLoop().RunUntilIdle();
184  }
185
186  virtual ServiceProcessControl* GetServiceProcessControl() OVERRIDE {
187    return &process_control_;
188  }
189  MockServiceProcessControl* GetMockServiceProcessControl() {
190    return &process_control_;
191  }
192
193  void EnableForUser() {
194    EnableForUserWithRobot("123", "123@gmail.com",
195                           MockServiceProcessControl::EnabledUserId(),
196                           base::DictionaryValue());
197  }
198
199 private:
200  MockServiceProcessControl process_control_;
201};
202
203class CloudPrintProxyPolicyTest : public ::testing::Test {
204 public:
205  CloudPrintProxyPolicyTest()
206      : ui_thread_(content::BrowserThread::UI, &message_loop_) {
207  }
208
209  bool LaunchBrowser(const CommandLine& command_line, Profile* profile) {
210    int return_code = 0;
211    StartupBrowserCreator browser_creator;
212    return StartupBrowserCreator::ProcessCmdLineImpl(
213        command_line, base::FilePath(), false, profile,
214        StartupBrowserCreator::Profiles(), &return_code, &browser_creator);
215  }
216
217 protected:
218  base::MessageLoopForUI message_loop_;
219  content::TestBrowserThread ui_thread_;
220  TestingProfile profile_;
221};
222
223TEST_F(CloudPrintProxyPolicyTest, VerifyExpectations) {
224  MockServiceProcessControl mock_control;
225  mock_control.SetConnectSuccessMockExpectations(
226      MockServiceProcessControl::kServiceStateNone, false);
227
228  EXPECT_FALSE(mock_control.IsConnected());
229  mock_control.Launch(base::Closure(), base::Closure());
230  EXPECT_TRUE(mock_control.IsConnected());
231  mock_control.Launch(base::Closure(), base::Closure());
232  EXPECT_TRUE(mock_control.IsConnected());
233  mock_control.Disconnect();
234  EXPECT_FALSE(mock_control.IsConnected());
235}
236
237TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyDisabled) {
238  TestCloudPrintProxyService service(&profile_);
239
240  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
241      MockServiceProcessControl::kServiceStateDisabled, false);
242
243  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
244  prefs->SetUserPref(
245      prefs::kCloudPrintEmail,
246      new base::StringValue(MockServiceProcessControl::EnabledUserId()));
247
248  service.Initialize();
249
250  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
251}
252
253TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyEnabled) {
254  TestCloudPrintProxyService service(&profile_);
255
256  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
257      MockServiceProcessControl::kServiceStateEnabled, false);
258
259  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
260  prefs->SetUserPref(prefs::kCloudPrintEmail,
261                     new base::StringValue(std::string()));
262
263  service.Initialize();
264  service.RefreshStatusFromService();
265
266  EXPECT_EQ(MockServiceProcessControl::EnabledUserId(),
267            prefs->GetString(prefs::kCloudPrintEmail));
268}
269
270TEST_F(CloudPrintProxyPolicyTest, StartWithPolicySetProxyDisabled) {
271  TestCloudPrintProxyService service(&profile_);
272
273  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
274      MockServiceProcessControl::kServiceStateDisabled, false);
275
276  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
277  prefs->SetUserPref(prefs::kCloudPrintEmail,
278                     new base::StringValue(std::string()));
279  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
280                        new base::FundamentalValue(false));
281
282  service.Initialize();
283
284  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
285}
286
287TEST_F(CloudPrintProxyPolicyTest, StartWithPolicySetProxyEnabled) {
288  TestCloudPrintProxyService service(&profile_);
289
290  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
291      MockServiceProcessControl::kServiceStateEnabled, false);
292  service.GetMockServiceProcessControl()->SetWillBeDisabledExpectations();
293
294  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
295  prefs->SetUserPref(prefs::kCloudPrintEmail,
296                     new base::StringValue(std::string()));
297  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
298                        new base::FundamentalValue(false));
299
300  service.Initialize();
301
302  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
303}
304
305TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyDisabledThenSetPolicy) {
306  TestCloudPrintProxyService service(&profile_);
307
308  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
309      MockServiceProcessControl::kServiceStateDisabled, false);
310
311  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
312  prefs->SetUserPref(
313      prefs::kCloudPrintEmail,
314      new base::StringValue(MockServiceProcessControl::EnabledUserId()));
315
316  service.Initialize();
317
318  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
319
320  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
321                        new base::FundamentalValue(false));
322
323  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
324}
325
326TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyEnabledThenSetPolicy) {
327  TestCloudPrintProxyService service(&profile_);
328
329  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
330      MockServiceProcessControl::kServiceStateEnabled, false);
331
332  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
333  prefs->SetUserPref(prefs::kCloudPrintEmail,
334                     new base::StringValue(std::string()));
335
336  service.Initialize();
337  service.RefreshStatusFromService();
338
339  EXPECT_EQ(MockServiceProcessControl::EnabledUserId(),
340            prefs->GetString(prefs::kCloudPrintEmail));
341
342  service.GetMockServiceProcessControl()->SetWillBeDisabledExpectations();
343  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
344                        new base::FundamentalValue(false));
345
346  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
347}
348
349TEST_F(CloudPrintProxyPolicyTest,
350       StartWithPolicySetProxyDisabledThenClearPolicy) {
351  TestCloudPrintProxyService service(&profile_);
352
353  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
354      MockServiceProcessControl::kServiceStateDisabled, false);
355
356  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
357  prefs->SetUserPref(prefs::kCloudPrintEmail,
358                     new base::StringValue(std::string()));
359  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
360                        new base::FundamentalValue(false));
361
362  service.Initialize();
363
364  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
365  prefs->RemoveManagedPref(prefs::kCloudPrintProxyEnabled);
366  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
367}
368
369TEST_F(CloudPrintProxyPolicyTest,
370       StartWithPolicySetProxyEnabledThenClearPolicy) {
371  TestCloudPrintProxyService service(&profile_);
372
373  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
374      MockServiceProcessControl::kServiceStateEnabled, false);
375  service.GetMockServiceProcessControl()->SetWillBeDisabledExpectations();
376
377  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
378  prefs->SetUserPref(prefs::kCloudPrintEmail,
379                     new base::StringValue(std::string()));
380  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
381                        new base::FundamentalValue(false));
382
383  service.Initialize();
384
385  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
386  prefs->RemoveManagedPref(prefs::kCloudPrintProxyEnabled);
387  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
388}
389
390TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyDisabledThenEnable) {
391  TestCloudPrintProxyService service(&profile_);
392
393  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
394      MockServiceProcessControl::kServiceStateDisabled, false);
395
396  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
397  prefs->SetUserPref(
398      prefs::kCloudPrintEmail,
399      new base::StringValue(MockServiceProcessControl::EnabledUserId()));
400
401  service.Initialize();
402  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
403
404  service.GetMockServiceProcessControl()->SetWillBeEnabledExpectations();
405  service.EnableForUser();
406
407  EXPECT_EQ(MockServiceProcessControl::EnabledUserId(),
408            prefs->GetString(prefs::kCloudPrintEmail));
409}
410
411TEST_F(CloudPrintProxyPolicyTest,
412       StartWithPolicySetProxyEnabledThenClearPolicyAndEnable) {
413  TestCloudPrintProxyService service(&profile_);
414
415  service.GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
416      MockServiceProcessControl::kServiceStateEnabled, false);
417  service.GetMockServiceProcessControl()->SetWillBeDisabledExpectations();
418
419  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
420  prefs->SetUserPref(prefs::kCloudPrintEmail,
421                     new base::StringValue(std::string()));
422  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
423                        new base::FundamentalValue(false));
424
425  service.Initialize();
426
427  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
428  service.EnableForUser();
429  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
430
431  prefs->RemoveManagedPref(prefs::kCloudPrintProxyEnabled);
432  EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
433
434  service.GetMockServiceProcessControl()->SetWillBeEnabledExpectations();
435  service.EnableForUser();
436
437  EXPECT_EQ(MockServiceProcessControl::EnabledUserId(),
438            prefs->GetString(prefs::kCloudPrintEmail));
439}
440
441KeyedService* TestCloudPrintProxyServiceFactory(
442    content::BrowserContext* profile) {
443  TestCloudPrintProxyService* service =
444      new TestCloudPrintProxyService(static_cast<Profile*>(profile));
445
446  service->GetMockServiceProcessControl()->SetConnectSuccessMockExpectations(
447      MockServiceProcessControl::kServiceStateEnabled, true);
448  service->GetMockServiceProcessControl()->SetWillBeDisabledExpectations();
449
450  service->Initialize();
451  return service;
452}
453
454TEST_F(CloudPrintProxyPolicyTest, StartupBrowserCreatorWithCommandLine) {
455  TestingPrefServiceSyncable* prefs = profile_.GetTestingPrefService();
456  prefs->SetUserPref(prefs::kCloudPrintEmail,
457                     new base::StringValue(std::string()));
458  prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
459                        new base::FundamentalValue(false));
460
461  CloudPrintProxyServiceFactory::GetInstance()->
462      SetTestingFactory(&profile_, TestCloudPrintProxyServiceFactory);
463
464  CommandLine command_line(CommandLine::NO_PROGRAM);
465  command_line.AppendSwitch(switches::kCheckCloudPrintConnectorPolicy);
466
467  EXPECT_FALSE(LaunchBrowser(command_line, &profile_));
468  base::RunLoop().RunUntilIdle();
469}
470