| OLD | NEW |
| (Empty) |
| 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 "remoting/host/url_fetcher.h" | |
| 6 | |
| 7 #include "base/location.h" | |
| 8 #include "base/message_loop_proxy.h" | |
| 9 #include "googleurl/src/gurl.h" | |
| 10 #include "net/base/io_buffer.h" | |
| 11 #include "net/url_request/url_request.h" | |
| 12 #include "net/url_request/url_request_context_getter.h" | |
| 13 | |
| 14 namespace remoting { | |
| 15 | |
| 16 const int kBufferSize = 4096; | |
| 17 | |
| 18 class UrlFetcher::Core : public base::RefCountedThreadSafe<Core>, | |
| 19 public net::URLRequest::Delegate { | |
| 20 public: | |
| 21 Core(const GURL& url, Method method); | |
| 22 | |
| 23 void SetRequestContext( | |
| 24 net::URLRequestContextGetter* request_context_getter); | |
| 25 void SetUploadData(const std::string& upload_content_type, | |
| 26 const std::string& upload_content); | |
| 27 void SetHeader(const std::string& key, const std::string& value); | |
| 28 void Start(const UrlFetcher::DoneCallback& done_callback); | |
| 29 | |
| 30 void Detach(); | |
| 31 | |
| 32 // net::UrlRequest::Delegate interface. | |
| 33 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE; | |
| 34 virtual void OnReadCompleted(net::URLRequest* request, | |
| 35 int bytes_read) OVERRIDE; | |
| 36 | |
| 37 private: | |
| 38 friend class base::RefCountedThreadSafe<Core>; | |
| 39 virtual ~Core(); | |
| 40 | |
| 41 // Helper methods called on the IO thread. | |
| 42 void DoStart(); | |
| 43 void ReadResponse(); | |
| 44 void CancelRequest(); | |
| 45 | |
| 46 // Helper called on the delegate thread to invoke |done_callback_|. | |
| 47 void CallCallback(const net::URLRequestStatus& status, | |
| 48 int response_code); | |
| 49 | |
| 50 GURL url_; | |
| 51 Method method_; | |
| 52 | |
| 53 scoped_refptr<base::MessageLoopProxy> delegate_message_loop_; | |
| 54 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; | |
| 55 | |
| 56 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | |
| 57 | |
| 58 std::string upload_content_; | |
| 59 std::string upload_content_type_; | |
| 60 | |
| 61 net::HttpRequestHeaders request_headers_; | |
| 62 | |
| 63 scoped_ptr<net::URLRequest> request_; | |
| 64 | |
| 65 scoped_refptr<net::IOBuffer> buffer_; | |
| 66 std::string data_; | |
| 67 | |
| 68 UrlFetcher::DoneCallback done_callback_; | |
| 69 | |
| 70 DISALLOW_COPY_AND_ASSIGN(Core); | |
| 71 }; | |
| 72 | |
| 73 UrlFetcher::Core::Core(const GURL& url, Method method) | |
| 74 : url_(url), | |
| 75 method_(method), | |
| 76 delegate_message_loop_(base::MessageLoopProxy::current()), | |
| 77 buffer_(new net::IOBuffer(kBufferSize)) { | |
| 78 CHECK(url_.is_valid()); | |
| 79 } | |
| 80 | |
| 81 UrlFetcher::Core::~Core() { | |
| 82 } | |
| 83 | |
| 84 void UrlFetcher::Core::SetRequestContext( | |
| 85 net::URLRequestContextGetter* request_context_getter) { | |
| 86 DCHECK(!request_context_getter_); | |
| 87 request_context_getter_ = request_context_getter; | |
| 88 } | |
| 89 | |
| 90 void UrlFetcher::Core::SetUploadData(const std::string& upload_content_type, | |
| 91 const std::string& upload_content) { | |
| 92 upload_content_type_ = upload_content_type; | |
| 93 upload_content_ = upload_content; | |
| 94 } | |
| 95 | |
| 96 void UrlFetcher::Core::SetHeader(const std::string& key, | |
| 97 const std::string& value) { | |
| 98 request_headers_.SetHeader(key, value); | |
| 99 } | |
| 100 | |
| 101 void UrlFetcher::Core::Start(const UrlFetcher::DoneCallback& done_callback) { | |
| 102 done_callback_ = done_callback; | |
| 103 network_task_runner_ = request_context_getter_->GetNetworkTaskRunner(); | |
| 104 DCHECK(network_task_runner_); | |
| 105 network_task_runner_->PostTask(FROM_HERE, base::Bind( | |
| 106 &UrlFetcher::Core::DoStart, this)); | |
| 107 } | |
| 108 | |
| 109 void UrlFetcher::Core::Detach() { | |
| 110 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); | |
| 111 network_task_runner_->PostTask( | |
| 112 FROM_HERE, base::Bind(&UrlFetcher::Core::CancelRequest, this)); | |
| 113 done_callback_.Reset(); | |
| 114 } | |
| 115 | |
| 116 void UrlFetcher::Core::OnResponseStarted(net::URLRequest* request) { | |
| 117 DCHECK_EQ(request, request_.get()); | |
| 118 DCHECK(network_task_runner_->BelongsToCurrentThread()); | |
| 119 ReadResponse(); | |
| 120 } | |
| 121 | |
| 122 void UrlFetcher::Core::OnReadCompleted(net::URLRequest* request, | |
| 123 int bytes_read) { | |
| 124 DCHECK_EQ(request, request_.get()); | |
| 125 DCHECK(network_task_runner_->BelongsToCurrentThread()); | |
| 126 | |
| 127 do { | |
| 128 if (!request_->status().is_success() || bytes_read <= 0) | |
| 129 break; | |
| 130 | |
| 131 data_.append(buffer_->data(), bytes_read); | |
| 132 } while (request_->Read(buffer_, kBufferSize, &bytes_read)); | |
| 133 | |
| 134 const net::URLRequestStatus status = request_->status(); | |
| 135 if (!status.is_io_pending()) { | |
| 136 // We are done. Post a task to call |done_callback_|. | |
| 137 delegate_message_loop_->PostTask( | |
| 138 FROM_HERE, base::Bind(&UrlFetcher::Core::CallCallback, this, status, | |
| 139 request_->GetResponseCode())); | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 void UrlFetcher::Core::DoStart() { | |
| 144 DCHECK(network_task_runner_->BelongsToCurrentThread()); | |
| 145 | |
| 146 request_.reset(new net::URLRequest( | |
| 147 url_, this, request_context_getter_->GetURLRequestContext())); | |
| 148 | |
| 149 switch (method_) { | |
| 150 case GET: | |
| 151 break; | |
| 152 | |
| 153 case POST: | |
| 154 DCHECK(!upload_content_.empty()); | |
| 155 DCHECK(!upload_content_type_.empty()); | |
| 156 request_->set_method("POST"); | |
| 157 | |
| 158 request_headers_.SetHeader(net::HttpRequestHeaders::kContentType, | |
| 159 upload_content_type_); | |
| 160 | |
| 161 request_->AppendBytesToUpload( | |
| 162 upload_content_.data(), static_cast<int>(upload_content_.length())); | |
| 163 break; | |
| 164 } | |
| 165 | |
| 166 request_->SetExtraRequestHeaders(request_headers_); | |
| 167 | |
| 168 request_->Start(); | |
| 169 } | |
| 170 | |
| 171 void UrlFetcher::Core::ReadResponse() { | |
| 172 int bytes_read = 0; | |
| 173 if (request_->status().is_success()) { | |
| 174 request_->Read(buffer_, kBufferSize, &bytes_read); | |
| 175 } | |
| 176 OnReadCompleted(request_.get(), bytes_read); | |
| 177 } | |
| 178 | |
| 179 void UrlFetcher::Core::CallCallback(const net::URLRequestStatus& status, | |
| 180 int response_code) { | |
| 181 DCHECK(delegate_message_loop_->BelongsToCurrentThread()); | |
| 182 if (!done_callback_.is_null()) { | |
| 183 done_callback_.Run(status, response_code, data_); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 void UrlFetcher::Core::CancelRequest() { | |
| 188 if (request_.get()) { | |
| 189 request_->Cancel(); | |
| 190 request_.reset(); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 UrlFetcher::UrlFetcher(const GURL& url, Method method) | |
| 195 : core_ (new Core(url, method)) { | |
| 196 } | |
| 197 | |
| 198 UrlFetcher::~UrlFetcher() { | |
| 199 core_->Detach(); | |
| 200 } | |
| 201 | |
| 202 void UrlFetcher::SetRequestContext( | |
| 203 net::URLRequestContextGetter* request_context_getter) { | |
| 204 core_->SetRequestContext(request_context_getter); | |
| 205 } | |
| 206 | |
| 207 void UrlFetcher::SetUploadData(const std::string& upload_content_type, | |
| 208 const std::string& upload_content) { | |
| 209 core_->SetUploadData(upload_content_type, upload_content); | |
| 210 } | |
| 211 | |
| 212 void UrlFetcher::SetHeader(const std::string& key, const std::string& value) { | |
| 213 core_->SetHeader(key, value); | |
| 214 } | |
| 215 | |
| 216 void UrlFetcher::Start(const DoneCallback& done_callback) { | |
| 217 core_->Start(done_callback); | |
| 218 } | |
| 219 | |
| 220 } // namespace remoting | |
| OLD | NEW |