Merge remote-tracking branch 'weave/master' into 'weave/aosp-master'
4ab5002 Change interface of ClaimRootClientAuthToken and ConfirmAuthToken
c3bc82a Check if device already claimed
34668e7 Reformat
2d24e0e Return Root Client Authorization Token using /privet/v3/accessControl/*
305ab61 Rename ConfirmAuthToken -> ConfirmClientAuthToken
8d0cfef Fix new schema to match the new server definitions
287346b Add "manager" scope into privet API
f3fd9c3 Update format of upsertLocalAuthInfo request
9921b87 Enable component information on device state update patches
5fddf87 Mark request as failed even if server replied with error
3264eca Include build rules for clang with address sanitizer
Change-Id: I2398764e8f4a18ab2b32cd4e57349cd752df0d11
diff --git a/.clang-format b/.clang-format
index 685c597..cff09b2 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,4 +2,7 @@
Language: Cpp
# Usage: git clang-format -f m/master --style=file
BasedOnStyle: Chromium
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
...
diff --git a/examples/daemon/common/daemon.h b/examples/daemon/common/daemon.h
index 5a90988..4cccff3 100644
--- a/examples/daemon/common/daemon.h
+++ b/examples/daemon/common/daemon.h
@@ -70,7 +70,8 @@
Daemon(const Options& opts)
: config_store_{new weave::examples::FileConfigStore(
- opts.disable_security_, opts.model_id_)},
+ opts.disable_security_,
+ opts.model_id_)},
task_runner_{new weave::examples::EventTaskRunner},
http_client_{new weave::examples::CurlHttpClient(task_runner_.get())},
network_{new weave::examples::EventNetworkImpl(task_runner_.get())},
diff --git a/examples/daemon/ledflasher/ledflasher.cc b/examples/daemon/ledflasher/ledflasher.cc
index e63deac..d26728f 100644
--- a/examples/daemon/ledflasher/ledflasher.cc
+++ b/examples/daemon/ledflasher/ledflasher.cc
@@ -18,21 +18,21 @@
const char kTraits[] = R"({
"_ledflasher": {
"commands": {
- "_set": {
+ "set": {
"minimalRole": "user",
"parameters": {
- "_led": {
+ "led": {
"type": "integer",
"minimum": 1,
"maximum": 3
},
- "_on": { "type": "boolean" }
+ "on": { "type": "boolean" }
}
},
- "_toggle": {
+ "toggle": {
"minimalRole": "user",
"parameters": {
- "_led": {
+ "led": {
"type": "integer",
"minimum": 1,
"maximum": 3
@@ -41,7 +41,7 @@
}
},
"state": {
- "_leds": {
+ "leds": {
"type": "array",
"items": { "type": "boolean" }
}
@@ -66,11 +66,11 @@
UpdateLedState();
device->AddCommandHandler(
- kComponent, "_ledflasher._toggle",
+ kComponent, "_ledflasher.toggle",
base::Bind(&LedFlasherHandler::OnFlasherToggleCommand,
weak_ptr_factory_.GetWeakPtr()));
device->AddCommandHandler(
- kComponent, "_ledflasher._set",
+ kComponent, "_ledflasher.set",
base::Bind(&LedFlasherHandler::OnFlasherSetCommand,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -134,7 +134,7 @@
for (uint32_t i = 0; i < led_status_.size(); i++)
list.AppendBoolean(led_status_[i] ? true : false);
- device_->SetStateProperty(kComponent, "_ledflasher._leds", list, nullptr);
+ device_->SetStateProperty(kComponent, "_ledflasher.leds", list, nullptr);
}
weave::Device* device_{nullptr};
diff --git a/examples/daemon/light/light.cc b/examples/daemon/light/light.cc
index eaf9392..298fcaf 100644
--- a/examples/daemon/light/light.cc
+++ b/examples/daemon/light/light.cc
@@ -27,7 +27,8 @@
"state": {
"state": {
"type": "string",
- "enum": [ "on", "standby" ]
+ "enum": [ "on", "standby" ],
+ "isRequired": true
}
}
},
@@ -44,7 +45,14 @@
}
}
},
- "state": { "brightness": { "type": "integer" } }
+ "state": {
+ "brightness": {
+ "type": "integer",
+ "isRequired": true,
+ "minimum": 0,
+ "maximum": 100
+ }
+ }
},
"colorXY": {
"commands": {
@@ -71,11 +79,15 @@
},
"additionalProperties": false
}
- }
+ },
+ "errors": ["colorOutOfRange"]
}
},
"state": {
"colorSetting": {
+ "type": "object",
+ "isRequired": true,
+ "required": [ "colorX", "colorY" ],
"properties": {
"colorX": {
"type": "number",
@@ -90,6 +102,9 @@
}
},
"colorCapRed": {
+ "type": "object",
+ "isRequired": true,
+ "required": [ "colorX", "colorY" ],
"properties": {
"colorX": {
"type": "number",
@@ -104,6 +119,9 @@
}
},
"colorCapGreen": {
+ "type": "object",
+ "isRequired": true,
+ "required": [ "colorX", "colorY" ],
"properties": {
"colorX": {
"type": "number",
@@ -118,6 +136,9 @@
}
},
"colorCapBlue": {
+ "type": "object",
+ "isRequired": true,
+ "required": [ "colorX", "colorY" ],
"properties": {
"colorX": {
"type": "number",
@@ -159,8 +180,8 @@
device->AddTraitDefinitionsFromJson(kTraits);
CHECK(device->AddComponent(kComponent, {"onOff", "brightness", "colorXY"},
nullptr));
- CHECK(device->SetStatePropertiesFromJson(kComponent, kDefaultState,
- nullptr));
+ CHECK(
+ device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
UpdateLightState();
device->AddCommandHandler(kComponent, "onOff.setConfig",
diff --git a/examples/daemon/lock/lock.cc b/examples/daemon/lock/lock.cc
index 61961f0..0785c14 100644
--- a/examples/daemon/lock/lock.cc
+++ b/examples/daemon/lock/lock.cc
@@ -37,15 +37,20 @@
"type": "string",
"enum": [ "locked", "unlocked" ]
}
- }
+ },
+ "errors": ["batteryTooLow", "jammed", "lockingNotSupported"]
}
},
"state": {
"lockedState": {
"type": "string",
- "enum": [ "locked", "unlocked", "partiallyLocked" ]
+ "enum": [ "locked", "unlocked", "partiallyLocked" ],
+ "isRequired": true
},
- "isLockingSupported": { "type": "boolean" }
+ "isLockingSupported": {
+ "type": "boolean",
+ "isRequired": true
+ }
}
}
})";
@@ -68,8 +73,8 @@
device->AddTraitDefinitionsFromJson(kTraits);
CHECK(device->AddComponent(kComponent, {"lock"}, nullptr));
- CHECK(device->SetStatePropertiesFromJson(kComponent, kDefaultState,
- nullptr));
+ CHECK(
+ device->SetStatePropertiesFromJson(kComponent, kDefaultState, nullptr));
UpdateLockState();
device->AddCommandHandler(kComponent, "lock.setConfig",
diff --git a/examples/daemon/oven/oven.cc b/examples/daemon/oven/oven.cc
index 79fc925..ff1c60b 100644
--- a/examples/daemon/oven/oven.cc
+++ b/examples/daemon/oven/oven.cc
@@ -30,7 +30,50 @@
"tempSetting": {
"type": "number"
}
- }
+ },
+ "errors": ["tempOutOfRange", "unsupportedUnits"]
+ }
+ },
+ "state": {
+ "supportedUnits": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [ "celsius", "fahrenheit", "kelvin" ]
+ },
+ "minItems": 1,
+ "uniqueItems": true,
+ "isRequired": true
+ },
+ "units": {
+ "type": "string",
+ "enum": [ "celsius", "fahrenheit", "kelvin" ],
+ "isRequired": true
+ },
+ "tempSetting": {
+ "type": "number",
+ "isRequired": true
+ },
+ "maxTempSetting": {
+ "type": "number",
+ "isRequired": true
+ },
+ "minTempSetting": {
+ "type": "number",
+ "isRequired": true
+ }
+ }
+ },
+ "temperatureSensor": {
+ "commands": {
+ "setConfig": {
+ "minimalRole": "user",
+ "parameters": {
+ "units": {
+ "type": "string"
+ }
+ },
+ "errors": ["unsupportedUnits"]
}
},
"state": {
@@ -43,40 +86,19 @@
"fahrenheit",
"kelvin"
]
- }
+ },
+ "minItems": 1,
+ "uniqueItems": true,
+ "isRequired": true
},
"units": {
- "type": "string"
- },
- "tempSetting": {
- "type": "number"
- },
- "maxTempSetting": {
- "type": "number"
- },
- "minTempSetting": {
- "type": "number"
- }
- }
- },
- "temperatureSensor": {
- "state": {
- "supportedUnits": {
- "type": "array",
- "items": {
- "type": "string",
- "enum": [
- "celsius",
- "fahrenheit",
- "kelvin"
- ]
- }
- },
- "units": {
- "type": "string"
+ "type": "string",
+ "enum": [ "celsius", "fahrenheit", "kelvin" ],
+ "isRequired": true
},
"value": {
- "type": "number"
+ "type": "number",
+ "isRequired": true
}
}
},
@@ -95,7 +117,10 @@
},
"state": {
"brightness": {
- "type": "number"
+ "type": "integer",
+ "isRequired": true,
+ "minimum": 0,
+ "maximum": 100
}
}
}
@@ -136,7 +161,7 @@
weak_ptr_factory_.GetWeakPtr()));
}
-private:
+ private:
void OnSetTempCommand(const std::weak_ptr<weave::Command>& command) {
auto cmd = command.lock();
if (!cmd)
@@ -158,8 +183,8 @@
LOG(INFO) << cmd->GetName() << " updated oven, matching temp";
if (target_temperature_ != current_temperature_ && !is_match_ticking_) {
- double tickIncrement = ((target_temperature_ - current_temperature_) /
- kWarmUpTime);
+ double tickIncrement =
+ ((target_temperature_ - current_temperature_) / kWarmUpTime);
DoTick(tickIncrement);
}
return;
diff --git a/examples/daemon/sample/sample.cc b/examples/daemon/sample/sample.cc
index 2ab4b27..1d036d5 100644
--- a/examples/daemon/sample/sample.cc
+++ b/examples/daemon/sample/sample.cc
@@ -15,19 +15,20 @@
const char kTraits[] = R"({
"_sample": {
"commands": {
- "_hello": {
+ "hello": {
"minimalRole": "user",
"parameters": {
- "_name": { "type": "string" }
+ "name": { "type": "string" }
}
},
- "_ping": {
- "minimalRole": "user"
+ "ping": {
+ "minimalRole": "user",
+ "parameters": {}
},
- "_countdown": {
+ "countdown": {
"minimalRole": "user",
"parameters": {
- "_seconds": {
+ "seconds": {
"type": "integer",
"minimum": 1,
"maximum": 25
@@ -36,7 +37,7 @@
}
},
"state": {
- "_ping_count": { "type": "integer" }
+ "pingCount": { "type": "integer" }
}
}
})";
@@ -60,15 +61,15 @@
device->AddTraitDefinitionsFromJson(kTraits);
CHECK(device->AddComponent(kComponent, {"_sample"}, nullptr));
CHECK(device->SetStatePropertiesFromJson(
- kComponent, R"({"_sample": {"_ping_count": 0}})", nullptr));
+ kComponent, R"({"_sample": {"pingCount": 0}})", nullptr));
- device->AddCommandHandler(kComponent, "_sample._hello",
+ device->AddCommandHandler(kComponent, "_sample.hello",
base::Bind(&SampleHandler::OnHelloCommand,
weak_ptr_factory_.GetWeakPtr()));
- device->AddCommandHandler(kComponent, "_sample._ping",
+ device->AddCommandHandler(kComponent, "_sample.ping",
base::Bind(&SampleHandler::OnPingCommand,
weak_ptr_factory_.GetWeakPtr()));
- device->AddCommandHandler(kComponent, "_sample._countdown",
+ device->AddCommandHandler(kComponent, "_sample.countdown",
base::Bind(&SampleHandler::OnCountdownCommand,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -82,7 +83,7 @@
const auto& params = cmd->GetParameters();
std::string name;
- if (!params.GetString("_name", &name)) {
+ if (!params.GetString("name", &name)) {
weave::ErrorPtr error;
weave::Error::AddTo(&error, FROM_HERE, "example",
"invalid_parameter_value", "Name is missing");
@@ -91,7 +92,7 @@
}
base::DictionaryValue result;
- result.SetString("_reply", "Hello " + name);
+ result.SetString("reply", "Hello " + name);
cmd->Complete(result, nullptr);
LOG(INFO) << cmd->GetName() << " command finished: " << result;
}
@@ -102,7 +103,7 @@
return;
LOG(INFO) << "received command: " << cmd->GetName();
- device_->SetStateProperty(kComponent, "_sample._ping_count",
+ device_->SetStateProperty(kComponent, "_sample.pingCount",
base::FundamentalValue{++ping_count_}, nullptr);
LOG(INFO) << "New component state: " << device_->GetComponents();
@@ -120,7 +121,7 @@
const auto& params = cmd->GetParameters();
int seconds;
- if (!params.GetInteger("_seconds", &seconds))
+ if (!params.GetInteger("seconds", &seconds))
seconds = 10;
LOG(INFO) << "starting countdown";
@@ -133,13 +134,9 @@
return;
if (seconds > 0) {
- const auto& params = cmd->GetParameters();
- std::string todo;
- params.GetString("_todo", &todo);
LOG(INFO) << "countdown tick: " << seconds << " seconds left";
-
base::DictionaryValue progress;
- progress.SetInteger("_seconds_left", seconds);
+ progress.SetInteger("seconds_left", seconds);
cmd->SetProgress(progress, nullptr);
task_runner_->PostDelayedTask(
FROM_HERE,
diff --git a/examples/daemon/speaker/speaker.cc b/examples/daemon/speaker/speaker.cc
index 8b3e41b..35eee2f 100644
--- a/examples/daemon/speaker/speaker.cc
+++ b/examples/daemon/speaker/speaker.cc
@@ -25,8 +25,11 @@
}
},
"state": {
- "type": "string",
- "enum": [ "on", "standby" ]
+ "state": {
+ "type": "string",
+ "enum": [ "on", "standby" ],
+ "isRequired": true
+ }
}
},
"volume": {
@@ -44,8 +47,16 @@
}
},
"state": {
- "isMuted": { "type": "boolean" },
- "volume": { "type": "integer" }
+ "isMuted": {
+ "type": "boolean",
+ "isRequired": true
+ },
+ "volume": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 100,
+ "isRequired": true
+ }
}
}
})";
diff --git a/examples/provider/curl_http_client.cc b/examples/provider/curl_http_client.cc
index 6f0ba64..2bf10f5 100644
--- a/examples/provider/curl_http_client.cc
+++ b/examples/provider/curl_http_client.cc
@@ -29,8 +29,8 @@
};
size_t WriteFunction(void* contents, size_t size, size_t nmemb, void* userp) {
- static_cast<std::string*>(userp)
- ->append(static_cast<const char*>(contents), size * nmemb);
+ static_cast<std::string*>(userp)->append(static_cast<const char*>(contents),
+ size * nmemb);
return size * nmemb;
}
@@ -49,8 +49,8 @@
header_pair.second = header.substr(pos, last_non_space - pos + 1);
}
- static_cast<provider::HttpClient::Headers*>(userp)
- ->emplace_back(std::move(header_pair));
+ static_cast<provider::HttpClient::Headers*>(userp)->emplace_back(
+ std::move(header_pair));
}
return size * nmemb;
}
diff --git a/examples/provider/curl_http_client.h b/examples/provider/curl_http_client.h
index c342076..8c5ccac 100644
--- a/examples/provider/curl_http_client.h
+++ b/examples/provider/curl_http_client.h
@@ -37,7 +37,8 @@
std::vector<
std::pair<std::future<std::pair<std::unique_ptr<Response>, ErrorPtr>>,
- SendRequestCallback>> pending_tasks_;
+ SendRequestCallback>>
+ pending_tasks_;
provider::TaskRunner* task_runner_{nullptr};
base::WeakPtrFactory<CurlHttpClient> weak_ptr_factory_{this};
diff --git a/examples/provider/event_http_client.cc b/examples/provider/event_http_client.cc
index 1931547..fbfc6d8 100644
--- a/examples/provider/event_http_client.cc
+++ b/examples/provider/event_http_client.cc
@@ -5,10 +5,9 @@
#include "examples/provider/event_http_client.h"
#include "examples/provider/event_task_runner.h"
-
#include <base/bind.h>
-#include <event2/bufferevent.h>
#include <event2/buffer.h>
+#include <event2/bufferevent.h>
#include <event2/http.h>
#include <weave/enum_to_string.h>
diff --git a/examples/provider/event_http_server.cc b/examples/provider/event_http_server.cc
index ae8bbec..ae9833e 100644
--- a/examples/provider/event_http_server.cc
+++ b/examples/provider/event_http_server.cc
@@ -34,8 +34,7 @@
class HttpServerImpl::RequestImpl : public Request {
public:
- RequestImpl(evhttp_request* req, provider::TaskRunner* task_runner)
- : task_runner_{task_runner} {
+ RequestImpl(evhttp_request* req) {
req_.reset(req);
uri_ = evhttp_request_get_evhttp_uri(req_.get());
@@ -70,7 +69,6 @@
private:
std::unique_ptr<evhttp_request, decltype(&evhttp_cancel_request)> req_{
nullptr, &evhttp_cancel_request};
- provider::TaskRunner* task_runner_{nullptr};
std::string data_;
const evhttp_uri* uri_{nullptr};
};
@@ -147,7 +145,7 @@
}
void HttpServerImpl::ProcessRequest(evhttp_request* req) {
- std::unique_ptr<RequestImpl> request{new RequestImpl{req, task_runner_}};
+ std::unique_ptr<RequestImpl> request{new RequestImpl{req}};
std::string path = request->GetPath();
auto it = handlers_.find(path);
if (it != handlers_.end()) {
diff --git a/examples/provider/event_network.cc b/examples/provider/event_network.cc
index ba03e8f..0b18a0a 100644
--- a/examples/provider/event_network.cc
+++ b/examples/provider/event_network.cc
@@ -7,8 +7,8 @@
#include <weave/enum_to_string.h>
#include <base/bind.h>
-#include <event2/dns.h>
#include <event2/bufferevent.h>
+#include <event2/dns.h>
#include "examples/provider/event_task_runner.h"
#include "examples/provider/ssl_stream.h"
diff --git a/examples/provider/event_task_runner.h b/examples/provider/event_task_runner.h
index 7291314..97f9db9 100644
--- a/examples/provider/event_task_runner.h
+++ b/examples/provider/event_task_runner.h
@@ -83,7 +83,8 @@
std::priority_queue<QueueItem,
std::vector<QueueItem>,
- EventTaskRunner::Greater> queue_;
+ EventTaskRunner::Greater>
+ queue_;
EventPtr<event_base> base_{event_base_new()};
diff --git a/examples/provider/file_config_store.cc b/examples/provider/file_config_store.cc
index 2214be8..6faa242 100644
--- a/examples/provider/file_config_store.cc
+++ b/examples/provider/file_config_store.cc
@@ -17,8 +17,10 @@
const char kSettingsDir[] = "/var/lib/weave/";
-FileConfigStore::FileConfigStore(bool disable_security, const std::string& model_id)
- : disable_security_{disable_security}, model_id_{model_id},
+FileConfigStore::FileConfigStore(bool disable_security,
+ const std::string& model_id)
+ : disable_security_{disable_security},
+ model_id_{model_id},
settings_path_{"/var/lib/weave/weave_settings_" + model_id + ".json"} {}
bool FileConfigStore::LoadDefaults(Settings* settings) {
diff --git a/include/weave/device.h b/include/weave/device.h
index 99035f4..069e688 100644
--- a/include/weave/device.h
+++ b/include/weave/device.h
@@ -54,8 +54,7 @@
virtual const base::DictionaryValue& GetTraits() const = 0;
// Sets callback which is called when new trait definitions are added.
- virtual void AddTraitDefsChangedCallback(
- const base::Closure& callback) = 0;
+ virtual void AddTraitDefsChangedCallback(const base::Closure& callback) = 0;
// Adds a new component instance to device. Traits used by this component
// must be already defined.
@@ -77,29 +76,25 @@
// "{'base':{'firmwareVersion':'123'}}")
// Method completely replaces properties included |json| or |dict|.
// Properties of the state not included |json| or |dict| will stay unchanged.
- virtual bool SetStatePropertiesFromJson(
- const std::string& component,
- const std::string& json,
- ErrorPtr* error) = 0;
- virtual bool SetStateProperties(
- const std::string& component,
- const base::DictionaryValue& dict,
- ErrorPtr* error) = 0;
+ virtual bool SetStatePropertiesFromJson(const std::string& component,
+ const std::string& json,
+ ErrorPtr* error) = 0;
+ virtual bool SetStateProperties(const std::string& component,
+ const base::DictionaryValue& dict,
+ ErrorPtr* error) = 0;
// Returns value of the single property.
// |name| is full property name, including trait name. e.g. "base.network".
- virtual const base::Value* GetStateProperty(
- const std::string& component,
- const std::string& name,
- ErrorPtr* error) const = 0;
+ virtual const base::Value* GetStateProperty(const std::string& component,
+ const std::string& name,
+ ErrorPtr* error) const = 0;
// Sets value of the single property.
// |name| is full property name, including trait name. e.g. "base.network".
- virtual bool SetStateProperty(
- const std::string& component,
- const std::string& name,
- const base::Value& value,
- ErrorPtr* error) = 0;
+ virtual bool SetStateProperty(const std::string& component,
+ const std::string& name,
+ const base::Value& value,
+ ErrorPtr* error) = 0;
// Callback type for AddCommandHandler.
using CommandHandlerCallback =
@@ -113,10 +108,9 @@
// Empty |component| and |command_name| sets default handler for all unhanded
// commands.
// No new command handlers can be set after default handler was set.
- virtual void AddCommandHandler(
- const std::string& component,
- const std::string& command_name,
- const CommandHandlerCallback& callback) = 0;
+ virtual void AddCommandHandler(const std::string& component,
+ const std::string& command_name,
+ const CommandHandlerCallback& callback) = 0;
// Adds a new command to the command queue.
virtual bool AddCommand(const base::DictionaryValue& command,
@@ -225,10 +219,9 @@
// Sets value of the single property.
// |name| is full property name, including package name. e.g. "base.network".
// DO NOT USE IN YOUR CODE: use SetStateProperty() with component parameter.
- LIBWEAVE_DEPRECATED virtual bool SetStateProperty(
- const std::string& name,
- const base::Value& value,
- ErrorPtr* error) = 0;
+ LIBWEAVE_DEPRECATED virtual bool SetStateProperty(const std::string& name,
+ const base::Value& value,
+ ErrorPtr* error) = 0;
// Returns aggregated state properties across all registered packages.
// DO NOT USE IN YOUR CODE: use GetComponents() instead.
diff --git a/include/weave/enum_to_string.h b/include/weave/enum_to_string.h
index 67d6154..b6cfca3 100644
--- a/include/weave/enum_to_string.h
+++ b/include/weave/enum_to_string.h
@@ -37,7 +37,7 @@
private:
template <size_t size>
- explicit EnumToStringMap(const Map(&map)[size])
+ explicit EnumToStringMap(const Map (&map)[size])
: begin_(map), end_(map + size) {}
const Map* begin_;
diff --git a/include/weave/error.h b/include/weave/error.h
index 6687d98..14a85be 100644
--- a/include/weave/error.h
+++ b/include/weave/error.h
@@ -9,9 +9,9 @@
#include <string>
#include <base/callback.h>
-#include <base/macros.h>
-#include <base/location.h>
#include <base/compiler_specific.h>
+#include <base/location.h>
+#include <base/macros.h>
#include <weave/export.h>
namespace weave {
diff --git a/include/weave/provider/test/fake_task_runner.h b/include/weave/provider/test/fake_task_runner.h
index 06ccd6b..bb79455 100644
--- a/include/weave/provider/test/fake_task_runner.h
+++ b/include/weave/provider/test/fake_task_runner.h
@@ -53,7 +53,8 @@
std::priority_queue<QueueItem,
std::vector<QueueItem>,
- FakeTaskRunner::Greater> queue_;
+ FakeTaskRunner::Greater>
+ queue_;
};
} // namespace test
diff --git a/include/weave/settings.h b/include/weave/settings.h
index 1c8b095..eeb3f93 100644
--- a/include/weave/settings.h
+++ b/include/weave/settings.h
@@ -17,6 +17,7 @@
kNone,
kViewer,
kUser,
+ kManager,
kOwner,
};
diff --git a/include/weave/test/mock_device.h b/include/weave/test/mock_device.h
index 612afb9..ddd3f59 100644
--- a/include/weave/test/mock_device.h
+++ b/include/weave/test/mock_device.h
@@ -26,29 +26,34 @@
MOCK_CONST_METHOD0(GetTraits, const base::DictionaryValue&());
MOCK_METHOD1(AddTraitDefsChangedCallback,
void(const base::Closure& callback));
- MOCK_METHOD3(AddComponent, bool(const std::string& name,
- const std::vector<std::string>& traits,
- ErrorPtr* error));
+ MOCK_METHOD3(AddComponent,
+ bool(const std::string& name,
+ const std::vector<std::string>& traits,
+ ErrorPtr* error));
MOCK_METHOD1(AddComponentTreeChangedCallback,
void(const base::Closure& callback));
MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
- MOCK_METHOD3(SetStatePropertiesFromJson, bool(const std::string& component,
- const std::string& json,
- ErrorPtr* error));
- MOCK_METHOD3(SetStateProperties, bool(const std::string& component,
- const base::DictionaryValue& dict,
- ErrorPtr* error));
+ MOCK_METHOD3(SetStatePropertiesFromJson,
+ bool(const std::string& component,
+ const std::string& json,
+ ErrorPtr* error));
+ MOCK_METHOD3(SetStateProperties,
+ bool(const std::string& component,
+ const base::DictionaryValue& dict,
+ ErrorPtr* error));
MOCK_CONST_METHOD3(GetStateProperty,
const base::Value*(const std::string& component,
const std::string& name,
ErrorPtr* error));
- MOCK_METHOD4(SetStateProperty, bool(const std::string& component,
- const std::string& name,
- const base::Value& value,
- ErrorPtr* error));
- MOCK_METHOD3(AddCommandHandler, void(const std::string& component,
- const std::string& command_name,
- const CommandHandlerCallback& callback));
+ MOCK_METHOD4(SetStateProperty,
+ bool(const std::string& component,
+ const std::string& name,
+ const base::Value& value,
+ ErrorPtr* error));
+ MOCK_METHOD3(AddCommandHandler,
+ void(const std::string& component,
+ const std::string& command_name,
+ const CommandHandlerCallback& callback));
MOCK_METHOD3(AddCommand,
bool(const base::DictionaryValue&, std::string*, ErrorPtr*));
MOCK_METHOD1(FindCommand, Command*(const std::string&));
diff --git a/libweave_common.gypi b/libweave_common.gypi
index e4251d8..e7b45ce 100644
--- a/libweave_common.gypi
+++ b/libweave_common.gypi
@@ -2,6 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
+ 'variables': {
+ 'clang%': 0,
+ },
'target_defaults': {
'configurations': {
'Release': {
@@ -58,6 +61,27 @@
# 'library_dirs' does not work as expected with make files
'-Lthird_party/lib',
],
- 'library_dirs': ['third_party/lib']
+ 'library_dirs': ['third_party/lib'],
},
+ 'conditions': [
+ ['clang==1', {
+ 'target_defaults': {
+ 'cflags!': ['-Wl,--exclude-libs,ALL'],
+ 'cflags': [
+ '-fsanitize=address',
+ '-fno-omit-frame-pointer',
+ '-Wno-deprecated-register',
+ '-Wno-inconsistent-missing-override',
+ ],
+ 'ldflags': [
+ '-fsanitize=address',
+ ],
+ },
+ 'make_global_settings': [
+ ['CC','/usr/bin/clang-3.6'],
+ ['CXX','/usr/bin/clang++-3.6'],
+ ['LINK','/usr/bin/clang++-3.6'],
+ ],
+ }],
+ ]
}
diff --git a/src/base_api_handler.cc b/src/base_api_handler.cc
index 6808949..5562b6c 100644
--- a/src/base_api_handler.cc
+++ b/src/base_api_handler.cc
@@ -13,7 +13,7 @@
namespace weave {
namespace {
-const char kBaseComponent[] = "weave";
+const char kBaseComponent[] = "base";
const char kBaseTrait[] = "base";
const char kBaseStateFirmwareVersion[] = "base.firmwareVersion";
const char kBaseStateAnonymousAccessRole[] = "base.localAnonymousAccessMaxRole";
@@ -55,13 +55,45 @@
"type": "string"
}
}
+ },
+ "reboot": {
+ "minimalRole": "user",
+ "parameters": {},
+ "errors": ["notEnoughBattery"]
+ },
+ "identify": {
+ "minimalRole": "user",
+ "parameters": {}
}
},
"state": {
- "firmwareVersion": "string",
- "localDiscoveryEnabled": "boolean",
- "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
- "localPairingEnabled": "boolean"
+ "firmwareVersion": {
+ "type": "string",
+ "isRequired": true
+ },
+ "localDiscoveryEnabled": {
+ "type": "boolean",
+ "isRequired": true
+ },
+ "localAnonymousAccessMaxRole": {
+ "type": "string",
+ "enum": [ "none", "viewer", "user" ],
+ "isRequired": true
+ },
+ "localPairingEnabled": {
+ "type": "boolean",
+ "isRequired": true
+ },
+ "connectionStatus": {
+ "type": "string"
+ },
+ "network": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": { "type": "string" }
+ }
+ }
}
}
})");
@@ -76,8 +108,7 @@
nullptr));
device_->AddCommandHandler(
- kBaseComponent,
- "base.updateBaseConfiguration",
+ kBaseComponent, "base.updateBaseConfiguration",
base::Bind(&BaseApiHandler::UpdateBaseConfiguration,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/src/base_api_handler_unittest.cc b/src/base_api_handler_unittest.cc
index 14421b0..6f8460b 100644
--- a/src/base_api_handler_unittest.cc
+++ b/src/base_api_handler_unittest.cc
@@ -35,11 +35,11 @@
EXPECT_TRUE(component_manager_.LoadTraits(json, nullptr));
}));
EXPECT_CALL(device_, SetStateProperties(_, _, _))
- .WillRepeatedly(Invoke(&component_manager_,
- &ComponentManager::SetStateProperties));
+ .WillRepeatedly(
+ Invoke(&component_manager_, &ComponentManager::SetStateProperties));
EXPECT_CALL(device_, SetStateProperty(_, _, _, _))
- .WillRepeatedly(Invoke(&component_manager_,
- &ComponentManager::SetStateProperty));
+ .WillRepeatedly(
+ Invoke(&component_manager_, &ComponentManager::SetStateProperty));
EXPECT_CALL(device_, AddComponent(_, _, _))
.WillRepeatedly(Invoke([this](const std::string& name,
const std::vector<std::string>& traits,
@@ -47,12 +47,12 @@
return component_manager_.AddComponent("", name, traits, error);
}));
- EXPECT_CALL(device_, AddCommandHandler(_,
- AnyOf("base.updateBaseConfiguration",
- "base.updateDeviceInfo"),
- _))
- .WillRepeatedly(Invoke(&component_manager_,
- &ComponentManager::AddCommandHandler));
+ EXPECT_CALL(device_,
+ AddCommandHandler(_, AnyOf("base.updateBaseConfiguration",
+ "base.updateDeviceInfo"),
+ _))
+ .WillRepeatedly(
+ Invoke(&component_manager_, &ComponentManager::AddCommandHandler));
config_.Load();
dev_reg_.reset(new DeviceRegistrationInfo(&config_, &component_manager_,
@@ -133,14 +133,46 @@
"type": "string"
}
}
+ },
+ "reboot": {
+ "minimalRole": "user",
+ "parameters": {},
+ "errors": ["notEnoughBattery"]
+ },
+ "identify": {
+ "minimalRole": "user",
+ "parameters": {}
}
},
- "state": {
- "firmwareVersion": "string",
- "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
- "localDiscoveryEnabled": "boolean",
- "localPairingEnabled": "boolean"
- }
+ "state": {
+ "firmwareVersion": {
+ "type": "string",
+ "isRequired": true
+ },
+ "localDiscoveryEnabled": {
+ "type": "boolean",
+ "isRequired": true
+ },
+ "localAnonymousAccessMaxRole": {
+ "type": "string",
+ "enum": [ "none", "viewer", "user" ],
+ "isRequired": true
+ },
+ "localPairingEnabled": {
+ "type": "boolean",
+ "isRequired": true
+ },
+ "connectionStatus": {
+ "type": "string"
+ },
+ "network": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": { "type": "string" }
+ }
+ }
+ }
})";
EXPECT_JSON_EQ(expected, *trait);
}
@@ -150,7 +182,7 @@
AddCommand(R"({
'name' : 'base.updateBaseConfiguration',
- 'component': 'weave',
+ 'component': 'base',
'parameters': {
'localDiscoveryEnabled': false,
'localAnonymousAccessMaxRole': 'none',
@@ -171,7 +203,7 @@
AddCommand(R"({
'name' : 'base.updateBaseConfiguration',
- 'component': 'weave',
+ 'component': 'base',
'parameters': {
'localDiscoveryEnabled': true,
'localAnonymousAccessMaxRole': 'user',
@@ -205,7 +237,7 @@
TEST_F(BaseApiHandlerTest, UpdateDeviceInfo) {
AddCommand(R"({
'name' : 'base.updateDeviceInfo',
- 'component': 'weave',
+ 'component': 'base',
'parameters': {
'name': 'testName',
'description': 'testDescription',
@@ -220,7 +252,7 @@
AddCommand(R"({
'name' : 'base.updateDeviceInfo',
- 'component': 'weave',
+ 'component': 'base',
'parameters': {
'location': 'newLocation'
}
diff --git a/src/commands/cloud_command_proxy_unittest.cc b/src/commands/cloud_command_proxy_unittest.cc
index d3a9965..0e998ef 100644
--- a/src/commands/cloud_command_proxy_unittest.cc
+++ b/src/commands/cloud_command_proxy_unittest.cc
@@ -66,8 +66,8 @@
protected:
void SetUp() override {
// Set up the test ComponentManager.
- auto callback =
- [this](const base::Callback<void(ComponentManager::UpdateID)>& call) {
+ auto callback = [this](
+ const base::Callback<void(ComponentManager::UpdateID)>& call) {
return callbacks_.Add(call).release();
};
EXPECT_CALL(component_manager_, MockAddServerStateUpdatedCallback(_))
diff --git a/src/commands/command_instance.h b/src/commands/command_instance.h
index 15f3ac2..b1028d0 100644
--- a/src/commands/command_instance.h
+++ b/src/commands/command_instance.h
@@ -12,8 +12,8 @@
#include <base/macros.h>
#include <base/observer_list.h>
-#include <weave/error.h>
#include <weave/command.h>
+#include <weave/error.h>
namespace base {
class Value;
@@ -72,11 +72,10 @@
// The command ID extracted (if present in the JSON object) even if other
// parsing/validation error occurs and command instance is not constructed.
// This is used to report parse failures back to the server.
- static std::unique_ptr<CommandInstance> FromJson(
- const base::Value* value,
- Command::Origin origin,
- std::string* command_id,
- ErrorPtr* error);
+ static std::unique_ptr<CommandInstance> FromJson(const base::Value* value,
+ Command::Origin origin,
+ std::string* command_id,
+ ErrorPtr* error);
std::unique_ptr<base::DictionaryValue> ToJson() const;
diff --git a/src/commands/command_queue_unittest.cc b/src/commands/command_queue_unittest.cc
index 08e8102..b4c5938 100644
--- a/src/commands/command_queue_unittest.cc
+++ b/src/commands/command_queue_unittest.cc
@@ -21,8 +21,8 @@
std::unique_ptr<CommandInstance> CreateDummyCommandInstance(
const std::string& name,
const std::string& id) {
- std::unique_ptr<CommandInstance> cmd{new CommandInstance{
- name, Command::Origin::kLocal, {}}};
+ std::unique_ptr<CommandInstance> cmd{
+ new CommandInstance{name, Command::Origin::kLocal, {}}};
cmd->SetID(id);
return cmd;
}
diff --git a/src/component_manager.h b/src/component_manager.h
index 5f16ac4..cf16720 100644
--- a/src/component_manager.h
+++ b/src/component_manager.h
@@ -34,7 +34,8 @@
ComponentStateChange(base::Time time,
const std::string& path,
std::unique_ptr<base::DictionaryValue> properties)
- : timestamp{time}, component{path},
+ : timestamp{time},
+ component{path},
changed_properties{std::move(properties)} {}
base::Time timestamp;
std::string component;
@@ -91,8 +92,8 @@
// Adds a new command instance to the command queue. The command specified in
// |command_instance| must be fully initialized and have its name, component,
// id populated.
- virtual void AddCommand(
- std::unique_ptr<CommandInstance> command_instance) = 0;
+ virtual void
+ AddCommand(std::unique_ptr<CommandInstance> command_instance) = 0;
// Parses the command definition from a json dictionary. The resulting command
// instance is populated with all the required fields and partially validated
@@ -125,9 +126,8 @@
const Device::CommandHandlerCallback& callback) = 0;
// Finds a component instance by its full path.
- virtual const base::DictionaryValue* FindComponent(
- const std::string& path,
- ErrorPtr* error) const = 0;
+ virtual const base::DictionaryValue* FindComponent(const std::string& path,
+ ErrorPtr* error) const = 0;
// Finds a definition of trait with the given |name|.
virtual const base::DictionaryValue* FindTraitDefinition(
const std::string& name) const = 0;
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index 89ca0cd..b1f3289 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -4,9 +4,9 @@
#include "src/component_manager_impl.h"
-#include <base/strings/stringprintf.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
+#include <base/strings/stringprintf.h>
#include "src/commands/schema_constants.h"
#include "src/json_error_codes.h"
@@ -124,8 +124,7 @@
if (!existing_def->Equals(&it.value())) {
Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
errors::commands::kTypeMismatch,
- "Trait '%s' cannot be redefined",
- it.key().c_str());
+ "Trait '%s' cannot be redefined", it.key().c_str());
result = false;
break;
}
@@ -168,8 +167,8 @@
std::string* id,
ErrorPtr* error) {
std::string command_id;
- auto command_instance = CommandInstance::FromJson(&command, command_origin,
- &command_id, error);
+ auto command_instance =
+ CommandInstance::FromJson(&command, command_origin, &command_id, error);
// If we fail to validate the command definition, but there was a command ID
// specified there, return it to the caller when requested. This will be
// used to abort cloud commands.
@@ -195,14 +194,15 @@
if (component_path.empty()) {
// Find the component to which to route this command. Get the trait name
// from the command name and find the first component that has this trait.
- auto trait_name = SplitAtFirst(command_instance->GetName(), ".", true).first;
+ auto trait_name =
+ SplitAtFirst(command_instance->GetName(), ".", true).first;
component_path = FindComponentWithTrait(trait_name);
if (component_path.empty()) {
Error::AddToPrintf(
error, FROM_HERE, errors::commands::kDomain, "unrouted_command",
"Unable route command '%s' because there is no component supporting"
- "trait '%s'", command_instance->GetName().c_str(),
- trait_name.c_str());
+ "trait '%s'",
+ command_instance->GetName().c_str(), trait_name.c_str());
return nullptr;
}
command_instance->SetComponent(component_path);
@@ -267,14 +267,15 @@
// If both component_path and command_name are empty, we are adding the
// default handler for all commands.
if (!component_path.empty() || !command_name.empty()) {
- CHECK(FindCommandDefinition(command_name))
- << "Command undefined: " << command_name;
+ CHECK(FindCommandDefinition(command_name)) << "Command undefined: "
+ << command_name;
}
command_queue_.AddCommandHandler(component_path, command_name, callback);
}
const base::DictionaryValue* ComponentManagerImpl::FindComponent(
- const std::string& path, ErrorPtr* error) const {
+ const std::string& path,
+ ErrorPtr* error) const {
return FindComponentAt(&components_, path, error);
}
@@ -488,8 +489,8 @@
if (traits_.GetDictionary(key, nullptr)) {
Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
errors::commands::kInvalidPropValue,
- "Redefining command '%s.%s'",
- it.key().c_str(), it_def.key().c_str());
+ "Redefining command '%s.%s'", it.key().c_str(),
+ it_def.key().c_str());
result = false;
continue;
}
@@ -559,8 +560,8 @@
return legacy_state_;
}
-const base::DictionaryValue&
-ComponentManagerImpl::GetLegacyCommandDefinitions() const {
+const base::DictionaryValue& ComponentManagerImpl::GetLegacyCommandDefinitions()
+ const {
legacy_command_defs_.Clear();
// Build commandDefs from traits.
for (base::DictionaryValue::Iterator it(traits_); !it.IsAtEnd();
@@ -603,7 +604,8 @@
}
base::DictionaryValue* ComponentManagerImpl::FindComponentGraftNode(
- const std::string& path, ErrorPtr* error) {
+ const std::string& path,
+ ErrorPtr* error) {
base::DictionaryValue* root = nullptr;
base::DictionaryValue* component = FindMutableComponent(path, error);
if (component && !component->GetDictionary("components", &root)) {
@@ -680,15 +682,15 @@
if (value->GetType() == base::Value::TYPE_LIST && array_index < 0) {
Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
errors::commands::kTypeMismatch,
- "Element '%s.%s' is an array",
- root_path.c_str(), element.first.c_str());
+ "Element '%s.%s' is an array", root_path.c_str(),
+ element.first.c_str());
return nullptr;
}
if (value->GetType() == base::Value::TYPE_DICTIONARY && array_index >= 0) {
Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
errors::commands::kTypeMismatch,
- "Element '%s.%s' is not an array",
- root_path.c_str(), element.first.c_str());
+ "Element '%s.%s' is not an array", root_path.c_str(),
+ element.first.c_str());
return nullptr;
}
diff --git a/src/component_manager_impl.h b/src/component_manager_impl.h
index 6b8ff13..97d302d 100644
--- a/src/component_manager_impl.h
+++ b/src/component_manager_impl.h
@@ -53,8 +53,7 @@
// Adds a new command instance to the command queue. The command specified in
// |command_instance| must be fully initialized and have its name, component,
// id populated.
- void AddCommand(
- std::unique_ptr<CommandInstance> command_instance) override;
+ void AddCommand(std::unique_ptr<CommandInstance> command_instance) override;
// Parses the command definition from a json dictionary. The resulting command
// instance is populated with all the required fields and partially validated
@@ -199,7 +198,7 @@
// This member must be defined before |command_queue_|.
base::CallbackList<void(UpdateID)> on_server_state_updated_;
- base::DictionaryValue traits_; // Trait definitions.
+ base::DictionaryValue traits_; // Trait definitions.
base::DictionaryValue components_; // Component instances.
CommandQueue command_queue_; // Command queue containing command instances.
std::vector<base::Closure> on_trait_changed_;
@@ -209,7 +208,7 @@
std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
// Legacy API support.
- mutable base::DictionaryValue legacy_state_; // Device state.
+ mutable base::DictionaryValue legacy_state_; // Device state.
mutable base::DictionaryValue legacy_command_defs_; // Command definitions.
DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl);
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc
index c3cf445..6b660b1 100644
--- a/src/component_manager_unittest.cc
+++ b/src/component_manager_unittest.cc
@@ -957,8 +957,8 @@
CreateTestComponentTree(&manager_);
ASSERT_TRUE(manager_.SetStatePropertiesFromJson(
- "comp1.comp2[1].comp3.comp4", R"({"t5": {"p1": 3}, "t6": {"p2": 5}})",
- nullptr));
+ "comp1.comp2[1].comp3.comp4",
+ R"({"t5": {"p1": 3}, "t6": {"p2": 5}})", nullptr));
const char kExpected[] = R"({
"comp1": {
diff --git a/src/config.cc b/src/config.cc
index 18e50b5..442a87a 100644
--- a/src/config.cc
+++ b/src/config.cc
@@ -85,8 +85,7 @@
: EnumToStringMap(kRootClientTokenOwnerMap) {}
Config::Config(provider::ConfigStore* config_store)
- : settings_{CreateDefaultSettings()}, config_store_{config_store} {
-}
+ : settings_{CreateDefaultSettings()}, config_store_{config_store} {}
void Config::AddOnChangedCallback(const OnChangedCallback& callback) {
on_changed_.push_back(callback);
diff --git a/src/config.h b/src/config.h
index 0c7ea5f..f5a8a77 100644
--- a/src/config.h
+++ b/src/config.h
@@ -21,6 +21,7 @@
class StorageInterface;
enum class RootClientTokenOwner {
+ // Keep order as it's used with order comparison operators.
kNone,
kClient,
kCloud,
diff --git a/src/device_manager.cc b/src/device_manager.cc
index 88256da..ab2e225 100644
--- a/src/device_manager.cc
+++ b/src/device_manager.cc
@@ -129,10 +129,9 @@
return component_manager_->SetStateProperties(component, dict, error);
}
-const base::Value* DeviceManager::GetStateProperty(
- const std::string& component,
- const std::string& name,
- ErrorPtr* error) const {
+const base::Value* DeviceManager::GetStateProperty(const std::string& component,
+ const std::string& name,
+ ErrorPtr* error) const {
return component_manager_->GetStateProperty(component, name, error);
}
@@ -162,9 +161,8 @@
bool DeviceManager::AddCommand(const base::DictionaryValue& command,
std::string* id,
ErrorPtr* error) {
- auto command_instance =
- component_manager_->ParseCommandInstance(command, Command::Origin::kLocal,
- UserRole::kOwner, id, error);
+ auto command_instance = component_manager_->ParseCommandInstance(
+ command, Command::Origin::kLocal, UserRole::kOwner, id, error);
if (!command_instance)
return false;
component_manager_->AddCommand(std::move(command_instance));
@@ -212,10 +210,12 @@
std::string component =
component_manager_->FindComponentWithTrait(it.key());
if (component.empty()) {
- Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain, "unrouted_state",
- "Unable to set property value because there is no component supporting "
- "trait '%s'", it.key().c_str());
+ Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
+ "unrouted_state",
+ "Unable to set property value because there is no "
+ "component supporting "
+ "trait '%s'",
+ it.key().c_str());
return false;
}
base::DictionaryValue trait_state;
@@ -242,9 +242,10 @@
std::string component = component_manager_->FindComponentWithTrait(trait);
if (component.empty()) {
Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain, "unrouted_state",
- "Unable set value of state property '%s' because there is no component "
- "supporting trait '%s'", name.c_str(), trait.c_str());
+ error, FROM_HERE, errors::commands::kDomain, "unrouted_state",
+ "Unable set value of state property '%s' because there is no component "
+ "supporting trait '%s'",
+ name.c_str(), trait.c_str());
return false;
}
return component_manager_->SetStateProperty(component, name, value, error);
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc
index f52c292..445c138 100644
--- a/src/device_registration_info.cc
+++ b/src/device_registration_info.cc
@@ -235,17 +235,6 @@
return code >= http::kContinue && code < http::kBadRequest;
}
-std::unique_ptr<base::DictionaryValue> BuildDeviceLocalAuth(
- const std::string& id,
- const std::string& client_token,
- const std::string& cert_fingerprint) {
- std::unique_ptr<base::DictionaryValue> auth{new base::DictionaryValue};
- auth->SetString("localId", id);
- auth->SetString("clientToken", client_token);
- auth->SetString("certFingerprint", cert_fingerprint);
- return auth;
-}
-
} // anonymous namespace
DeviceRegistrationInfo::DeviceRegistrationInfo(
@@ -277,12 +266,11 @@
gcd_state_ =
revoked ? GcdState::kInvalidCredentials : GcdState::kUnconfigured;
- component_manager_->AddTraitDefChangedCallback(
- base::Bind(&DeviceRegistrationInfo::OnTraitDefsChanged,
+ component_manager_->AddTraitDefChangedCallback(base::Bind(
+ &DeviceRegistrationInfo::OnTraitDefsChanged, weak_factory_.GetWeakPtr()));
+ component_manager_->AddComponentTreeChangedCallback(
+ base::Bind(&DeviceRegistrationInfo::OnComponentTreeChanged,
weak_factory_.GetWeakPtr()));
- component_manager_->AddComponentTreeChangedCallback(base::Bind(
- &DeviceRegistrationInfo::OnComponentTreeChanged,
- weak_factory_.GetWeakPtr()));
component_manager_->AddStateChangedCallback(base::Bind(
&DeviceRegistrationInfo::OnStateChanged, weak_factory_.GetWeakPtr()));
}
@@ -513,9 +501,6 @@
channel->SetString("supportedType", "pull");
}
resource->Set("channel", channel.release());
- resource->Set("commandDefs",
- component_manager_->GetLegacyCommandDefinitions().DeepCopy());
- resource->Set("state", component_manager_->GetLegacyState().DeepCopy());
resource->Set("traits", component_manager_->GetTraits().DeepCopy());
resource->Set("components", component_manager_->GetComponents().DeepCopy());
@@ -611,12 +596,11 @@
// Now get access_token and refresh_token
RequestSender sender2{HttpClient::Method::kPost, GetOAuthURL("token"),
http_client_};
- sender2.SetFormData(
- {{"code", auth_code},
- {"client_id", GetSettings().client_id},
- {"client_secret", GetSettings().client_secret},
- {"redirect_uri", "oob"},
- {"grant_type", "authorization_code"}});
+ sender2.SetFormData({{"code", auth_code},
+ {"client_id", GetSettings().client_id},
+ {"client_secret", GetSettings().client_secret},
+ {"redirect_uri", "oob"},
+ {"grant_type", "authorization_code"}});
sender2.Send(base::Bind(&DeviceRegistrationInfo::RegisterDeviceOnAuthCodeSent,
weak_factory_.GetWeakPtr(), cloud_id, robot_account,
callback));
@@ -715,9 +699,8 @@
int status_code = response->GetStatusCode();
if (status_code == http::kDenied) {
cloud_backoff_entry_->InformOfRequest(true);
- RefreshAccessToken(
- base::Bind(&DeviceRegistrationInfo::OnAccessTokenRefreshed, AsWeakPtr(),
- data));
+ RefreshAccessToken(base::Bind(
+ &DeviceRegistrationInfo::OnAccessTokenRefreshed, AsWeakPtr(), data));
return;
}
@@ -738,7 +721,7 @@
auto json_resp = ParseJsonResponse(*response, &error);
if (!json_resp) {
- cloud_backoff_entry_->InformOfRequest(true);
+ cloud_backoff_entry_->InformOfRequest(false);
return data->callback.Run({}, std::move(error));
}
@@ -749,7 +732,8 @@
// If we exceeded server quota, retry the request later.
return RetryCloudRequest(data);
}
- cloud_backoff_entry_->InformOfRequest(true);
+
+ cloud_backoff_entry_->InformOfRequest(false);
return data->callback.Run({}, std::move(error));
}
@@ -813,7 +797,8 @@
LOG(INFO) << "Device connected to cloud server";
connected_to_cloud_ = true;
FetchCommands(base::Bind(&DeviceRegistrationInfo::ProcessInitialCommandList,
- AsWeakPtr()), fetch_reason::kDeviceStart);
+ AsWeakPtr()),
+ fetch_reason::kDeviceStart);
// In case there are any pending state updates since we sent off the initial
// UpdateDeviceResource() request, update the server with any state changes.
PublishStateUpdates();
@@ -933,24 +918,33 @@
void DeviceRegistrationInfo::SendAuthInfo() {
if (!auth_manager_ || auth_info_update_inprogress_)
return;
+
+ if (GetSettings().root_client_token_owner == RootClientTokenOwner::kCloud) {
+ // Avoid re-claiming if device is already claimed by the Cloud. Cloud is
+ // allowed to re-claim device at any time. However this will invalidate all
+ // issued tokens.
+ return;
+ }
+
auth_info_update_inprogress_ = true;
+ std::vector<uint8_t> token = auth_manager_->ClaimRootClientAuthToken(
+ RootClientTokenOwner::kCloud, nullptr);
+ CHECK(!token.empty());
std::string id = GetSettings().device_id;
- std::vector<uint8_t> token =
- auth_manager_->ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
std::string token_base64 = Base64Encode(token);
std::string fingerprint =
Base64Encode(auth_manager_->GetCertificateFingerprint());
- std::unique_ptr<base::DictionaryValue> auth =
- BuildDeviceLocalAuth(id, token_base64, fingerprint);
+ std::unique_ptr<base::DictionaryValue> auth{new base::DictionaryValue};
+ auth->SetString("localId", id);
+ auth->SetString("clientToken", token_base64);
+ auth->SetString("certFingerprint", fingerprint);
+ std::unique_ptr<base::DictionaryValue> root{new base::DictionaryValue};
+ root->Set("localAuthInfo", auth.release());
- // TODO(vitalybuka): Remove args from URL when server is ready.
- std::string url =
- GetDeviceURL("upsertLocalAuthInfo", {{"localid", id},
- {"clienttoken", token_base64},
- {"certfingerprint", fingerprint}});
- DoCloudRequest(HttpClient::Method::kPost, url, auth.get(),
+ std::string url = GetDeviceURL("upsertLocalAuthInfo", {});
+ DoCloudRequest(HttpClient::Method::kPost, url, root.get(),
base::Bind(&DeviceRegistrationInfo::OnSendAuthInfoDone,
AsWeakPtr(), token));
}
@@ -962,7 +956,7 @@
CHECK(auth_info_update_inprogress_);
auth_info_update_inprogress_ = false;
- if (!error && auth_manager_->ConfirmAuthToken(token))
+ if (!error && auth_manager_->ConfirmClientAuthToken(token, nullptr))
return;
task_runner_->PostDelayedTask(
@@ -1056,8 +1050,8 @@
fetch_commands_request_queued_ = false;
DoCloudRequest(
HttpClient::Method::kGet,
- GetServiceURL("commands/queue", {{"deviceId", GetSettings().cloud_id},
- {"reason", reason}}),
+ GetServiceURL("commands/queue",
+ {{"deviceId", GetSettings().cloud_id}, {"reason", reason}}),
nullptr, base::Bind(&DeviceRegistrationInfo::OnFetchCommandsDone,
AsWeakPtr(), callback));
}
@@ -1146,9 +1140,9 @@
<< "' arrived, ID: " << command_instance->GetID();
std::unique_ptr<BackoffEntry> backoff_entry{
new BackoffEntry{cloud_backoff_policy_.get()}};
- std::unique_ptr<CloudCommandProxy> cloud_proxy{new CloudCommandProxy{
- command_instance.get(), this, component_manager_,
- std::move(backoff_entry), task_runner_}};
+ std::unique_ptr<CloudCommandProxy> cloud_proxy{
+ new CloudCommandProxy{command_instance.get(), this, component_manager_,
+ std::move(backoff_entry), task_runner_}};
// CloudCommandProxy::CloudCommandProxy() subscribe itself to Command
// notifications. When Command is being destroyed it sends
// ::OnCommandDestroyed() and CloudCommandProxy deletes itself.
@@ -1171,9 +1165,7 @@
std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
patch->SetString("timeMs",
std::to_string(state_change.timestamp.ToJavaTime()));
- // TODO(avakulenko): Uncomment this once server supports "component"
- // attribute on a state patch object.
- // patch->SetString("component", state_change.component);
+ patch->SetString("component", state_change.component);
patch->Set("patch", state_change.changed_properties.release());
patches->Append(patch.release());
}
@@ -1300,8 +1292,8 @@
// channel (XMPP) is active, we are doing a backup poll, so mark the request
// appropriately.
bool just_in_case =
- (channel_name == kPullChannelName) &&
- (current_notification_channel_ == primary_notification_channel_.get());
+ (channel_name == kPullChannelName) &&
+ (current_notification_channel_ == primary_notification_channel_.get());
std::string reason =
just_in_case ? fetch_reason::kJustInCase : fetch_reason::kNewCommand;
@@ -1328,6 +1320,9 @@
connected_to_cloud_ = false;
LOG(INFO) << "Device is unregistered from the cloud. Deleting credentials";
+ if (auth_manager_)
+ auth_manager_->SetSecret({}, RootClientTokenOwner::kNone);
+
Config::Transaction change{config_};
// Keep cloud_id to switch to detect kInvalidCredentials after restart.
change.set_robot_account("");
diff --git a/src/device_registration_info_unittest.cc b/src/device_registration_info_unittest.cc
index 66a9b1d..808f545 100644
--- a/src/device_registration_info_unittest.cc
+++ b/src/device_registration_info_unittest.cc
@@ -68,9 +68,11 @@
"6ed0b3f54f9bd619b942f4ad2441c252@"
"clouddevices.gserviceaccount.com";
const char kAuthInfo[] = R"({
- "certFingerprint":
- "FQY6BEINDjw3FgsmYChRWgMzMhc4TC8uG0UUUFhdDz0=",
- "localId": "f6885e46-b432-42d7-86a5-d759bfb61f62"
+ "localAuthInfo": {
+ "certFingerprint":
+ "FQY6BEINDjw3FgsmYChRWgMzMhc4TC8uG0UUUFhdDz0=",
+ "localId": "f6885e46-b432-42d7-86a5-d759bfb61f62"
+ }
})";
} // namespace test_data
@@ -244,22 +246,22 @@
http_client_,
SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
HttpClient::Headers{GetFormHeader()}, _, _))
- .WillOnce(WithArgs<3, 4>(Invoke([](
- const std::string& data,
- const HttpClient::SendRequestCallback& callback) {
- EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
- EXPECT_EQ(test_data::kRefreshToken,
- GetFormField(data, "refresh_token"));
- EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- GetFormField(data, "client_secret"));
+ .WillOnce(WithArgs<3, 4>(
+ Invoke([](const std::string& data,
+ const HttpClient::SendRequestCallback& callback) {
+ EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRefreshToken,
+ GetFormField(data, "refresh_token"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
- base::DictionaryValue json;
- json.SetString("access_token", test_data::kAccessToken);
- json.SetInteger("expires_in", 3600);
+ base::DictionaryValue json;
+ json.SetString("access_token", test_data::kAccessToken);
+ json.SetInteger("expires_in", 3600);
- callback.Run(ReplyWithJson(200, json), nullptr);
- })));
+ callback.Run(ReplyWithJson(200, json), nullptr);
+ })));
EXPECT_CALL(
http_client_,
@@ -269,8 +271,7 @@
Invoke([](const std::string& data,
const HttpClient::SendRequestCallback& callback) {
auto dict = CreateDictionaryValue(data);
- EXPECT_TRUE(dict->HasKey("clientToken"));
- dict->Remove("clientToken", nullptr);
+ EXPECT_TRUE(dict->Remove("localAuthInfo.clientToken", nullptr));
EXPECT_JSON_EQ(test_data::kAuthInfo, *dict);
base::DictionaryValue json;
callback.Run(ReplyWithJson(200, json), nullptr);
@@ -288,20 +289,20 @@
http_client_,
SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
HttpClient::Headers{GetFormHeader()}, _, _))
- .WillOnce(WithArgs<3, 4>(Invoke([](
- const std::string& data,
- const HttpClient::SendRequestCallback& callback) {
- EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
- EXPECT_EQ(test_data::kRefreshToken,
- GetFormField(data, "refresh_token"));
- EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- GetFormField(data, "client_secret"));
+ .WillOnce(WithArgs<3, 4>(
+ Invoke([](const std::string& data,
+ const HttpClient::SendRequestCallback& callback) {
+ EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRefreshToken,
+ GetFormField(data, "refresh_token"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
- base::DictionaryValue json;
- json.SetString("error", "unable_to_authenticate");
- callback.Run(ReplyWithJson(400, json), nullptr);
- })));
+ base::DictionaryValue json;
+ json.SetString("error", "unable_to_authenticate");
+ callback.Run(ReplyWithJson(400, json), nullptr);
+ })));
ErrorPtr error;
EXPECT_FALSE(RefreshAccessToken(&error));
@@ -317,20 +318,20 @@
http_client_,
SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
HttpClient::Headers{GetFormHeader()}, _, _))
- .WillOnce(WithArgs<3, 4>(Invoke([](
- const std::string& data,
- const HttpClient::SendRequestCallback& callback) {
- EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
- EXPECT_EQ(test_data::kRefreshToken,
- GetFormField(data, "refresh_token"));
- EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- GetFormField(data, "client_secret"));
+ .WillOnce(WithArgs<3, 4>(
+ Invoke([](const std::string& data,
+ const HttpClient::SendRequestCallback& callback) {
+ EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
+ EXPECT_EQ(test_data::kRefreshToken,
+ GetFormField(data, "refresh_token"));
+ EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
+ EXPECT_EQ(test_data::kClientSecret,
+ GetFormField(data, "client_secret"));
- base::DictionaryValue json;
- json.SetString("error", "invalid_grant");
- callback.Run(ReplyWithJson(400, json), nullptr);
- })));
+ base::DictionaryValue json;
+ json.SetString("error", "invalid_grant");
+ callback.Run(ReplyWithJson(400, json), nullptr);
+ })));
ErrorPtr error;
EXPECT_FALSE(RefreshAccessToken(&error));
@@ -396,8 +397,8 @@
}
})");
EXPECT_TRUE(component_manager_.LoadTraits(*json_traits, nullptr));
- EXPECT_TRUE(component_manager_.AddComponent("", "comp", {"base", "robot"},
- nullptr));
+ EXPECT_TRUE(
+ component_manager_.AddComponent("", "comp", {"base", "robot"}, nullptr));
base::StringValue ver{"1.0"};
EXPECT_TRUE(component_manager_.SetStateProperty(
"comp", "base.firmwareVersion", ver, nullptr));
@@ -408,110 +409,78 @@
SendRequest(HttpClient::Method::kPatch,
ticket_url + "?key=" + test_data::kApiKey,
HttpClient::Headers{GetJsonHeader()}, _, _))
- .WillOnce(WithArgs<3, 4>(Invoke([](
- const std::string& data,
- const HttpClient::SendRequestCallback& callback) {
- auto json = test::CreateDictionaryValue(data);
- EXPECT_NE(nullptr, json.get());
- std::string value;
- EXPECT_TRUE(json->GetString("id", &value));
- EXPECT_EQ(test_data::kClaimTicketId, value);
- EXPECT_TRUE(
- json->GetString("deviceDraft.channel.supportedType", &value));
- EXPECT_EQ("pull", value);
- EXPECT_TRUE(json->GetString("oauthClientId", &value));
- EXPECT_EQ(test_data::kClientId, value);
- EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
- EXPECT_EQ("Easy to clean", value);
- EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
- EXPECT_EQ("Kitchen", value);
- EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
- EXPECT_EQ("AAAAA", value);
- EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
- EXPECT_EQ("Coffee Pot", value);
- base::DictionaryValue* dict = nullptr;
- EXPECT_TRUE(json->GetDictionary("deviceDraft.commandDefs", &dict));
- auto expectedCommandDefs = R"({
- 'base': {
- 'reboot': {
- 'parameters': {
- 'delay': {
- 'minimum': 10,
- 'type': 'integer'
+ .WillOnce(WithArgs<3, 4>(
+ Invoke([](const std::string& data,
+ const HttpClient::SendRequestCallback& callback) {
+ auto json = test::CreateDictionaryValue(data);
+ EXPECT_NE(nullptr, json.get());
+ std::string value;
+ EXPECT_TRUE(json->GetString("id", &value));
+ EXPECT_EQ(test_data::kClaimTicketId, value);
+ EXPECT_TRUE(
+ json->GetString("deviceDraft.channel.supportedType", &value));
+ EXPECT_EQ("pull", value);
+ EXPECT_TRUE(json->GetString("oauthClientId", &value));
+ EXPECT_EQ(test_data::kClientId, value);
+ EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
+ EXPECT_EQ("Easy to clean", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
+ EXPECT_EQ("Kitchen", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
+ EXPECT_EQ("AAAAA", value);
+ EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
+ EXPECT_EQ("Coffee Pot", value);
+ base::DictionaryValue* dict = nullptr;
+ EXPECT_FALSE(json->GetDictionary("deviceDraft.commandDefs", &dict));
+ EXPECT_FALSE(json->GetDictionary("deviceDraft.state", &dict));
+ EXPECT_TRUE(json->GetDictionary("deviceDraft.traits", &dict));
+ auto expectedTraits = R"({
+ 'base': {
+ 'commands': {
+ 'reboot': {
+ 'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
+ 'minimalRole': 'user'
}
},
- 'minimalRole': 'user'
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {
- '_height': {
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- }
- })";
- EXPECT_JSON_EQ(expectedCommandDefs, *dict);
-
- EXPECT_TRUE(json->GetDictionary("deviceDraft.state", &dict));
- auto expectedState = R"({
- 'base': {
- 'firmwareVersion': '1.0'
- }
- })";
- EXPECT_JSON_EQ(expectedState, *dict);
-
- EXPECT_TRUE(json->GetDictionary("deviceDraft.traits", &dict));
- auto expectedTraits = R"({
- 'base': {
- 'commands': {
- 'reboot': {
- 'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
- 'minimalRole': 'user'
+ 'state': {
+ 'firmwareVersion': {'type': 'string'}
}
},
- 'state': {
- 'firmwareVersion': {'type': 'string'}
- }
- },
- 'robot': {
- 'commands': {
- '_jump': {
- 'parameters': {'_height': {'type': 'integer'}},
- 'minimalRole': 'user'
+ 'robot': {
+ 'commands': {
+ '_jump': {
+ 'parameters': {'_height': {'type': 'integer'}},
+ 'minimalRole': 'user'
+ }
}
}
- }
- })";
- EXPECT_JSON_EQ(expectedTraits, *dict);
+ })";
+ EXPECT_JSON_EQ(expectedTraits, *dict);
- EXPECT_TRUE(json->GetDictionary("deviceDraft.components", &dict));
- auto expectedComponents = R"({
- 'comp': {
- 'traits': ['base', 'robot'],
- 'state': {
- 'base': { 'firmwareVersion': '1.0' }
+ EXPECT_TRUE(json->GetDictionary("deviceDraft.components", &dict));
+ auto expectedComponents = R"({
+ 'comp': {
+ 'traits': ['base', 'robot'],
+ 'state': {
+ 'base': { 'firmwareVersion': '1.0' }
+ }
}
- }
- })";
- EXPECT_JSON_EQ(expectedComponents, *dict);
+ })";
+ EXPECT_JSON_EQ(expectedComponents, *dict);
- base::DictionaryValue json_resp;
- json_resp.SetString("id", test_data::kClaimTicketId);
- json_resp.SetString("kind", "weave#registrationTicket");
- json_resp.SetString("oauthClientId", test_data::kClientId);
- base::DictionaryValue* device_draft = nullptr;
- EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
- device_draft = device_draft->DeepCopy();
- device_draft->SetString("id", test_data::kCloudId);
- device_draft->SetString("kind", "weave#device");
- json_resp.Set("deviceDraft", device_draft);
+ base::DictionaryValue json_resp;
+ json_resp.SetString("id", test_data::kClaimTicketId);
+ json_resp.SetString("kind", "weave#registrationTicket");
+ json_resp.SetString("oauthClientId", test_data::kClientId);
+ base::DictionaryValue* device_draft = nullptr;
+ EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
+ device_draft = device_draft->DeepCopy();
+ device_draft->SetString("id", test_data::kCloudId);
+ device_draft->SetString("kind", "weave#device");
+ json_resp.Set("deviceDraft", device_draft);
- callback.Run(ReplyWithJson(200, json_resp), nullptr);
- })));
+ callback.Run(ReplyWithJson(200, json_resp), nullptr);
+ })));
EXPECT_CALL(http_client_,
SendRequest(HttpClient::Method::kPost,
@@ -564,8 +533,7 @@
Invoke([](const std::string& data,
const HttpClient::SendRequestCallback& callback) {
auto dict = CreateDictionaryValue(data);
- EXPECT_TRUE(dict->HasKey("clientToken"));
- dict->Remove("clientToken", nullptr);
+ EXPECT_TRUE(dict->Remove("localAuthInfo.clientToken", nullptr));
EXPECT_JSON_EQ(test_data::kAuthInfo, *dict);
base::DictionaryValue json;
callback.Run(ReplyWithJson(200, json), nullptr);
@@ -621,8 +589,8 @@
}
})");
EXPECT_TRUE(component_manager_.LoadTraits(*json_traits, nullptr));
- EXPECT_TRUE(component_manager_.AddComponent("", "comp", {"robot"},
- nullptr));
+ EXPECT_TRUE(
+ component_manager_.AddComponent("", "comp", {"robot"}, nullptr));
command_url_ = dev_reg_->GetServiceURL("commands/1234");
@@ -689,14 +657,14 @@
http_client_,
SendRequest(HttpClient::Method::kPatch, command_url_,
HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
- .WillOnce(WithArgs<3, 4>(Invoke([](
- const std::string& data,
- const HttpClient::SendRequestCallback& callback) {
- EXPECT_JSON_EQ(R"({"state":"cancelled"})",
- *CreateDictionaryValue(data));
- base::DictionaryValue json;
- callback.Run(ReplyWithJson(200, json), nullptr);
- })));
+ .WillOnce(WithArgs<3, 4>(
+ Invoke([](const std::string& data,
+ const HttpClient::SendRequestCallback& callback) {
+ EXPECT_JSON_EQ(R"({"state":"cancelled"})",
+ *CreateDictionaryValue(data));
+ base::DictionaryValue json;
+ callback.Run(ReplyWithJson(200, json), nullptr);
+ })));
EXPECT_TRUE(command_->Cancel(nullptr));
}
diff --git a/src/mock_component_manager.h b/src/mock_component_manager.h
index e30b8b0..08c1e59 100644
--- a/src/mock_component_manager.h
+++ b/src/mock_component_manager.h
@@ -14,14 +14,15 @@
class MockComponentManager : public ComponentManager {
public:
~MockComponentManager() override {}
- MOCK_METHOD2(LoadTraits, bool(const base::DictionaryValue& dict,
- ErrorPtr* error));
+ MOCK_METHOD2(LoadTraits,
+ bool(const base::DictionaryValue& dict, ErrorPtr* error));
MOCK_METHOD2(LoadTraits, bool(const std::string& json, ErrorPtr* error));
MOCK_METHOD1(AddTraitDefChangedCallback, void(const base::Closure& callback));
- MOCK_METHOD4(AddComponent, bool(const std::string& path,
- const std::string& name,
- const std::vector<std::string>& traits,
- ErrorPtr* error));
+ MOCK_METHOD4(AddComponent,
+ bool(const std::string& path,
+ const std::string& name,
+ const std::vector<std::string>& traits,
+ ErrorPtr* error));
MOCK_METHOD4(AddComponentArrayItem,
bool(const std::string& path,
const std::string& name,
@@ -53,14 +54,16 @@
MOCK_CONST_METHOD1(
FindCommandDefinition,
const base::DictionaryValue*(const std::string& command_name));
- MOCK_CONST_METHOD3(GetMinimalRole, bool(const std::string& command_name,
- UserRole* minimal_role,
- ErrorPtr* error));
+ MOCK_CONST_METHOD3(GetMinimalRole,
+ bool(const std::string& command_name,
+ UserRole* minimal_role,
+ ErrorPtr* error));
MOCK_CONST_METHOD0(GetTraits, const base::DictionaryValue&());
MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
- MOCK_METHOD3(SetStateProperties, bool(const std::string& component_path,
- const base::DictionaryValue& dict,
- ErrorPtr* error));
+ MOCK_METHOD3(SetStateProperties,
+ bool(const std::string& component_path,
+ const base::DictionaryValue& dict,
+ ErrorPtr* error));
MOCK_METHOD3(SetStatePropertiesFromJson,
bool(const std::string& component_path,
const std::string& json,
@@ -69,17 +72,18 @@
const base::Value*(const std::string& component_path,
const std::string& name,
ErrorPtr* error));
- MOCK_METHOD4(SetStateProperty, bool(const std::string& component_path,
- const std::string& name,
- const base::Value& value,
- ErrorPtr* error));
+ MOCK_METHOD4(SetStateProperty,
+ bool(const std::string& component_path,
+ const std::string& name,
+ const base::Value& value,
+ ErrorPtr* error));
MOCK_METHOD1(AddStateChangedCallback, void(const base::Closure& callback));
MOCK_METHOD0(MockGetAndClearRecordedStateChanges, StateSnapshot&());
MOCK_METHOD1(NotifyStateUpdatedOnServer, void(UpdateID id));
MOCK_CONST_METHOD0(GetLastStateChangeId, UpdateID());
MOCK_METHOD1(MockAddServerStateUpdatedCallback,
base::CallbackList<void(UpdateID)>::Subscription*(
- const base::Callback<void(UpdateID)>& callback));
+ const base::Callback<void(UpdateID)>& callback));
MOCK_CONST_METHOD1(FindComponentWithTrait,
std::string(const std::string& trait));
MOCK_METHOD2(AddLegacyCommandDefinitions,
@@ -100,8 +104,8 @@
UserRole role,
std::string* id,
ErrorPtr* error) {
- return std::unique_ptr<CommandInstance>{MockParseCommandInstance(
- command, command_origin, role, id, error)};
+ return std::unique_ptr<CommandInstance>{
+ MockParseCommandInstance(command, command_origin, role, id, error)};
}
StateSnapshot GetAndClearRecordedStateChanges() override {
return std::move(MockGetAndClearRecordedStateChanges());
diff --git a/src/notification/notification_parser.cc b/src/notification/notification_parser.cc
index d7c4f48..69e7e7e 100644
--- a/src/notification/notification_parser.cc
+++ b/src/notification/notification_parser.cc
@@ -45,8 +45,7 @@
CHECK(delegate);
std::string kind;
- if (!notification.GetString("kind", &kind) ||
- kind != "weave#notification") {
+ if (!notification.GetString("kind", &kind) || kind != "weave#notification") {
LOG(WARNING) << "Push notification should have 'kind' property set to "
"weave#notification";
return false;
diff --git a/src/notification/notification_parser_unittest.cc b/src/notification/notification_parser_unittest.cc
index c69f9dd..fd5f0a7 100644
--- a/src/notification/notification_parser_unittest.cc
+++ b/src/notification/notification_parser_unittest.cc
@@ -25,8 +25,9 @@
MOCK_METHOD1(OnConnected, void(const std::string&));
MOCK_METHOD0(OnDisconnected, void());
MOCK_METHOD0(OnPermanentFailure, void());
- MOCK_METHOD2(OnCommandCreated, void(const base::DictionaryValue& command,
- const std::string& channel_name));
+ MOCK_METHOD2(OnCommandCreated,
+ void(const base::DictionaryValue& command,
+ const std::string& channel_name));
MOCK_METHOD1(OnDeviceDeleted, void(const std::string&));
};
diff --git a/src/notification/xmpp_iq_stanza_handler.h b/src/notification/xmpp_iq_stanza_handler.h
index 052e5d2..7259cff 100644
--- a/src/notification/xmpp_iq_stanza_handler.h
+++ b/src/notification/xmpp_iq_stanza_handler.h
@@ -11,8 +11,8 @@
#include <base/callback_forward.h>
#include <base/macros.h>
-#include <base/time/time.h>
#include <base/memory/weak_ptr.h>
+#include <base/time/time.h>
#include "src/notification/xmpp_stream_parser.h"
diff --git a/src/notification/xmpp_stream_parser_unittest.cc b/src/notification/xmpp_stream_parser_unittest.cc
index f6466fe..72ca7b2 100644
--- a/src/notification/xmpp_stream_parser_unittest.cc
+++ b/src/notification/xmpp_stream_parser_unittest.cc
@@ -4,9 +4,9 @@
#include "src/notification/xmpp_stream_parser.h"
+#include <gtest/gtest.h>
#include <memory>
#include <vector>
-#include <gtest/gtest.h>
#include "src/notification/xml_node.h"
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc
index fa1d685..62a640f 100644
--- a/src/privet/auth_manager.cc
+++ b/src/privet/auth_manager.cc
@@ -9,6 +9,7 @@
#include "src/config.h"
#include "src/data_encoding.h"
+#include "src/privet/constants.h"
#include "src/privet/openssl_utils.h"
#include "src/string_utils.h"
@@ -80,6 +81,10 @@
return secret;
}
+bool IsClaimAllowed(RootClientTokenOwner curret, RootClientTokenOwner claimer) {
+ return claimer > curret || claimer == RootClientTokenOwner::kCloud;
+}
+
} // namespace
AuthManager::AuthManager(Config* config,
@@ -146,7 +151,19 @@
}
std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken(
- RootClientTokenOwner owner) {
+ RootClientTokenOwner owner,
+ ErrorPtr* error) {
+ CHECK(RootClientTokenOwner::kNone != owner);
+ if (config_) {
+ auto current = config_->GetSettings().root_client_token_owner;
+ if (!IsClaimAllowed(current, owner)) {
+ Error::AddToPrintf(
+ error, FROM_HERE, errors::kDomain, errors::kAlreadyClaimed,
+ "Device already claimed by '%s'", EnumToString(current).c_str());
+ return {};
+ }
+ };
+
pending_claims_.push_back(std::make_pair(
std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}}, owner));
if (pending_claims_.size() > kMaxPendingClaims)
@@ -154,7 +171,8 @@
return pending_claims_.back().first->GetRootClientAuthToken();
}
-bool AuthManager::ConfirmAuthToken(const std::vector<uint8_t>& token) {
+bool AuthManager::ConfirmClientAuthToken(const std::vector<uint8_t>& token,
+ ErrorPtr* error) {
// Cover case when caller sent confirm twice.
if (pending_claims_.empty() && IsValidAuthToken(token))
return true;
@@ -164,8 +182,11 @@
[&token](const decltype(pending_claims_)::value_type& auth) {
return auth.first->IsValidAuthToken(token);
});
- if (claim == pending_claims_.end())
+ if (claim == pending_claims_.end()) {
+ Error::AddTo(error, FROM_HERE, errors::kDomain, errors::kNotFound,
+ "Unknown claim");
return false;
+ }
SetSecret(claim->first->GetSecret(), claim->second);
pending_claims_.clear();
diff --git a/src/privet/auth_manager.h b/src/privet/auth_manager.h
index 62a1606..44b8bca 100644
--- a/src/privet/auth_manager.h
+++ b/src/privet/auth_manager.h
@@ -44,16 +44,18 @@
base::Time Now() const;
- std::vector<uint8_t> ClaimRootClientAuthToken(RootClientTokenOwner owner);
- bool ConfirmAuthToken(const std::vector<uint8_t>& token);
+ std::vector<uint8_t> ClaimRootClientAuthToken(RootClientTokenOwner owner,
+ ErrorPtr* error);
+ bool ConfirmClientAuthToken(const std::vector<uint8_t>& token,
+ ErrorPtr* error);
std::vector<uint8_t> GetRootClientAuthToken() const;
bool IsValidAuthToken(const std::vector<uint8_t>& token) const;
- private:
void SetSecret(const std::vector<uint8_t>& secret,
RootClientTokenOwner owner);
+ private:
Config* config_{nullptr};
base::DefaultClock default_clock_;
base::Clock* clock_{&default_clock_};
diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc
index 4dd753b..a571d4f 100644
--- a/src/privet/auth_manager_unittest.cc
+++ b/src/privet/auth_manager_unittest.cc
@@ -64,11 +64,14 @@
EXPECT_EQ(
"iZx0qgEHFF5lq+Q503GtgU0d6gLQ9TlLsU+DcFbZb2QxOjIzNDoxNDEwMDAwMDAw",
Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kViewer, 234})));
+ EXPECT_EQ("cWkAHxSBYtTFV3Va/9mcynR8iFZo2qr+8+WewmumF74zOjI1NzoxNDEwMDAwMDAw",
+ Base64Encode(
+ auth_.CreateAccessToken(UserInfo{AuthScope::kManager, 257})));
EXPECT_EQ(
- "fTjecsbwtYj6i8/qPJz900B8EMAjRqU8jLT9kfMoz0czOjQ1NjoxNDEwMDAwMDAw",
+ "s3GnCThkQXIzGQoPDlJoiehQiJ5yy4SYUVQzMN2kY0o0OjQ1NjoxNDEwMDAwMDAw",
Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456})));
- EXPECT_CALL(clock_, Now())
- .WillRepeatedly(Return(clock_.Now() + base::TimeDelta::FromDays(11)));
+ auto new_time = clock_.Now() + base::TimeDelta::FromDays(11);
+ EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
EXPECT_EQ(
"qAmlJykiPTnFljfOKSf3BUII9YZG8/ttzD76q+fII1YyOjM0NToxNDEwOTUwNDAw",
Base64Encode(auth_.CreateAccessToken(UserInfo{AuthScope::kUser, 345})));
@@ -123,8 +126,8 @@
}
TEST_F(AuthManagerTest, GetRootClientAuthTokenDifferentTime) {
- EXPECT_CALL(clock_, Now())
- .WillRepeatedly(Return(clock_.Now() + base::TimeDelta::FromDays(15)));
+ auto new_time = clock_.Now() + base::TimeDelta::FromDays(15);
+ EXPECT_CALL(clock_, Now()).WillRepeatedly(Return(new_time));
EXPECT_EQ("UGKqwMYGQNOd8jeYFDOsM02CQgECRgMaVB6rAA==",
Base64Encode(auth_.GetRootClientAuthToken()));
}
@@ -147,32 +150,79 @@
}
}
-TEST_F(AuthManagerTest, ClaimRootClientAuthToken) {
- auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
+class AuthManagerClaimTest : public testing::Test {
+ public:
+ void SetUp() override { EXPECT_GE(auth_.GetSecret().size(), 32u); }
+
+ bool TestClaim(RootClientTokenOwner owner, RootClientTokenOwner claimer) {
+ Config::Transaction change{&config_};
+ change.set_root_client_token_owner(owner);
+ change.Commit();
+ return !auth_.ClaimRootClientAuthToken(claimer, nullptr).empty();
+ }
+
+ protected:
+ Config config_{nullptr};
+ AuthManager auth_{&config_, {}};
+};
+
+TEST_F(AuthManagerClaimTest, WithPreviosOwner) {
+ EXPECT_DEATH(
+ TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kNone), "");
+ EXPECT_DEATH(
+ TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kNone),
+ "");
+ EXPECT_DEATH(
+ TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kNone), "");
+ EXPECT_TRUE(
+ TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kClient));
+ EXPECT_FALSE(
+ TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kClient));
+ EXPECT_FALSE(
+ TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kClient));
+ EXPECT_TRUE(
+ TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kCloud));
+ EXPECT_TRUE(
+ TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kCloud));
+ EXPECT_TRUE(
+ TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kCloud));
+}
+
+TEST_F(AuthManagerClaimTest, NormalClaim) {
+ auto token =
+ auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
EXPECT_FALSE(auth_.IsValidAuthToken(token));
+ EXPECT_EQ(RootClientTokenOwner::kNone,
+ config_.GetSettings().root_client_token_owner);
- EXPECT_TRUE(auth_.ConfirmAuthToken(token));
+ EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr));
EXPECT_TRUE(auth_.IsValidAuthToken(token));
+ EXPECT_EQ(RootClientTokenOwner::kCloud,
+ config_.GetSettings().root_client_token_owner);
}
-TEST_F(AuthManagerTest, ClaimRootClientAuthTokenDoubleConfirm) {
- auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
- EXPECT_TRUE(auth_.ConfirmAuthToken(token));
- EXPECT_TRUE(auth_.ConfirmAuthToken(token));
+TEST_F(AuthManagerClaimTest, DoubleConfirm) {
+ auto token =
+ auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
+ EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr));
+ EXPECT_TRUE(auth_.ConfirmClientAuthToken(token, nullptr));
}
-TEST_F(AuthManagerTest, DoubleClaimRootClientAuthToken) {
- auto token1 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
- auto token2 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
- EXPECT_TRUE(auth_.ConfirmAuthToken(token1));
- EXPECT_FALSE(auth_.ConfirmAuthToken(token2));
+TEST_F(AuthManagerClaimTest, DoubleClaim) {
+ auto token1 =
+ auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
+ auto token2 =
+ auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
+ EXPECT_TRUE(auth_.ConfirmClientAuthToken(token1, nullptr));
+ EXPECT_FALSE(auth_.ConfirmClientAuthToken(token2, nullptr));
}
-TEST_F(AuthManagerTest, ClaimRootClientAuthTokenOverflow) {
- auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
+TEST_F(AuthManagerClaimTest, TokenOverflow) {
+ auto token =
+ auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
for (size_t i = 0; i < 100; ++i)
- auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud);
- EXPECT_FALSE(auth_.ConfirmAuthToken(token));
+ auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr);
+ EXPECT_FALSE(auth_.ConfirmClientAuthToken(token, nullptr));
}
} // namespace privet
diff --git a/src/privet/cloud_delegate.cc b/src/privet/cloud_delegate.cc
index 3c3f0bb..ed22c15 100644
--- a/src/privet/cloud_delegate.cc
+++ b/src/privet/cloud_delegate.cc
@@ -50,19 +50,18 @@
device_->AddGcdStateChangedCallback(base::Bind(
&CloudDelegateImpl::OnRegistrationChanged, weak_factory_.GetWeakPtr()));
- component_manager_->AddTraitDefChangedCallback(base::Bind(
- &CloudDelegateImpl::NotifyOnTraitDefsChanged,
- weak_factory_.GetWeakPtr()));
+ component_manager_->AddTraitDefChangedCallback(
+ base::Bind(&CloudDelegateImpl::NotifyOnTraitDefsChanged,
+ weak_factory_.GetWeakPtr()));
component_manager_->AddCommandAddedCallback(base::Bind(
&CloudDelegateImpl::OnCommandAdded, weak_factory_.GetWeakPtr()));
component_manager_->AddCommandRemovedCallback(base::Bind(
&CloudDelegateImpl::OnCommandRemoved, weak_factory_.GetWeakPtr()));
component_manager_->AddStateChangedCallback(base::Bind(
- &CloudDelegateImpl::NotifyOnStateChanged,
- weak_factory_.GetWeakPtr()));
- component_manager_->AddComponentTreeChangedCallback(base::Bind(
- &CloudDelegateImpl::NotifyOnComponentTreeChanged,
- weak_factory_.GetWeakPtr()));
+ &CloudDelegateImpl::NotifyOnStateChanged, weak_factory_.GetWeakPtr()));
+ component_manager_->AddComponentTreeChangedCallback(
+ base::Bind(&CloudDelegateImpl::NotifyOnComponentTreeChanged,
+ weak_factory_.GetWeakPtr()));
}
~CloudDelegateImpl() override = default;
@@ -128,9 +127,8 @@
setup_weak_factory_.InvalidateWeakPtrs();
backoff_entry_.Reset();
task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
- setup_weak_factory_.GetWeakPtr()),
+ FROM_HERE, base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
+ setup_weak_factory_.GetWeakPtr()),
{});
// Return true because we initiated setup.
return true;
@@ -276,9 +274,9 @@
return;
}
- device_->RegisterDevice(
- ticket_id_, base::Bind(&CloudDelegateImpl::RegisterDeviceDone,
- setup_weak_factory_.GetWeakPtr()));
+ device_->RegisterDevice(ticket_id_,
+ base::Bind(&CloudDelegateImpl::RegisterDeviceDone,
+ setup_weak_factory_.GetWeakPtr()));
}
void RegisterDeviceDone(ErrorPtr error) {
@@ -286,9 +284,8 @@
// Registration failed. Retry with backoff.
backoff_entry_.InformOfRequest(false);
return task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
- setup_weak_factory_.GetWeakPtr()),
+ FROM_HERE, base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
+ setup_weak_factory_.GetWeakPtr()),
backoff_entry_.GetTimeUntilRelease());
}
backoff_entry_.InformOfRequest(true);
@@ -298,7 +295,7 @@
CommandInstance* GetCommandInternal(const std::string& command_id,
const UserInfo& user_info,
ErrorPtr* error) const {
- if (user_info.scope() != AuthScope::kOwner) {
+ if (user_info.scope() < AuthScope::kManager) {
auto it = command_owners_.find(command_id);
if (it == command_owners_.end())
return ReturnNotFound(command_id, error);
@@ -319,7 +316,7 @@
CHECK(user_info.scope() != AuthScope::kNone);
CHECK_NE(user_info.user_id(), 0u);
- if (user_info.scope() == AuthScope::kOwner ||
+ if (user_info.scope() == AuthScope::kManager ||
owner_id == user_info.user_id()) {
return true;
}
@@ -369,8 +366,8 @@
provider::TaskRunner* task_runner,
DeviceRegistrationInfo* device,
ComponentManager* component_manager) {
- return std::unique_ptr<CloudDelegateImpl>{new CloudDelegateImpl{
- task_runner, device, component_manager}};
+ return std::unique_ptr<CloudDelegateImpl>{
+ new CloudDelegateImpl{task_runner, device, component_manager}};
}
void CloudDelegate::NotifyOnDeviceInfoChanged() {
diff --git a/src/privet/cloud_delegate.h b/src/privet/cloud_delegate.h
index 4aa9bcb..9f053d8 100644
--- a/src/privet/cloud_delegate.h
+++ b/src/privet/cloud_delegate.h
@@ -105,9 +105,8 @@
virtual const base::DictionaryValue& GetComponents() const = 0;
// Finds a component at the given path. Return nullptr in case of an error.
- virtual const base::DictionaryValue* FindComponent(
- const std::string& path,
- ErrorPtr* error) const = 0;
+ virtual const base::DictionaryValue* FindComponent(const std::string& path,
+ ErrorPtr* error) const = 0;
// Returns dictionary with trait definitions.
virtual const base::DictionaryValue& GetTraits() const = 0;
diff --git a/src/privet/constants.cc b/src/privet/constants.cc
index 3cc3e4a..e1962bd 100644
--- a/src/privet/constants.cc
+++ b/src/privet/constants.cc
@@ -30,6 +30,7 @@
const char kInvalidPassphrase[] = "invalidPassphrase";
const char kNotFound[] = "notFound";
const char kNotImplemented[] = "notImplemented";
+const char kAlreadyClaimed[] = "alreadyClaimed";
} // namespace errors
} // namespace privet
diff --git a/src/privet/constants.h b/src/privet/constants.h
index 0668879..2b001aa 100644
--- a/src/privet/constants.h
+++ b/src/privet/constants.h
@@ -32,6 +32,7 @@
extern const char kInvalidPassphrase[];
extern const char kNotFound[];
extern const char kNotImplemented[];
+extern const char kAlreadyClaimed[];
} // namespace errors
} // namespace privet
} // namespace weave
diff --git a/src/privet/device_delegate.cc b/src/privet/device_delegate.cc
index 5722357..552cbe2 100644
--- a/src/privet/device_delegate.cc
+++ b/src/privet/device_delegate.cc
@@ -20,8 +20,10 @@
uint16_t http_port,
uint16_t https_port,
base::TimeDelta http_request_timeout)
- : task_runner_{task_runner}, http_request_timeout_{http_request_timeout},
- http_port_{http_port}, https_port_{https_port} {}
+ : task_runner_{task_runner},
+ http_request_timeout_{http_request_timeout},
+ http_port_{http_port},
+ https_port_{https_port} {}
~DeviceDelegateImpl() override = default;
std::pair<uint16_t, uint16_t> GetHttpEnpoint() const override {
@@ -59,9 +61,8 @@
uint16_t http_port,
uint16_t https_port,
base::TimeDelta http_request_timeout) {
- return std::unique_ptr<DeviceDelegate>(
- new DeviceDelegateImpl(task_runner, http_port, https_port,
- http_request_timeout));
+ return std::unique_ptr<DeviceDelegate>(new DeviceDelegateImpl(
+ task_runner, http_port, https_port, http_request_timeout));
}
} // namespace privet
diff --git a/src/privet/device_ui_kind.cc b/src/privet/device_ui_kind.cc
index 8909bed..cc740e8 100644
--- a/src/privet/device_ui_kind.cc
+++ b/src/privet/device_ui_kind.cc
@@ -12,9 +12,9 @@
namespace privet {
std::string GetDeviceUiKind(const std::string& manifest_id) {
-
// Map of device short id to ui device kind
static const std::unordered_map<std::string, std::string> device_kind_map = {
+ // clang-format off
{"AC", "accessPoint"},
{"AK", "aggregator"},
{"AM", "camera"},
@@ -28,7 +28,8 @@
{"AL", "storage"},
{"AJ", "toy"},
{"AA", "vendor"},
- {"AN", "video"}
+ {"AN", "video"},
+ // clang-format on
};
CHECK_EQ(5u, manifest_id.size());
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h
index 6762481..de94fe9 100644
--- a/src/privet/mock_delegates.h
+++ b/src/privet/mock_delegates.h
@@ -13,6 +13,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "src/config.h"
#include "src/privet/cloud_delegate.h"
#include "src/privet/device_delegate.h"
#include "src/privet/security_delegate.h"
@@ -24,6 +25,7 @@
using testing::SetArgPointee;
namespace weave {
+
namespace privet {
ACTION_TEMPLATE(RunCallback,
@@ -45,9 +47,10 @@
MOCK_CONST_METHOD0(GetHttpEnpoint, IntPair());
MOCK_CONST_METHOD0(GetHttpsEnpoint, IntPair());
MOCK_CONST_METHOD0(GetHttpRequestTimeout, base::TimeDelta());
- MOCK_METHOD3(PostDelayedTask, void(const tracked_objects::Location&,
- const base::Closure&,
- base::TimeDelta));
+ MOCK_METHOD3(PostDelayedTask,
+ void(const tracked_objects::Location&,
+ const base::Closure&,
+ base::TimeDelta));
MockDeviceDelegate() {
EXPECT_CALL(*this, GetHttpEnpoint())
@@ -64,8 +67,8 @@
UserInfo(const std::string&, base::Time*));
MOCK_CONST_METHOD0(GetPairingTypes, std::set<PairingType>());
MOCK_CONST_METHOD0(GetCryptoTypes, std::set<CryptoType>());
- MOCK_METHOD0(ClaimRootClientAuthToken, std::string());
- MOCK_METHOD1(ConfirmAuthToken, bool(const std::string& token));
+ MOCK_METHOD1(ClaimRootClientAuthToken, std::string(ErrorPtr*));
+ MOCK_METHOD2(ConfirmClientAuthToken, bool(const std::string&, ErrorPtr*));
MOCK_CONST_METHOD1(IsValidPairingCode, bool(const std::string&));
MOCK_METHOD5(
StartPairing,
@@ -82,9 +85,12 @@
EXPECT_CALL(*this, CreateAccessToken(_))
.WillRepeatedly(Return("GuestAccessToken"));
- EXPECT_CALL(*this, ClaimRootClientAuthToken())
+ EXPECT_CALL(*this, ClaimRootClientAuthToken(_))
.WillRepeatedly(Return("RootClientAuthToken"));
+ EXPECT_CALL(*this, ConfirmClientAuthToken("DerivedClientAuthToken", _))
+ .WillRepeatedly(Return(true));
+
EXPECT_CALL(*this, ParseAccessToken(_, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()),
Return(UserInfo{AuthScope::kViewer, 1234567})));
@@ -192,8 +198,8 @@
EXPECT_CALL(*this, GetCloudId()).WillRepeatedly(Return("TestCloudId"));
test_dict_.Set("test", new base::DictionaryValue);
EXPECT_CALL(*this, GetLegacyState()).WillRepeatedly(ReturnRef(test_dict_));
- EXPECT_CALL(*this,
- GetLegacyCommandDef()).WillRepeatedly(ReturnRef(test_dict_));
+ EXPECT_CALL(*this, GetLegacyCommandDef())
+ .WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, GetTraits()).WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, GetComponents()).WillRepeatedly(ReturnRef(test_dict_));
EXPECT_CALL(*this, FindComponent(_, _)).Times(0);
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index 86a2a85..57c8633 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -17,6 +17,7 @@
#include <weave/enum_to_string.h>
#include <weave/provider/task_runner.h>
+#include "src/config.h"
#include "src/http_constants.h"
#include "src/privet/cloud_delegate.h"
#include "src/privet/constants.h"
@@ -90,6 +91,7 @@
const char kAuthTokenTypeKey[] = "tokenType";
const char kAuthExpiresInKey[] = "expiresIn";
const char kAuthScopeKey[] = "scope";
+const char kAuthClientTokenKey[] = "clientToken";
const char kAuthorizationHeaderPrefix[] = "Privet";
@@ -153,6 +155,7 @@
{errors::kInvalidState, http::kInternalServerError},
{errors::kNotFound, http::kNotFound},
{errors::kNotImplemented, http::kNotSupported},
+ {errors::kAlreadyClaimed, http::kDenied},
};
AuthScope AuthScopeFromString(const std::string& scope, AuthScope auto_scope) {
@@ -391,7 +394,10 @@
SecurityDelegate* security,
WifiDelegate* wifi,
base::Clock* clock)
- : cloud_(cloud), device_(device), security_(security), wifi_(wifi),
+ : cloud_(cloud),
+ device_(device),
+ security_(security),
+ wifi_(wifi),
clock_(clock ? clock : &default_clock_) {
CHECK(cloud_);
CHECK(device_);
@@ -409,10 +415,15 @@
AddSecureHandler("/privet/v3/auth", &PrivetHandler::HandleAuth,
AuthScope::kNone);
+ AddSecureHandler("/privet/v3/accessControl/claim",
+ &PrivetHandler::HandleAccessControlClaim, AuthScope::kOwner);
+ AddSecureHandler("/privet/v3/accessControl/confirm",
+ &PrivetHandler::HandleAccessControlConfirm,
+ AuthScope::kOwner);
AddSecureHandler("/privet/v3/setup/start", &PrivetHandler::HandleSetupStart,
- AuthScope::kOwner);
+ AuthScope::kManager);
AddSecureHandler("/privet/v3/setup/status", &PrivetHandler::HandleSetupStatus,
- AuthScope::kOwner);
+ AuthScope::kManager);
AddSecureHandler("/privet/v3/state", &PrivetHandler::HandleState,
AuthScope::kViewer);
AddSecureHandler("/privet/v3/commandDefs", &PrivetHandler::HandleCommandDefs,
@@ -738,6 +749,40 @@
callback.Run(http::kOk, output);
}
+void PrivetHandler::HandleAccessControlClaim(const base::DictionaryValue& input,
+ const UserInfo& user_info,
+ const RequestCallback& callback) {
+ ErrorPtr error;
+ auto token = security_->ClaimRootClientAuthToken(&error);
+ if (token.empty())
+ return ReturnError(*error, callback);
+
+ base::DictionaryValue output;
+ output.SetString(kAuthClientTokenKey, token);
+ callback.Run(http::kOk, output);
+}
+
+void PrivetHandler::HandleAccessControlConfirm(
+ const base::DictionaryValue& input,
+ const UserInfo& user_info,
+ const RequestCallback& callback) {
+ ErrorPtr error;
+
+ std::string token;
+ if (!input.GetString(kAuthClientTokenKey, &token)) {
+ Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
+ errors::kInvalidParams, kInvalidParamValueFormat,
+ kAuthClientTokenKey, token.c_str());
+ return ReturnError(*error, callback);
+ }
+
+ if (!security_->ConfirmClientAuthToken(token, &error))
+ return ReturnError(*error, callback);
+
+ base::DictionaryValue output;
+ callback.Run(http::kOk, output);
+}
+
void PrivetHandler::HandleSetupStart(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback) {
@@ -776,6 +821,13 @@
const base::DictionaryValue* registration = nullptr;
if (input.GetDictionary(kGcdKey, ®istration)) {
+ if (user_info.scope() < AuthScope::kOwner) {
+ ErrorPtr error;
+ Error::AddTo(&error, FROM_HERE, errors::kDomain,
+ errors::kInvalidAuthorizationScope,
+ "Only owner can register device");
+ return ReturnError(*error, callback);
+ }
registration->GetString(kSetupStartTicketIdKey, &ticket);
if (ticket.empty()) {
ErrorPtr error;
@@ -1028,8 +1080,7 @@
output.SetString(kStateFingerprintKey, std::to_string(state_fingerprint_));
output.SetString(kCommandsFingerprintKey,
std::to_string(traits_fingerprint_));
- output.SetString(kTraitsFingerprintKey,
- std::to_string(traits_fingerprint_));
+ output.SetString(kTraitsFingerprintKey, std::to_string(traits_fingerprint_));
output.SetString(kComponentsFingerprintKey,
std::to_string(components_fingerprint_));
callback.Run(http::kOk, output);
diff --git a/src/privet/privet_handler.h b/src/privet/privet_handler.h
index 5241233..646cab2 100644
--- a/src/privet/privet_handler.h
+++ b/src/privet/privet_handler.h
@@ -94,6 +94,12 @@
void HandleAuth(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
+ void HandleAccessControlClaim(const base::DictionaryValue& input,
+ const UserInfo& user_info,
+ const RequestCallback& callback);
+ void HandleAccessControlConfirm(const base::DictionaryValue& input,
+ const UserInfo& user_info,
+ const RequestCallback& callback);
void HandleSetupStart(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index 20856f7..fcbd0d0 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -71,8 +71,8 @@
}
// Some error sections in response JSON objects contained debugging information
-// which is of no interest for this test. So, remove the debug info from the JSON
-// before running validation logic on it.
+// which is of no interest for this test. So, remove the debug info from the
+// JSON before running validation logic on it.
std::unique_ptr<base::DictionaryValue> StripDebugErrorDetails(
const std::string& path_to_error_object,
const base::DictionaryValue& value) {
@@ -97,8 +97,8 @@
.WillRepeatedly(Return(base::Time::FromTimeT(1410000001)));
auth_header_ = "Privet anonymous";
- handler_.reset(new PrivetHandler(&cloud_, &device_, &security_, &wifi_,
- &clock_));
+ handler_.reset(
+ new PrivetHandler(&cloud_, &device_, &security_, &wifi_, &clock_));
}
const base::DictionaryValue& HandleRequest(
@@ -129,8 +129,8 @@
int GetResponseCount() const { return response_count_; }
void SetNoWifiAndGcd() {
- handler_.reset(new PrivetHandler(&cloud_, &device_, &security_, nullptr,
- &clock_));
+ handler_.reset(
+ new PrivetHandler(&cloud_, &device_, &security_, nullptr, &clock_));
EXPECT_CALL(cloud_, GetCloudId()).WillRepeatedly(Return(""));
EXPECT_CALL(cloud_, GetConnectionState())
.WillRepeatedly(ReturnRef(gcd_disabled_state_));
@@ -339,9 +339,8 @@
}
TEST_F(PrivetHandlerTest, PairingCancel) {
- EXPECT_JSON_EQ("{}",
- HandleRequest("/privet/v3/pairing/cancel",
- "{'sessionId': 'testSession'}"));
+ EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/pairing/cancel",
+ "{'sessionId': 'testSession'}"));
}
TEST_F(PrivetHandlerTest, AuthErrorNoType) {
@@ -459,9 +458,8 @@
}
})";
EXPECT_JSON_EQ(kExpected,
- *StripDebugErrorDetails("wifi",
- HandleRequest(
- "/privet/v3/setup/status", "{}")));
+ *StripDebugErrorDetails(
+ "wifi", HandleRequest("/privet/v3/setup/status", "{}")));
}
TEST_F(PrivetHandlerSetupTest, StatusGcd) {
@@ -490,9 +488,8 @@
}
})";
EXPECT_JSON_EQ(kExpected,
- *StripDebugErrorDetails("gcd",
- HandleRequest(
- "/privet/v3/setup/status", "{}")));
+ *StripDebugErrorDetails(
+ "gcd", HandleRequest("/privet/v3/setup/status", "{}")));
}
TEST_F(PrivetHandlerSetupTest, SetupNameDescriptionLocation) {
@@ -597,7 +594,33 @@
EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/start", kInput));
}
-TEST_F(PrivetHandlerSetupTest, State) {
+TEST_F(PrivetHandlerSetupTest, GcdSetupAsMaster) {
+ EXPECT_CALL(security_, ParseAccessToken(_, _))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()),
+ Return(UserInfo{AuthScope::kManager, 1})));
+ const char kInput[] = R"({
+ 'gcd': {
+ 'ticketId': 'testTicket',
+ 'user': 'testUser'
+ }
+ })";
+
+ EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthorizationScope"),
+ HandleRequest("/privet/v3/setup/start", kInput));
+}
+
+TEST_F(PrivetHandlerTestWithAuth, ClaimAccessControl) {
+ EXPECT_JSON_EQ("{'clientToken': 'RootClientAuthToken'}",
+ HandleRequest("/privet/v3/accessControl/claim", "{}"));
+}
+
+TEST_F(PrivetHandlerTestWithAuth, ConfirmAccessControl) {
+ EXPECT_JSON_EQ("{}",
+ HandleRequest("/privet/v3/accessControl/confirm",
+ "{'clientToken': 'DerivedClientAuthToken'}"));
+}
+
+TEST_F(PrivetHandlerTestWithAuth, State) {
EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/state", "{}"));
@@ -607,7 +630,7 @@
HandleRequest("/privet/v3/state", "{}"));
}
-TEST_F(PrivetHandlerSetupTest, CommandsDefs) {
+TEST_F(PrivetHandlerTestWithAuth, CommandsDefs) {
EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/commandDefs", "{}"));
@@ -617,7 +640,7 @@
HandleRequest("/privet/v3/commandDefs", "{}"));
}
-TEST_F(PrivetHandlerSetupTest, Traits) {
+TEST_F(PrivetHandlerTestWithAuth, Traits) {
EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/traits", "{}"));
@@ -627,7 +650,7 @@
HandleRequest("/privet/v3/traits", "{}"));
}
-TEST_F(PrivetHandlerSetupTest, Components) {
+TEST_F(PrivetHandlerTestWithAuth, Components) {
EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '1'}",
HandleRequest("/privet/v3/components", "{}"));
@@ -643,7 +666,7 @@
HandleRequest("/privet/v3/components", "{}"));
}
-TEST_F(PrivetHandlerSetupTest, ComponentsWithFiltersAndPaths) {
+TEST_F(PrivetHandlerTestWithAuth, ComponentsWithFiltersAndPaths) {
const char kComponents[] = R"({
"comp1": {
"traits": ["a", "b"],
@@ -747,8 +770,7 @@
const base::DictionaryValue* comp2 = nullptr;
ASSERT_TRUE(components.GetDictionary("comp1.components.comp2", &comp2));
- EXPECT_CALL(cloud_, FindComponent("comp1.comp2", _))
- .WillOnce(Return(comp2));
+ EXPECT_CALL(cloud_, FindComponent("comp1.comp2", _)).WillOnce(Return(comp2));
const char kExpected5[] = R"({
"components": {
@@ -763,9 +785,11 @@
},
"fingerprint": "1"
})";
- EXPECT_JSON_EQ(kExpected5, HandleRequest(
- "/privet/v3/components",
- "{'path':'comp1.comp2', 'filter':['traits', 'components']}"));
+ EXPECT_JSON_EQ(
+ kExpected5,
+ HandleRequest(
+ "/privet/v3/components",
+ "{'path':'comp1.comp2', 'filter':['traits', 'components']}"));
auto error_handler = [](ErrorPtr* error) -> const base::DictionaryValue* {
Error::AddTo(error, FROM_HERE, errors::kDomain, "componentNotFound", "");
@@ -775,14 +799,12 @@
.WillOnce(WithArgs<1>(Invoke(error_handler)));
EXPECT_PRED2(
- IsEqualError,
- CodeWithReason(500, "componentNotFound"),
- HandleRequest(
- "/privet/v3/components",
- "{'path':'comp7', 'filter':['traits', 'components']}"));
+ IsEqualError, CodeWithReason(500, "componentNotFound"),
+ HandleRequest("/privet/v3/components",
+ "{'path':'comp7', 'filter':['traits', 'components']}"));
}
-TEST_F(PrivetHandlerSetupTest, CommandsExecute) {
+TEST_F(PrivetHandlerTestWithAuth, CommandsExecute) {
const char kInput[] = "{'name': 'test'}";
base::DictionaryValue command;
LoadTestJson(kInput, &command);
@@ -797,7 +819,7 @@
HandleRequest("/privet/v3/commands/execute", kInput));
}
-TEST_F(PrivetHandlerSetupTest, CommandsStatus) {
+TEST_F(PrivetHandlerTestWithAuth, CommandsStatus) {
const char kInput[] = "{'id': '5'}";
base::DictionaryValue command;
LoadTestJson(kInput, &command);
@@ -823,7 +845,7 @@
HandleRequest("/privet/v3/commands/status", "{'id': '15'}"));
}
-TEST_F(PrivetHandlerSetupTest, CommandsCancel) {
+TEST_F(PrivetHandlerTestWithAuth, CommandsCancel) {
const char kExpected[] = "{'id': '5', 'name':'test', 'state':'cancelled'}";
base::DictionaryValue command;
LoadTestJson(kExpected, &command);
@@ -848,7 +870,7 @@
HandleRequest("/privet/v3/commands/cancel", "{'id': '11'}"));
}
-TEST_F(PrivetHandlerSetupTest, CommandsList) {
+TEST_F(PrivetHandlerTestWithAuth, CommandsList) {
const char kExpected[] = R"({
'commands' : [
{'id':'5', 'state':'cancelled'},
diff --git a/src/privet/privet_manager.cc b/src/privet/privet_manager.cc
index 16c552e..c3f3885 100644
--- a/src/privet/privet_manager.cc
+++ b/src/privet/privet_manager.cc
@@ -58,8 +58,8 @@
device_ = DeviceDelegate::CreateDefault(
task_runner_, http_server->GetHttpPort(), http_server->GetHttpsPort(),
http_server->GetRequestTimeout());
- cloud_ = CloudDelegate::CreateDefault(task_runner_, device,
- component_manager);
+ cloud_ =
+ CloudDelegate::CreateDefault(task_runner_, device, component_manager);
cloud_observer_.Add(cloud_.get());
security_.reset(new SecurityManager(
diff --git a/src/privet/privet_types.cc b/src/privet/privet_types.cc
index ab026e1..7c85937 100644
--- a/src/privet/privet_types.cc
+++ b/src/privet/privet_types.cc
@@ -53,6 +53,7 @@
{AuthScope::kNone, "none"},
{AuthScope::kViewer, "viewer"},
{AuthScope::kUser, "user"},
+ {AuthScope::kManager, "manager"},
{AuthScope::kOwner, "owner"},
};
diff --git a/src/privet/security_delegate.h b/src/privet/security_delegate.h
index 3446c48..54f957d 100644
--- a/src/privet/security_delegate.h
+++ b/src/privet/security_delegate.h
@@ -35,11 +35,12 @@
virtual std::set<CryptoType> GetCryptoTypes() const = 0;
// Returns Root Client Authorization Token.
- virtual std::string ClaimRootClientAuthToken() = 0;
+ virtual std::string ClaimRootClientAuthToken(ErrorPtr* error) = 0;
// Confirms pending pending token claim or checks that token is valid for the
// active secret.
- virtual bool ConfirmAuthToken(const std::string& token) = 0;
+ virtual bool ConfirmClientAuthToken(const std::string& token,
+ ErrorPtr* error) = 0;
// Returns true if |auth_code| provided by client is valid. Client should
// obtain |auth_code| during pairing process.
diff --git a/src/privet/security_manager.cc b/src/privet/security_manager.cc
index 5fa41be..d2025b1 100644
--- a/src/privet/security_manager.cc
+++ b/src/privet/security_manager.cc
@@ -135,16 +135,21 @@
return result;
}
-std::string SecurityManager::ClaimRootClientAuthToken() {
- return Base64Encode(
- auth_manager_->ClaimRootClientAuthToken(RootClientTokenOwner::kClient));
+std::string SecurityManager::ClaimRootClientAuthToken(ErrorPtr* error) {
+ return Base64Encode(auth_manager_->ClaimRootClientAuthToken(
+ RootClientTokenOwner::kClient, error));
}
-bool SecurityManager::ConfirmAuthToken(const std::string& token) {
+bool SecurityManager::ConfirmClientAuthToken(const std::string& token,
+ ErrorPtr* error) {
std::vector<uint8_t> token_decoded;
- if (!Base64Decode(token, &token_decoded))
+ if (!Base64Decode(token, &token_decoded)) {
+ Error::AddToPrintf(error, FROM_HERE, errors::kDomain,
+ errors::kInvalidFormat,
+ "Invalid auth token string: '%s'", token.c_str());
return false;
- return auth_manager_->ConfirmAuthToken(token_decoded);
+ }
+ return auth_manager_->ConfirmClientAuthToken(token_decoded, error);
}
bool SecurityManager::IsValidPairingCode(const std::string& auth_code) const {
diff --git a/src/privet/security_manager.h b/src/privet/security_manager.h
index 5d9b75a..93618d2 100644
--- a/src/privet/security_manager.h
+++ b/src/privet/security_manager.h
@@ -65,8 +65,9 @@
base::Time* time) const override;
std::set<PairingType> GetPairingTypes() const override;
std::set<CryptoType> GetCryptoTypes() const override;
- std::string ClaimRootClientAuthToken() override;
- bool ConfirmAuthToken(const std::string& token) override;
+ std::string ClaimRootClientAuthToken(ErrorPtr* error) override;
+ bool ConfirmClientAuthToken(const std::string& token,
+ ErrorPtr* error) override;
bool IsValidPairingCode(const std::string& auth_code) const override;
bool StartPairing(PairingType mode,
@@ -85,8 +86,6 @@
void RegisterPairingListeners(const PairingStartListener& on_start,
const PairingEndListener& on_end);
- const AuthManager* GetAuthManager() const { return auth_manager_; }
-
private:
FRIEND_TEST_ALL_PREFIXES(SecurityManagerTest, ThrottlePairing);
// Allows limited number of new sessions without successful authorization.
diff --git a/src/privet/wifi_bootstrap_manager.cc b/src/privet/wifi_bootstrap_manager.cc
index 292622d..086e21c 100644
--- a/src/privet/wifi_bootstrap_manager.cc
+++ b/src/privet/wifi_bootstrap_manager.cc
@@ -12,8 +12,8 @@
#include <weave/provider/wifi.h>
#include "src/bind_lambda.h"
-#include "src/privet/constants.h"
#include "src/config.h"
+#include "src/privet/constants.h"
namespace weave {
namespace privet {
diff --git a/src/states/state_change_queue.h b/src/states/state_change_queue.h
index 3aef8d5..1539ffc 100644
--- a/src/states/state_change_queue.h
+++ b/src/states/state_change_queue.h
@@ -32,9 +32,8 @@
public:
explicit StateChangeQueue(size_t max_queue_size);
- bool NotifyPropertiesUpdated(
- base::Time timestamp,
- const base::DictionaryValue& changed_properties);
+ bool NotifyPropertiesUpdated(base::Time timestamp,
+ const base::DictionaryValue& changed_properties);
std::vector<StateChange> GetAndClearRecordedStateChanges();
private:
diff --git a/src/states/state_change_queue_unittest.cc b/src/states/state_change_queue_unittest.cc
index 57cf490..7eeaa28 100644
--- a/src/states/state_change_queue_unittest.cc
+++ b/src/states/state_change_queue_unittest.cc
@@ -43,10 +43,10 @@
auto timestamp2 = timestamp1 + base::TimeDelta::FromSeconds(1);
const std::string state2 =
"{'prop': {'name1': 17, 'name2': 1.0, 'name3': false}}";
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- timestamp1, *CreateDictionaryValue(state1)));
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- timestamp2, *CreateDictionaryValue(state2)));
+ ASSERT_TRUE(queue_->NotifyPropertiesUpdated(timestamp1,
+ *CreateDictionaryValue(state1)));
+ ASSERT_TRUE(queue_->NotifyPropertiesUpdated(timestamp2,
+ *CreateDictionaryValue(state2)));
auto changes = queue_->GetAndClearRecordedStateChanges();
ASSERT_EQ(2u, changes.size());
@@ -111,8 +111,7 @@
EXPECT_EQ(start_time + time_delta1, changes[0].timestamp);
EXPECT_JSON_EQ(expected1, *changes[0].changed_properties);
- const std::string expected2 =
- "{'prop': {'name10': 10, 'name11': 11}}";
+ const std::string expected2 = "{'prop': {'name10': 10, 'name11': 11}}";
EXPECT_EQ(start_time + time_delta2, changes[1].timestamp);
EXPECT_JSON_EQ(expected2, *changes[1].changed_properties);
}
diff --git a/src/streams_unittest.cc b/src/streams_unittest.cc
index fba6ca5..2eae050 100644
--- a/src/streams_unittest.cc
+++ b/src/streams_unittest.cc
@@ -5,6 +5,7 @@
#include "src/streams.h"
#include <functional>
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <weave/provider/test/fake_task_runner.h>
diff --git a/src/string_utils.cc b/src/string_utils.cc
index d4386f0..1604903 100644
--- a/src/string_utils.cc
+++ b/src/string_utils.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <algorithm>
#include <string.h>
+#include <algorithm>
#include <utility>
#include <base/strings/string_util.h>
diff --git a/src/test/fake_stream.cc b/src/test/fake_stream.cc
index 1101779..42c5fe2 100644
--- a/src/test/fake_stream.cc
+++ b/src/test/fake_stream.cc
@@ -49,9 +49,8 @@
size_t size_to_write,
const WriteCallback& callback) {
size_t size = std::min(size_to_write, write_data_.size());
- EXPECT_EQ(
- write_data_.substr(0, size),
- std::string(reinterpret_cast<const char*>(buffer), size_to_write));
+ EXPECT_EQ(write_data_.substr(0, size),
+ std::string(reinterpret_cast<const char*>(buffer), size_to_write));
write_data_ = write_data_.substr(size);
task_runner_->PostDelayedTask(FROM_HERE, base::Bind(callback, nullptr),
base::TimeDelta::FromSeconds(0));
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc
index 24c6973..987b0c4 100644
--- a/src/weave_unittest.cc
+++ b/src/weave_unittest.cc
@@ -188,20 +188,20 @@
const UrlMatcher& url_matcher,
const std::string& json_response) {
EXPECT_CALL(http_client_, SendRequest(method, url_matcher, _, _, _))
- .WillOnce(WithArgs<4>(Invoke([json_response](
- const HttpClient::SendRequestCallback& callback) {
- std::unique_ptr<provider::test::MockHttpClientResponse> response{
- new StrictMock<provider::test::MockHttpClientResponse>};
- EXPECT_CALL(*response, GetStatusCode())
- .Times(AtLeast(1))
- .WillRepeatedly(Return(200));
- EXPECT_CALL(*response, GetContentType())
- .Times(AtLeast(1))
- .WillRepeatedly(Return("application/json; charset=utf-8"));
- EXPECT_CALL(*response, GetData())
- .WillRepeatedly(Return(json_response));
- callback.Run(std::move(response), nullptr);
- })));
+ .WillOnce(WithArgs<4>(Invoke(
+ [json_response](const HttpClient::SendRequestCallback& callback) {
+ std::unique_ptr<provider::test::MockHttpClientResponse> response{
+ new StrictMock<provider::test::MockHttpClientResponse>};
+ EXPECT_CALL(*response, GetStatusCode())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(200));
+ EXPECT_CALL(*response, GetContentType())
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return("application/json; charset=utf-8"));
+ EXPECT_CALL(*response, GetData())
+ .WillRepeatedly(Return(json_response));
+ callback.Run(std::move(response), nullptr);
+ })));
}
void InitConfigStore() {
@@ -281,23 +281,41 @@
&http_server_, &wifi_, &bluetooth_);
EXPECT_EQ((std::set<std::string>{
- "/privet/info", "/privet/v3/pairing/cancel",
- "/privet/v3/pairing/confirm", "/privet/v3/pairing/start"}),
+ // clang-format off
+ "/privet/info",
+ "/privet/v3/pairing/cancel",
+ "/privet/v3/pairing/confirm",
+ "/privet/v3/pairing/start",
+ // clang-format on
+ }),
GetKeys(http_handlers_));
EXPECT_EQ((std::set<std::string>{
- "/privet/info", "/privet/v3/auth",
- "/privet/v3/checkForUpdates", "/privet/v3/commandDefs",
- "/privet/v3/commands/cancel", "/privet/v3/commands/execute",
- "/privet/v3/commands/list", "/privet/v3/commands/status",
- "/privet/v3/components", "/privet/v3/pairing/cancel",
- "/privet/v3/pairing/confirm", "/privet/v3/pairing/start",
- "/privet/v3/setup/start", "/privet/v3/setup/status",
- "/privet/v3/state", "/privet/v3/traits"}),
+ // clang-format off
+ "/privet/info",
+ "/privet/v3/accessControl/claim",
+ "/privet/v3/accessControl/confirm",
+ "/privet/v3/auth",
+ "/privet/v3/checkForUpdates",
+ "/privet/v3/commandDefs",
+ "/privet/v3/commands/cancel",
+ "/privet/v3/commands/execute",
+ "/privet/v3/commands/list",
+ "/privet/v3/commands/status",
+ "/privet/v3/components",
+ "/privet/v3/pairing/cancel",
+ "/privet/v3/pairing/confirm",
+ "/privet/v3/pairing/start",
+ "/privet/v3/setup/start",
+ "/privet/v3/setup/status",
+ "/privet/v3/state",
+ "/privet/v3/traits",
+ // clang-format on
+ }),
GetKeys(https_handlers_));
device_->AddTraitDefinitionsFromJson(kTraitDefs);
- EXPECT_TRUE(device_->AddComponent("myComponent", {"trait1", "trait2"},
- nullptr));
+ EXPECT_TRUE(
+ device_->AddComponent("myComponent", {"trait1", "trait2"}, nullptr));
EXPECT_TRUE(device_->SetStatePropertiesFromJson(
"myComponent", R"({"trait2": {"battery_level":44}})", nullptr));
@@ -358,8 +376,8 @@
&network_, &dns_sd_, &http_server_, nullptr,
&bluetooth_);
device_->AddTraitDefinitionsFromJson(kTraitDefs);
- EXPECT_TRUE(device_->AddComponent("myComponent", {"trait1", "trait2"},
- nullptr));
+ EXPECT_TRUE(
+ device_->AddComponent("myComponent", {"trait1", "trait2"}, nullptr));
task_runner_.Run();
}