blob: 78f87cb0ead5e3f4ca66209c769da07223300fb4 [file] [log] [blame]
Anton Muhin59755522014-11-05 21:30:12 +04001// Copyright 2014 The Chromium OS 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 "buffet/commands/cloud_command_proxy.h"
6
Alex Vakulenkob211c102015-04-21 11:43:23 -07007#include <base/message_loop/message_loop.h>
8
Anton Muhin59755522014-11-05 21:30:12 +04009#include "buffet/commands/command_instance.h"
10#include "buffet/commands/prop_constraints.h"
11#include "buffet/commands/prop_types.h"
Vitaly Buka906d39e2015-03-24 10:08:26 -070012#include "buffet/commands/schema_constants.h"
Anton Muhin59755522014-11-05 21:30:12 +040013#include "buffet/device_registration_info.h"
14
15namespace buffet {
16
Alex Vakulenkob211c102015-04-21 11:43:23 -070017namespace {
18// Bits used in CommandUpdateFlags for various command resource parts.
19enum {
20 kFlagResults,
21 kFlagState,
22 kFlagProgress
23};
24
25// Retry timeout for re-sending failed command update request.
26static const int64_t kCommandUpdateRetryTimeoutSeconds = 5;
27
28} // anonymous namespace
29
Anton Muhin59755522014-11-05 21:30:12 +040030CloudCommandProxy::CloudCommandProxy(
31 CommandInstance* command_instance,
32 DeviceRegistrationInfo* device_registration_info)
33 : command_instance_(command_instance),
34 device_registration_info_(device_registration_info) {
35}
36
Alex Vakulenkob211c102015-04-21 11:43:23 -070037void CloudCommandProxy::OnResultsChanged() {
38 new_pending_command_updates_.set(kFlagResults);
39 SendCommandUpdate();
Anton Muhincfde8692014-11-25 03:36:59 +040040}
41
Alex Vakulenkob211c102015-04-21 11:43:23 -070042void CloudCommandProxy::OnStatusChanged() {
43 new_pending_command_updates_.set(kFlagState);
44 SendCommandUpdate();
Anton Muhin59755522014-11-05 21:30:12 +040045}
46
Alex Vakulenkob211c102015-04-21 11:43:23 -070047void CloudCommandProxy::OnProgressChanged() {
48 new_pending_command_updates_.set(kFlagProgress);
49 SendCommandUpdate();
50}
51
52void CloudCommandProxy::SendCommandUpdate() {
53 if (command_update_in_progress_ || new_pending_command_updates_.none())
54 return;
55
Anton Muhin59755522014-11-05 21:30:12 +040056 base::DictionaryValue patch;
Alex Vakulenkob211c102015-04-21 11:43:23 -070057 if (new_pending_command_updates_.test(kFlagResults)) {
58 auto json = TypedValueToJson(command_instance_->GetResults(), nullptr);
59 patch.Set(commands::attributes::kCommand_Results, json.release());
60 }
61
62 if (new_pending_command_updates_.test(kFlagState)) {
63 patch.SetString(commands::attributes::kCommand_State,
64 command_instance_->GetStatus());
65 }
66
67 if (new_pending_command_updates_.test(kFlagProgress)) {
Vitaly Buka4129dfa2015-04-29 12:16:58 -070068 auto json = TypedValueToJson(command_instance_->GetProgress(), nullptr);
69 patch.Set(commands::attributes::kCommand_Progress, json.release());
Alex Vakulenkob211c102015-04-21 11:43:23 -070070 }
71 command_update_in_progress_ = true;
72 in_progress_command_updates_ = new_pending_command_updates_;
73 new_pending_command_updates_.reset();
74 device_registration_info_->UpdateCommand(
75 command_instance_->GetID(), patch,
76 base::Bind(&CloudCommandProxy::OnUpdateCommandFinished,
77 weak_ptr_factory_.GetWeakPtr(), true),
78 base::Bind(&CloudCommandProxy::OnUpdateCommandFinished,
79 weak_ptr_factory_.GetWeakPtr(), false));
80}
81
82void CloudCommandProxy::ResendCommandUpdate() {
83 command_update_in_progress_ = false;
84 SendCommandUpdate();
85}
86
87void CloudCommandProxy::OnUpdateCommandFinished(bool success) {
88 if (success) {
89 command_update_in_progress_ = false;
90 // If previous update was successful, and we have new pending updates,
91 // send a new request to the server immediately.
92 SendCommandUpdate();
93 } else {
94 // If previous request failed, re-send the old data as well.
95 new_pending_command_updates_ |= in_progress_command_updates_;
96 auto message_loop = base::MessageLoop::current();
97 if (message_loop == nullptr) {
98 // Assume we are in unit tests, resend the request immediately...
99 ResendCommandUpdate();
100 } else {
101 // Resend the request to the server after a pre-set delay...
102 message_loop->PostDelayedTask(
103 FROM_HERE,
104 base::Bind(&CloudCommandProxy::ResendCommandUpdate,
105 weak_ptr_factory_.GetWeakPtr()),
106 base::TimeDelta::FromSeconds(kCommandUpdateRetryTimeoutSeconds));
107 }
108 }
Anton Muhin59755522014-11-05 21:30:12 +0400109}
110
111} // namespace buffet