1// Copyright (c) 2012 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/browser/loader/sync_resource_handler.h"
6
7#include "base/logging.h"
8#include "content/browser/devtools/devtools_netlog_observer.h"
9#include "content/browser/loader/resource_dispatcher_host_impl.h"
10#include "content/browser/loader/resource_message_filter.h"
11#include "content/browser/loader/resource_request_info_impl.h"
12#include "content/common/resource_messages.h"
13#include "content/public/browser/resource_dispatcher_host_delegate.h"
14#include "content/public/browser/resource_request_info.h"
15#include "net/base/io_buffer.h"
16#include "net/http/http_response_headers.h"
17
18namespace content {
19
20SyncResourceHandler::SyncResourceHandler(
21    net::URLRequest* request,
22    IPC::Message* result_message,
23    ResourceDispatcherHostImpl* resource_dispatcher_host)
24    : ResourceHandler(request),
25      read_buffer_(new net::IOBuffer(kReadBufSize)),
26      result_message_(result_message),
27      rdh_(resource_dispatcher_host),
28      total_transfer_size_(0) {
29  result_.final_url = request->url();
30}
31
32SyncResourceHandler::~SyncResourceHandler() {
33  if (result_message_) {
34    result_message_->set_reply_error();
35    ResourceMessageFilter* filter = GetFilter();
36    // If the filter doesn't exist at this point, the process has died and isn't
37    // waiting for the result message anymore.
38    if (filter)
39      filter->Send(result_message_);
40  }
41}
42
43bool SyncResourceHandler::OnUploadProgress(uint64 position, uint64 size) {
44  return true;
45}
46
47bool SyncResourceHandler::OnRequestRedirected(
48    const GURL& new_url,
49    ResourceResponse* response,
50    bool* defer) {
51  if (rdh_->delegate()) {
52    rdh_->delegate()->OnRequestRedirected(
53        new_url, request(), GetRequestInfo()->GetContext(), response);
54  }
55
56  DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
57  // TODO(darin): It would be much better if this could live in WebCore, but
58  // doing so requires API changes at all levels.  Similar code exists in
59  // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
60  if (new_url.GetOrigin() != result_.final_url.GetOrigin()) {
61    LOG(ERROR) << "Cross origin redirect denied";
62    return false;
63  }
64  result_.final_url = new_url;
65
66  total_transfer_size_ += request()->GetTotalReceivedBytes();
67  return true;
68}
69
70bool SyncResourceHandler::OnResponseStarted(
71    ResourceResponse* response,
72    bool* defer) {
73  const ResourceRequestInfoImpl* info = GetRequestInfo();
74  if (!info->filter())
75    return false;
76
77  if (rdh_->delegate()) {
78    rdh_->delegate()->OnResponseStarted(
79        request(), info->GetContext(), response, info->filter());
80  }
81
82  DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
83
84  // We don't care about copying the status here.
85  result_.headers = response->head.headers;
86  result_.mime_type = response->head.mime_type;
87  result_.charset = response->head.charset;
88  result_.download_file_path = response->head.download_file_path;
89  result_.request_time = response->head.request_time;
90  result_.response_time = response->head.response_time;
91  result_.load_timing = response->head.load_timing;
92  result_.devtools_info = response->head.devtools_info;
93  return true;
94}
95
96bool SyncResourceHandler::OnWillStart(const GURL& url, bool* defer) {
97  return true;
98}
99
100bool SyncResourceHandler::OnBeforeNetworkStart(const GURL& url, bool* defer) {
101  return true;
102}
103
104bool SyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
105                                     int* buf_size,
106                                     int min_size) {
107  DCHECK(min_size == -1);
108  *buf = read_buffer_.get();
109  *buf_size = kReadBufSize;
110  return true;
111}
112
113bool SyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
114  if (!bytes_read)
115    return true;
116  result_.data.append(read_buffer_->data(), bytes_read);
117  return true;
118}
119
120void SyncResourceHandler::OnResponseCompleted(
121    const net::URLRequestStatus& status,
122    const std::string& security_info,
123    bool* defer) {
124  ResourceMessageFilter* filter = GetFilter();
125  if (!filter)
126    return;
127
128  result_.error_code = status.error();
129
130  int total_transfer_size = request()->GetTotalReceivedBytes();
131  result_.encoded_data_length = total_transfer_size_ + total_transfer_size;
132
133  ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_);
134  filter->Send(result_message_);
135  result_message_ = NULL;
136  return;
137}
138
139void SyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
140  // Sync requests don't involve ResourceMsg_DataDownloaded messages
141  // being sent back to renderers as progress is made.
142}
143
144}  // namespace content
145