Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1452)

Unified Diff: chrome/browser/extensions/api/dial/device_description_fetcher.cc

Issue 2583853004: [chrome.dial] Adds chrome.dial.fetchDeviceDecription API. (Closed)
Patch Set: Rebase and fix typo. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/dial/device_description_fetcher.cc
diff --git a/chrome/browser/extensions/api/dial/device_description_fetcher.cc b/chrome/browser/extensions/api/dial/device_description_fetcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..654fc3355c770bd83057e9b61b2abf9cfa3d9fe4
--- /dev/null
+++ b/chrome/browser/extensions/api/dial/device_description_fetcher.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2017 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 "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/extensions/api/dial/device_description_fetcher.h"
+#include "chrome/browser/extensions/api/dial/dial_device_data.h"
+#include "chrome/browser/profiles/profile.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_status_code.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_fetcher.h"
+
+using content::BrowserThread;
+
+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 extensions {
+namespace api {
+namespace dial {
+
+DeviceDescriptionFetcher::DeviceDescriptionFetcher(
+ const GURL& device_description_url,
+ Profile* profile,
+ base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb,
+ base::OnceCallback<void(const std::string&)> error_cb)
+ : device_description_url_(device_description_url),
+ profile_(profile),
+ success_cb_(std::move(success_cb)),
+ error_cb_(std::move(error_cb)) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(profile_);
+ DCHECK(device_description_url_.is_valid());
+}
+
+DeviceDescriptionFetcher::~DeviceDescriptionFetcher() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+void DeviceDescriptionFetcher::Start() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!fetcher_);
+
+ // DIAL returns device descriptions via GET request.
+ fetcher_ =
+ net::URLFetcher::Create(kURLFetcherIDForTest, device_description_url_,
+ net::URLFetcher::GET, this);
+
+ // 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.
+ fetcher_->SetLoadFlags(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);
+
+ // Section 5.4 of the DIAL spec prohibits redirects.
+ fetcher_->SetStopOnRedirect(true);
+
+ // Allow the fetcher to retry on 5XX responses and ERR_NETWORK_CHANGED.
+ fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
+ fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
+
+ fetcher_->SetRequestContext(profile_->GetRequestContext());
+ fetcher_->Start();
+}
+
+void DeviceDescriptionFetcher::OnURLFetchComplete(
+ const net::URLFetcher* source) {
+ DCHECK_EQ(fetcher_.get(), source);
+
+ if (source->GetResponseCode() != net::HTTP_OK) {
+ ReportError(
+ base::StringPrintf("HTTP %d: Unable to fetch device description",
+ source->GetResponseCode()));
+ return;
+ }
+
+ const net::HttpResponseHeaders* headers = source->GetResponseHeaders();
+
+ // NOTE: The uPnP spec requires devices to set a Content-Type: header of
+ // text/xml; charset="utf-8" (sec 2.11). However Chromecast (and possibly
+ // other devices) do not comply, so specifically not checking this header.
+ std::string app_url_header;
+ if (!headers->GetNormalizedHeader(kApplicationUrlHeaderName,
+ &app_url_header) ||
+ app_url_header.empty()) {
+ ReportError("Missing or empty Application-URL:");
+ return;
+ }
+
+ // Section 5.4 of the DIAL spec implies that the Application URL should not
+ // have path, query or fragment...unsure if that can be enforced.
+ GURL app_url(app_url_header);
+ if (!app_url.is_valid() || !app_url.SchemeIs("http") ||
+ !app_url.HostIsIPAddress() ||
+ app_url.host() != device_description_url_.host()) {
+ ReportError(base::StringPrintf("Invalid Application-URL: %s",
+ app_url_header.c_str()));
+ return;
+ }
+
+ if (source->GetReceivedResponseContentLength() > kMaxDescriptionSizeBytes) {
+ ReportError("Response too large");
+ return;
+ }
+
+ std::string device_description;
+ if (!source->GetResponseAsString(&device_description) ||
+ device_description.empty()) {
+ ReportError("Missing or empty response");
+ return;
+ }
+
+ if (!base::IsStringUTF8(device_description)) {
+ ReportError("Invalid response encoding");
+ return;
+ }
+
+ std::move(success_cb_)
+ .Run(DialDeviceDescriptionData(std::move(device_description), app_url));
+}
+
+void DeviceDescriptionFetcher::OnURLFetchDownloadProgress(
+ const net::URLFetcher* source,
+ int64_t current,
+ int64_t total,
+ int64_t current_network_bytes) {}
+
+void DeviceDescriptionFetcher::OnURLFetchUploadProgress(
+ const net::URLFetcher* source,
+ int64_t current,
+ int64_t total) {}
+
+void DeviceDescriptionFetcher::ReportError(const std::string& message) {
+ std::move(error_cb_).Run(message);
+}
+
+} // namespace dial
+} // namespace api
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698