Commit e876b37d authored by stevenjb@chromium.org's avatar stevenjb@chromium.org

Add NetworkingPrivateDelegate class

This CL introduces NetworkingPrivateDelegate and moves (almost) all extension API specific code into a common NetworkingPrivateApi class.

The ChromeOS specific Delegate is now in networking_private_api_chromeos.cc (now a profile keyed service).

The Windows/Mac specific Delegate is now in networking_private_service_client.cc. networking_private_api_nonchromeos.cc has been deleted.

BUG=392708

Review URL: https://codereview.chromium.org/378103002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284019 0039d316-1c4b-4281-b951-d872f2087c98
parent c0233a18
...@@ -111,23 +111,24 @@ class TestListener : public content::NotificationObserver { ...@@ -111,23 +111,24 @@ class TestListener : public content::NotificationObserver {
// That will eliminate the need for mock implementation. // That will eliminate the need for mock implementation.
class CryptoVerifyStub class CryptoVerifyStub
: public extensions::NetworkingPrivateServiceClient::CryptoVerify { : public extensions::NetworkingPrivateServiceClient::CryptoVerify {
virtual void VerifyDestination(scoped_ptr<base::ListValue> args, virtual void VerifyDestination(const Credentials& verification_properties,
bool* verified, bool* verified,
std::string* error) OVERRIDE { std::string* error) OVERRIDE {
*verified = true; *verified = true;
} }
virtual void VerifyAndEncryptCredentials( virtual void VerifyAndEncryptCredentials(
scoped_ptr<base::ListValue> args, const std::string& network_guid,
const extensions::NetworkingPrivateServiceClient::CryptoVerify:: const Credentials& credentials,
VerifyAndEncryptCredentialsCallback& callback) OVERRIDE { const VerifyAndEncryptCredentialsCallback& callback) OVERRIDE {
callback.Run("encrypted_credentials", ""); callback.Run("encrypted_credentials", "");
} }
virtual void VerifyAndEncryptData(scoped_ptr<base::ListValue> args, virtual void VerifyAndEncryptData(const Credentials& verification_properties,
std::string* encoded_data, const std::string& data,
std::string* base64_encoded_ciphertext,
std::string* error) OVERRIDE { std::string* error) OVERRIDE {
*encoded_data = "encrypted_data"; *base64_encoded_ciphertext = "encrypted_data";
} }
}; };
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
......
// Copyright 2014 The Chromium 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 CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CHROMEOS_H_
#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CHROMEOS_H_
#include "chrome/browser/extensions/api/networking_private/networking_private_delegate.h"
#include "components/keyed_service/core/keyed_service.h"
namespace context {
class BrowserContext;
}
namespace extensions {
// Chrome OS NetworkingPrivateDelegate implementation.
class NetworkingPrivateChromeOS : public KeyedService,
public NetworkingPrivateDelegate {
public:
explicit NetworkingPrivateChromeOS(content::BrowserContext* browser_context);
// NetworkingPrivateApi
virtual void GetProperties(const std::string& guid,
const DictionaryCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void GetManagedProperties(
const std::string& guid,
const DictionaryCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void GetState(const std::string& guid,
const DictionaryCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void SetProperties(const std::string& guid,
scoped_ptr<base::DictionaryValue> properties,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void CreateNetwork(bool shared,
scoped_ptr<base::DictionaryValue> properties,
const StringCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void GetNetworks(const std::string& network_type,
bool configured_only,
bool visible_only,
int limit,
const NetworkListCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void StartConnect(const std::string& guid,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void StartDisconnect(
const std::string& guid,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void VerifyDestination(
const VerificationProperties& verification_properties,
const BoolCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void VerifyAndEncryptCredentials(
const std::string& guid,
const VerificationProperties& verification_properties,
const StringCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void VerifyAndEncryptData(
const VerificationProperties& verification_properties,
const std::string& data,
const StringCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void SetWifiTDLSEnabledState(
const std::string& ip_or_mac_address,
bool enabled,
const StringCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void GetWifiTDLSStatus(
const std::string& ip_or_mac_address,
const StringCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual void GetCaptivePortalStatus(
const std::string& guid,
const StringCallback& success_callback,
const FailureCallback& failure_callback) OVERRIDE;
virtual scoped_ptr<base::ListValue> GetEnabledNetworkTypes() OVERRIDE;
virtual bool EnableNetworkType(const std::string& type) OVERRIDE;
virtual bool DisableNetworkType(const std::string& type) OVERRIDE;
virtual bool RequestScan() OVERRIDE;
private:
virtual ~NetworkingPrivateChromeOS();
content::BrowserContext* browser_context_;
DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateChromeOS);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_CHROMEOS_H_
// Copyright 2014 The Chromium 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 CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_DELEGATE_H_
#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_DELEGATE_H_
#include <string>
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
namespace content {
class BrowserContext;
}
namespace extensions {
namespace api {
namespace networking_private {
struct VerificationProperties;
} // networking_private
} // api
// Base class for platform dependent networkingPrivate API implementations.
// All inputs and results for this class use ONC values. See
// networking_private.json for descriptions of the expected inputs and results.
class NetworkingPrivateDelegate {
public:
typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
DictionaryCallback;
typedef base::Callback<void()> VoidCallback;
typedef base::Callback<void(bool)> BoolCallback;
typedef base::Callback<void(const std::string&)> StringCallback;
typedef base::Callback<void(scoped_ptr<base::ListValue>)> NetworkListCallback;
typedef base::Callback<void(const std::string&)> FailureCallback;
typedef api::networking_private::VerificationProperties
VerificationProperties;
static NetworkingPrivateDelegate* GetForBrowserContext(
content::BrowserContext* browser_context);
// Asynchronous methods
virtual void GetProperties(const std::string& guid,
const DictionaryCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void GetManagedProperties(
const std::string& guid,
const DictionaryCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void GetState(const std::string& guid,
const DictionaryCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void SetProperties(const std::string& guid,
scoped_ptr<base::DictionaryValue> properties,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void CreateNetwork(bool shared,
scoped_ptr<base::DictionaryValue> properties,
const StringCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void GetNetworks(const std::string& network_type,
bool configured_only,
bool visible_only,
int limit,
const NetworkListCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void StartConnect(const std::string& guid,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void StartDisconnect(const std::string& guid,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void VerifyDestination(
const VerificationProperties& verification_properties,
const BoolCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void VerifyAndEncryptCredentials(
const std::string& guid,
const VerificationProperties& verification_properties,
const StringCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void VerifyAndEncryptData(
const VerificationProperties& verification_properties,
const std::string& data,
const StringCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void SetWifiTDLSEnabledState(
const std::string& ip_or_mac_address,
bool enabled,
const StringCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void GetWifiTDLSStatus(
const std::string& ip_or_mac_address,
const StringCallback& success_callback,
const FailureCallback& failure_callback) = 0;
virtual void GetCaptivePortalStatus(
const std::string& guid,
const StringCallback& success_callback,
const FailureCallback& failure_callback) = 0;
// Synchronous methods
// Returns a list of ONC type strings.
virtual scoped_ptr<base::ListValue> GetEnabledNetworkTypes() = 0;
// Returns true if the ONC network type |type| is enabled.
virtual bool EnableNetworkType(const std::string& type) = 0;
// Returns true if the ONC network type |type| is disabled.
virtual bool DisableNetworkType(const std::string& type) = 0;
// Returns true if a scan was requested. It may take many seconds for a scan
// to complete. The scan may or may not trigger API events when complete.
virtual bool RequestScan() = 0;
protected:
virtual ~NetworkingPrivateDelegate() {}
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_DELEGATE_H_
...@@ -81,7 +81,7 @@ void NetworkingPrivateEventRouterImpl::Shutdown() { ...@@ -81,7 +81,7 @@ void NetworkingPrivateEventRouterImpl::Shutdown() {
return; return;
listening_ = false; listening_ = false;
NetworkingPrivateServiceClient* process_client = NetworkingPrivateServiceClient* process_client =
NetworkingPrivateServiceClientFactory::GetForProfile(profile_); NetworkingPrivateServiceClientFactory::GetForBrowserContext(profile_);
process_client->RemoveObserver(this); process_client->RemoveObserver(this);
} }
...@@ -110,13 +110,13 @@ void NetworkingPrivateEventRouterImpl::StartOrStopListeningForNetworkChanges() { ...@@ -110,13 +110,13 @@ void NetworkingPrivateEventRouterImpl::StartOrStopListeningForNetworkChanges() {
if (should_listen && !listening_) { if (should_listen && !listening_) {
NetworkingPrivateServiceClient* process_client = NetworkingPrivateServiceClient* process_client =
NetworkingPrivateServiceClientFactory::GetForProfile(profile_); NetworkingPrivateServiceClientFactory::GetForBrowserContext(profile_);
process_client->AddObserver(this); process_client->AddObserver(this);
} }
if (!should_listen && listening_) { if (!should_listen && listening_) {
NetworkingPrivateServiceClient* process_client = NetworkingPrivateServiceClient* process_client =
NetworkingPrivateServiceClientFactory::GetForProfile(profile_); NetworkingPrivateServiceClientFactory::GetForBrowserContext(profile_);
process_client->RemoveObserver(this); process_client->RemoveObserver(this);
} }
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/networking_private/networking_private_factory_chromeos.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_chromeos.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_delegate.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_thread.h"
namespace extensions {
// static
NetworkingPrivateDelegate* NetworkingPrivateDelegate::GetForBrowserContext(
content::BrowserContext* browser_context) {
return NetworkingPrivateChromeOSFactory::GetForBrowserContext(
browser_context);
}
// static
NetworkingPrivateChromeOS*
NetworkingPrivateChromeOSFactory::GetForBrowserContext(
content::BrowserContext* browser_context) {
return static_cast<NetworkingPrivateChromeOS*>(
GetInstance()->GetServiceForBrowserContext(browser_context, true));
}
// static
NetworkingPrivateChromeOSFactory*
NetworkingPrivateChromeOSFactory::GetInstance() {
return Singleton<NetworkingPrivateChromeOSFactory>::get();
}
NetworkingPrivateChromeOSFactory::NetworkingPrivateChromeOSFactory()
: BrowserContextKeyedServiceFactory(
"NetworkingPrivateChromeOS",
BrowserContextDependencyManager::GetInstance()) {
}
NetworkingPrivateChromeOSFactory::~NetworkingPrivateChromeOSFactory() {
}
KeyedService* NetworkingPrivateChromeOSFactory::BuildServiceInstanceFor(
content::BrowserContext* browser_context) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return new NetworkingPrivateChromeOS(browser_context);
}
bool NetworkingPrivateChromeOSFactory::ServiceIsCreatedWithBrowserContext()
const {
return false;
}
bool NetworkingPrivateChromeOSFactory::ServiceIsNULLWhileTesting() const {
return false;
}
} // namespace extensions
// Copyright 2014 The Chromium 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 CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_FACTORY_CHROMEOS_H_
#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_FACTORY_CHROMEOS_H_
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace context {
class BrowserContext;
}
namespace extensions {
class NetworkingPrivateChromeOS;
class NetworkingPrivateChromeOSFactory
: public BrowserContextKeyedServiceFactory {
public:
static NetworkingPrivateChromeOS* GetForBrowserContext(
content::BrowserContext* browser_context);
static NetworkingPrivateChromeOSFactory* GetInstance();
private:
friend struct DefaultSingletonTraits<NetworkingPrivateChromeOSFactory>;
NetworkingPrivateChromeOSFactory();
virtual ~NetworkingPrivateChromeOSFactory();
// BrowserContextKeyedServiceFactory:
virtual KeyedService* BuildServiceInstanceFor(
content::BrowserContext* browser_context) const OVERRIDE;
virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
virtual bool ServiceIsNULLWhileTesting() const OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateChromeOSFactory);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_FACTORY_CHROMEOS_H_
...@@ -4,20 +4,26 @@ ...@@ -4,20 +4,26 @@
#include "chrome/browser/extensions/api/networking_private/networking_private_service_client_factory.h" #include "chrome/browser/extensions/api/networking_private/networking_private_service_client_factory.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_delegate.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_service_client.h" #include "chrome/browser/extensions/api/networking_private/networking_private_service_client.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_system_provider.h"
#include "extensions/browser/extensions_browser_client.h"
namespace extensions { namespace extensions {
// static
NetworkingPrivateDelegate* NetworkingPrivateDelegate::GetForBrowserContext(
content::BrowserContext* browser_context) {
return NetworkingPrivateServiceClientFactory::GetForBrowserContext(
browser_context);
}
// static // static
NetworkingPrivateServiceClient* NetworkingPrivateServiceClient*
NetworkingPrivateServiceClientFactory::GetForProfile(Profile* profile) { NetworkingPrivateServiceClientFactory::GetForBrowserContext(
content::BrowserContext* browser_context) {
return static_cast<NetworkingPrivateServiceClient*>( return static_cast<NetworkingPrivateServiceClient*>(
GetInstance()->GetServiceForBrowserContext(profile, true)); GetInstance()->GetServiceForBrowserContext(browser_context, true));
} }
// static // static
...@@ -30,7 +36,6 @@ NetworkingPrivateServiceClientFactory::NetworkingPrivateServiceClientFactory() ...@@ -30,7 +36,6 @@ NetworkingPrivateServiceClientFactory::NetworkingPrivateServiceClientFactory()
: BrowserContextKeyedServiceFactory( : BrowserContextKeyedServiceFactory(
"NetworkingPrivateServiceClient", "NetworkingPrivateServiceClient",
BrowserContextDependencyManager::GetInstance()) { BrowserContextDependencyManager::GetInstance()) {
DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
} }
NetworkingPrivateServiceClientFactory NetworkingPrivateServiceClientFactory
...@@ -38,7 +43,7 @@ NetworkingPrivateServiceClientFactory ...@@ -38,7 +43,7 @@ NetworkingPrivateServiceClientFactory
} }
KeyedService* NetworkingPrivateServiceClientFactory::BuildServiceInstanceFor( KeyedService* NetworkingPrivateServiceClientFactory::BuildServiceInstanceFor(
content::BrowserContext* profile) const { content::BrowserContext* browser_context) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return new NetworkingPrivateServiceClient( return new NetworkingPrivateServiceClient(
wifi::WiFiService::Create(), wifi::WiFiService::Create(),
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class Profile; namespace context {
class BrowserContext;
}
namespace extensions { namespace extensions {
...@@ -17,7 +19,8 @@ class NetworkingPrivateServiceClient; ...@@ -17,7 +19,8 @@ class NetworkingPrivateServiceClient;
class NetworkingPrivateServiceClientFactory class NetworkingPrivateServiceClientFactory
: public BrowserContextKeyedServiceFactory { : public BrowserContextKeyedServiceFactory {
public: public:
static NetworkingPrivateServiceClient* GetForProfile(Profile* profile); static NetworkingPrivateServiceClient* GetForBrowserContext(
content::BrowserContext* browser_context);
static NetworkingPrivateServiceClientFactory* GetInstance(); static NetworkingPrivateServiceClientFactory* GetInstance();
...@@ -29,7 +32,7 @@ class NetworkingPrivateServiceClientFactory ...@@ -29,7 +32,7 @@ class NetworkingPrivateServiceClientFactory
// BrowserContextKeyedServiceFactory: // BrowserContextKeyedServiceFactory:
virtual KeyedService* BuildServiceInstanceFor( virtual KeyedService* BuildServiceInstanceFor(
content::BrowserContext* profile) const OVERRIDE; content::BrowserContext* browser_context) const OVERRIDE;
virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE; virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
virtual bool ServiceIsNULLWhileTesting() const OVERRIDE; virtual bool ServiceIsNULLWhileTesting() const OVERRIDE;
......
...@@ -684,12 +684,17 @@ ...@@ -684,12 +684,17 @@
'browser/extensions/api/music_manager_private/device_id_win.cc', 'browser/extensions/api/music_manager_private/device_id_win.cc',
'browser/extensions/api/music_manager_private/music_manager_private_api.cc', 'browser/extensions/api/music_manager_private/music_manager_private_api.cc',
'browser/extensions/api/music_manager_private/music_manager_private_api.h', 'browser/extensions/api/music_manager_private/music_manager_private_api.h',
'browser/extensions/api/networking_private/networking_private_api.cc',
'browser/extensions/api/networking_private/networking_private_api.h', 'browser/extensions/api/networking_private/networking_private_api.h',
'browser/extensions/api/networking_private/networking_private_api_chromeos.cc', 'browser/extensions/api/networking_private/networking_private_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_chromeos.h',
'browser/extensions/api/networking_private/networking_private_delegate.h',
'browser/extensions/api/networking_private/networking_private_event_router.h', 'browser/extensions/api/networking_private/networking_private_event_router.h',
'browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc', 'browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_event_router_factory.cc', 'browser/extensions/api/networking_private/networking_private_event_router_factory.cc',
'browser/extensions/api/networking_private/networking_private_event_router_factory.h', 'browser/extensions/api/networking_private/networking_private_event_router_factory.h',
'browser/extensions/api/networking_private/networking_private_factory_chromeos.cc',
'browser/extensions/api/networking_private/networking_private_factory_chromeos.h',
'browser/extensions/api/notifications/notifications_api.cc', 'browser/extensions/api/notifications/notifications_api.cc',
'browser/extensions/api/notifications/notifications_api.h', 'browser/extensions/api/notifications/notifications_api.h',
'browser/extensions/api/omnibox/omnibox_api.cc', 'browser/extensions/api/omnibox/omnibox_api.cc',
...@@ -909,7 +914,6 @@ ...@@ -909,7 +914,6 @@
], ],
'chrome_browser_extensions_networking_private_sources': [ 'chrome_browser_extensions_networking_private_sources': [
'browser/extensions/api/networking_private/networking_private_api.h', 'browser/extensions/api/networking_private/networking_private_api.h',
'browser/extensions/api/networking_private/networking_private_api_nonchromeos.cc',
'browser/extensions/api/networking_private/networking_private_credentials_getter.h', 'browser/extensions/api/networking_private/networking_private_credentials_getter.h',
'browser/extensions/api/networking_private/networking_private_credentials_getter_mac.cc', 'browser/extensions/api/networking_private/networking_private_credentials_getter_mac.cc',
'browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc', 'browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc',
......
...@@ -11,9 +11,9 @@ var assertEq = chrome.test.assertEq; ...@@ -11,9 +11,9 @@ var assertEq = chrome.test.assertEq;
// Test properties for the verification API. // Test properties for the verification API.
var verificationProperties = { var verificationProperties = {
"certificate": "certificate", "certificate": "certificate",
"publicKey": "public_key", "publicKey": "cHVibGljX2tleQ==", // Base64("public_key")
"nonce": "nonce", "nonce": "nonce",
"signedData": "signed_data", "signedData": "c2lnbmVkX2RhdGE=", // Base64("signed_data")
"deviceSerial": "device_serial", "deviceSerial": "device_serial",
"deviceSsid": "Device 0123", "deviceSsid": "Device 0123",
"deviceBssid": "00:01:02:03:04:05" "deviceBssid": "00:01:02:03:04:05"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment