Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: chrome_frame/urlmon_url_request.cc

Issue 402107: ChromeFrame's host network stack implementation for IE full tab mode implicit... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome_frame/urlmon_url_request.h ('k') | net/http/http_response_headers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome_frame/urlmon_url_request.h" 5 #include "chrome_frame/urlmon_url_request.h"
6 6
7 #include <wininet.h> 7 #include <wininet.h>
8 8
9 #include "base/scoped_ptr.h" 9 #include "base/scoped_ptr.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "chrome_frame/chrome_frame_activex_base.h" 13 #include "chrome_frame/chrome_frame_activex_base.h"
14 #include "chrome_frame/html_utils.h" 14 #include "chrome_frame/html_utils.h"
15 #include "chrome_frame/urlmon_upload_data_stream.h" 15 #include "chrome_frame/urlmon_upload_data_stream.h"
16 #include "chrome_frame/utils.h" 16 #include "chrome_frame/utils.h"
17 #include "net/http/http_util.h" 17 #include "net/http/http_util.h"
18 #include "net/http/http_response_headers.h" 18 #include "net/http/http_response_headers.h"
19 19
20 static const LARGE_INTEGER kZero = {0}; 20 static const LARGE_INTEGER kZero = {0};
21 static const ULARGE_INTEGER kUnsignedZero = {0}; 21 static const ULARGE_INTEGER kUnsignedZero = {0};
22 int UrlmonUrlRequest::instance_count_ = 0; 22 int UrlmonUrlRequest::instance_count_ = 0;
23 23
24 UrlmonUrlRequest::UrlmonUrlRequest() 24 UrlmonUrlRequest::UrlmonUrlRequest()
25 : pending_read_size_(0), 25 : pending_read_size_(0),
26 status_(URLRequestStatus::FAILED, net::ERR_FAILED), 26 status_(URLRequestStatus::FAILED, net::ERR_FAILED),
27 thread_(PlatformThread::CurrentId()), 27 thread_(PlatformThread::CurrentId()),
28 redirect_status_(0), 28 redirect_status_(0),
29 parent_window_(NULL), 29 parent_window_(NULL),
30 worker_thread_(NULL) { 30 worker_thread_(NULL),
31 ignore_redirect_stop_binding_error_(false) {
31 DLOG(INFO) << StringPrintf("Created request. Obj: %X", this) 32 DLOG(INFO) << StringPrintf("Created request. Obj: %X", this)
32 << " Count: " << ++instance_count_; 33 << " Count: " << ++instance_count_;
33 } 34 }
34 35
35 UrlmonUrlRequest::~UrlmonUrlRequest() { 36 UrlmonUrlRequest::~UrlmonUrlRequest() {
36 DLOG(INFO) << StringPrintf("Deleted request. Obj: %X", this) 37 DLOG(INFO) << StringPrintf("Deleted request. Obj: %X", this)
37 << " Count: " << --instance_count_; 38 << " Count: " << --instance_count_;
38 } 39 }
39 40
40 bool UrlmonUrlRequest::Start() { 41 bool UrlmonUrlRequest::Start() {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 *priority = THREAD_PRIORITY_NORMAL; 171 *priority = THREAD_PRIORITY_NORMAL;
171 return S_OK; 172 return S_OK;
172 } 173 }
173 174
174 STDMETHODIMP UrlmonUrlRequest::OnLowResource(DWORD reserved) { 175 STDMETHODIMP UrlmonUrlRequest::OnLowResource(DWORD reserved) {
175 return S_OK; 176 return S_OK;
176 } 177 }
177 178
178 STDMETHODIMP UrlmonUrlRequest::OnProgress(ULONG progress, ULONG max_progress, 179 STDMETHODIMP UrlmonUrlRequest::OnProgress(ULONG progress, ULONG max_progress,
179 ULONG status_code, LPCWSTR status_text) { 180 ULONG status_code, LPCWSTR status_text) {
181 static const int kDefaultHttpRedirectCode = 302;
182
180 switch (status_code) { 183 switch (status_code) {
181 case BINDSTATUS_REDIRECTING: 184 case BINDSTATUS_REDIRECTING: {
185 // Fetch the redirect status as they aren't all equal (307 in particular
186 // retains the HTTP request verb).
187 // We assume that valid redirect codes are 301, 302, 303 and 307. If we
188 // receive anything else we would abort the request which would
189 // eventually result in the request getting cancelled in Chrome.
190 int redirect_status = GetHttpResponseStatus();
182 DCHECK(status_text != NULL); 191 DCHECK(status_text != NULL);
183 DLOG(INFO) << "URL: " << url() << " redirected to " 192 DLOG(INFO) << "URL: " << url() << " redirected to "
184 << status_text; 193 << status_text;
185 redirect_url_ = status_text; 194 redirect_url_ = status_text;
186 // Fetch the redirect status as they aren't all equal (307 in particular 195 redirect_status_ =
187 // retains the HTTP request verb). 196 redirect_status > 0 ? redirect_status : kDefaultHttpRedirectCode;
188 redirect_status_ = GetHttpResponseStatus(); 197 // Chrome should decide whether a redirect has to be followed. To achieve
189 // NOTE: Even though RFC 2616 says to preserve the request method when 198 // this we send over a fake response to Chrome and abort the redirect.
190 // following a 302 redirect, normal browsers don't do that. Instead they 199 std::string headers = GetHttpHeaders();
191 // all convert a POST into a GET in response to a 302 and so shall we. 200 OnResponse(0, UTF8ToWide(headers).c_str(), NULL, NULL);
192 // For 307 redirects, browsers preserve the method. The RFC says to 201 ignore_redirect_stop_binding_error_ = true;
193 // prompt the user to confirm the generation of a new POST request, but 202 DCHECK(binding_ != NULL);
194 // IE omits this prompt and so shall we. 203 binding_->Abort();
195 if (redirect_status_ != 307 && 204 binding_ = NULL;
196 LowerCaseEqualsASCII(method(), "post")) { 205 return E_ABORT;
197 set_method("get"); 206 }
198 ClearPostData();
199 }
200 break;
201 207
202 default: 208 default:
203 DLOG(INFO) << " Obj: " << std::hex << this << " OnProgress(" << url() 209 DLOG(INFO) << " Obj: " << std::hex << this << " OnProgress(" << url()
204 << StringPrintf(L") code: %i status: %ls", status_code, status_text); 210 << StringPrintf(L") code: %i status: %ls", status_code, status_text);
205 break; 211 break;
206 } 212 }
207 213
208 return S_OK; 214 return S_OK;
209 } 215 }
210 216
211 STDMETHODIMP UrlmonUrlRequest::OnStopBinding(HRESULT result, LPCWSTR error) { 217 STDMETHODIMP UrlmonUrlRequest::OnStopBinding(HRESULT result, LPCWSTR error) {
212 DCHECK(worker_thread_ != NULL); 218 DCHECK(worker_thread_ != NULL);
213 DCHECK_EQ(PlatformThread::CurrentId(), worker_thread_->thread_id()); 219 DCHECK_EQ(PlatformThread::CurrentId(), worker_thread_->thread_id());
214 220
215 DLOG(INFO) << StringPrintf("URL: %s Obj: %X", url().c_str(), this) << 221 DLOG(INFO) << StringPrintf("URL: %s Obj: %X", url().c_str(), this) <<
216 " - Request stopped, Result: " << std::hex << result << 222 " - Request stopped, Result: " << std::hex << result <<
217 " Status: " << status_.status(); 223 " Status: " << status_.status();
224
218 if (FAILED(result)) { 225 if (FAILED(result)) {
219 status_.set_status(URLRequestStatus::FAILED); 226 status_.set_status(URLRequestStatus::FAILED);
220 status_.set_os_error(HresultToNetError(result)); 227 status_.set_os_error(HresultToNetError(result));
221 EndRequest(); 228 EndRequest();
222 } else { 229 } else {
223 status_.set_status(URLRequestStatus::SUCCESS); 230 status_.set_status(URLRequestStatus::SUCCESS);
224 status_.set_os_error(0); 231 status_.set_os_error(0);
225 } 232 }
226 233
227 DLOG(INFO) << "OnStopBinding received for request id: " << id(); 234 DLOG(INFO) << "OnStopBinding received for request id: " << id();
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 } 607 }
601 608
602 DLOG_IF(ERROR, FAILED(hr)) 609 DLOG_IF(ERROR, FAILED(hr))
603 << StringPrintf(L"StartAsyncDownload failed: 0x%08X", hr); 610 << StringPrintf(L"StartAsyncDownload failed: 0x%08X", hr);
604 611
605 return hr; 612 return hr;
606 } 613 }
607 614
608 void UrlmonUrlRequest::EndRequest() { 615 void UrlmonUrlRequest::EndRequest() {
609 DLOG(INFO) << __FUNCTION__; 616 DLOG(INFO) << __FUNCTION__;
610 // Special case. If the last request was a redirect and the current OS 617
611 // error value is E_ACCESSDENIED, that means an unsafe redirect was attempted. 618 // In case of a redirect notification we prevent urlmon from following the
612 // In that case, correct the OS error value to be the more specific 619 // redirect and rely on Chrome, in which case AutomationMsg_RequestEnd
613 // ERR_UNSAFE_REDIRECT error value. 620 // IPC will be sent over by Chrome to end this request.
614 if (!status_.is_success() && status_.os_error() == net::ERR_ACCESS_DENIED) { 621 if (!ignore_redirect_stop_binding_error_) {
615 int status = GetHttpResponseStatus(); 622 // Special case. If the last request was a redirect and the current OS
616 if (status >= 300 && status < 400) { 623 // error value is E_ACCESSDENIED, that means an unsafe redirect was
617 redirect_status_ = status; // store the latest redirect status value. 624 // attempted. In that case, correct the OS error value to be the more
618 status_.set_os_error(net::ERR_UNSAFE_REDIRECT); 625 // specific ERR_UNSAFE_REDIRECT error value.
626 if (!status_.is_success() && status_.os_error() == net::ERR_ACCESS_DENIED) {
627 int status = GetHttpResponseStatus();
628 if (status >= 300 && status < 400) {
629 redirect_status_ = status; // store the latest redirect status value.
630 status_.set_os_error(net::ERR_UNSAFE_REDIRECT);
631 }
619 } 632 }
633 OnResponseEnd(status_);
634 } else {
635 ignore_redirect_stop_binding_error_ = false;
620 } 636 }
621 637
622 OnResponseEnd(status_);
623
624 // Remove the request mapping and release the outstanding reference to us in 638 // Remove the request mapping and release the outstanding reference to us in
625 // the context of the UI thread. 639 // the context of the UI thread.
626 PostTask(FROM_HERE, 640 PostTask(FROM_HERE,
627 NewRunnableMethod(this, &UrlmonUrlRequest::EndRequestInternal)); 641 NewRunnableMethod(this, &UrlmonUrlRequest::EndRequestInternal));
628 } 642 }
629 643
630 void UrlmonUrlRequest::EndRequestInternal() { 644 void UrlmonUrlRequest::EndRequestInternal() {
631 // The request object could have been removed from the map in the 645 // The request object could have been removed from the map in the
632 // OnRequestEnd callback which executes on receiving the 646 // OnRequestEnd callback which executes on receiving the
633 // AutomationMsg_RequestEnd IPC from Chrome. 647 // AutomationMsg_RequestEnd IPC from Chrome.
634 request_handler()->RemoveRequest(this); 648 request_handler()->RemoveRequest(this);
635 // The current instance could get destroyed in the context of DestroyWindow. 649 // The current instance could get destroyed in the context of DestroyWindow.
636 // We should not access the object after this. 650 // We should not access the object after this.
637 DestroyWindow(); 651 DestroyWindow();
638 } 652 }
639 653
640 int UrlmonUrlRequest::GetHttpResponseStatus() const { 654 int UrlmonUrlRequest::GetHttpResponseStatus() const {
641 if (binding_ == NULL) { 655 if (binding_ == NULL) {
642 DLOG(WARNING) << "GetHttpResponseStatus - no binding_"; 656 DLOG(WARNING) << "GetHttpResponseStatus - no binding_";
643 return 0; 657 return 0;
644 } 658 }
645 659
646 int http_status = 0; 660 int http_status = 0;
647 661
648 ScopedComPtr<IWinInetHttpInfo> info; 662 ScopedComPtr<IWinInetHttpInfo> info;
649 if (SUCCEEDED(info.QueryFrom(binding_))) { 663 if (SUCCEEDED(info.QueryFrom(binding_))) {
650 char status[10] = {0}; 664 char status[10] = {0};
651 DWORD buf_size = sizeof(status); 665 DWORD buf_size = sizeof(status);
666 DWORD flags = 0;
667 DWORD reserved = 0;
652 if (SUCCEEDED(info->QueryInfo(HTTP_QUERY_STATUS_CODE, status, &buf_size, 668 if (SUCCEEDED(info->QueryInfo(HTTP_QUERY_STATUS_CODE, status, &buf_size,
653 0, NULL))) { 669 &flags, &reserved))) {
654 http_status = StringToInt(status); 670 http_status = StringToInt(status);
655 } else { 671 } else {
656 NOTREACHED() << "Failed to get HTTP status"; 672 NOTREACHED() << "Failed to get HTTP status";
657 } 673 }
658 } else { 674 } else {
659 NOTREACHED() << "failed to get IWinInetHttpInfo from binding_"; 675 NOTREACHED() << "failed to get IWinInetHttpInfo from binding_";
660 } 676 }
661 677
662 return http_status; 678 return http_status;
663 } 679 }
664 680
681 std::string UrlmonUrlRequest::GetHttpHeaders() const {
682 if (binding_ == NULL) {
683 DLOG(WARNING) << "GetHttpResponseStatus - no binding_";
684 return std::string();
685 }
686
687 ScopedComPtr<IWinInetHttpInfo> info;
688 if (FAILED(info.QueryFrom(binding_))) {
689 DLOG(WARNING) << "Failed to QI for IWinInetHttpInfo";
690 return std::string();
691 }
692
693 scoped_ptr<char> buffer;
694 DWORD size = 0;
695 DWORD flags = 0;
696 DWORD reserved = 0;
697 HRESULT hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &size,
698 &flags, &reserved);
699 if (!size) {
700 DLOG(WARNING) << "Failed to query HTTP headers size. Error 0x%x" << hr;
701 return std::string();
702 }
703
704 buffer.reset(new char[size]);
705 memset(buffer.get(), 0, size);
706
707 hr = info->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, buffer.get(),
708 &size, &flags, &reserved);
709 if (FAILED(hr)) {
710 DLOG(WARNING) << "Failed to query HTTP headers. Error 0x%x" << hr;
711 return std::string();
712 }
713
714 return buffer.get();
715 }
716
665 // 717 //
666 // UrlmonUrlRequest::Cache implementation. 718 // UrlmonUrlRequest::Cache implementation.
667 // 719 //
668 720
669 size_t UrlmonUrlRequest::Cache::Size() { 721 size_t UrlmonUrlRequest::Cache::Size() {
670 size_t size = 0; 722 size_t size = 0;
671 if (stream_) { 723 if (stream_) {
672 STATSTG cache_stat = {0}; 724 STATSTG cache_stat = {0};
673 stream_->Stat(&cache_stat, STATFLAG_NONAME); 725 stream_->Stat(&cache_stat, STATFLAG_NONAME);
674 726
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 ret = net::ERR_ACCESS_DENIED; 877 ret = net::ERR_ACCESS_DENIED;
826 break; 878 break;
827 879
828 default: 880 default:
829 DLOG(WARNING) 881 DLOG(WARNING)
830 << StringPrintf("TODO: translate HRESULT 0x%08X to net::Error", hr); 882 << StringPrintf("TODO: translate HRESULT 0x%08X to net::Error", hr);
831 break; 883 break;
832 } 884 }
833 return ret; 885 return ret;
834 } 886 }
OLDNEW
« no previous file with comments | « chrome_frame/urlmon_url_request.h ('k') | net/http/http_response_headers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698