device_status_collector_browsertest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/chromeos/policy/device_status_collector.h"
6
7#include "base/environment.h"
8#include "base/logging.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/message_loop.h"
11#include "base/prefs/pref_service.h"
12#include "base/prefs/testing_pref_service.h"
13#include "base/threading/sequenced_worker_pool.h"
14#include "chrome/browser/chromeos/settings/cros_settings.h"
15#include "chrome/browser/chromeos/settings/cros_settings_names.h"
16#include "chrome/browser/chromeos/settings/cros_settings_provider.h"
17#include "chrome/browser/chromeos/settings/device_settings_service.h"
18#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
19#include "chrome/browser/chromeos/system/mock_statistics_provider.h"
20#include "chrome/browser/chromeos/system/statistics_provider.h"
21#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
22#include "chrome/common/pref_names.h"
23#include "content/public/browser/browser_thread.h"
24#include "content/public/browser/geolocation_provider.h"
25#include "content/public/test/test_browser_thread.h"
26#include "content/public/test/test_utils.h"
27#include "testing/gmock/include/gmock/gmock.h"
28#include "testing/gtest/include/gtest/gtest.h"
29
30using ::testing::DoAll;
31using ::testing::NotNull;
32using ::testing::Return;
33using ::testing::SetArgPointee;
34using ::testing::_;
35using base::Time;
36using base::TimeDelta;
37
38namespace em = enterprise_management;
39
40namespace {
41
42const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000;
43
44scoped_ptr<content::Geoposition> mock_position_to_return_next;
45
46void SetMockPositionToReturnNext(const content::Geoposition &position) {
47  mock_position_to_return_next.reset(new content::Geoposition(position));
48}
49
50void MockPositionUpdateRequester(
51    const content::GeolocationProvider::LocationUpdateCallback& callback) {
52  if (!mock_position_to_return_next.get())
53    return;
54
55  // If the fix is invalid, the DeviceStatusCollector will immediately request
56  // another update when it receives the callback. This is desirable and safe in
57  // real life where geolocation updates arrive asynchronously. In this testing
58  // harness, the callback is invoked synchronously upon request, leading to a
59  // request-callback loop. The loop is broken by returning the mock position
60  // only once.
61  scoped_ptr<content::Geoposition> position(
62      mock_position_to_return_next.release());
63  callback.Run(*position);
64}
65
66class TestingDeviceStatusCollector : public policy::DeviceStatusCollector {
67 public:
68  TestingDeviceStatusCollector(
69      PrefService* local_state,
70      chromeos::system::StatisticsProvider* provider,
71      policy::DeviceStatusCollector::LocationUpdateRequester*
72          location_update_requester)
73      : policy::DeviceStatusCollector(
74          local_state,
75          provider,
76          location_update_requester) {
77    // Set the baseline time to a fixed value (1 AM) to prevent test flakiness
78    // due to a single activity period spanning two days.
79    SetBaselineTime(Time::Now().LocalMidnight() + TimeDelta::FromHours(1));
80  }
81
82  void Simulate(IdleState* states, int len) {
83    for (int i = 0; i < len; i++)
84      IdleStateCallback(states[i]);
85  }
86
87  void set_max_stored_past_activity_days(unsigned int value) {
88    max_stored_past_activity_days_ = value;
89  }
90
91  void set_max_stored_future_activity_days(unsigned int value) {
92    max_stored_future_activity_days_ = value;
93  }
94
95  // Reset the baseline time.
96  void SetBaselineTime(Time time) {
97    baseline_time_ = time;
98    baseline_offset_periods_ = 0;
99  }
100
101 protected:
102  virtual void CheckIdleState() OVERRIDE {
103    // This should never be called in testing, as it results in a dbus call.
104    ADD_FAILURE();
105  }
106
107  // Each time this is called, returns a time that is a fixed increment
108  // later than the previous time.
109  virtual Time GetCurrentTime() OVERRIDE {
110    int poll_interval = policy::DeviceStatusCollector::kIdlePollIntervalSeconds;
111    return baseline_time_ +
112        TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++);
113  }
114
115 private:
116  // Baseline time for the fake times returned from GetCurrentTime().
117  Time baseline_time_;
118
119  // The number of simulated periods since the baseline time.
120  int baseline_offset_periods_;
121};
122
123// Return the total number of active milliseconds contained in a device
124// status report.
125int64 GetActiveMilliseconds(em::DeviceStatusReportRequest& status) {
126  int64 active_milliseconds = 0;
127  for (int i = 0; i < status.active_period_size(); i++) {
128    active_milliseconds += status.active_period(i).active_duration();
129  }
130  return active_milliseconds;
131}
132
133}  // namespace
134
135namespace policy {
136
137// Though it is a unit test, this test is linked with browser_tests so that it
138// runs in a separate process. The intention is to avoid overriding the timezone
139// environment variable for other tests.
140class DeviceStatusCollectorTest : public testing::Test {
141 public:
142  DeviceStatusCollectorTest()
143    : message_loop_(base::MessageLoop::TYPE_UI),
144      ui_thread_(content::BrowserThread::UI, &message_loop_),
145      file_thread_(content::BrowserThread::FILE, &message_loop_),
146      io_thread_(content::BrowserThread::IO, &message_loop_) {
147    // Run this test with a well-known timezone so that Time::LocalMidnight()
148    // returns the same values on all machines.
149    scoped_ptr<base::Environment> env(base::Environment::Create());
150    env->SetVar("TZ", "UTC");
151
152    TestingDeviceStatusCollector::RegisterPrefs(prefs_.registry());
153
154    EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, NotNull()))
155        .WillRepeatedly(Return(false));
156
157    // Remove the real DeviceSettingsProvider and replace it with a stub.
158    cros_settings_ = chromeos::CrosSettings::Get();
159    device_settings_provider_ =
160        cros_settings_->GetProvider(chromeos::kReportDeviceVersionInfo);
161    EXPECT_TRUE(device_settings_provider_ != NULL);
162    EXPECT_TRUE(
163        cros_settings_->RemoveSettingsProvider(device_settings_provider_));
164    cros_settings_->AddSettingsProvider(&stub_settings_provider_);
165
166    RestartStatusCollector();
167  }
168
169  virtual ~DeviceStatusCollectorTest() {
170    // Finish pending tasks.
171    content::BrowserThread::GetBlockingPool()->FlushForTesting();
172    message_loop_.RunUntilIdle();
173
174    // Restore the real DeviceSettingsProvider.
175    EXPECT_TRUE(
176      cros_settings_->RemoveSettingsProvider(&stub_settings_provider_));
177    cros_settings_->AddSettingsProvider(device_settings_provider_);
178  }
179
180  void RestartStatusCollector() {
181    policy::DeviceStatusCollector::LocationUpdateRequester callback =
182        base::Bind(&MockPositionUpdateRequester);
183    status_collector_.reset(
184        new TestingDeviceStatusCollector(&prefs_,
185                                         &statistics_provider_,
186                                         &callback));
187  }
188
189  void GetStatus() {
190    status_.Clear();
191    status_collector_->GetDeviceStatus(&status_);
192  }
193
194  void CheckThatNoLocationIsReported() {
195    GetStatus();
196    EXPECT_FALSE(status_.has_device_location());
197  }
198
199  void CheckThatAValidLocationIsReported() {
200    // Checks that a location is being reported which matches the valid fix
201    // set using SetMockPositionToReturnNext().
202    GetStatus();
203    EXPECT_TRUE(status_.has_device_location());
204    em::DeviceLocation location = status_.device_location();
205    if (location.has_error_code())
206      EXPECT_EQ(em::DeviceLocation::ERROR_CODE_NONE, location.error_code());
207    EXPECT_TRUE(location.has_latitude());
208    EXPECT_TRUE(location.has_longitude());
209    EXPECT_TRUE(location.has_accuracy());
210    EXPECT_TRUE(location.has_timestamp());
211    EXPECT_FALSE(location.has_altitude());
212    EXPECT_FALSE(location.has_altitude_accuracy());
213    EXPECT_FALSE(location.has_heading());
214    EXPECT_FALSE(location.has_speed());
215    EXPECT_FALSE(location.has_error_message());
216    EXPECT_DOUBLE_EQ(4.3, location.latitude());
217    EXPECT_DOUBLE_EQ(-7.8, location.longitude());
218    EXPECT_DOUBLE_EQ(3., location.accuracy());
219    // Check that the timestamp is not older than ten minutes.
220    EXPECT_TRUE(Time::Now() - Time::FromDoubleT(location.timestamp() / 1000.) <
221                TimeDelta::FromMinutes(10));
222  }
223
224  void CheckThatALocationErrorIsReported() {
225    GetStatus();
226    EXPECT_TRUE(status_.has_device_location());
227    em::DeviceLocation location = status_.device_location();
228    EXPECT_TRUE(location.has_error_code());
229    EXPECT_EQ(em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE,
230              location.error_code());
231  }
232
233 protected:
234  // Convenience method.
235  int64 ActivePeriodMilliseconds() {
236    return policy::DeviceStatusCollector::kIdlePollIntervalSeconds * 1000;
237  }
238
239  base::MessageLoop message_loop_;
240  content::TestBrowserThread ui_thread_;
241  content::TestBrowserThread file_thread_;
242  content::TestBrowserThread io_thread_;
243
244  TestingPrefServiceSimple prefs_;
245  chromeos::system::MockStatisticsProvider statistics_provider_;
246  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
247  chromeos::ScopedTestCrosSettings test_cros_settings_;
248  chromeos::CrosSettings* cros_settings_;
249  chromeos::CrosSettingsProvider* device_settings_provider_;
250  chromeos::StubCrosSettingsProvider stub_settings_provider_;
251  em::DeviceStatusReportRequest status_;
252  scoped_ptr<TestingDeviceStatusCollector> status_collector_;
253};
254
255TEST_F(DeviceStatusCollectorTest, AllIdle) {
256  IdleState test_states[] = {
257    IDLE_STATE_IDLE,
258    IDLE_STATE_IDLE,
259    IDLE_STATE_IDLE
260  };
261  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
262
263  // Test reporting with no data.
264  GetStatus();
265  EXPECT_EQ(0, status_.active_period_size());
266  EXPECT_EQ(0, GetActiveMilliseconds(status_));
267
268  // Test reporting with a single idle sample.
269  status_collector_->Simulate(test_states, 1);
270  GetStatus();
271  EXPECT_EQ(0, status_.active_period_size());
272  EXPECT_EQ(0, GetActiveMilliseconds(status_));
273
274  // Test reporting with multiple consecutive idle samples.
275  status_collector_->Simulate(test_states,
276                              sizeof(test_states) / sizeof(IdleState));
277  GetStatus();
278  EXPECT_EQ(0, status_.active_period_size());
279  EXPECT_EQ(0, GetActiveMilliseconds(status_));
280}
281
282TEST_F(DeviceStatusCollectorTest, AllActive) {
283  IdleState test_states[] = {
284    IDLE_STATE_ACTIVE,
285    IDLE_STATE_ACTIVE,
286    IDLE_STATE_ACTIVE
287  };
288  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
289
290  // Test a single active sample.
291  status_collector_->Simulate(test_states, 1);
292  GetStatus();
293  EXPECT_EQ(1, status_.active_period_size());
294  EXPECT_EQ(1 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
295  status_.clear_active_period(); // Clear the result protobuf.
296
297  // Test multiple consecutive active samples.
298  status_collector_->Simulate(test_states,
299                              sizeof(test_states) / sizeof(IdleState));
300  GetStatus();
301  EXPECT_EQ(1, status_.active_period_size());
302  EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
303}
304
305TEST_F(DeviceStatusCollectorTest, MixedStates) {
306  IdleState test_states[] = {
307    IDLE_STATE_ACTIVE,
308    IDLE_STATE_IDLE,
309    IDLE_STATE_ACTIVE,
310    IDLE_STATE_ACTIVE,
311    IDLE_STATE_IDLE,
312    IDLE_STATE_IDLE,
313    IDLE_STATE_ACTIVE
314  };
315  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
316  status_collector_->Simulate(test_states,
317                              sizeof(test_states) / sizeof(IdleState));
318  GetStatus();
319  EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
320}
321
322TEST_F(DeviceStatusCollectorTest, StateKeptInPref) {
323  IdleState test_states[] = {
324    IDLE_STATE_ACTIVE,
325    IDLE_STATE_IDLE,
326    IDLE_STATE_ACTIVE,
327    IDLE_STATE_ACTIVE,
328    IDLE_STATE_IDLE,
329    IDLE_STATE_IDLE
330  };
331  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
332  status_collector_->Simulate(test_states,
333                              sizeof(test_states) / sizeof(IdleState));
334
335  // Process the list a second time after restarting the collector. It should be
336  // able to count the active periods found by the original collector, because
337  // the results are stored in a pref.
338  RestartStatusCollector();
339  status_collector_->Simulate(test_states,
340                              sizeof(test_states) / sizeof(IdleState));
341
342  GetStatus();
343  EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
344}
345
346TEST_F(DeviceStatusCollectorTest, Times) {
347  IdleState test_states[] = {
348    IDLE_STATE_ACTIVE,
349    IDLE_STATE_IDLE,
350    IDLE_STATE_ACTIVE,
351    IDLE_STATE_ACTIVE,
352    IDLE_STATE_IDLE,
353    IDLE_STATE_IDLE
354  };
355  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
356  status_collector_->Simulate(test_states,
357                              sizeof(test_states) / sizeof(IdleState));
358  GetStatus();
359  EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
360}
361
362TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) {
363  IdleState test_states[] = {
364    IDLE_STATE_ACTIVE,
365    IDLE_STATE_IDLE
366  };
367  const int kMaxDays = 10;
368
369  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
370  status_collector_->set_max_stored_past_activity_days(kMaxDays - 1);
371  status_collector_->set_max_stored_future_activity_days(1);
372  Time baseline = Time::Now().LocalMidnight();
373
374  // Simulate 12 active periods.
375  for (int i = 0; i < kMaxDays + 2; i++) {
376    status_collector_->Simulate(test_states,
377                                sizeof(test_states) / sizeof(IdleState));
378    // Advance the simulated clock by a day.
379    baseline += TimeDelta::FromDays(1);
380    status_collector_->SetBaselineTime(baseline);
381  }
382
383  // Check that we don't exceed the max number of periods.
384  GetStatus();
385  EXPECT_EQ(kMaxDays - 1, status_.active_period_size());
386
387  // Simulate some future times.
388  for (int i = 0; i < kMaxDays + 2; i++) {
389    status_collector_->Simulate(test_states,
390                                sizeof(test_states) / sizeof(IdleState));
391    // Advance the simulated clock by a day.
392    baseline += TimeDelta::FromDays(1);
393    status_collector_->SetBaselineTime(baseline);
394  }
395  // Set the clock back so the previous simulated times are in the future.
396  baseline -= TimeDelta::FromDays(20);
397  status_collector_->SetBaselineTime(baseline);
398
399  // Collect one more data point to trigger pruning.
400  status_collector_->Simulate(test_states, 1);
401
402  // Check that we don't exceed the max number of periods.
403  status_.clear_active_period();
404  GetStatus();
405  EXPECT_LT(status_.active_period_size(), kMaxDays);
406}
407
408TEST_F(DeviceStatusCollectorTest, ActivityTimesDisabledByDefault) {
409  // If the pref for collecting device activity times isn't explicitly turned
410  // on, no data on activity times should be reported.
411
412  IdleState test_states[] = {
413    IDLE_STATE_ACTIVE,
414    IDLE_STATE_ACTIVE,
415    IDLE_STATE_ACTIVE
416  };
417  status_collector_->Simulate(test_states,
418                              sizeof(test_states) / sizeof(IdleState));
419  GetStatus();
420  EXPECT_EQ(0, status_.active_period_size());
421  EXPECT_EQ(0, GetActiveMilliseconds(status_));
422}
423
424TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) {
425  IdleState test_states[] = {
426    IDLE_STATE_ACTIVE
427  };
428  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
429
430  // Set the baseline time to 10 seconds after midnight.
431  status_collector_->SetBaselineTime(
432      Time::Now().LocalMidnight() + TimeDelta::FromSeconds(10));
433
434  status_collector_->Simulate(test_states, 1);
435  GetStatus();
436  ASSERT_EQ(2, status_.active_period_size());
437
438  em::ActiveTimePeriod period0 = status_.active_period(0);
439  em::ActiveTimePeriod period1 = status_.active_period(1);
440  EXPECT_EQ(ActivePeriodMilliseconds() - 10000, period0.active_duration());
441  EXPECT_EQ(10000, period1.active_duration());
442
443  em::TimePeriod time_period0 = period0.time_period();
444  em::TimePeriod time_period1 = period1.time_period();
445
446  EXPECT_EQ(time_period0.end_timestamp(), time_period1.start_timestamp());
447
448  // Ensure that the start and end times for the period are a day apart.
449  EXPECT_EQ(time_period0.end_timestamp() - time_period0.start_timestamp(),
450            kMillisecondsPerDay);
451  EXPECT_EQ(time_period1.end_timestamp() - time_period1.start_timestamp(),
452            kMillisecondsPerDay);
453}
454
455TEST_F(DeviceStatusCollectorTest, ActivityTimesKeptUntilSubmittedSuccessfully) {
456  IdleState test_states[] = {
457    IDLE_STATE_ACTIVE,
458    IDLE_STATE_ACTIVE,
459  };
460  cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true);
461
462  status_collector_->Simulate(test_states, 2);
463  GetStatus();
464  EXPECT_EQ(2 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
465  em::DeviceStatusReportRequest first_status(status_);
466
467  // The collector returns the same status again.
468  GetStatus();
469  EXPECT_EQ(first_status.SerializeAsString(), status_.SerializeAsString());
470
471  // After indicating a successful submit, the submitted status gets cleared,
472  // but what got collected meanwhile sticks around.
473  status_collector_->Simulate(test_states, 1);
474  status_collector_->OnSubmittedSuccessfully();
475  GetStatus();
476  EXPECT_EQ(ActivePeriodMilliseconds(), GetActiveMilliseconds(status_));
477}
478
479TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) {
480  // Test that boot mode data is not reported if the pref is not turned on.
481  EXPECT_CALL(statistics_provider_,
482              GetMachineStatistic("devsw_boot", NotNull()))
483      .WillRepeatedly(DoAll(SetArgPointee<1>("0"), Return(true)));
484  GetStatus();
485  EXPECT_FALSE(status_.has_boot_mode());
486
487  // Turn the pref on, and check that the status is reported iff the
488  // statistics provider returns valid data.
489  cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, true);
490
491  EXPECT_CALL(statistics_provider_,
492              GetMachineStatistic("devsw_boot", NotNull()))
493      .WillOnce(DoAll(SetArgPointee<1>("(error)"), Return(true)));
494  GetStatus();
495  EXPECT_FALSE(status_.has_boot_mode());
496
497  EXPECT_CALL(statistics_provider_,
498              GetMachineStatistic("devsw_boot", NotNull()))
499      .WillOnce(DoAll(SetArgPointee<1>(" "), Return(true)));
500  GetStatus();
501  EXPECT_FALSE(status_.has_boot_mode());
502
503  EXPECT_CALL(statistics_provider_,
504              GetMachineStatistic("devsw_boot", NotNull()))
505      .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true)));
506  GetStatus();
507  EXPECT_EQ("Verified", status_.boot_mode());
508
509  EXPECT_CALL(statistics_provider_,
510              GetMachineStatistic("devsw_boot", NotNull()))
511      .WillOnce(DoAll(SetArgPointee<1>("1"), Return(true)));
512  GetStatus();
513  EXPECT_EQ("Dev", status_.boot_mode());
514}
515
516TEST_F(DeviceStatusCollectorTest, VersionInfo) {
517  // When the pref to collect this data is not enabled, expect that none of
518  // the fields are present in the protobuf.
519  GetStatus();
520  EXPECT_FALSE(status_.has_browser_version());
521  EXPECT_FALSE(status_.has_os_version());
522  EXPECT_FALSE(status_.has_firmware_version());
523
524  cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, true);
525  GetStatus();
526  EXPECT_TRUE(status_.has_browser_version());
527  EXPECT_TRUE(status_.has_os_version());
528  EXPECT_TRUE(status_.has_firmware_version());
529
530  // Check that the browser version is not empty. OS version & firmware
531  // don't have any reasonable values inside the unit test, so those
532  // aren't checked.
533  EXPECT_NE("", status_.browser_version());
534}
535
536TEST_F(DeviceStatusCollectorTest, Location) {
537  content::Geoposition valid_fix;
538  valid_fix.latitude = 4.3;
539  valid_fix.longitude = -7.8;
540  valid_fix.accuracy = 3.;
541  valid_fix.timestamp = Time::Now();
542
543  content::Geoposition invalid_fix;
544  invalid_fix.error_code =
545      content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
546  invalid_fix.timestamp = Time::Now();
547
548  // Check that when device location reporting is disabled, no location is
549  // reported.
550  SetMockPositionToReturnNext(valid_fix);
551  CheckThatNoLocationIsReported();
552
553  // Check that when device location reporting is enabled and a valid fix is
554  // available, the location is reported and is stored in local state.
555  SetMockPositionToReturnNext(valid_fix);
556  cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true);
557  EXPECT_FALSE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty());
558  CheckThatAValidLocationIsReported();
559
560  // Restart the status collector. Check that the last known location has been
561  // retrieved from local state without requesting a geolocation update.
562  SetMockPositionToReturnNext(valid_fix);
563  RestartStatusCollector();
564  CheckThatAValidLocationIsReported();
565  EXPECT_TRUE(mock_position_to_return_next.get());
566
567  // Check that after disabling location reporting again, the last known
568  // location has been cleared from local state and is no longer reported.
569  SetMockPositionToReturnNext(valid_fix);
570  cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, false);
571  // Allow the new pref to propagate to the status collector.
572  message_loop_.RunUntilIdle();
573  EXPECT_TRUE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty());
574  CheckThatNoLocationIsReported();
575
576  // Check that after enabling location reporting again, an error is reported
577  // if no valid fix is available.
578  SetMockPositionToReturnNext(invalid_fix);
579  cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true);
580  // Allow the new pref to propagate to the status collector.
581  message_loop_.RunUntilIdle();
582  CheckThatALocationErrorIsReported();
583}
584
585}  // namespace policy
586