blob: b4075b578ef8e7a4fa17ae983c687a726c2b0794 [file] [log] [blame]
[email protected]27a112c2011-01-06 04:19:301// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]3eb07da2010-02-01 19:48:362// 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]60cc89e2011-05-11 18:26:3712#include "base/callback_old.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.
[email protected]4736610c2011-03-04 06:43:3542 typedef Callback4<IMoniker*, IBindCtx*, IStream*, const char*>::Type
[email protected]f4fbae682011-02-28 22:18:3343 TerminateBindCallback;
[email protected]5cec0eb32010-04-28 21:00:5444 void TerminateBind(TerminateBindCallback* callback);
[email protected]3eb07da2010-02-01 19:48:3645
46 // Parent Window for UrlMon error dialogs
47 void set_parent_window(HWND parent_window) {
48 parent_window_ = parent_window;
49 }
50
[email protected]7403d38f2010-03-22 22:50:4951 // This function passes information on whether ChromeFrame is running in
52 // privileged mode.
53 void set_privileged_mode(bool privileged_mode) {
54 privileged_mode_ = privileged_mode;
55 }
56
[email protected]1a5b2c2422010-05-08 15:36:1757 // Returns a string in the form " id: %i Obj: %X URL: %s" which is useful
58 // to identify request objects in the log.
59 std::string me() const;
[email protected]3ee61122010-04-14 00:35:5260
[email protected]b0938a42011-10-05 20:59:3861 static bool ImplementsThreadSafeReferenceCounting() {
62 return true;
63 }
64
[email protected]3eb07da2010-02-01 19:48:3665 protected:
66 UrlmonUrlRequest();
67 ~UrlmonUrlRequest();
68
69 BEGIN_COM_MAP(UrlmonUrlRequest)
70 COM_INTERFACE_ENTRY(IHttpNegotiate)
71 COM_INTERFACE_ENTRY(IServiceProvider)
72 COM_INTERFACE_ENTRY(IBindStatusCallback)
73 COM_INTERFACE_ENTRY(IWindowForBindingUI)
74 COM_INTERFACE_ENTRY(IAuthenticate)
75 COM_INTERFACE_ENTRY(IHttpSecurity)
76 END_COM_MAP()
77
78 BEGIN_SERVICE_MAP(UrlmonUrlRequest)
79 SERVICE_ENTRY(IID_IHttpNegotiate);
80 END_SERVICE_MAP()
81
[email protected]3eb07da2010-02-01 19:48:3682 // IBindStatusCallback implementation
83 STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding);
84 STDMETHOD(GetPriority)(LONG* priority);
85 STDMETHOD(OnLowResource)(DWORD reserved);
86 STDMETHOD(OnProgress)(ULONG progress, ULONG max_progress,
[email protected]1a5b2c2422010-05-08 15:36:1787 ULONG status_code, LPCWSTR status_text);
[email protected]3eb07da2010-02-01 19:48:3688 STDMETHOD(OnStopBinding)(HRESULT result, LPCWSTR error);
89 STDMETHOD(GetBindInfo)(DWORD* bind_flags, BINDINFO* bind_info);
90 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc,
[email protected]1a5b2c2422010-05-08 15:36:1791 STGMEDIUM* storage);
[email protected]3eb07da2010-02-01 19:48:3692 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object);
93
94 // IHttpNegotiate implementation
95 STDMETHOD(BeginningTransaction)(const wchar_t* url,
[email protected]1a5b2c2422010-05-08 15:36:1796 const wchar_t* current_headers, DWORD reserved,
97 wchar_t** additional_headers);
[email protected]3eb07da2010-02-01 19:48:3698 STDMETHOD(OnResponse)(DWORD dwResponseCode, const wchar_t* response_headers,
[email protected]1a5b2c2422010-05-08 15:36:1799 const wchar_t* request_headers, wchar_t** additional_headers);
[email protected]3eb07da2010-02-01 19:48:36100
101 // IWindowForBindingUI implementation. This interface is used typically to
102 // query the window handle which URLMON uses as the parent of error dialogs.
103 STDMETHOD(GetWindow)(REFGUID guid_reason, HWND* parent_window);
104
105 // IAuthenticate implementation. Used to return the parent window for the
106 // dialog displayed by IE for authenticating with a proxy.
107 STDMETHOD(Authenticate)(HWND* parent_window, LPWSTR* user_name,
[email protected]1a5b2c2422010-05-08 15:36:17108 LPWSTR* password);
[email protected]3eb07da2010-02-01 19:48:36109
110 // IHttpSecurity implementation.
111 STDMETHOD(OnSecurityProblem)(DWORD problem);
112
[email protected]70277f62010-04-15 01:39:26113 void set_pending(bool pending) {
114 pending_ = pending;
115 }
116
117 bool pending() const {
118 return pending_;
119 }
120
[email protected]5cec0eb32010-04-28 21:00:54121 bool terminate_requested() const {
122 return terminate_bind_callback_.get() != NULL;
123 }
124
[email protected]70277f62010-04-15 01:39:26125 std::string response_headers() {
126 return response_headers_;
127 }
128
[email protected]3eb07da2010-02-01 19:48:36129 protected:
130 void ReleaseBindings();
131
[email protected]3eb07da2010-02-01 19:48:36132 HRESULT StartAsyncDownload();
133 void NotifyDelegateAndDie();
[email protected]233469df2010-10-08 22:18:53134 void TerminateTransaction();
[email protected]3eb07da2010-02-01 19:48:36135 static net::Error HresultToNetError(HRESULT hr);
136
137 private:
[email protected]0ce46402010-04-08 16:53:57138 size_t SendDataToDelegate(size_t bytes);
[email protected]1a5b2c2422010-05-08 15:36:17139
[email protected]3eb07da2010-02-01 19:48:36140 // This class simplifies tracking the progress of operation. We have 3 main
141 // states: DONE, WORKING and ABORTING.
142 // When in [DONE] or [ABORTING] state, there is additional information
143 // about the result of operation.
144 // Start(), SetRedirected(), Cancel() and Done() methods trigger the state
145 // change. See comments bellow.
146 class Status {
147 public:
148 enum State {DONE, ABORTING, WORKING};
149 struct Redirection {
150 Redirection() : http_code(0) { }
151 int http_code;
152 std::string utf8_url;
153 };
154
155 Status() : state_(Status::DONE) {
156 }
157
158 State get_state() const {
159 return state_;
160 }
161
162 // Switch from [DONE] to [WORKING].
163 void Start() {
164 DCHECK_EQ(state_, DONE);
165 state_ = WORKING;
166 }
167
168 // Save redirection information and switch to [ABORTING] state.
169 // Assumes binding_->Abort() will be called!
170 void SetRedirected(int http_code, const std::string& utf8_url) {
171 DCHECK_EQ(state_, WORKING);
[email protected]27a112c2011-01-06 04:19:30172 DCHECK_EQ(result_.status(), net::URLRequestStatus::SUCCESS);
[email protected]3eb07da2010-02-01 19:48:36173 redirect_.utf8_url = utf8_url;
174
175 // At times we receive invalid redirect codes like 0, 200, etc. We
176 // default to 302 in this case.
177 redirect_.http_code = http_code;
178 if (!net::HttpResponseHeaders::IsRedirectResponseCode(http_code))
179 redirect_.http_code = 302;
180
181 state_ = ABORTING;
182 }
183
[email protected]27a112c2011-01-06 04:19:30184 // Set the result as net::URLRequestStatus::CANCELED.
[email protected]3eb07da2010-02-01 19:48:36185 // Switch to [ABORTING] state (if not already in that state).
186 void Cancel() {
187 if (state_ == DONE)
188 return;
189
190 if (state_ == WORKING) {
191 state_ = ABORTING;
192 } else {
193 // state_ == ABORTING
194 redirect_.http_code = 0;
195 redirect_.utf8_url.clear();
196 }
197
[email protected]27a112c2011-01-06 04:19:30198 set_result(net::URLRequestStatus::CANCELED, 0);
[email protected]3eb07da2010-02-01 19:48:36199 }
200
201 void Done() {
202 state_ = DONE;
203 }
204
205 bool was_redirected() const {
206 return redirect_.http_code != 0;
207 }
208
209 const Redirection& get_redirection() const {
210 return redirect_;
211 }
212
[email protected]27a112c2011-01-06 04:19:30213 const net::URLRequestStatus& get_result() const {
[email protected]3eb07da2010-02-01 19:48:36214 return result_;
215 }
216
[email protected]d0cc35b2011-09-08 12:02:05217 void set_result(net::URLRequestStatus::Status status, int error) {
[email protected]3eb07da2010-02-01 19:48:36218 result_.set_status(status);
[email protected]d0cc35b2011-09-08 12:02:05219 result_.set_error(error);
[email protected]3eb07da2010-02-01 19:48:36220 }
221
222 void set_result(HRESULT hr) {
[email protected]27a112c2011-01-06 04:19:30223 result_.set_status(FAILED(hr)? net::URLRequestStatus::FAILED:
224 net::URLRequestStatus::SUCCESS);
[email protected]d0cc35b2011-09-08 12:02:05225 result_.set_error(HresultToNetError(hr));
[email protected]3eb07da2010-02-01 19:48:36226 }
227
228 private:
229 Redirection redirect_;
230 State state_;
[email protected]27a112c2011-01-06 04:19:30231 net::URLRequestStatus result_;
[email protected]3eb07da2010-02-01 19:48:36232 };
233
234 Status status_;
[email protected]8ee65ba2011-04-12 20:53:23235 base::win::ScopedComPtr<IBinding> binding_;
236 base::win::ScopedComPtr<IMoniker> moniker_;
237 base::win::ScopedComPtr<IBindCtx> bind_context_;
238 base::win::ScopedComPtr<IStream> cache_;
239 base::win::ScopedComPtr<IStream> pending_data_;
[email protected]1a5b2c2422010-05-08 15:36:17240
[email protected]3eb07da2010-02-01 19:48:36241 size_t pending_read_size_;
[email protected]ce072a72010-12-31 20:02:16242 base::PlatformThreadId thread_;
[email protected]3eb07da2010-02-01 19:48:36243 HWND parent_window_;
[email protected]290c5372010-02-12 17:02:09244 bool headers_received_;
[email protected]0ce46402010-04-08 16:53:57245 int calling_delegate_; // re-entrancy protection.
[email protected]7403d38f2010-03-22 22:50:49246 // Set to true if the ChromeFrame instance is running in privileged mode.
247 bool privileged_mode_;
[email protected]70277f62010-04-15 01:39:26248 bool pending_;
[email protected]5cec0eb32010-04-28 21:00:54249 scoped_ptr<TerminateBindCallback> terminate_bind_callback_;
[email protected]70277f62010-04-15 01:39:26250 std::string response_headers_;
[email protected]233469df2010-10-08 22:18:53251 // Defaults to true and indicates whether we want to keep the original
252 // transaction alive when we receive the last data notification from
253 // urlmon.
254 bool is_expecting_download_;
255 // Set to true if the Urlmon transaction object needs to be cleaned up
256 // when this object is destroyed. Happens if we return
257 // INET_E_TERMINATE_BIND from OnDataAvailable in the last data notification.
258 bool cleanup_transaction_;
[email protected]f4fbae682011-02-28 22:18:33259 // Copy of the request headers.
260 std::string request_headers_;
[email protected]233469df2010-10-08 22:18:53261
[email protected]3eb07da2010-02-01 19:48:36262 DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest);
263};
264
265#endif // CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_