Commit 32778ae4 authored by Bin Zhao's avatar Bin Zhao Committed by Commit Bot

[DIAL] Added a DialURLFetcher to handle Dial related HTTP requests

DeviceDescriptionFetcher and DialAppInfoFetcher have some common code.
Create a DialURLFetcher class to get rid of some duplications.

The common URLFetcher class can also be used to launch and stop Dial
apps when we implement DIAL launch at browser side.

Bug: 816628
Change-Id: I26bdfbbf7e2d59a68e3bf5aeaba8b6e3664bf430
Reviewed-on: https://chromium-review.googlesource.com/938158Reviewed-by: default avatarRamin Halavati <rhalavati@chromium.org>
Reviewed-by: default avatarDerek Cheng <imcheng@chromium.org>
Reviewed-by: default avatarmark a. foltz <mfoltz@chromium.org>
Commit-Queue: Bin Zhao <zhaobin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540242}
parent 42e81a6a
...@@ -25,8 +25,6 @@ static_library("discovery") { ...@@ -25,8 +25,6 @@ static_library("discovery") {
"dial/device_description_service.h", "dial/device_description_service.h",
"dial/dial_app_discovery_service.cc", "dial/dial_app_discovery_service.cc",
"dial/dial_app_discovery_service.h", "dial/dial_app_discovery_service.h",
"dial/dial_app_info_fetcher.cc",
"dial/dial_app_info_fetcher.h",
"dial/dial_device_data.cc", "dial/dial_device_data.cc",
"dial/dial_device_data.h", "dial/dial_device_data.h",
"dial/dial_media_sink_service.cc", "dial/dial_media_sink_service.cc",
...@@ -37,6 +35,8 @@ static_library("discovery") { ...@@ -37,6 +35,8 @@ static_library("discovery") {
"dial/dial_registry.h", "dial/dial_registry.h",
"dial/dial_service.cc", "dial/dial_service.cc",
"dial/dial_service.h", "dial/dial_service.h",
"dial/dial_url_fetcher.cc",
"dial/dial_url_fetcher.h",
"dial/parsed_dial_app_info.cc", "dial/parsed_dial_app_info.cc",
"dial/parsed_dial_app_info.h", "dial/parsed_dial_app_info.h",
"dial/parsed_dial_device_description.cc", "dial/parsed_dial_device_description.cc",
......
...@@ -4,72 +4,14 @@ ...@@ -4,72 +4,14 @@
#include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h" #include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/media/router/discovery/dial/dial_device_data.h" #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
constexpr char kApplicationUrlHeaderName[] = "Application-URL"; constexpr char kApplicationUrlHeaderName[] = "Application-URL";
constexpr int kMaxRetries = 3;
// DIAL devices are unlikely to expose uPnP functions other than DIAL, so 256kb
// should be more than sufficient.
constexpr int kMaxDescriptionSizeBytes = 262144;
namespace media_router { namespace media_router {
namespace {
constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("dial_get_device_description", R"(
semantics {
sender: "DIAL"
description:
"Chromium sends a request to a device (such as a smart TV) "
"discovered via the DIAL (Disovery and Launch) protocol to obtain "
"its device description. Chromium then uses the device description "
"to determine the capabilities of the device to be used as a "
"target for casting media content."
trigger:
"A new or updated device has been discovered via DIAL in the local "
"network."
data: "An HTTP GET request."
destination: OTHER
destination_other:
"A device in the local network."
}
policy {
cookies_allowed: NO
setting:
"This feature cannot be disabled by settings and can only be "
"disabled by media-router flag."
chrome_policy {
EnableMediaRouter {
policy_options {mode: MANDATORY}
EnableMediaRouter: false
}
}
})");
void BindURLLoaderFactoryRequestOnUIThread(
network::mojom::URLLoaderFactoryRequest request) {
network::mojom::URLLoaderFactory* factory =
g_browser_process->system_network_context_manager()
->GetURLLoaderFactory();
factory->Clone(std::move(request));
}
} // namespace
DeviceDescriptionFetcher::DeviceDescriptionFetcher( DeviceDescriptionFetcher::DeviceDescriptionFetcher(
const GURL& device_description_url, const GURL& device_description_url,
base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb, base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb,
...@@ -86,75 +28,24 @@ DeviceDescriptionFetcher::~DeviceDescriptionFetcher() { ...@@ -86,75 +28,24 @@ DeviceDescriptionFetcher::~DeviceDescriptionFetcher() {
void DeviceDescriptionFetcher::Start() { void DeviceDescriptionFetcher::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!loader_); DCHECK(!fetcher_);
auto request = std::make_unique<network::ResourceRequest>();
request->url = device_description_url_;
// net::LOAD_BYPASS_PROXY: Proxies almost certainly hurt more cases than they
// help.
// net::LOAD_DISABLE_CACHE: The request should not touch the cache.
// net::LOAD_DO_NOT_{SAVE,SEND}_COOKIES: The request should not touch cookies.
// net::LOAD_DO_NOT_SEND_AUTH_DATA: The request should not send auth data.
request->load_flags = net::LOAD_BYPASS_PROXY | net::LOAD_DISABLE_CACHE |
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA;
loader_ =
network::SimpleURLLoader::Create(std::move(request), kTrafficAnnotation);
// Allow the fetcher to retry on 5XX responses and ERR_NETWORK_CHANGED.
loader_->SetRetryOptions(
kMaxRetries,
network::SimpleURLLoader::RetryMode::RETRY_ON_5XX |
network::SimpleURLLoader::RetryMode::RETRY_ON_NETWORK_CHANGE);
// Section 5.4 of the DIAL spec prohibits redirects.
// In practice, the callback will only get called once, since |loader_| will
// be deleted on redirect.
loader_->SetOnRedirectCallback(base::BindRepeating(
&DeviceDescriptionFetcher::ReportRedirectError, base::Unretained(this)));
StartDownload();
}
void DeviceDescriptionFetcher::StartDownload() { fetcher_ = std::make_unique<DialURLFetcher>(
// Bind the request to the system URLLoaderFactory obtained on UI thread. device_description_url_,
// Currently this is the only way to guarantee a live URLLoaderFactory.
// TOOD(mmenke): Figure out a way to do this transparently on IO thread.
network::mojom::URLLoaderFactoryPtr loader_factory;
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(&BindURLLoaderFactoryRequestOnUIThread,
mojo::MakeRequest(&loader_factory)));
loader_->DownloadToString(
loader_factory.get(),
base::BindOnce(&DeviceDescriptionFetcher::ProcessResponse, base::BindOnce(&DeviceDescriptionFetcher::ProcessResponse,
base::Unretained(this)), base::Unretained(this)),
kMaxDescriptionSizeBytes); base::BindOnce(&DeviceDescriptionFetcher::ReportError,
base::Unretained(this)));
fetcher_->Start();
} }
void DeviceDescriptionFetcher::ProcessResponse( void DeviceDescriptionFetcher::ProcessResponse(const std::string& response) {
std::unique_ptr<std::string> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (loader_->NetError() != net::Error::OK) { DCHECK(fetcher_);
ReportError(base::StringPrintf(
"HTTP %d: Unable to fetch device description", loader_->NetError()));
return;
}
if (!response || response->empty()) {
ReportError("Missing or empty response");
return;
}
if (!base::IsStringUTF8(*response)) {
ReportError("Invalid response encoding");
return;
}
const network::ResourceResponseHead* response_info = loader_->ResponseInfo(); const network::ResourceResponseHead* response_info =
fetcher_->GetResponseHead();
DCHECK(response_info); DCHECK(response_info);
// NOTE: The uPnP spec requires devices to set a Content-Type: header of // NOTE: The uPnP spec requires devices to set a Content-Type: header of
...@@ -165,7 +56,7 @@ void DeviceDescriptionFetcher::ProcessResponse( ...@@ -165,7 +56,7 @@ void DeviceDescriptionFetcher::ProcessResponse(
!response_info->headers->GetNormalizedHeader(kApplicationUrlHeaderName, !response_info->headers->GetNormalizedHeader(kApplicationUrlHeaderName,
&app_url_header) || &app_url_header) ||
app_url_header.empty()) { app_url_header.empty()) {
ReportError("Missing or empty Application-URL:"); ReportError(net::Error::OK, "Missing or empty Application-URL:");
return; return;
} }
...@@ -175,7 +66,8 @@ void DeviceDescriptionFetcher::ProcessResponse( ...@@ -175,7 +66,8 @@ void DeviceDescriptionFetcher::ProcessResponse(
if (!app_url.is_valid() || !app_url.SchemeIs("http") || if (!app_url.is_valid() || !app_url.SchemeIs("http") ||
!app_url.HostIsIPAddress() || !app_url.HostIsIPAddress() ||
app_url.host() != device_description_url_.host()) { app_url.host() != device_description_url_.host()) {
ReportError(base::StringPrintf("Invalid Application-URL: %s", ReportError(net::Error::OK,
base::StringPrintf("Invalid Application-URL: %s",
app_url_header.c_str())); app_url_header.c_str()));
return; return;
} }
...@@ -186,20 +78,14 @@ void DeviceDescriptionFetcher::ProcessResponse( ...@@ -186,20 +78,14 @@ void DeviceDescriptionFetcher::ProcessResponse(
app_url = GURL(app_url_header.substr(0, app_url_header.length() - 1)); app_url = GURL(app_url_header.substr(0, app_url_header.length() - 1));
} }
std::move(success_cb_).Run(DialDeviceDescriptionData(*response, app_url)); std::move(success_cb_).Run(DialDeviceDescriptionData(response, app_url));
} fetcher_.reset();
void DeviceDescriptionFetcher::ReportRedirectError(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) {
// Cancel the request.
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
loader_.reset();
ReportError("Redirect not allowed");
} }
void DeviceDescriptionFetcher::ReportError(const std::string& message) { void DeviceDescriptionFetcher::ReportError(int response_code,
const std::string& message) {
std::move(error_cb_).Run(message); std::move(error_cb_).Run(message);
fetcher_.reset();
} }
} // namespace media_router } // namespace media_router
...@@ -10,18 +10,9 @@ ...@@ -10,18 +10,9 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "chrome/browser/media/router/discovery/dial/dial_url_fetcher.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace net {
struct RedirectInfo;
}
namespace network {
class SimpleURLLoader;
struct ResourceResponseHead;
}
namespace media_router { namespace media_router {
struct DialDeviceDescriptionData; struct DialDeviceDescriptionData;
...@@ -42,31 +33,24 @@ class DeviceDescriptionFetcher { ...@@ -42,31 +33,24 @@ class DeviceDescriptionFetcher {
const GURL& device_description_url() { return device_description_url_; } const GURL& device_description_url() { return device_description_url_; }
void Start(); // Marked virtual for tests.
virtual void Start();
private: private:
friend class TestDeviceDescriptionFetcher; friend class TestDeviceDescriptionFetcher;
// Starts the download on |loader_|.
virtual void StartDownload();
// Processes the response from the GET request and invoke the success or // Processes the response from the GET request and invoke the success or
// error callback. // error callback.
void ProcessResponse(std::unique_ptr<std::string> response); void ProcessResponse(const std::string& response);
// Invokes the error callback due to a redirect that had occurred. Also
// aborts the request.
void ReportRedirectError(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head);
// Runs |error_cb_| with |message| and clears it. // Runs |error_cb_| with |message| and clears it.
void ReportError(const std::string& message); void ReportError(int response_code, const std::string& message);
const GURL device_description_url_; const GURL device_description_url_;
base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb_; base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb_;
base::OnceCallback<void(const std::string&)> error_cb_; base::OnceCallback<void(const std::string&)> error_cb_;
std::unique_ptr<network::SimpleURLLoader> loader_; std::unique_ptr<DialURLFetcher> fetcher_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(DeviceDescriptionFetcher); DISALLOW_COPY_AND_ASSIGN(DeviceDescriptionFetcher);
......
...@@ -12,11 +12,9 @@ ...@@ -12,11 +12,9 @@
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h" #include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h"
#include "chrome/browser/media/router/discovery/dial/dial_device_data.h" #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
#include "net/http/http_response_headers.h" #include "chrome/browser/media/router/test/test_helper.h"
#include "net/http/http_status_code.h"
#include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -37,12 +35,15 @@ class TestDeviceDescriptionFetcher : public DeviceDescriptionFetcher { ...@@ -37,12 +35,15 @@ class TestDeviceDescriptionFetcher : public DeviceDescriptionFetcher {
factory_(factory) {} factory_(factory) {}
~TestDeviceDescriptionFetcher() override = default; ~TestDeviceDescriptionFetcher() override = default;
void StartDownload() override { void Start() override {
loader_->DownloadToString( fetcher_ = std::make_unique<TestDialURLFetcher>(
factory_, device_description_url_,
base::BindOnce(&DeviceDescriptionFetcher::ProcessResponse, base::BindOnce(&DeviceDescriptionFetcher::ProcessResponse,
base::Unretained(this)), base::Unretained(this)),
256 * 1024); base::BindOnce(&DeviceDescriptionFetcher::ReportError,
base::Unretained(this)),
factory_);
fetcher_->Start();
} }
private: private:
...@@ -67,14 +68,14 @@ class DeviceDescriptionFetcherTest : public testing::Test { ...@@ -67,14 +68,14 @@ class DeviceDescriptionFetcherTest : public testing::Test {
} }
void StartRequest() { void StartRequest() {
fetcher_ = std::make_unique<TestDeviceDescriptionFetcher>( description_fetcher_ = std::make_unique<TestDeviceDescriptionFetcher>(
url_, url_,
base::BindOnce(&DeviceDescriptionFetcherTest::OnSuccess, base::BindOnce(&DeviceDescriptionFetcherTest::OnSuccess,
base::Unretained(this)), base::Unretained(this)),
base::BindOnce(&DeviceDescriptionFetcherTest::OnError, base::BindOnce(&DeviceDescriptionFetcherTest::OnError,
base::Unretained(this)), base::Unretained(this)),
&loader_factory_); &loader_factory_);
fetcher_->Start(); description_fetcher_->Start();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
...@@ -84,7 +85,7 @@ class DeviceDescriptionFetcherTest : public testing::Test { ...@@ -84,7 +85,7 @@ class DeviceDescriptionFetcherTest : public testing::Test {
network::TestURLLoaderFactory loader_factory_; network::TestURLLoaderFactory loader_factory_;
base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb_; base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb_;
base::OnceCallback<void(const std::string&)> error_cb_; base::OnceCallback<void(const std::string&)> error_cb_;
std::unique_ptr<TestDeviceDescriptionFetcher> fetcher_; std::unique_ptr<TestDeviceDescriptionFetcher> description_fetcher_;
GURL expected_app_url_; GURL expected_app_url_;
std::string expected_description_; std::string expected_description_;
std::string expected_error_; std::string expected_error_;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/time/default_clock.h" #include "base/time/default_clock.h"
#include "chrome/browser/media/router/discovery/dial/dial_app_info_fetcher.h" #include "chrome/browser/media/router/discovery/dial/dial_url_fetcher.h"
#include "chrome/browser/media/router/discovery/dial/safe_dial_app_info_parser.h" #include "chrome/browser/media/router/discovery/dial/safe_dial_app_info_parser.h"
#include "net/http/http_status_code.h" #include "net/http/http_status_code.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -62,13 +62,12 @@ void DialAppDiscoveryService::FetchDialAppInfo(const MediaSinkInternal& sink, ...@@ -62,13 +62,12 @@ void DialAppDiscoveryService::FetchDialAppInfo(const MediaSinkInternal& sink,
GURL app_url = GetAppUrl(sink, app_name); GURL app_url = GetAppUrl(sink, app_name);
DVLOG(2) << "Fetch DIAL app info from: " << app_url.spec(); DVLOG(2) << "Fetch DIAL app info from: " << app_url.spec();
std::unique_ptr<DialAppInfoFetcher> fetcher = std::unique_ptr<DialURLFetcher> fetcher = std::make_unique<DialURLFetcher>(
std::make_unique<DialAppInfoFetcher>( app_url,
app_url, base::BindOnce(&DialAppDiscoveryService::OnDialAppInfoFetchComplete,
base::BindOnce(&DialAppDiscoveryService::OnDialAppInfoFetchComplete, base::Unretained(this), sink_id, app_name),
base::Unretained(this), sink_id, app_name), base::BindOnce(&DialAppDiscoveryService::OnDialAppInfoFetchError,
base::BindOnce(&DialAppDiscoveryService::OnDialAppInfoFetchError, base::Unretained(this), sink_id, app_name));
base::Unretained(this), sink_id, app_name));
fetcher->Start(); fetcher->Start();
pending_fetcher_map_.emplace(request_id, std::move(fetcher)); pending_fetcher_map_.emplace(request_id, std::move(fetcher));
} }
......
...@@ -24,7 +24,7 @@ class Connector; ...@@ -24,7 +24,7 @@ class Connector;
namespace media_router { namespace media_router {
class DialAppInfoFetcher; class DialURLFetcher;
class SafeDialAppInfoParser; class SafeDialAppInfoParser;
// Represents DIAL app status on receiver device. // Represents DIAL app status on receiver device.
...@@ -117,7 +117,7 @@ class DialAppDiscoveryService { ...@@ -117,7 +117,7 @@ class DialAppDiscoveryService {
SafeDialAppInfoParser::ParsingResult parsing_result); SafeDialAppInfoParser::ParsingResult parsing_result);
// Map of pending app info fetchers, keyed by request id. // Map of pending app info fetchers, keyed by request id.
base::flat_map<std::string, std::unique_ptr<DialAppInfoFetcher>> base::flat_map<std::string, std::unique_ptr<DialURLFetcher>>
pending_fetcher_map_; pending_fetcher_map_;
// See comments for DialAppInfoParseCompletedCallback. // See comments for DialAppInfoParseCompletedCallback.
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/test/mock_callback.h" #include "base/test/mock_callback.h"
#include "chrome/browser/media/router/discovery/dial/dial_app_info_fetcher.h"
#include "chrome/browser/media/router/discovery/dial/parsed_dial_device_description.h" #include "chrome/browser/media/router/discovery/dial/parsed_dial_device_description.h"
#include "chrome/browser/media/router/discovery/dial/safe_dial_app_info_parser.h" #include "chrome/browser/media/router/discovery/dial/safe_dial_app_info_parser.h"
#include "chrome/browser/media/router/test/test_helper.h" #include "chrome/browser/media/router/test/test_helper.h"
......
...@@ -2,9 +2,8 @@ ...@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/media/router/discovery/dial/dial_app_info_fetcher.h" #include "chrome/browser/media/router/discovery/dial/dial_url_fetcher.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/net/system_network_context_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -20,22 +19,22 @@ ...@@ -20,22 +19,22 @@
constexpr int kMaxRetries = 3; constexpr int kMaxRetries = 3;
// DIAL devices are unlikely to expose uPnP functions other than DIAL, so 256kb // DIAL devices are unlikely to expose uPnP functions other than DIAL, so 256kb
// should be more than sufficient. // should be more than sufficient.
constexpr int kMaxAppInfoSizeBytes = 262144; constexpr int kMaxResponseSizeBytes = 262144;
namespace media_router { namespace media_router {
namespace { namespace {
constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("dial_get_app_info", R"( net::DefineNetworkTrafficAnnotation("dial_url_fetcher", R"(
semantics { semantics {
sender: "DIAL" sender: "DIAL"
description: description:
"Chromium sends a request to a device (such as a smart TV) " "Chromium sends a request to a device (such as a smart TV) "
"discovered via the DIAL (Discovery and Launch) protocol to obtain " "discovered via the DIAL (Discovery and Launch) protocol to obtain "
"its app info data. Chromium then uses the app info data to" "its device description or app info data. Chromium then uses the "
"determine the capabilities of the device to be used as a target" "data to determine the capabilities of the device to be used as a "
"for casting media content." "targetfor casting media content."
trigger: trigger:
"A new or updated device has been discovered via DIAL in the local " "A new or updated device has been discovered via DIAL in the local "
"network." "network."
...@@ -66,26 +65,31 @@ void BindURLLoaderFactoryRequestOnUIThread( ...@@ -66,26 +65,31 @@ void BindURLLoaderFactoryRequestOnUIThread(
} // namespace } // namespace
DialAppInfoFetcher::DialAppInfoFetcher( DialURLFetcher::DialURLFetcher(
const GURL& app_url, const GURL& url,
base::OnceCallback<void(const std::string&)> success_cb, base::OnceCallback<void(const std::string&)> success_cb,
base::OnceCallback<void(int, const std::string&)> error_cb) base::OnceCallback<void(int, const std::string&)> error_cb)
: app_url_(app_url), : url_(url),
success_cb_(std::move(success_cb)), success_cb_(std::move(success_cb)),
error_cb_(std::move(error_cb)) { error_cb_(std::move(error_cb)) {
DCHECK(app_url_.is_valid()); DCHECK(url_.is_valid());
} }
DialAppInfoFetcher::~DialAppInfoFetcher() { DialURLFetcher::~DialURLFetcher() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
} }
void DialAppInfoFetcher::Start() { const network::ResourceResponseHead* DialURLFetcher::GetResponseHead() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return loader_ ? loader_->ResponseInfo() : nullptr;
}
void DialURLFetcher::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!loader_); DCHECK(!loader_);
auto request = std::make_unique<network::ResourceRequest>(); auto request = std::make_unique<network::ResourceRequest>();
request->url = app_url_; request->url = url_;
// net::LOAD_BYPASS_PROXY: Proxies almost certainly hurt more cases than they // net::LOAD_BYPASS_PROXY: Proxies almost certainly hurt more cases than they
// help. // help.
...@@ -110,17 +114,17 @@ void DialAppInfoFetcher::Start() { ...@@ -110,17 +114,17 @@ void DialAppInfoFetcher::Start() {
// In practice, the callback will only get called once, since |loader_| will // In practice, the callback will only get called once, since |loader_| will
// be deleted. // be deleted.
loader_->SetOnRedirectCallback(base::BindRepeating( loader_->SetOnRedirectCallback(base::BindRepeating(
&DialAppInfoFetcher::ReportRedirectError, base::Unretained(this))); &DialURLFetcher::ReportRedirectError, base::Unretained(this)));
StartDownload(); StartDownload();
} }
void DialAppInfoFetcher::ReportError(int response_code, void DialURLFetcher::ReportError(int response_code,
const std::string& message) { const std::string& message) {
std::move(error_cb_).Run(response_code, message); std::move(error_cb_).Run(response_code, message);
} }
void DialAppInfoFetcher::ReportRedirectError( void DialURLFetcher::ReportRedirectError(
const net::RedirectInfo& redirect_info, const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) { const network::ResourceResponseHead& response_head) {
// Cancel the request. // Cancel the request.
...@@ -131,7 +135,7 @@ void DialAppInfoFetcher::ReportRedirectError( ...@@ -131,7 +135,7 @@ void DialAppInfoFetcher::ReportRedirectError(
ReportError(net::Error::OK, "Redirect not allowed"); ReportError(net::Error::OK, "Redirect not allowed");
} }
void DialAppInfoFetcher::StartDownload() { void DialURLFetcher::StartDownload() {
// Bind the request to the system URLLoaderFactory obtained on UI thread. // Bind the request to the system URLLoaderFactory obtained on UI thread.
// Currently this is the only way to guarantee a live URLLoaderFactory. // Currently this is the only way to guarantee a live URLLoaderFactory.
// TOOD(mmenke): Figure out a way to do this transparently on IO thread. // TOOD(mmenke): Figure out a way to do this transparently on IO thread.
...@@ -141,14 +145,13 @@ void DialAppInfoFetcher::StartDownload() { ...@@ -141,14 +145,13 @@ void DialAppInfoFetcher::StartDownload() {
base::BindOnce(&BindURLLoaderFactoryRequestOnUIThread, base::BindOnce(&BindURLLoaderFactoryRequestOnUIThread,
mojo::MakeRequest(&loader_factory))); mojo::MakeRequest(&loader_factory)));
loader_->DownloadToString(loader_factory.get(), loader_->DownloadToString(
base::BindOnce(&DialAppInfoFetcher::ProcessResponse, loader_factory.get(),
base::Unretained(this)), base::BindOnce(&DialURLFetcher::ProcessResponse, base::Unretained(this)),
kMaxAppInfoSizeBytes); kMaxResponseSizeBytes);
} }
void DialAppInfoFetcher::ProcessResponse( void DialURLFetcher::ProcessResponse(std::unique_ptr<std::string> response) {
std::unique_ptr<std::string> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
int response_code = loader_->NetError(); int response_code = loader_->NetError();
if (response_code != net::Error::OK) { if (response_code != net::Error::OK) {
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DIAL_DIAL_APP_INFO_FETCHER_H_ #ifndef CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DIAL_DIAL_URL_FETCHER_H_
#define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DIAL_DIAL_APP_INFO_FETCHER_H_ #define CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DIAL_DIAL_URL_FETCHER_H_
#include <memory> #include <memory>
#include <string> #include <string>
...@@ -23,27 +23,39 @@ struct ResourceResponseHead; ...@@ -23,27 +23,39 @@ struct ResourceResponseHead;
namespace media_router { namespace media_router {
// Used to make a single HTTP GET request with |app_url| to fetch an app info // Used to make a single HTTP GET request with |url| to fetch a response
// from a DIAL device. If successful, |success_cb| is invoked with the result; // from a DIAL device. If successful, |success_cb| is invoked with the result;
// otherwise, |error_cb| is invoked with an error reason. // otherwise, |error_cb| is invoked with an error reason.
// This class is not sequence safe. // This class is not sequence safe.
class DialAppInfoFetcher { class DialURLFetcher {
public: public:
DialAppInfoFetcher( // Constructor.
const GURL& app_url, // |url|: HTTP request URL
base::OnceCallback<void(const std::string&)> success_cb, // |success_cb|: Invoked when HTTP request to |url| succeeds
base::OnceCallback<void(int, const std::string&)> error_cb); // |arg 0|: response text of the HTTP request
// |error_cb|: Invoked when HTTP request to |url| fails
// |arg 0|: HTTP response code
// |arg 1|: error message
DialURLFetcher(const GURL& url,
base::OnceCallback<void(const std::string&)> success_cb,
base::OnceCallback<void(int, const std::string&)> error_cb);
virtual ~DialAppInfoFetcher(); virtual ~DialURLFetcher();
const GURL& app_url() { return app_url_; } const GURL& url() { return url_; }
// Starts the fetch. |ProcessResponse| will be invoked on completion. // Starts the fetch. |ProcessResponse| will be invoked on completion.
// |ReportRedirectError| will be invoked when a redirect occurrs. // |ReportRedirectError| will be invoked when a redirect occurrs.
void Start(); void Start();
// Returns the response header of an HTTP request. The response header is
// owned by underlying |loader_| object and is reset per HTTP request. Returns
// nullptr if this function is called before |loader_| has informed the caller
// of completion.
const network::ResourceResponseHead* GetResponseHead() const;
private: private:
friend class TestDialAppInfoFetcher; friend class TestDialURLFetcher;
// Starts the download on |loader_|. // Starts the download on |loader_|.
virtual void StartDownload(); virtual void StartDownload();
...@@ -58,15 +70,15 @@ class DialAppInfoFetcher { ...@@ -58,15 +70,15 @@ class DialAppInfoFetcher {
// Runs |error_cb_| with |message| and clears it. // Runs |error_cb_| with |message| and clears it.
void ReportError(int response_code, const std::string& message); void ReportError(int response_code, const std::string& message);
const GURL app_url_; const GURL url_;
base::OnceCallback<void(const std::string&)> success_cb_; base::OnceCallback<void(const std::string&)> success_cb_;
base::OnceCallback<void(int, const std::string&)> error_cb_; base::OnceCallback<void(int, const std::string&)> error_cb_;
std::unique_ptr<network::SimpleURLLoader> loader_; std::unique_ptr<network::SimpleURLLoader> loader_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(DialAppInfoFetcher); DISALLOW_COPY_AND_ASSIGN(DialURLFetcher);
}; };
} // namespace media_router } // namespace media_router
#endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DIAL_DIAL_APP_INFO_FETCHER_H_ #endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_DIAL_DIAL_URL_FETCHER_H_
...@@ -9,14 +9,14 @@ ...@@ -9,14 +9,14 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "chrome/browser/media/router/discovery/dial/dial_app_info_fetcher.h" #include "chrome/browser/media/router/discovery/dial/dial_url_fetcher.h"
#include "chrome/browser/media/router/test/test_helper.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_browser_thread_bundle.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h" #include "net/http/http_status_code.h"
#include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -24,32 +24,9 @@ ...@@ -24,32 +24,9 @@
namespace media_router { namespace media_router {
class TestDialAppInfoFetcher : public DialAppInfoFetcher { class DialURLFetcherTest : public testing::Test {
public: public:
TestDialAppInfoFetcher( DialURLFetcherTest() : url_("http://127.0.0.1/app/Youtube") {}
const GURL& app_url,
base::OnceCallback<void(const std::string&)> success_cb,
base::OnceCallback<void(int, const std::string&)> error_cb,
network::TestURLLoaderFactory* factory)
: DialAppInfoFetcher(app_url, std::move(success_cb), std::move(error_cb)),
factory_(factory) {}
~TestDialAppInfoFetcher() override = default;
void StartDownload() override {
loader_->DownloadToString(
factory_,
base::BindOnce(&DialAppInfoFetcher::ProcessResponse,
base::Unretained(this)),
256 * 1024);
}
private:
network::TestURLLoaderFactory* const factory_;
};
class DialAppInfoFetcherTest : public testing::Test {
public:
DialAppInfoFetcherTest() : url_("http://127.0.0.1/app/Youtube") {}
void ExpectSuccess(const std::string& expected_app_info) { void ExpectSuccess(const std::string& expected_app_info) {
EXPECT_CALL(*this, OnSuccess(expected_app_info)); EXPECT_CALL(*this, OnSuccess(expected_app_info));
...@@ -61,12 +38,10 @@ class DialAppInfoFetcherTest : public testing::Test { ...@@ -61,12 +38,10 @@ class DialAppInfoFetcherTest : public testing::Test {
} }
void StartRequest() { void StartRequest() {
fetcher_ = std::make_unique<TestDialAppInfoFetcher>( fetcher_ = std::make_unique<TestDialURLFetcher>(
url_, url_,
base::BindOnce(&DialAppInfoFetcherTest::OnSuccess, base::BindOnce(&DialURLFetcherTest::OnSuccess, base::Unretained(this)),
base::Unretained(this)), base::BindOnce(&DialURLFetcherTest::OnError, base::Unretained(this)),
base::BindOnce(&DialAppInfoFetcherTest::OnError,
base::Unretained(this)),
&loader_factory_); &loader_factory_);
fetcher_->Start(); fetcher_->Start();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -77,7 +52,7 @@ class DialAppInfoFetcherTest : public testing::Test { ...@@ -77,7 +52,7 @@ class DialAppInfoFetcherTest : public testing::Test {
network::TestURLLoaderFactory loader_factory_; network::TestURLLoaderFactory loader_factory_;
const GURL url_; const GURL url_;
std::string expected_error_; std::string expected_error_;
std::unique_ptr<TestDialAppInfoFetcher> fetcher_; std::unique_ptr<TestDialURLFetcher> fetcher_;
private: private:
MOCK_METHOD1(OnSuccess, void(const std::string&)); MOCK_METHOD1(OnSuccess, void(const std::string&));
...@@ -88,10 +63,10 @@ class DialAppInfoFetcherTest : public testing::Test { ...@@ -88,10 +63,10 @@ class DialAppInfoFetcherTest : public testing::Test {
DoOnError(); DoOnError();
} }
DISALLOW_COPY_AND_ASSIGN(DialAppInfoFetcherTest); DISALLOW_COPY_AND_ASSIGN(DialURLFetcherTest);
}; };
TEST_F(DialAppInfoFetcherTest, FetchSuccessful) { TEST_F(DialURLFetcherTest, FetchSuccessful) {
std::string body("<xml>appInfo</xml>"); std::string body("<xml>appInfo</xml>");
ExpectSuccess(body); ExpectSuccess(body);
network::URLLoaderCompletionStatus status; network::URLLoaderCompletionStatus status;
...@@ -101,7 +76,7 @@ TEST_F(DialAppInfoFetcherTest, FetchSuccessful) { ...@@ -101,7 +76,7 @@ TEST_F(DialAppInfoFetcherTest, FetchSuccessful) {
StartRequest(); StartRequest();
} }
TEST_F(DialAppInfoFetcherTest, FetchFailsOnMissingAppInfo) { TEST_F(DialURLFetcherTest, FetchFailsOnMissingAppInfo) {
ExpectError("HTTP 404:"); ExpectError("HTTP 404:");
loader_factory_.AddResponse( loader_factory_.AddResponse(
...@@ -110,7 +85,7 @@ TEST_F(DialAppInfoFetcherTest, FetchFailsOnMissingAppInfo) { ...@@ -110,7 +85,7 @@ TEST_F(DialAppInfoFetcherTest, FetchFailsOnMissingAppInfo) {
StartRequest(); StartRequest();
} }
TEST_F(DialAppInfoFetcherTest, FetchFailsOnEmptyAppInfo) { TEST_F(DialURLFetcherTest, FetchFailsOnEmptyAppInfo) {
ExpectError("Missing or empty response"); ExpectError("Missing or empty response");
loader_factory_.AddResponse(url_, network::ResourceResponseHead(), "", loader_factory_.AddResponse(url_, network::ResourceResponseHead(), "",
...@@ -118,7 +93,7 @@ TEST_F(DialAppInfoFetcherTest, FetchFailsOnEmptyAppInfo) { ...@@ -118,7 +93,7 @@ TEST_F(DialAppInfoFetcherTest, FetchFailsOnEmptyAppInfo) {
StartRequest(); StartRequest();
} }
TEST_F(DialAppInfoFetcherTest, FetchFailsOnBadAppInfo) { TEST_F(DialURLFetcherTest, FetchFailsOnBadAppInfo) {
ExpectError("Invalid response encoding"); ExpectError("Invalid response encoding");
std::string body("\xfc\x9c\xbf\x80\xbf\x80"); std::string body("\xfc\x9c\xbf\x80\xbf\x80");
network::URLLoaderCompletionStatus status; network::URLLoaderCompletionStatus status;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/json/string_escape.h" #include "base/json/string_escape.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "chrome/common/media_router/media_source.h" #include "chrome/common/media_router/media_source.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace media_router { namespace media_router {
...@@ -55,6 +56,22 @@ MockDialMediaSinkService::~MockDialMediaSinkService() = default; ...@@ -55,6 +56,22 @@ MockDialMediaSinkService::~MockDialMediaSinkService() = default;
MockCastMediaSinkService::MockCastMediaSinkService() : CastMediaSinkService() {} MockCastMediaSinkService::MockCastMediaSinkService() : CastMediaSinkService() {}
MockCastMediaSinkService::~MockCastMediaSinkService() = default; MockCastMediaSinkService::~MockCastMediaSinkService() = default;
TestDialURLFetcher::TestDialURLFetcher(
const GURL& url,
base::OnceCallback<void(const std::string&)> success_cb,
base::OnceCallback<void(int, const std::string&)> error_cb,
network::TestURLLoaderFactory* factory)
: DialURLFetcher(url, std::move(success_cb), std::move(error_cb)),
factory_(factory) {}
TestDialURLFetcher::~TestDialURLFetcher() = default;
void TestDialURLFetcher::StartDownload() {
loader_->DownloadToString(
factory_,
base::BindOnce(&DialURLFetcher::ProcessResponse, base::Unretained(this)),
256 * 1024);
}
#endif // !defined(OS_ANDROID) #endif // !defined(OS_ANDROID)
net::IPEndPoint CreateIPEndPoint(int num) { net::IPEndPoint CreateIPEndPoint(int num) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/media/router/discovery/dial/dial_media_sink_service.h" #include "chrome/browser/media/router/discovery/dial/dial_media_sink_service.h"
#include "chrome/browser/media/router/discovery/dial/dial_url_fetcher.h"
#include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h" #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h"
#include "chrome/browser/media/router/issue_manager.h" #include "chrome/browser/media/router/issue_manager.h"
#include "chrome/browser/media/router/issues_observer.h" #include "chrome/browser/media/router/issues_observer.h"
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
#include "content/public/browser/presentation_service_delegate.h" #include "content/public/browser/presentation_service_delegate.h"
#include "content/public/common/presentation_connection_message.h" #include "content/public/common/presentation_connection_message.h"
#include "net/base/ip_endpoint.h" #include "net/base/ip_endpoint.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
namespace media_router { namespace media_router {
...@@ -131,6 +133,19 @@ class MockCastMediaSinkService : public CastMediaSinkService { ...@@ -131,6 +133,19 @@ class MockCastMediaSinkService : public CastMediaSinkService {
MOCK_METHOD0(OnUserGesture, void()); MOCK_METHOD0(OnUserGesture, void());
MOCK_METHOD0(StartMdnsDiscovery, void()); MOCK_METHOD0(StartMdnsDiscovery, void());
}; };
class TestDialURLFetcher : public DialURLFetcher {
public:
TestDialURLFetcher(const GURL& url,
base::OnceCallback<void(const std::string&)> success_cb,
base::OnceCallback<void(int, const std::string&)> error_cb,
network::TestURLLoaderFactory* factory);
~TestDialURLFetcher() override;
void StartDownload() override;
private:
network::TestURLLoaderFactory* const factory_;
};
#endif // !defined(OS_ANDROID) #endif // !defined(OS_ANDROID)
// Helper function to create an IP endpoint object. // Helper function to create an IP endpoint object.
......
...@@ -3029,12 +3029,12 @@ test("unit_tests") { ...@@ -3029,12 +3029,12 @@ test("unit_tests") {
"../browser/media/router/discovery/dial/device_description_fetcher_unittest.cc", "../browser/media/router/discovery/dial/device_description_fetcher_unittest.cc",
"../browser/media/router/discovery/dial/device_description_service_unittest.cc", "../browser/media/router/discovery/dial/device_description_service_unittest.cc",
"../browser/media/router/discovery/dial/dial_app_discovery_service_unittest.cc", "../browser/media/router/discovery/dial/dial_app_discovery_service_unittest.cc",
"../browser/media/router/discovery/dial/dial_app_info_fetcher_unittest.cc",
"../browser/media/router/discovery/dial/dial_device_data_unittest.cc", "../browser/media/router/discovery/dial/dial_device_data_unittest.cc",
"../browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc", "../browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc",
"../browser/media/router/discovery/dial/dial_media_sink_service_unittest.cc", "../browser/media/router/discovery/dial/dial_media_sink_service_unittest.cc",
"../browser/media/router/discovery/dial/dial_registry_unittest.cc", "../browser/media/router/discovery/dial/dial_registry_unittest.cc",
"../browser/media/router/discovery/dial/dial_service_unittest.cc", "../browser/media/router/discovery/dial/dial_service_unittest.cc",
"../browser/media/router/discovery/dial/dial_url_fetcher_unittest.cc",
"../browser/media/router/discovery/dial/safe_dial_app_info_parser_unittest.cc", "../browser/media/router/discovery/dial/safe_dial_app_info_parser_unittest.cc",
"../browser/media/router/discovery/dial/safe_dial_device_description_parser_unittest.cc", "../browser/media/router/discovery/dial/safe_dial_device_description_parser_unittest.cc",
"../browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc", "../browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc",
......
...@@ -74,8 +74,9 @@ Refer to README.md for content description and update process. ...@@ -74,8 +74,9 @@ Refer to README.md for content description and update process.
<item id="devtools_http_handler" hash_code="49160454" type="0" content_hash_code="88414393" os_list="linux,windows" file_path="content/browser/devtools/devtools_http_handler.cc"/> <item id="devtools_http_handler" hash_code="49160454" type="0" content_hash_code="88414393" os_list="linux,windows" file_path="content/browser/devtools/devtools_http_handler.cc"/>
<item id="devtools_interceptor" hash_code="98123737" type="0" content_hash_code="19053470" os_list="linux,windows" file_path="content/browser/devtools/devtools_url_interceptor_request_job.cc"/> <item id="devtools_interceptor" hash_code="98123737" type="0" content_hash_code="19053470" os_list="linux,windows" file_path="content/browser/devtools/devtools_url_interceptor_request_job.cc"/>
<item id="devtools_network_resource" hash_code="129652775" type="0" content_hash_code="24059212" os_list="linux,windows" file_path="chrome/browser/devtools/devtools_ui_bindings.cc"/> <item id="devtools_network_resource" hash_code="129652775" type="0" content_hash_code="24059212" os_list="linux,windows" file_path="chrome/browser/devtools/devtools_ui_bindings.cc"/>
<item id="dial_get_app_info" hash_code="15952025" type="0" content_hash_code="90542080" os_list="linux,windows" file_path="chrome/browser/media/router/discovery/dial/dial_app_info_fetcher.cc"/> <item id="dial_get_app_info" hash_code="15952025" type="0" deprecated="2018-02-27" content_hash_code="90542080" file_path=""/>
<item id="dial_get_device_description" hash_code="50422598" type="0" content_hash_code="129827780" os_list="linux,windows" file_path="chrome/browser/media/router/discovery/dial/device_description_fetcher.cc"/> <item id="dial_get_device_description" hash_code="50422598" type="0" deprecated="2018-02-27" content_hash_code="129827780" file_path=""/>
<item id="dial_url_fetcher" hash_code="41424546" type="0" content_hash_code="129828432" os_list="linux,windows" file_path="chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc"/>
<item id="dns_over_https" hash_code="79895226" type="0" content_hash_code="45123510" os_list="linux,windows" file_path="net/dns/dns_transaction.cc"/> <item id="dns_over_https" hash_code="79895226" type="0" content_hash_code="45123510" os_list="linux,windows" file_path="net/dns/dns_transaction.cc"/>
<item id="dns_transaction" hash_code="79227717" type="0" content_hash_code="132206495" os_list="linux,windows" file_path="net/dns/dns_transaction.cc"/> <item id="dns_transaction" hash_code="79227717" type="0" content_hash_code="132206495" os_list="linux,windows" file_path="net/dns/dns_transaction.cc"/>
<item id="dom_distiller" hash_code="3989826" type="0" content_hash_code="106153970" os_list="linux,windows" file_path="components/dom_distiller/core/distiller_url_fetcher.cc"/> <item id="dom_distiller" hash_code="3989826" type="0" content_hash_code="106153970" os_list="linux,windows" file_path="components/dom_distiller/core/distiller_url_fetcher.cc"/>
......
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