// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIBWEAVE_SRC_PRIVET_PRIVET_HANDLER_H_
#define LIBWEAVE_SRC_PRIVET_PRIVET_HANDLER_H_
#include <map>
#include <string>
#include <utility>
#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <base/scoped_observer.h>
#include <base/time/default_clock.h>
#include "src/privet/cloud_delegate.h"
namespace base {
class Value;
class DictionaryValue;
} // namespace base
namespace weave {
namespace privet {
class DeviceDelegate;
class IdentityDelegate;
class SecurityDelegate;
class WifiDelegate;
// Privet V3 HTTP/HTTPS requests handler.
// API details at https://developers.google.com/cloud-devices/
class PrivetHandler : public CloudDelegate::Observer {
public:
// Callback to handle requests asynchronously.
// |status| is HTTP status code.
// |output| is result returned in HTTP response. Contains result of
// successfully request of information about error.
using RequestCallback =
base::Callback<void(int status, const base::DictionaryValue& output)>;
PrivetHandler(CloudDelegate* cloud,
DeviceDelegate* device,
SecurityDelegate* pairing,
WifiDelegate* wifi,
base::Clock* clock = nullptr);
~PrivetHandler() override;
void OnTraitDefsChanged() override;
void OnStateChanged() override;
void OnComponentTreeChanged() override;
std::vector<std::string> GetHttpPaths() const;
std::vector<std::string> GetHttpsPaths() const;
// Handles HTTP/HTTPS Privet request.
// |api| is the path from the HTTP request, e.g /privet/info.
// |auth_header| is the Authentication header from HTTP request.
// |input| is the POST data from HTTP request. If nullptr, data format is
// not valid JSON.
// |callback| will be called exactly once during or after |HandleRequest|
// call.
void HandleRequest(const std::string& api,
const std::string& auth_header,
const base::DictionaryValue* input,
const RequestCallback& callback);
private:
using ApiHandler = void (PrivetHandler::*)(const base::DictionaryValue&,
const UserInfo&,
const RequestCallback&);
// Adds a handler for both HTTP and HTTPS interfaces.
void AddHandler(const std::string& path, ApiHandler handler, AuthScope scope);
// Adds a handler for both HTTPS interface only.
void AddSecureHandler(const std::string& path,
ApiHandler handler,
AuthScope scope);
void HandleInfo(const base::DictionaryValue&,
const UserInfo& user_info,
const RequestCallback& callback);
void HandlePairingStart(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandlePairingConfirm(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandlePairingCancel(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
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);
void HandleSetupStatus(const base::DictionaryValue&,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleState(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleCommandDefs(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleCommandsExecute(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleCommandsStatus(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleCommandsList(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleCommandsCancel(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleCheckForUpdates(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleTraits(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void HandleComponents(const base::DictionaryValue& input,
const UserInfo& user_info,
const RequestCallback& callback);
void ReplyWithSetupStatus(const RequestCallback& callback) const;
void ReplyToUpdateRequest(const RequestCallback& callback) const;
void OnUpdateRequestTimeout(int update_request_id);
CloudDelegate* cloud_{nullptr};
DeviceDelegate* device_{nullptr};
SecurityDelegate* security_{nullptr};
WifiDelegate* wifi_{nullptr};
base::DefaultClock default_clock_;
base::Clock* clock_{nullptr};
struct HandlerParameters {
ApiHandler handler;
AuthScope scope;
bool https_only = true;
};
std::map<std::string, HandlerParameters> handlers_;
struct UpdateRequestParameters {
RequestCallback callback;
int request_id{0};
uint64_t state_fingerprint{0};
uint64_t traits_fingerprint{0};
uint64_t components_fingerprint{0};
};
std::vector<UpdateRequestParameters> update_requests_;
int last_update_request_id_{0};
uint64_t state_fingerprint_{1};
uint64_t traits_fingerprint_{1};
uint64_t components_fingerprint_{1};
ScopedObserver<CloudDelegate, CloudDelegate::Observer> cloud_observer_{this};
base::WeakPtrFactory<PrivetHandler> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PrivetHandler);
};
} // namespace privet
} // namespace weave
#endif // LIBWEAVE_SRC_PRIVET_PRIVET_HANDLER_H_