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.
5 #ifndef CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_
6 #define CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_
13 #include "base/gtest_prod_util.h"
14 #include "base/threading/platform_thread.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/url_request/url_request_status.h"
19 class UrlmonUrlRequest
20 : public CComObjectRootEx
<CComMultiThreadModel
>,
21 public PluginUrlRequest
,
22 public IServiceProviderImpl
<UrlmonUrlRequest
>,
23 public IBindStatusCallback
,
24 public IHttpNegotiate
,
26 public IHttpSecurity
{
30 virtual bool Read(int bytes_to_read
);
32 // Special function needed by ActiveDocument::Load()
33 HRESULT
InitPending(const GURL
& url
, IMoniker
* moniker
, IBindCtx
* bind_ctx
,
34 bool enable_frame_busting
, bool privileged_mode
,
35 HWND notification_window
, IStream
* cache
);
37 // Used from "DownloadRequestInHost".
38 // Callback will be invoked either right away (if operation is finished) or
39 // from inside ::OnStopBinding() when it is safe to reuse the bind_context.
40 typedef base::Callback
<void(IMoniker
*, IBindCtx
*, IStream
*, const char*)>
41 TerminateBindCallback
;
42 void TerminateBind(const TerminateBindCallback
& callback
);
44 // Parent Window for UrlMon error dialogs
45 void set_parent_window(HWND parent_window
) {
46 parent_window_
= parent_window
;
49 // This function passes information on whether ChromeFrame is running in
51 void set_privileged_mode(bool privileged_mode
) {
52 privileged_mode_
= privileged_mode
;
55 // Returns a string in the form " id: %i Obj: %X URL: %s" which is useful
56 // to identify request objects in the log.
57 std::string
me() const;
59 static bool ImplementsThreadSafeReferenceCounting() {
67 BEGIN_COM_MAP(UrlmonUrlRequest
)
68 COM_INTERFACE_ENTRY(IHttpNegotiate
)
69 COM_INTERFACE_ENTRY(IServiceProvider
)
70 COM_INTERFACE_ENTRY(IBindStatusCallback
)
71 COM_INTERFACE_ENTRY(IWindowForBindingUI
)
72 COM_INTERFACE_ENTRY(IAuthenticate
)
73 COM_INTERFACE_ENTRY(IHttpSecurity
)
76 BEGIN_SERVICE_MAP(UrlmonUrlRequest
)
77 SERVICE_ENTRY(IID_IHttpNegotiate
);
80 // IBindStatusCallback implementation
81 STDMETHOD(OnStartBinding
)(DWORD reserved
, IBinding
* binding
);
82 STDMETHOD(GetPriority
)(LONG
* priority
);
83 STDMETHOD(OnLowResource
)(DWORD reserved
);
84 STDMETHOD(OnProgress
)(ULONG progress
, ULONG max_progress
,
85 ULONG status_code
, LPCWSTR status_text
);
86 STDMETHOD(OnStopBinding
)(HRESULT result
, LPCWSTR error
);
87 STDMETHOD(GetBindInfo
)(DWORD
* bind_flags
, BINDINFO
* bind_info
);
88 STDMETHOD(OnDataAvailable
)(DWORD flags
, DWORD size
, FORMATETC
* formatetc
,
90 STDMETHOD(OnObjectAvailable
)(REFIID iid
, IUnknown
* object
);
92 // IHttpNegotiate implementation
93 STDMETHOD(BeginningTransaction
)(const wchar_t* url
,
94 const wchar_t* current_headers
, DWORD reserved
,
95 wchar_t** additional_headers
);
96 STDMETHOD(OnResponse
)(DWORD dwResponseCode
, const wchar_t* response_headers
,
97 const wchar_t* request_headers
, wchar_t** additional_headers
);
99 // IWindowForBindingUI implementation. This interface is used typically to
100 // query the window handle which URLMON uses as the parent of error dialogs.
101 STDMETHOD(GetWindow
)(REFGUID guid_reason
, HWND
* parent_window
);
103 // IAuthenticate implementation. Used to return the parent window for the
104 // dialog displayed by IE for authenticating with a proxy.
105 STDMETHOD(Authenticate
)(HWND
* parent_window
, LPWSTR
* user_name
,
108 // IHttpSecurity implementation.
109 STDMETHOD(OnSecurityProblem
)(DWORD problem
);
111 void set_pending(bool pending
) {
115 bool pending() const {
119 bool terminate_requested() const {
120 return !terminate_bind_callback_
.is_null();
123 std::string
response_headers() {
124 return response_headers_
;
128 void ReleaseBindings();
130 HRESULT
StartAsyncDownload();
131 void NotifyDelegateAndDie();
132 void TerminateTransaction();
133 static net::Error
HresultToNetError(HRESULT hr
);
136 size_t SendDataToDelegate(size_t bytes
);
138 // This class simplifies tracking the progress of operation. We have 3 main
139 // states: DONE, WORKING and ABORTING.
140 // When in [DONE] or [ABORTING] state, there is additional information
141 // about the result of operation.
142 // Start(), SetRedirected(), Cancel() and Done() methods trigger the state
143 // change. See comments bellow.
146 enum State
{DONE
, ABORTING
, WORKING
};
148 Redirection() : http_code(0) { }
150 std::string utf8_url
;
153 Status() : state_(Status::DONE
) {
156 State
get_state() const {
160 // Switch from [DONE] to [WORKING].
162 DCHECK_EQ(state_
, DONE
);
166 // Save redirection information and switch to [ABORTING] state.
167 // Assumes binding_->Abort() will be called!
168 void SetRedirected(int http_code
, const std::string
& utf8_url
) {
169 DCHECK_EQ(state_
, WORKING
);
170 DCHECK_EQ(result_
.status(), net::URLRequestStatus::SUCCESS
);
171 redirect_
.utf8_url
= utf8_url
;
173 // At times we receive invalid redirect codes like 0, 200, etc. We
174 // default to 302 in this case.
175 redirect_
.http_code
= http_code
;
176 if (!net::HttpResponseHeaders::IsRedirectResponseCode(http_code
))
177 redirect_
.http_code
= 302;
182 // Set the result as net::URLRequestStatus::CANCELED.
183 // Switch to [ABORTING] state (if not already in that state).
188 if (state_
== WORKING
) {
191 // state_ == ABORTING
192 redirect_
.http_code
= 0;
193 redirect_
.utf8_url
.clear();
196 set_result(net::URLRequestStatus::CANCELED
, 0);
203 bool was_redirected() const {
204 return redirect_
.http_code
!= 0;
207 const Redirection
& get_redirection() const {
211 const net::URLRequestStatus
& get_result() const {
215 void set_result(net::URLRequestStatus::Status status
, int error
) {
216 result_
.set_status(status
);
217 result_
.set_error(error
);
220 void set_result(HRESULT hr
) {
221 result_
.set_status(FAILED(hr
)? net::URLRequestStatus::FAILED
:
222 net::URLRequestStatus::SUCCESS
);
223 result_
.set_error(HresultToNetError(hr
));
227 Redirection redirect_
;
229 net::URLRequestStatus result_
;
233 base::win::ScopedComPtr
<IBinding
> binding_
;
234 base::win::ScopedComPtr
<IMoniker
> moniker_
;
235 base::win::ScopedComPtr
<IBindCtx
> bind_context_
;
236 base::win::ScopedComPtr
<IStream
> cache_
;
237 base::win::ScopedComPtr
<IStream
> pending_data_
;
239 size_t pending_read_size_
;
240 base::PlatformThreadId thread_
;
242 bool headers_received_
;
243 int calling_delegate_
; // re-entrancy protection.
244 // Set to true if the ChromeFrame instance is running in privileged mode.
245 bool privileged_mode_
;
247 TerminateBindCallback terminate_bind_callback_
;
248 std::string response_headers_
;
249 // Defaults to true and indicates whether we want to keep the original
250 // transaction alive when we receive the last data notification from
252 bool is_expecting_download_
;
253 // Set to true if the Urlmon transaction object needs to be cleaned up
254 // when this object is destroyed. Happens if we return
255 // INET_E_TERMINATE_BIND from OnDataAvailable in the last data notification.
256 bool cleanup_transaction_
;
257 // Copy of the request headers.
258 std::string request_headers_
;
260 DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest
);
263 #endif // CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_