blob: 47c2bfe054eedc6aa0256d64ba7486ca1f370900 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/client/notification/gstatic_json_fetcher.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/ranges/algorithm.h"
#include "base/task/single_thread_task_runner.h"
#include "net/http/http_status_code.h"
#include "remoting/base/url_request_context_getter.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
namespace remoting {
namespace {
constexpr char kGstaticUrlPrefix[] = "https://www.gstatic.com/chromoting/";
std::optional<base::Value> GetResponse(std::unique_ptr<std::string> body) {
if (!body)
return std::nullopt;
return base::JSONReader::Read(*body);
}
} // namespace
GstaticJsonFetcher::GstaticJsonFetcher(
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
: url_loader_factory_owner_(
base::MakeRefCounted<remoting::URLRequestContextGetter>(
network_task_runner)) {}
GstaticJsonFetcher::~GstaticJsonFetcher() = default;
void GstaticJsonFetcher::FetchJsonFile(
const std::string& relative_path,
FetchJsonFileCallback done,
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
auto request = std::make_unique<network::ResourceRequest>();
request->url = GetFullUrl(relative_path);
auto loader =
network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
auto* loader_ptr = loader.get();
loader_callback_map_[std::move(loader)] = std::move(done);
loader_ptr->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
url_loader_factory_owner_.GetURLLoaderFactory().get(),
base::BindOnce(&GstaticJsonFetcher::OnURLLoadComplete,
base::Unretained(this), loader_ptr));
}
// static
GURL GstaticJsonFetcher::GetFullUrl(const std::string& relative_path) {
return GURL(kGstaticUrlPrefix + relative_path);
}
void GstaticJsonFetcher::OnURLLoadComplete(
const network::SimpleURLLoader* source,
std::unique_ptr<std::string> body) {
auto it =
base::ranges::find(loader_callback_map_, source,
[](const auto& pair) { return pair.first.get(); });
if (it == loader_callback_map_.end()) {
LOG(DFATAL) << "Fetcher not found in the map";
return;
}
// callback can potentially add new requests to the JSON fetcher, which makes
// the iterator unstable, so we erase the iterator before running the
// callback.
auto callback =
base::BindOnce(std::move(it->second), GetResponse(std::move(body)));
loader_callback_map_.erase(it);
std::move(callback).Run();
}
} // namespace remoting