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

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: Respond to lazyboy@ comments. Rebase w/namespace changes 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 "content/public/browser/browser_thread.h"
11 #include "net/base/load_flags.h"
12 #include "net/http/http_response_headers.h"
13 #include "net/http/http_status_code.h"
14 #include "net/http/http_util.h"
15 #include "net/url_request/url_fetcher.h"
16
17 using content::BrowserThread;
18
19 constexpr char kApplicationUrlHeaderName[] = "Application-URL";
20 constexpr int kMaxRetries = 3;
21 constexpr int kMaxDescriptionSizeBytes = 262144;
Wez 2017/01/05 22:29:24 nit: For max-size constants it is helpful if you c
mark a. foltz 2017/01/09 21:38:07 Done.
22
23 namespace extensions {
24 namespace api {
25 namespace dial {
26
27 DeviceDescriptionFetcher::DeviceDescriptionFetcher(
28 const GURL& device_description_url,
29 Profile* profile,
30 base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb,
31 base::OnceCallback<void(const std::string&)> error_cb)
32 : device_description_url_(device_description_url),
33 profile_(profile),
34 success_cb_(std::move(success_cb)),
35 error_cb_(std::move(error_cb)) {
36 DCHECK_CURRENTLY_ON(BrowserThread::UI);
37 DCHECK(profile_);
38 DCHECK(device_description_url_.is_valid());
39 }
40
41 DeviceDescriptionFetcher::~DeviceDescriptionFetcher() {
42 DCHECK_CURRENTLY_ON(BrowserThread::UI);
43 }
44
45 void DeviceDescriptionFetcher::Start() {
46 DCHECK_CURRENTLY_ON(BrowserThread::UI);
47 DCHECK(!fetcher_);
Wez 2017/01/05 22:29:24 nit: I usually recommend a blank line between DCHE
mark a. foltz 2017/01/09 21:38:07 Done.
48 fetcher_ = net::URLFetcher::Create(kURLFetcherID, device_description_url_,
49 net::URLFetcher::GET, this);
Wez 2017/01/05 22:29:24 nit: Consider introducing this with e.g. "// uPnP
mark a. foltz 2017/01/09 21:38:06 Done.
50
51 // The request should not side effect cache or the cookie store or send auth
52 // data. Proxies almost certainly hurt more cases than they help.
Wez 2017/01/05 22:29:24 nit: It might be more readable to create a local i
mark a. foltz 2017/01/09 21:38:07 Reformatted comment to be more explicit about flag
53 fetcher_->SetLoadFlags(net::LOAD_BYPASS_PROXY | net::LOAD_DISABLE_CACHE |
54 net::LOAD_DO_NOT_SAVE_COOKIES |
55 net::LOAD_DO_NOT_SEND_COOKIES |
56 net::LOAD_DO_NOT_SEND_AUTH_DATA);
57
58 // Technically uPnP allows devices to issue HTTP 307 redirects (sec
59 // 2.1). However, we want to enforce that redirects are not followed to hosts
60 // other than the DIAL device; and there is no logical reason why a device
61 // needs to redirect a request for the device description.
62 //
63 // We can relax this restriction if there are well-behaved devices that
64 // actually need redirects.
Wez 2017/01/05 22:29:24 Presumably we would only do that if we had the abi
mark a. foltz 2017/01/09 21:38:07 Good catch, I was looking at the uPnP spec which d
Wez 2017/01/09 22:12:58 Acknowledged.
65 fetcher_->SetStopOnRedirect(true);
66
67 // Allow the fetcher to retry on 5XX responses and ERR_NETWORK_CHANGED.
68 fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
69 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
70
71 fetcher_->SetRequestContext(profile_->GetRequestContext());
72 fetcher_->Start();
73 }
74
75 void DeviceDescriptionFetcher::OnURLFetchComplete(
76 const net::URLFetcher* source) {
Wez 2017/01/05 22:29:24 nit: DCHECK_EQ(fetcher_.get(), source);
mark a. foltz 2017/01/09 21:38:07 This code doesn't refer to fetcher_.
Wez 2017/01/09 22:12:58 Doesn't this method expect that |source| is the sa
mark a. foltz 2017/01/10 00:36:13 Ah, I misread your earlier comment. Done.
77 if (source->GetResponseCode() != net::HTTP_OK) {
78 ReportError(
79 base::StringPrintf("HTTP %d: Unable to fetch device description",
80 source->GetResponseCode()));
81 return;
82 }
83
84 const net::HttpResponseHeaders* headers = source->GetResponseHeaders();
85
86 // NOTE: The uPnP spec requires devices to set a Content-Type: header of
87 // text/xml; charset="utf-8" (sec 2.11). However Chromecast (and possibly
88 // other devices) do not comply, so not checking this header specifcially.
Wez 2017/01/05 22:29:24 typo: specifically Also, reword: so specifically
mark a. foltz 2017/01/09 21:38:07 I know Cast devices don't comply; presumably they
Wez 2017/01/09 22:12:58 Acknowledged.
89
90 std::string app_url_header;
91 if (!headers->GetNormalizedHeader(kApplicationUrlHeaderName,
92 &app_url_header) ||
93 app_url_header.empty()) {
94 ReportError("Missing or empty Application-URL:");
95 return;
96 }
97
98 // Section 5.4 of the DIAL spec implies that the Application URL should not
99 // have path, query or fragment...unsure if that can be enforced.
Wez 2017/01/05 22:29:24 There seem to be a number of issues of this sort -
mark a. foltz 2017/01/09 21:38:07 I would probably start with UMA to determine preva
Wez 2017/01/09 22:12:58 Acknowledged.
100 GURL app_url(app_url_header);
101 if (!app_url.is_valid() || !app_url.SchemeIs("http") ||
102 !app_url.HostIsIPAddress() ||
Wez 2017/01/05 22:29:24 Strictly the spec says that the |host| must either
mark a. foltz 2017/01/09 21:38:07 Yes. We don't want domain name resolution here.
Wez 2017/01/09 22:12:58 The DIAL spec appears to allow for DNS names in ap
103 app_url.host() != device_description_url_.host()) {
104 ReportError(base::StringPrintf("Invalid Application-URL: %s",
105 app_url_header.c_str()));
106 return;
107 }
108
109 if (source->GetReceivedResponseContentLength() > kMaxDescriptionSizeBytes) {
110 ReportError("Response too large");
111 return;
112 }
113
114 std::string device_description;
115 if (!source->GetResponseAsString(&device_description) ||
116 device_description.empty()) {
117 ReportError("Missing or empty response");
118 return;
119 }
120
121 if (!base::IsStringUTF8(device_description)) {
122 ReportError("Invalid response encoding");
123 return;
124 }
125
126 std::move(success_cb_)
127 .Run(DialDeviceDescriptionData(device_description, app_url));
Wez 2017/01/05 22:29:24 nit: |device_description| can be up to 256KB in si
mark a. foltz 2017/01/09 21:38:06 Done.
128 }
129
130 void DeviceDescriptionFetcher::OnURLFetchDownloadProgress(
131 const net::URLFetcher* source,
132 int64_t current,
133 int64_t total,
134 int64_t current_network_bytes) {}
135
136 void DeviceDescriptionFetcher::OnURLFetchUploadProgress(
137 const net::URLFetcher* source,
138 int64_t current,
139 int64_t total) {}
140
141 void DeviceDescriptionFetcher::ReportError(const std::string& message) {
142 std::move(error_cb_).Run(message);
Wez 2017/01/05 22:29:24 I'm not familiar with the new OnceCallback semanti
mark a. foltz 2017/01/09 21:38:07 That's what the following says: https://chromium.
Wez 2017/01/09 22:12:58 Acknowledged.
143 }
144
145 } // namespace dial
146 } // namespace api
147 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698