blob: ebe027c336a8e9d56e3b5a5af4aef9bf76a4ec0d [file] [log] [blame]
[email protected]3eb07da2010-02-01 19:48:361// Copyright (c) 2010 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#ifndef CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_
6#define CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_
7
8#include <atlbase.h>
9#include <atlcom.h>
10#include <string>
[email protected]3eb07da2010-02-01 19:48:3611
[email protected]7e4468d52010-09-22 19:42:0012#include "base/callback.h"
[email protected]ce072a72010-12-31 20:02:1613#include "base/threading/platform_thread.h"
[email protected]3eb07da2010-02-01 19:48:3614#include "net/base/net_errors.h"
15#include "net/http/http_response_headers.h"
16#include "net/url_request/url_request_status.h"
[email protected]4cb6dca52010-04-08 22:11:3117#include "testing/gtest/include/gtest/gtest_prod.h"
[email protected]3eb07da2010-02-01 19:48:3618
[email protected]051236f2010-03-12 22:06:1419class RequestData;
20
[email protected]3eb07da2010-02-01 19:48:3621class UrlmonUrlRequest
22 : public CComObjectRootEx<CComMultiThreadModel>,
23 public PluginUrlRequest,
24 public IServiceProviderImpl<UrlmonUrlRequest>,
25 public IBindStatusCallback,
26 public IHttpNegotiate,
27 public IAuthenticate,
28 public IHttpSecurity {
29 public:
[email protected]3eb07da2010-02-01 19:48:3630 virtual bool Start();
31 virtual void Stop();
32 virtual bool Read(int bytes_to_read);
33
34 // Special function needed by ActiveDocument::Load()
[email protected]3ee61122010-04-14 00:35:5235 HRESULT InitPending(const GURL& url, IMoniker* moniker, IBindCtx* bind_ctx,
36 bool enable_frame_busting, bool privileged_mode,
[email protected]70277f62010-04-15 01:39:2637 HWND notification_window, IStream* cache);
[email protected]3eb07da2010-02-01 19:48:3638
[email protected]7ae80742010-03-25 22:02:2739 // Used from "DownloadRequestInHost".
[email protected]5cec0eb32010-04-28 21:00:5440 // Callback will be invoked either right away (if operation is finished) or
41 // from inside ::OnStopBinding() when it is safe to reuse the bind_context.
42 typedef Callback2<IMoniker*, IBindCtx*>::Type TerminateBindCallback;
43 void TerminateBind(TerminateBindCallback* callback);
[email protected]3eb07da2010-02-01 19:48:3644
45 // Parent Window for UrlMon error dialogs
46 void set_parent_window(HWND parent_window) {
47 parent_window_ = parent_window;
48 }
49
[email protected]7403d38f2010-03-22 22:50:4950 // This function passes information on whether ChromeFrame is running in
51 // privileged mode.
52 void set_privileged_mode(bool privileged_mode) {
53 privileged_mode_ = privileged_mode;
54 }
55
[email protected]1a5b2c2422010-05-08 15:36:1756 // Returns a string in the form " id: %i Obj: %X URL: %s" which is useful
57 // to identify request objects in the log.
58 std::string me() const;
[email protected]3ee61122010-04-14 00:35:5259
[email protected]3eb07da2010-02-01 19:48:3660 protected:
61 UrlmonUrlRequest();
62 ~UrlmonUrlRequest();
63
64 BEGIN_COM_MAP(UrlmonUrlRequest)
65 COM_INTERFACE_ENTRY(IHttpNegotiate)
66 COM_INTERFACE_ENTRY(IServiceProvider)
67 COM_INTERFACE_ENTRY(IBindStatusCallback)
68 COM_INTERFACE_ENTRY(IWindowForBindingUI)
69 COM_INTERFACE_ENTRY(IAuthenticate)
70 COM_INTERFACE_ENTRY(IHttpSecurity)
71 END_COM_MAP()
72
73 BEGIN_SERVICE_MAP(UrlmonUrlRequest)
74 SERVICE_ENTRY(IID_IHttpNegotiate);
75 END_SERVICE_MAP()
76
[email protected]3eb07da2010-02-01 19:48:3677 // IBindStatusCallback implementation
78 STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding);
79 STDMETHOD(GetPriority)(LONG* priority);
80 STDMETHOD(OnLowResource)(DWORD reserved);
81 STDMETHOD(OnProgress)(ULONG progress, ULONG max_progress,
[email protected]1a5b2c2422010-05-08 15:36:1782 ULONG status_code, LPCWSTR status_text);
[email protected]3eb07da2010-02-01 19:48:3683 STDMETHOD(OnStopBinding)(HRESULT result, LPCWSTR error);
84 STDMETHOD(GetBindInfo)(DWORD* bind_flags, BINDINFO* bind_info);
85 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc,
[email protected]1a5b2c2422010-05-08 15:36:1786 STGMEDIUM* storage);
[email protected]3eb07da2010-02-01 19:48:3687 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object);
88
89 // IHttpNegotiate implementation
90 STDMETHOD(BeginningTransaction)(const wchar_t* url,
[email protected]1a5b2c2422010-05-08 15:36:1791 const wchar_t* current_headers, DWORD reserved,
92 wchar_t** additional_headers);
[email protected]3eb07da2010-02-01 19:48:3693 STDMETHOD(OnResponse)(DWORD dwResponseCode, const wchar_t* response_headers,
[email protected]1a5b2c2422010-05-08 15:36:1794 const wchar_t* request_headers, wchar_t** additional_headers);
[email protected]3eb07da2010-02-01 19:48:3695
96 // IWindowForBindingUI implementation. This interface is used typically to
97 // query the window handle which URLMON uses as the parent of error dialogs.
98 STDMETHOD(GetWindow)(REFGUID guid_reason, HWND* parent_window);
99
100 // IAuthenticate implementation. Used to return the parent window for the
101 // dialog displayed by IE for authenticating with a proxy.
102 STDMETHOD(Authenticate)(HWND* parent_window, LPWSTR* user_name,
[email protected]1a5b2c2422010-05-08 15:36:17103 LPWSTR* password);
[email protected]3eb07da2010-02-01 19:48:36104
105 // IHttpSecurity implementation.
106 STDMETHOD(OnSecurityProblem)(DWORD problem);
107
[email protected]70277f62010-04-15 01:39:26108 void set_pending(bool pending) {
109 pending_ = pending;
110 }
111
112 bool pending() const {
113 return pending_;
114 }
115
[email protected]5cec0eb32010-04-28 21:00:54116 bool terminate_requested() const {
117 return terminate_bind_callback_.get() != NULL;
118 }
119
[email protected]70277f62010-04-15 01:39:26120 std::string response_headers() {
121 return response_headers_;
122 }
123
[email protected]3eb07da2010-02-01 19:48:36124 protected:
125 void ReleaseBindings();
126
[email protected]3eb07da2010-02-01 19:48:36127 HRESULT StartAsyncDownload();
128 void NotifyDelegateAndDie();
[email protected]233469df2010-10-08 22:18:53129 void TerminateTransaction();
[email protected]3eb07da2010-02-01 19:48:36130 static net::Error HresultToNetError(HRESULT hr);
131
132 private:
[email protected]0ce46402010-04-08 16:53:57133 size_t SendDataToDelegate(size_t bytes);
[email protected]1a5b2c2422010-05-08 15:36:17134
[email protected]3eb07da2010-02-01 19:48:36135 // This class simplifies tracking the progress of operation. We have 3 main
136 // states: DONE, WORKING and ABORTING.
137 // When in [DONE] or [ABORTING] state, there is additional information
138 // about the result of operation.
139 // Start(), SetRedirected(), Cancel() and Done() methods trigger the state
140 // change. See comments bellow.
141 class Status {
142 public:
143 enum State {DONE, ABORTING, WORKING};
144 struct Redirection {
145 Redirection() : http_code(0) { }
146 int http_code;
147 std::string utf8_url;
148 };
149
150 Status() : state_(Status::DONE) {
151 }
152
153 State get_state() const {
154 return state_;
155 }
156
157 // Switch from [DONE] to [WORKING].
158 void Start() {
159 DCHECK_EQ(state_, DONE);
160 state_ = WORKING;
161 }
162
163 // Save redirection information and switch to [ABORTING] state.
164 // Assumes binding_->Abort() will be called!
165 void SetRedirected(int http_code, const std::string& utf8_url) {
166 DCHECK_EQ(state_, WORKING);
167 DCHECK_EQ(result_.status(), URLRequestStatus::SUCCESS);
168 redirect_.utf8_url = utf8_url;
169
170 // At times we receive invalid redirect codes like 0, 200, etc. We
171 // default to 302 in this case.
172 redirect_.http_code = http_code;
173 if (!net::HttpResponseHeaders::IsRedirectResponseCode(http_code))
174 redirect_.http_code = 302;
175
176 state_ = ABORTING;
177 }
178
179 // Set the result as URLRequestStatus::CANCELED.
180 // Switch to [ABORTING] state (if not already in that state).
181 void Cancel() {
182 if (state_ == DONE)
183 return;
184
185 if (state_ == WORKING) {
186 state_ = ABORTING;
187 } else {
188 // state_ == ABORTING
189 redirect_.http_code = 0;
190 redirect_.utf8_url.clear();
191 }
192
193 set_result(URLRequestStatus::CANCELED, 0);
194 }
195
196 void Done() {
197 state_ = DONE;
198 }
199
200 bool was_redirected() const {
201 return redirect_.http_code != 0;
202 }
203
204 const Redirection& get_redirection() const {
205 return redirect_;
206 }
207
208 const URLRequestStatus& get_result() const {
209 return result_;
210 }
211
212 void set_result(URLRequestStatus::Status status, int os_error) {
213 result_.set_status(status);
214 result_.set_os_error(os_error);
215 }
216
217 void set_result(HRESULT hr) {
218 result_.set_status(FAILED(hr)? URLRequestStatus::FAILED:
219 URLRequestStatus::SUCCESS);
220 result_.set_os_error(HresultToNetError(hr));
221 }
222
223 private:
224 Redirection redirect_;
225 State state_;
226 URLRequestStatus result_;
227 };
228
229 Status status_;
230 ScopedComPtr<IBinding> binding_;
231 ScopedComPtr<IMoniker> moniker_;
232 ScopedComPtr<IBindCtx> bind_context_;
[email protected]1a5b2c2422010-05-08 15:36:17233 ScopedComPtr<IStream> cache_;
234 ScopedComPtr<IStream> pending_data_;
235
[email protected]3eb07da2010-02-01 19:48:36236 size_t pending_read_size_;
[email protected]ce072a72010-12-31 20:02:16237 base::PlatformThreadId thread_;
[email protected]3eb07da2010-02-01 19:48:36238 HWND parent_window_;
[email protected]290c5372010-02-12 17:02:09239 bool headers_received_;
[email protected]0ce46402010-04-08 16:53:57240 int calling_delegate_; // re-entrancy protection.
[email protected]7403d38f2010-03-22 22:50:49241 // Set to true if the ChromeFrame instance is running in privileged mode.
242 bool privileged_mode_;
[email protected]70277f62010-04-15 01:39:26243 bool pending_;
[email protected]5cec0eb32010-04-28 21:00:54244 scoped_ptr<TerminateBindCallback> terminate_bind_callback_;
[email protected]70277f62010-04-15 01:39:26245 std::string response_headers_;
[email protected]233469df2010-10-08 22:18:53246 // Defaults to true and indicates whether we want to keep the original
247 // transaction alive when we receive the last data notification from
248 // urlmon.
249 bool is_expecting_download_;
250 // Set to true if the Urlmon transaction object needs to be cleaned up
251 // when this object is destroyed. Happens if we return
252 // INET_E_TERMINATE_BIND from OnDataAvailable in the last data notification.
253 bool cleanup_transaction_;
254
[email protected]3eb07da2010-02-01 19:48:36255 DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest);
256};
257
258#endif // CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_