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

Side by Side Diff: chrome/browser/extensions/api/dial/device_description_fetcher.cc

Issue 2583853004: [chrome.dial] Adds chrome.dial.fetchDeviceDecription API. (Closed)
Patch Set: Fix initialization 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/string_util.h"
6 #include "base/strings/stringprintf.h"
7 #include "chrome/browser/extensions/api/dial/device_description_fetcher.h"
8 #include "chrome/browser/extensions/api/dial/dial_device_data.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "net/base/load_flags.h"
11 #include "net/http/http_response_headers.h"
12 #include "net/http/http_status_code.h"
13 #include "net/http/http_util.h"
14 #include "net/url_request/url_fetcher.h"
15
16 constexpr char kApplicationUrlHeaderName[] = "Application-URL";
17 constexpr int kMaxRetries = 3;
18 constexpr int kMaxDescriptionSizeBytes = 262144;
19
20 namespace extensions {
21
22 DeviceDescriptionFetcher::DeviceDescriptionFetcher(
23 const GURL& device_description_url,
24 Profile* profile,
25 base::OnceCallback<void(const DialDeviceDescription&)> success_cb,
26 base::OnceCallback<void(const std::string&)> error_cb)
27 : device_description_url_(device_description_url),
28 profile_(profile),
29 success_cb_(std::move(success_cb)),
30 error_cb_(std::move(error_cb)) {
31 DCHECK(profile_);
32 DCHECK(device_description_url_.is_valid());
33 }
34
35 DeviceDescriptionFetcher::~DeviceDescriptionFetcher() {}
36
37 void DeviceDescriptionFetcher::Start() {
38 DCHECK(!fetcher_);
39 fetcher_ = net::URLFetcher::Create(kURLFetcherID, device_description_url_,
40 net::URLFetcher::GET, this);
41
42 // The request should not side effect cache or the cookie store or send auth
43 // data. Proxies almost certainly hurt more cases than they help.
44 fetcher_->SetLoadFlags(net::LOAD_BYPASS_PROXY | net::LOAD_DISABLE_CACHE |
45 net::LOAD_DO_NOT_SAVE_COOKIES |
46 net::LOAD_DO_NOT_SEND_COOKIES |
47 net::LOAD_DO_NOT_SEND_AUTH_DATA);
48
49 // Technically uPnP allows devices to issue HTTP 307 redirects (sec
50 // 2.1). However, we want to enforce that redirects are not followed to hosts
51 // other than the DIAL device; and there is no logical reason why a device
52 // needs to redirect a request for the device description.
53 //
54 // We can relax this restriction if there are well-behaved devices that
55 // actually need redirects.
56 fetcher_->SetStopOnRedirect(true);
57
58 // Allow the fetcher to retry on 5XX responses and ERR_NETWORK_CHANGED.
59 fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
60 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
61
62 fetcher_->SetRequestContext(profile_->GetRequestContext());
63 fetcher_->Start();
64 }
65
66 void DeviceDescriptionFetcher::OnURLFetchComplete(
67 const net::URLFetcher* source) {
68 if (source->GetResponseCode() != net::HTTP_OK) {
69 ReportError(
70 base::StringPrintf("HTTP %d: Unable to fetch device description",
71 source->GetResponseCode()));
72 return;
73 }
74
75 const net::HttpResponseHeaders* headers = source->GetResponseHeaders();
76
77 // NOTE: The uPnP spec requires devices to set a Content-Type: header of
78 // text/xml; charset="utf-8" (sec 2.11). However Chromecast (and possibly
79 // other devices) do not comply, so not checking this header specifcially.
80
81 std::string app_url_header;
82 if (!headers->GetNormalizedHeader(kApplicationUrlHeaderName,
83 &app_url_header) ||
84 app_url_header.empty()) {
85 ReportError("Missing or empty Application-URL:");
86 return;
87 }
88
89 // Section 5.4 of the DIAL spec implies that the Application URL should not
90 // have path, query or fragment...unsure if that can be enforced.
91 GURL app_url(app_url_header);
92 if (!app_url.is_valid() || !app_url.SchemeIs("http") ||
93 !app_url.HostIsIPAddress() ||
94 app_url.host() != device_description_url_.host()) {
95 ReportError(base::StringPrintf("Invalid Application-URL: %s",
96 app_url_header.c_str()));
97 return;
98 }
99
100 if (source->GetReceivedResponseContentLength() > kMaxDescriptionSizeBytes) {
101 ReportError("Response too large");
102 return;
103 }
104
105 std::string device_description;
106 if (!source->GetResponseAsString(&device_description) ||
107 device_description.empty()) {
108 ReportError("Missing or empty response");
109 return;
110 }
111
112 if (!base::IsStringUTF8(device_description)) {
113 ReportError("Invalid response encoding");
114 return;
115 }
116
117 std::move(success_cb_)
118 .Run(DialDeviceDescription(device_description, app_url));
119 }
120
121 void DeviceDescriptionFetcher::OnURLFetchDownloadProgress(
122 const net::URLFetcher* source,
123 int64_t current,
124 int64_t total,
125 int64_t current_network_bytes) {}
126
127 void DeviceDescriptionFetcher::OnURLFetchUploadProgress(
128 const net::URLFetcher* source,
129 int64_t current,
130 int64_t total) {}
131
132 void DeviceDescriptionFetcher::ReportError(const std::string& message) {
133 std::move(error_cb_).Run(message);
134 }
135
136 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698