Home | History | Annotate | Download | only in android
      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.
      4 
      5 #include "content/renderer/media/android/media_info_loader.h"
      6 
      7 #include "base/bits.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"
     14 
     15 using blink::WebFrame;
     16 using blink::WebURLError;
     17 using blink::WebURLLoader;
     18 using blink::WebURLLoaderOptions;
     19 using blink::WebURLRequest;
     20 using blink::WebURLResponse;
     21 
     22 namespace content {
     23 
     24 static const int kHttpOK = 200;
     25 
     26 MediaInfoLoader::MediaInfoLoader(
     27     const GURL& url,
     28     blink::WebMediaPlayer::CORSMode cors_mode,
     29     const ReadyCB& ready_cb)
     30     : loader_failed_(false),
     31       url_(url),
     32       cors_mode_(cors_mode),
     33       single_origin_(true),
     34       ready_cb_(ready_cb) {}
     35 
     36 MediaInfoLoader::~MediaInfoLoader() {}
     37 
     38 void MediaInfoLoader::Start(blink::WebFrame* frame) {
     39   // Make sure we have not started.
     40   DCHECK(!ready_cb_.is_null());
     41   CHECK(frame);
     42 
     43   start_time_ = base::TimeTicks::Now();
     44 
     45   // Prepare the request.
     46   WebURLRequest request(url_);
     47   request.setTargetType(WebURLRequest::TargetIsMedia);
     48   frame->setReferrerForRequest(request, blink::WebURL());
     49 
     50   scoped_ptr<WebURLLoader> loader;
     51   if (test_loader_) {
     52     loader = test_loader_.Pass();
     53   } else {
     54     WebURLLoaderOptions options;
     55     if (cors_mode_ == blink::WebMediaPlayer::CORSModeUnspecified) {
     56       options.allowCredentials = true;
     57       options.crossOriginRequestPolicy =
     58           WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
     59     } else {
     60       options.exposeAllResponseHeaders = true;
     61       // The author header set is empty, no preflight should go ahead.
     62       options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
     63       options.crossOriginRequestPolicy =
     64           WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
     65       if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials)
     66         options.allowCredentials = true;
     67     }
     68     loader.reset(frame->createAssociatedURLLoader(options));
     69   }
     70 
     71   // Start the resource loading.
     72   loader->loadAsynchronously(request, this);
     73   active_loader_.reset(new ActiveLoader(loader.Pass()));
     74 }
     75 
     76 /////////////////////////////////////////////////////////////////////////////
     77 // blink::WebURLLoaderClient implementation.
     78 void MediaInfoLoader::willSendRequest(
     79     WebURLLoader* loader,
     80     WebURLRequest& newRequest,
     81     const WebURLResponse& redirectResponse) {
     82   // The load may have been stopped and |ready_cb| is destroyed.
     83   // In this case we shouldn't do anything.
     84   if (ready_cb_.is_null()) {
     85     // Set the url in the request to an invalid value (empty url).
     86     newRequest.setURL(blink::WebURL());
     87     return;
     88   }
     89 
     90   // Only allow |single_origin_| if we haven't seen a different origin yet.
     91   if (single_origin_)
     92     single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
     93 
     94   url_ = newRequest.url();
     95 }
     96 
     97 void MediaInfoLoader::didSendData(
     98     WebURLLoader* loader,
     99     unsigned long long bytes_sent,
    100     unsigned long long total_bytes_to_be_sent) {
    101   NOTIMPLEMENTED();
    102 }
    103 
    104 void MediaInfoLoader::didReceiveResponse(
    105     WebURLLoader* loader,
    106     const WebURLResponse& response) {
    107   DVLOG(1) << "didReceiveResponse: HTTP/"
    108            << (response.httpVersion() == WebURLResponse::HTTP_0_9 ? "0.9" :
    109                response.httpVersion() == WebURLResponse::HTTP_1_0 ? "1.0" :
    110                response.httpVersion() == WebURLResponse::HTTP_1_1 ? "1.1" :
    111                "Unknown")
    112            << " " << response.httpStatusCode();
    113   DCHECK(active_loader_.get());
    114   if (!url_.SchemeIs("http") && !url_.SchemeIs("https")) {
    115       DidBecomeReady(kOk);
    116       return;
    117   }
    118   if (response.httpStatusCode() == kHttpOK) {
    119     DidBecomeReady(kOk);
    120     return;
    121   }
    122   loader_failed_ = true;
    123   DidBecomeReady(kFailed);
    124 }
    125 
    126 void MediaInfoLoader::didReceiveData(
    127     WebURLLoader* loader,
    128     const char* data,
    129     int data_length,
    130     int encoded_data_length) {
    131   // Ignored.
    132 }
    133 
    134 void MediaInfoLoader::didDownloadData(
    135     blink::WebURLLoader* loader,
    136     int dataLength,
    137     int encodedDataLength) {
    138   NOTIMPLEMENTED();
    139 }
    140 
    141 void MediaInfoLoader::didReceiveCachedMetadata(
    142     WebURLLoader* loader,
    143     const char* data,
    144     int data_length) {
    145   NOTIMPLEMENTED();
    146 }
    147 
    148 void MediaInfoLoader::didFinishLoading(
    149     WebURLLoader* loader,
    150     double finishTime) {
    151   DCHECK(active_loader_.get());
    152   DidBecomeReady(kOk);
    153 }
    154 
    155 void MediaInfoLoader::didFail(
    156     WebURLLoader* loader,
    157     const WebURLError& error) {
    158   DVLOG(1) << "didFail: reason=" << error.reason
    159            << ", isCancellation=" << error.isCancellation
    160            << ", domain=" << error.domain.utf8().data()
    161            << ", localizedDescription="
    162            << error.localizedDescription.utf8().data();
    163   DCHECK(active_loader_.get());
    164   loader_failed_ = true;
    165   DidBecomeReady(kFailed);
    166 }
    167 
    168 bool MediaInfoLoader::HasSingleOrigin() const {
    169   DCHECK(ready_cb_.is_null())
    170       << "Must become ready before calling HasSingleOrigin()";
    171   return single_origin_;
    172 }
    173 
    174 bool MediaInfoLoader::DidPassCORSAccessCheck() const {
    175   DCHECK(ready_cb_.is_null())
    176       << "Must become ready before calling DidPassCORSAccessCheck()";
    177   return !loader_failed_ &&
    178       cors_mode_ != blink::WebMediaPlayer::CORSModeUnspecified;
    179 }
    180 
    181 /////////////////////////////////////////////////////////////////////////////
    182 // Helper methods.
    183 
    184 void MediaInfoLoader::DidBecomeReady(Status status) {
    185   UMA_HISTOGRAM_TIMES("Media.InfoLoadDelay",
    186                       base::TimeTicks::Now() - start_time_);
    187   active_loader_.reset();
    188   if (!ready_cb_.is_null())
    189     base::ResetAndReturn(&ready_cb_).Run(status);
    190 }
    191 
    192 }  // namespace content
    193