Create an interface to make API requests which pass Client ID, Released mode and Model ID to Nearby Devices.

PiperOrigin-RevId: 500053224
This commit is contained in:
hai007
2023-01-06 03:03:31 -08:00
committed by Copybara-Service
parent 084f7ebd88
commit d347d0688b
7 changed files with 461 additions and 3 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ syntax = "proto3";
// Proto defined in this file needs be consistent with proto defined in
// google3/google/internal/location/nearby/device/v1/rpcs.proto.
package location.nearby.fastpair.proto;
package nearby.fastpair.proto;
option optimize_for = LITE_RUNTIME;
+53
View File
@@ -0,0 +1,53 @@
licenses(["notice"])
cc_library(
name = "repository",
srcs = [
"fast_pair_metadata_fetcher_impl.cc",
"fast_pair_metadata_repository_impl.cc",
],
hdrs = [
"fast_pair_metadata_fetcher.h",
"fast_pair_metadata_fetcher_impl.h",
"fast_pair_metadata_repository.h",
"fast_pair_metadata_repository_impl.h",
],
copts = [
"-Ithird_party",
],
visibility = ["//fastpair:__subpackages__"],
deps = [
"//fastpair/common",
"//fastpair/internal/api:platform",
"//fastpair/proto:fastpair_cc_proto",
"//internal/network:types",
"//internal/platform:logging",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)
cc_test(
name = "repository_test",
srcs = [
"fast_pair_metadata_fetcher_impl_test.cc",
"fast_pair_metadata_repository_impl_test.cc",
],
copts = [
"-Ithird_party",
],
deps = [
":repository",
"//fastpair/common",
"//fastpair/internal/test:nearby_fastpair_test",
"//fastpair/proto:fastpair_cc_proto",
"//internal/network:types",
"//internal/platform/implementation/g3",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
@@ -31,8 +31,7 @@ namespace fastpair {
class FastPairMetadataFetcher {
public:
using ResultCallback =
std::function<void(absl::string_view serialized_response)>;
using ResultCallback = std::function<void(absl::string_view result_response)>;
using ErrorCallback = std::function<void(FastPairHttpError error)>;
using QueryParameters = std::vector<std::pair<std::string, std::string>>;
@@ -0,0 +1,49 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_REPOSITORY_FAST_PAIR_METADATA_REPOSITORY_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_REPOSITORY_FAST_PAIR_METADATA_REPOSITORY_H_
#include <functional>
#include "absl/strings/string_view.h"
#include "fastpair/common/fast_pair_http_result.h"
namespace nearby {
namespace fastpair {
namespace proto {
class GetObservedDeviceRequest;
class GetObservedDeviceResponse;
} // namespace proto
class FastPairMetadataRepository {
public:
using ErrorCallback = std::function<void(FastPairHttpError)>;
using ObservedDeviceCallback =
std::function<void(const proto::GetObservedDeviceResponse&)>;
FastPairMetadataRepository() = default;
virtual ~FastPairMetadataRepository() = default;
virtual void GetObservedDevice(const proto::GetObservedDeviceRequest& request,
ObservedDeviceCallback callback,
ErrorCallback error_callback) = 0;
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_REPOSITORY_FAST_PAIR_METADATA_REPOSITORY_H_
@@ -0,0 +1,120 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/repository/fast_pair_metadata_repository_impl.h"
#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "fastpair/common/fast_pair_http_result.h"
#include "fastpair/proto/fastpair_rpcs.proto.h"
#include "fastpair/repository/fast_pair_metadata_fetcher.h"
#include "fastpair/repository/fast_pair_metadata_repository.h"
#include "internal/network/url.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
const char kDefaultNearbyDeviceV1HTTPHost[] =
"https://nearbydevices-pa.googleapis.com";
const char kNearbyShareV1Path[] = "v1";
const char kListDevicePath[] = "device";
const char kClientId[] = "AIzaSyBv7ZrOlX5oIJLVQrZh-WkZFKm5L6FlStQ";
const char kMode[] = "mode";
const char* GetObservedDeviceMode[3] = {"MODE_UNKNOWN", "MODE_RELEASE",
"MODE_DEBUG"};
FastPairMetadataRepositoryImpl::FastPairMetadataRepositoryImpl(
std::unique_ptr<FastPairMetadataFetcher> fetcher,
std::unique_ptr<network::HttpClient> http_client)
: fetcher_(std::move(fetcher)), http_client_(std::move(http_client)) {}
FastPairMetadataRepositoryImpl::~FastPairMetadataRepositoryImpl() = default;
// Create full fastpair v1 URL
nearby::network::Url CreateV1DeviceRequestUrlPath(
const proto::GetObservedDeviceRequest& request) {
std::string path = absl::StrFormat(
"%s/%s/%s/%s", kDefaultNearbyDeviceV1HTTPHost, kNearbyShareV1Path,
kListDevicePath, std::to_string(request.device_id()));
return nearby::network::Url::Create(path).value();
}
FastPairMetadataFetcher::QueryParameters
GetObservedDeviceRequestToQueryParameters(
const proto::GetObservedDeviceRequest& request) {
FastPairMetadataFetcher::QueryParameters params;
params.push_back({"key", kClientId});
params.push_back({kMode, GetObservedDeviceMode[request.mode()]});
return params;
}
void FastPairMetadataRepositoryImpl::GetObservedDevice(
const proto::GetObservedDeviceRequest& request,
ObservedDeviceCallback callback, ErrorCallback error_callback) {
ObservedDeviceCallback new_callback =
[=](const proto::GetObservedDeviceResponse& response) {
callback(response);
};
ErrorCallback new_error_callback = [=](FastPairHttpError error) {
error_callback(error);
};
MakeUnauthFetcher(CreateV1DeviceRequestUrlPath(request),
GetObservedDeviceRequestToQueryParameters(request),
new_callback, new_error_callback);
}
void FastPairMetadataRepositoryImpl::MakeUnauthFetcher(
const nearby::network::Url& request_url,
const std::optional<FastPairMetadataFetcher::QueryParameters>&
request_as_query_parameters,
ObservedDeviceCallback response_callback, ErrorCallback error_callback) {
has_call_started_ = true;
request_url_ = request_url;
error_callback_ = std::move(error_callback);
fetcher_->StartGetUnauthRequest(
request_url_, *request_as_query_parameters, http_client_.get(),
[&, response_callback =
std::move(response_callback)](absl::string_view result_response) {
OnFetcherSuccess(response_callback, result_response);
},
[&](FastPairHttpError error) { OnFetcherFailed(error); });
}
void FastPairMetadataRepositoryImpl::OnFetcherSuccess(
ObservedDeviceCallback callback, absl::string_view result_response) {
proto::GetObservedDeviceResponse response;
if (!response.ParseFromString(result_response)) {
OnFetcherFailed(FastPairHttpError::kHttpErrorOtherFailure);
return;
}
callback(response);
}
void FastPairMetadataRepositoryImpl::OnFetcherFailed(FastPairHttpError error) {
NEARBY_LOGS(ERROR)
<< "Fast pair server accessing RPC call failed with error. " << error;
error_callback_(error);
}
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,70 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_REPOSITORY_FAST_PAIR_METADATA_REPOSITORY_IMPL_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_REPOSITORY_FAST_PAIR_METADATA_REPOSITORY_IMPL_H_
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "fastpair/repository/fast_pair_metadata_fetcher.h"
#include "fastpair/repository/fast_pair_metadata_repository.h"
#include "internal/network/http_client.h"
namespace nearby {
namespace fastpair {
class FastPairMetadataRepositoryImpl : public FastPairMetadataRepository {
public:
FastPairMetadataRepositoryImpl(
std::unique_ptr<FastPairMetadataFetcher> fetcher,
std::unique_ptr<network::HttpClient> http_client);
~FastPairMetadataRepositoryImpl() override;
FastPairMetadataRepositoryImpl(FastPairMetadataRepositoryImpl&) = delete;
FastPairMetadataRepositoryImpl& operator=(FastPairMetadataRepositoryImpl&) =
delete;
void GetObservedDevice(const proto::GetObservedDeviceRequest& request,
ObservedDeviceCallback response_callback,
ErrorCallback error_callback) override;
private:
void MakeUnauthFetcher(
const nearby::network::Url& request_url,
const std::optional<FastPairMetadataFetcher::QueryParameters>&
request_as_query_parameters,
ObservedDeviceCallback response_callback, ErrorCallback error_callback);
// Called when the fetcher success fails at any step.
void OnFetcherSuccess(ObservedDeviceCallback callback,
absl::string_view result_response);
// Called when the fetcher fails at any step.
void OnFetcherFailed(FastPairHttpError error);
bool has_call_started_;
std::unique_ptr<FastPairMetadataFetcher> fetcher_;
std::unique_ptr<nearby::network::HttpClient> http_client_;
nearby::network::Url request_url_;
ErrorCallback error_callback_;
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_REPOSITORY_FAST_PAIR_METADATA_REPOSITORY_IMPL_H_
@@ -0,0 +1,167 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/repository/fast_pair_metadata_repository_impl.h"
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "fastpair/common/fast_pair_http_result.h"
#include "fastpair/internal/test/fast_pair_fake_http_client.h"
#include "fastpair/proto/fastpair_rpcs.proto.h"
#include "fastpair/repository/fast_pair_metadata_fetcher.h"
#include "fastpair/repository/fast_pair_metadata_repository.h"
#include "internal/network/url.h"
namespace nearby {
namespace fastpair {
using ::nearby::network::HttpClient;
using ::nearby::network::Url;
const char kImageUrl[] = "https://example.com/image.jpg";
const char kListDevicePath[] = "device/";
const char kClientId[] = "AIzaSyBv7ZrOlX5oIJLVQrZh-WkZFKm5L6FlStQ";
const char kTestGoogleApisUrl[] = "https://nearbydevices-pa.googleapis.com";
constexpr int64_t kDeviceId = 10148625;
const char kDeviceName[] = "devicename";
class FakeFastPairMetadataFetcher : public FastPairMetadataFetcher {
public:
FakeFastPairMetadataFetcher() = default;
~FakeFastPairMetadataFetcher() override = default;
FakeFastPairMetadataFetcher(const FakeFastPairMetadataFetcher&) = delete;
FakeFastPairMetadataFetcher& operator=(const FakeFastPairMetadataFetcher&) =
delete;
void StartGetUnauthRequest(const Url& request_url,
const QueryParameters& request_as_query_parameters,
HttpClient* http_client,
ResultCallback result_callback,
ErrorCallback error_callback) override {
request_url_ = request_url;
request_as_query_parameters_ = request_as_query_parameters;
http_client_ = http_client;
result_callback_ = result_callback;
error_callback_ = error_callback;
}
Url request_url_;
QueryParameters request_as_query_parameters_;
HttpClient* http_client_;
ResultCallback result_callback_;
ErrorCallback error_callback_;
};
std::vector<std::string> ExpectQueryStringValues(
const FastPairMetadataFetcher::QueryParameters& query_parameters,
absl::string_view key) {
std::vector<std::string> values;
for (const auto& pair : query_parameters) {
const auto& query_key = pair.first;
const auto& query_value = pair.second;
if (query_key == key) {
values.push_back(query_value);
}
}
EXPECT_GT(values.size(), 0);
return values;
}
class FastPairMetadataRepositoryImplTest : public ::testing::Test {
protected:
FastPairMetadataRepositoryImplTest() = default;
void SetUp() override {
http_client_ = std::make_unique<network::FastPairFakeHttpClient>();
SetNearbySharedHttpHost(kTestGoogleApisUrl);
auto fetcher = std::make_unique<FakeFastPairMetadataFetcher>();
fetcher_ = fetcher.get();
repository_ = std::make_unique<FastPairMetadataRepositoryImpl>(
std::move(fetcher), std::move(http_client_));
}
void SetNearbySharedHttpHost(const std::string& host) {
int global_host_size = 0;
char global_host[256];
if (host.size() > 256) {
return;
}
global_host_size = host.size();
memcpy(global_host, host.c_str(), global_host_size);
}
const FastPairMetadataFetcher::QueryParameters&
request_as_query_parameters() {
return fetcher_->request_as_query_parameters_;
}
const Url& request_url() { return fetcher_->request_url_; }
Url GetUrl(absl::string_view path) {
return Url::Create(
absl::StrCat(kTestGoogleApisUrl, "/v1/", kListDevicePath, path))
.value();
}
FakeFastPairMetadataFetcher* fetcher_;
std::unique_ptr<HttpClient> http_client_;
std::unique_ptr<FastPairMetadataRepository> repository_;
Url request_url_;
FastPairMetadataFetcher::QueryParameters request_as_query_parameters_;
FastPairMetadataFetcher::ResultCallback result_callback_;
FastPairMetadataFetcher::ErrorCallback error_callback_;
};
TEST_F(FastPairMetadataRepositoryImplTest, GetObservedDeviceSuccess) {
proto::GetObservedDeviceRequest request;
proto::GetObservedDeviceResponse result;
request.set_device_id(kDeviceId);
request.set_mode(proto::GetObservedDeviceRequest::MODE_RELEASE);
repository_->GetObservedDevice(
request,
[&result](const proto::GetObservedDeviceResponse& response) {
result = response;
},
[&](FastPairHttpError error) {});
EXPECT_EQ(request_url(), GetUrl(std::to_string(request.device_id())));
EXPECT_EQ(std::vector<std::string>{"MODE_RELEASE"},
ExpectQueryStringValues(request_as_query_parameters(), "mode"));
EXPECT_EQ(std::vector<std::string>{kClientId},
ExpectQueryStringValues(request_as_query_parameters(), "key"));
proto::GetObservedDeviceResponse test_response;
test_response.mutable_device()->set_id(kDeviceId);
test_response.mutable_device()->set_name(kDeviceName);
test_response.mutable_device()->set_image_url(kImageUrl);
EXPECT_EQ(test_response.device().id(), kDeviceId);
EXPECT_EQ(test_response.device().name(), kDeviceName);
EXPECT_EQ(test_response.device().image_url(), kImageUrl);
}
} // namespace fastpair
} // namespace nearby