1 // Copyright (c) 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.
5 #include "chrome/browser/chromeos/policy/status_uploader.h"
10 #include "base/bind_helpers.h"
11 #include "base/location.h"
12 #include "base/sequenced_task_runner.h"
13 #include "chrome/browser/chromeos/policy/device_status_collector.h"
14 #include "chromeos/settings/cros_settings_names.h"
15 #include "chromeos/settings/cros_settings_provider.h"
16 #include "components/policy/core/common/cloud/cloud_policy_client.h"
17 #include "components/policy/core/common/cloud/device_management_service.h"
20 const int kMinUploadDelayMs
= 60 * 1000; // 60 seconds
25 const int64
StatusUploader::kDefaultUploadDelayMs
=
26 3 * 60 * 60 * 1000; // 3 hours
28 StatusUploader::StatusUploader(
29 CloudPolicyClient
* client
,
30 scoped_ptr
<DeviceStatusCollector
> collector
,
31 const scoped_refptr
<base::SequencedTaskRunner
>& task_runner
)
33 collector_(collector
.Pass()),
34 task_runner_(task_runner
),
35 upload_frequency_(base::TimeDelta::FromMilliseconds(
36 kDefaultUploadDelayMs
)),
38 // StatusUploader is currently only created for registered clients, and
39 // it is currently safe to assume that the client will not unregister while
40 // StatusUploader is alive.
42 // If future changes result in StatusUploader's lifetime extending beyond
43 // unregistration events, then this class should be updated
44 // to skip status uploads for unregistered clients, and to observe the client
45 // and kick off an upload when registration happens.
46 DCHECK(client
->is_registered());
48 // Listen for changes to the upload delay, and start sending updates to the
50 upload_frequency_observer_
=
51 chromeos::CrosSettings::Get()->AddSettingsObserver(
52 chromeos::kReportUploadFrequency
,
53 base::Bind(&StatusUploader::RefreshUploadFrequency
,
54 base::Unretained(this)));
56 // Update the upload frequency from settings.
57 RefreshUploadFrequency();
59 // Immediately schedule our next status upload (last_upload_ is set to the
60 // start of the epoch, so this will trigger an update in the immediate
62 ScheduleNextStatusUpload();
65 StatusUploader::~StatusUploader() {
68 void StatusUploader::ScheduleNextStatusUpload() {
69 // Calculate when to fire off the next update (if it should have already
70 // happened, this yields a TimeDelta of 0).
71 base::TimeDelta delay
= std::max(
72 (last_upload_
+ upload_frequency_
) - base::Time::NowFromSystemTime(),
74 upload_callback_
.Reset(base::Bind(&StatusUploader::UploadStatus
,
75 base::Unretained(this)));
76 task_runner_
->PostDelayedTask(FROM_HERE
, upload_callback_
.callback(), delay
);
79 void StatusUploader::RefreshUploadFrequency() {
80 // Attempt to fetch the current value of the reporting settings.
81 // If trusted values are not available, register this function to be called
82 // back when they are available.
83 chromeos::CrosSettings
* settings
= chromeos::CrosSettings::Get();
84 if (chromeos::CrosSettingsProvider::TRUSTED
!= settings
->PrepareTrustedValues(
85 base::Bind(&StatusUploader::RefreshUploadFrequency
,
86 weak_factory_
.GetWeakPtr()))) {
90 // CrosSettings are trusted - update our cached upload_frequency (we cache the
91 // value because CrosSettings can become untrusted at arbitrary times and we
92 // want to use the last trusted value).
94 if (settings
->GetInteger(chromeos::kReportUploadFrequency
, &frequency
)) {
95 upload_frequency_
= base::TimeDelta::FromMilliseconds(
96 std::max(kMinUploadDelayMs
, frequency
));
99 // Schedule a new upload with the new frequency - only do this if we've
100 // already performed the initial upload, because we want the initial upload
101 // to happen immediately on startup and not get cancelled by settings changes.
102 if (!last_upload_
.is_null())
103 ScheduleNextStatusUpload();
106 void StatusUploader::UploadStatus() {
107 enterprise_management::DeviceStatusReportRequest device_status
;
108 bool have_device_status
= collector_
->GetDeviceStatus(&device_status
);
109 enterprise_management::SessionStatusReportRequest session_status
;
110 bool have_session_status
= collector_
->GetDeviceSessionStatus(
112 if (!have_device_status
&& !have_session_status
) {
113 // Don't have any status to upload - just set our timer for next time.
114 last_upload_
= base::Time::NowFromSystemTime();
115 ScheduleNextStatusUpload();
119 client_
->UploadDeviceStatus(
120 have_device_status
? &device_status
: nullptr,
121 have_session_status
? &session_status
: nullptr,
122 base::Bind(&StatusUploader::OnUploadCompleted
,
123 weak_factory_
.GetWeakPtr()));
126 void StatusUploader::OnUploadCompleted(bool success
) {
127 // Set the last upload time, regardless of whether the upload was successful
128 // or not (we don't change the time of the next upload based on whether this
129 // upload succeeded or not - if a status upload fails, we just skip it and
130 // wait until it's time to try again.
131 last_upload_
= base::Time::NowFromSystemTime();
133 // If the upload was successful, tell the collector so it can clear its cache
136 collector_
->OnSubmittedSuccessfully();
138 ScheduleNextStatusUpload();
141 } // namespace policy