1 // Copyright 2013 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.
5 #include "content/renderer/media/android/media_info_loader.h"
8 #include "base/callback_helpers.h"
9 #include "base/metrics/histogram.h"
10 #include "third_party/WebKit/public/platform/WebURLError.h"
11 #include "third_party/WebKit/public/platform/WebURLLoader.h"
12 #include "third_party/WebKit/public/platform/WebURLResponse.h"
13 #include "third_party/WebKit/public/web/WebFrame.h"
15 using blink::WebFrame;
16 using blink::WebURLError;
17 using blink::WebURLLoader;
18 using blink::WebURLLoaderOptions;
19 using blink::WebURLRequest;
20 using blink::WebURLResponse;
24 static const int kHttpOK = 200;
26 MediaInfoLoader::MediaInfoLoader(
28 blink::WebMediaPlayer::CORSMode cors_mode,
29 const ReadyCB& ready_cb)
30 : loader_failed_(false),
32 allow_stored_credentials_(false),
33 cors_mode_(cors_mode),
35 ready_cb_(ready_cb) {}
37 MediaInfoLoader::~MediaInfoLoader() {}
39 void MediaInfoLoader::Start(blink::WebFrame* frame) {
40 // Make sure we have not started.
41 DCHECK(!ready_cb_.is_null());
44 start_time_ = base::TimeTicks::Now();
45 first_party_url_ = frame->document().firstPartyForCookies();
47 // Prepare the request.
48 WebURLRequest request(url_);
49 request.setTargetType(WebURLRequest::TargetIsMedia);
50 frame->setReferrerForRequest(request, blink::WebURL());
52 scoped_ptr<WebURLLoader> loader;
54 loader = test_loader_.Pass();
56 WebURLLoaderOptions options;
57 if (cors_mode_ == blink::WebMediaPlayer::CORSModeUnspecified) {
58 options.allowCredentials = true;
59 options.crossOriginRequestPolicy =
60 WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
61 allow_stored_credentials_ = true;
63 options.exposeAllResponseHeaders = true;
64 // The author header set is empty, no preflight should go ahead.
65 options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
66 options.crossOriginRequestPolicy =
67 WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
68 if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials) {
69 options.allowCredentials = true;
70 allow_stored_credentials_ = true;
73 loader.reset(frame->createAssociatedURLLoader(options));
76 // Start the resource loading.
77 loader->loadAsynchronously(request, this);
78 active_loader_.reset(new ActiveLoader(loader.Pass()));
81 /////////////////////////////////////////////////////////////////////////////
82 // blink::WebURLLoaderClient implementation.
83 void MediaInfoLoader::willSendRequest(
85 WebURLRequest& newRequest,
86 const WebURLResponse& redirectResponse) {
87 // The load may have been stopped and |ready_cb| is destroyed.
88 // In this case we shouldn't do anything.
89 if (ready_cb_.is_null()) {
90 // Set the url in the request to an invalid value (empty url).
91 newRequest.setURL(blink::WebURL());
95 // Only allow |single_origin_| if we haven't seen a different origin yet.
97 single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
99 url_ = newRequest.url();
100 first_party_url_ = newRequest.firstPartyForCookies();
101 allow_stored_credentials_ = newRequest.allowStoredCredentials();
104 void MediaInfoLoader::didSendData(
105 WebURLLoader* loader,
106 unsigned long long bytes_sent,
107 unsigned long long total_bytes_to_be_sent) {
111 void MediaInfoLoader::didReceiveResponse(
112 WebURLLoader* loader,
113 const WebURLResponse& response) {
114 DVLOG(1) << "didReceiveResponse: HTTP/"
115 << (response.httpVersion() == WebURLResponse::HTTP_0_9 ? "0.9" :
116 response.httpVersion() == WebURLResponse::HTTP_1_0 ? "1.0" :
117 response.httpVersion() == WebURLResponse::HTTP_1_1 ? "1.1" :
119 << " " << response.httpStatusCode();
120 DCHECK(active_loader_.get());
121 if (!url_.SchemeIs("http") && !url_.SchemeIs("https")) {
125 if (response.httpStatusCode() == kHttpOK) {
129 loader_failed_ = true;
130 DidBecomeReady(kFailed);
133 void MediaInfoLoader::didReceiveData(
134 WebURLLoader* loader,
137 int encoded_data_length) {
141 void MediaInfoLoader::didDownloadData(
142 blink::WebURLLoader* loader,
144 int encodedDataLength) {
148 void MediaInfoLoader::didReceiveCachedMetadata(
149 WebURLLoader* loader,
155 void MediaInfoLoader::didFinishLoading(
156 WebURLLoader* loader,
158 int64_t total_encoded_data_length) {
159 DCHECK(active_loader_.get());
163 void MediaInfoLoader::didFail(
164 WebURLLoader* loader,
165 const WebURLError& error) {
166 DVLOG(1) << "didFail: reason=" << error.reason
167 << ", isCancellation=" << error.isCancellation
168 << ", domain=" << error.domain.utf8().data()
169 << ", localizedDescription="
170 << error.localizedDescription.utf8().data();
171 DCHECK(active_loader_.get());
172 loader_failed_ = true;
173 DidBecomeReady(kFailed);
176 bool MediaInfoLoader::HasSingleOrigin() const {
177 DCHECK(ready_cb_.is_null())
178 << "Must become ready before calling HasSingleOrigin()";
179 return single_origin_;
182 bool MediaInfoLoader::DidPassCORSAccessCheck() const {
183 DCHECK(ready_cb_.is_null())
184 << "Must become ready before calling DidPassCORSAccessCheck()";
185 return !loader_failed_ &&
186 cors_mode_ != blink::WebMediaPlayer::CORSModeUnspecified;
189 /////////////////////////////////////////////////////////////////////////////
192 void MediaInfoLoader::DidBecomeReady(Status status) {
193 UMA_HISTOGRAM_TIMES("Media.InfoLoadDelay",
194 base::TimeTicks::Now() - start_time_);
195 active_loader_.reset();
196 if (!ready_cb_.is_null())
197 base::ResetAndReturn(&ready_cb_).Run(status, url_, first_party_url_,
198 allow_stored_credentials_);
201 } // namespace content