Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / url_request / url_request.cc
index dae9d0e..58697a2 100644 (file)
@@ -14,6 +14,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/stats_counters.h"
+#include "base/metrics/user_metrics.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
@@ -197,6 +198,10 @@ void URLRequest::Delegate::OnSSLCertificateError(URLRequest* request,
   request->Cancel();
 }
 
+void URLRequest::Delegate::OnBeforeNetworkStart(URLRequest* request,
+                                                bool* defer) {
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // URLRequest
 
@@ -219,12 +224,13 @@ URLRequest::URLRequest(const GURL& url,
       priority_(priority),
       identifier_(GenerateURLRequestIdentifier()),
       calling_delegate_(false),
-      delegate_info_usage_(DELEGATE_INFO_DEBUG_ONLY),
+      use_blocked_by_as_load_param_(false),
       before_request_callback_(base::Bind(&URLRequest::BeforeRequestComplete,
                                           base::Unretained(this))),
       has_notified_completion_(false),
       received_response_content_length_(0),
-      creation_time_(base::TimeTicks::Now()) {
+      creation_time_(base::TimeTicks::Now()),
+      notified_before_network_start_(false) {
   SIMPLE_STATS_COUNTER("URLRequestCount");
 
   // Sanity check out environment.
@@ -346,25 +352,32 @@ bool URLRequest::GetFullRequestHeaders(HttpRequestHeaders* headers) const {
   return job_->GetFullRequestHeaders(headers);
 }
 
+int64 URLRequest::GetTotalReceivedBytes() const {
+  if (!job_.get())
+    return 0;
+
+  return job_->GetTotalReceivedBytes();
+}
+
 LoadStateWithParam URLRequest::GetLoadState() const {
-  // The delegate_info_.empty() check allows |this| to report it's blocked on
-  // delegate before it has been started.
-  if (calling_delegate_ || !delegate_info_.empty()) {
+  // The !blocked_by_.empty() check allows |this| to report it's blocked on a
+  // delegate before it has been started.
+  if (calling_delegate_ || !blocked_by_.empty()) {
     return LoadStateWithParam(
         LOAD_STATE_WAITING_FOR_DELEGATE,
-        delegate_info_usage_ == DELEGATE_INFO_DISPLAY_TO_USER ?
-            UTF8ToUTF16(delegate_info_) : base::string16());
+        use_blocked_by_as_load_param_ ? base::UTF8ToUTF16(blocked_by_) :
+                                        base::string16());
   }
   return LoadStateWithParam(job_.get() ? job_->GetLoadState() : LOAD_STATE_IDLE,
                             base::string16());
 }
 
 base::Value* URLRequest::GetStateAsValue() const {
-  DictionaryValue* dict = new DictionaryValue();
+  base::DictionaryValue* dict = new base::DictionaryValue();
   dict->SetString("url", original_url().possibly_invalid_spec());
 
   if (url_chain_.size() > 1) {
-    ListValue* list = new ListValue();
+    base::ListValue* list = new base::ListValue();
     for (std::vector<GURL>::const_iterator url = url_chain_.begin();
          url != url_chain_.end(); ++url) {
       list->AppendString(url->possibly_invalid_spec());
@@ -378,8 +391,8 @@ base::Value* URLRequest::GetStateAsValue() const {
   dict->SetInteger("load_state", load_state.state);
   if (!load_state.param.empty())
     dict->SetString("load_state_param", load_state.param);
-  if (!delegate_info_.empty())
-    dict->SetString("delegate_info", delegate_info_);
+  if (!blocked_by_.empty())
+    dict->SetString("delegate_info", blocked_by_);
 
   dict->SetString("method", method_);
   dict->SetBoolean("has_upload", has_upload());
@@ -407,25 +420,35 @@ base::Value* URLRequest::GetStateAsValue() const {
   return dict;
 }
 
-void URLRequest::SetDelegateInfo(const char* delegate_info,
-                                 DelegateInfoUsage delegate_info_usage) {
-  // Only log delegate information to NetLog during startup and certain
-  // deferring calls to delegates.  For all reads but the first, delegate info
-  // is currently ignored.
+void URLRequest::LogBlockedBy(const char* blocked_by) {
+  DCHECK(blocked_by);
+  DCHECK_GT(strlen(blocked_by), 0u);
+
+  // Only log information to NetLog during startup and certain deferring calls
+  // to delegates.  For all reads but the first, do nothing.
   if (!calling_delegate_ && !response_info_.request_time.is_null())
     return;
 
-  if (!delegate_info_.empty()) {
-    delegate_info_.clear();
-    net_log_.EndEvent(NetLog::TYPE_DELEGATE_INFO);
-  }
-  if (delegate_info) {
-    delegate_info_ = delegate_info;
-    delegate_info_usage_ = delegate_info_usage;
-    net_log_.BeginEvent(
-        NetLog::TYPE_DELEGATE_INFO,
-        NetLog::StringCallback("delegate_info", &delegate_info_));
-  }
+  LogUnblocked();
+  blocked_by_ = blocked_by;
+  use_blocked_by_as_load_param_ = false;
+
+  net_log_.BeginEvent(
+      NetLog::TYPE_DELEGATE_INFO,
+      NetLog::StringCallback("delegate_info", &blocked_by_));
+}
+
+void URLRequest::LogAndReportBlockedBy(const char* source) {
+  LogBlockedBy(source);
+  use_blocked_by_as_load_param_ = true;
+}
+
+void URLRequest::LogUnblocked() {
+  if (blocked_by_.empty())
+    return;
+
+  net_log_.EndEvent(NetLog::TYPE_DELEGATE_INFO);
+  blocked_by_.clear();
 }
 
 UploadProgress URLRequest::GetUploadProgress() const {
@@ -498,6 +521,20 @@ int URLRequest::GetResponseCode() const {
   return job_->GetResponseCode();
 }
 
+void URLRequest::SetLoadFlags(int flags) {
+  if ((load_flags_ & LOAD_IGNORE_LIMITS) != (flags & LOAD_IGNORE_LIMITS)) {
+    DCHECK(!job_);
+    DCHECK(flags & LOAD_IGNORE_LIMITS);
+    DCHECK_EQ(priority_, MAXIMUM_PRIORITY);
+  }
+  load_flags_ = flags;
+
+  // This should be a no-op given the above DCHECKs, but do this
+  // anyway for release mode.
+  if ((load_flags_ & LOAD_IGNORE_LIMITS) != 0)
+    SetPriority(MAXIMUM_PRIORITY);
+}
+
 // static
 void URLRequest::SetDefaultCookiePolicyToBlock() {
   CHECK(!g_url_requests_started);
@@ -579,9 +616,9 @@ void URLRequest::set_delegate(Delegate* delegate) {
 
 void URLRequest::Start() {
   DCHECK_EQ(network_delegate_, context_->network_delegate());
-  // Anything that set delegate information before start should have cleaned up
-  // after itself.
-  DCHECK(delegate_info_.empty());
+  // Anything that sets |blocked_by_| before start should have cleaned up after
+  // itself.
+  DCHECK(blocked_by_.empty());
 
   g_url_requests_started = true;
   response_info_.request_time = base::Time::Now();
@@ -660,6 +697,20 @@ void URLRequest::StartJob(URLRequestJob* job) {
 
   response_info_.was_cached = false;
 
+  // If the referrer is secure, but the requested URL is not, the referrer
+  // policy should be something non-default. If you hit this, please file a
+  // bug.
+  if (referrer_policy_ ==
+          CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE &&
+      GURL(referrer_).SchemeIsSecure() && !url().SchemeIsSecure()) {
+#if !defined(OFFICIAL_BUILD)
+    LOG(FATAL) << "Trying to send secure referrer for insecure load";
+#endif
+    referrer_.clear();
+    base::RecordAction(
+        base::UserMetricsAction("Net.URLRequest_StartJob_InvalidReferrer"));
+  }
+
   // Don't allow errors to be sent from within Start().
   // TODO(brettw) this may cause NotifyDone to be sent synchronously,
   // we probably don't want this: they should be sent asynchronously so
@@ -701,7 +752,7 @@ void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) {
   DCHECK(error < 0);
   // If cancelled while calling a delegate, clear delegate info.
   if (calling_delegate_) {
-    SetDelegateInfo(NULL, DELEGATE_INFO_DEBUG_ONLY);
+    LogUnblocked();
     OnCallToDelegateComplete();
   }
 
@@ -788,6 +839,24 @@ void URLRequest::NotifyReceivedRedirect(const GURL& location,
   }
 }
 
+void URLRequest::NotifyBeforeNetworkStart(bool* defer) {
+  if (delegate_ && !notified_before_network_start_) {
+    OnCallToDelegate();
+    delegate_->OnBeforeNetworkStart(this, defer);
+    if (!*defer)
+      OnCallToDelegateComplete();
+    notified_before_network_start_ = true;
+  }
+}
+
+void URLRequest::ResumeNetworkStart() {
+  DCHECK(job_);
+  DCHECK(notified_before_network_start_);
+
+  OnCallToDelegateComplete();
+  job_->ResumeNetworkStart();
+}
+
 void URLRequest::NotifyResponseStarted() {
   int net_error = OK;
   if (!status_.is_success())
@@ -960,6 +1029,14 @@ int64 URLRequest::GetExpectedContentSize() const {
 void URLRequest::SetPriority(RequestPriority priority) {
   DCHECK_GE(priority, MINIMUM_PRIORITY);
   DCHECK_LE(priority, MAXIMUM_PRIORITY);
+
+  if ((load_flags_ & LOAD_IGNORE_LIMITS) && (priority != MAXIMUM_PRIORITY)) {
+    NOTREACHED();
+    // Maintain the invariant that requests with IGNORE_LIMITS set
+    // have MAXIMUM_PRIORITY for release mode.
+    return;
+  }
+
   if (priority_ == priority)
     return;
 
@@ -1140,14 +1217,14 @@ void URLRequest::NotifyRequestCompleted() {
 
 void URLRequest::OnCallToDelegate() {
   DCHECK(!calling_delegate_);
-  DCHECK(delegate_info_.empty());
+  DCHECK(blocked_by_.empty());
   calling_delegate_ = true;
   net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_DELEGATE);
 }
 
 void URLRequest::OnCallToDelegateComplete() {
-  // Delegates should clear their info when it becomes outdated.
-  DCHECK(delegate_info_.empty());
+  // This should have been cleared before resuming the request.
+  DCHECK(blocked_by_.empty());
   if (!calling_delegate_)
     return;
   calling_delegate_ = false;