OLD | NEW |
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 #ifndef CHROME_FRAME_URLMON_URL_REQUEST_H_ | 5 #ifndef CHROME_FRAME_URLMON_URL_REQUEST_H_ |
6 #define CHROME_FRAME_URLMON_URL_REQUEST_H_ | 6 #define CHROME_FRAME_URLMON_URL_REQUEST_H_ |
7 | 7 |
8 #include <urlmon.h> | 8 #include <urlmon.h> |
9 #include <atlbase.h> | 9 #include <atlbase.h> |
10 #include <atlcom.h> | 10 #include <atlcom.h> |
11 #include <atlwin.h> | |
12 #include <algorithm> | |
13 #include <string> | 11 #include <string> |
14 | 12 |
15 #include "base/lock.h" | 13 #include "base/scoped_comptr_win.h" |
16 #include "base/platform_thread.h" | |
17 #include "base/thread.h" | 14 #include "base/thread.h" |
18 #include "base/scoped_comptr_win.h" | 15 #include "base/waitable_event.h" |
19 #include "chrome_frame/plugin_url_request.h" | 16 #include "chrome_frame/plugin_url_request.h" |
20 #include "chrome_frame/chrome_frame_delegate.h" | 17 #include "chrome_frame/utils.h" |
21 | 18 |
22 #include "net/base/net_errors.h" | 19 class UrlmonUrlRequest; |
23 #include "net/base/upload_data.h" | |
24 | 20 |
25 class UrlmonUrlRequest | 21 class UrlmonUrlRequestManager : |
26 : public CComObjectRootEx<CComMultiThreadModel>, | 22 public PluginUrlRequestManager, |
27 public PluginUrlRequest, | 23 public PluginUrlRequestDelegate { |
28 public IServiceProviderImpl<UrlmonUrlRequest>, | |
29 public IBindStatusCallback, | |
30 public IHttpNegotiate, | |
31 public IAuthenticate, | |
32 public IHttpSecurity, | |
33 public CWindowImpl<UrlmonUrlRequest>, | |
34 public TaskMarshallerThroughWindowsMessages<UrlmonUrlRequest> { | |
35 public: | 24 public: |
36 typedef TaskMarshallerThroughWindowsMessages<UrlmonUrlRequest> | 25 UrlmonUrlRequestManager(); |
37 TaskMarshaller; | 26 ~UrlmonUrlRequestManager(); |
38 | 27 |
39 UrlmonUrlRequest(); | 28 // Use specific moniker and bind context when Chrome request this url. |
40 ~UrlmonUrlRequest(); | 29 // Used from ChromeActiveDocument's implementation of IPersistMoniker::Load(). |
41 | 30 void UseMonikerForUrl(IMoniker* moniker, IBindCtx* bind_ctx, |
42 BEGIN_COM_MAP(UrlmonUrlRequest) | 31 const std::wstring& url); |
43 COM_INTERFACE_ENTRY(IHttpNegotiate) | 32 void StealMonikerFromRequest(int request_id, IMoniker** moniker); |
44 COM_INTERFACE_ENTRY(IServiceProvider) | |
45 COM_INTERFACE_ENTRY(IBindStatusCallback) | |
46 COM_INTERFACE_ENTRY(IWindowForBindingUI) | |
47 COM_INTERFACE_ENTRY(IAuthenticate) | |
48 COM_INTERFACE_ENTRY(IHttpSecurity) | |
49 END_COM_MAP() | |
50 | |
51 BEGIN_SERVICE_MAP(UrlmonUrlRequest) | |
52 SERVICE_ENTRY(IID_IHttpNegotiate); | |
53 END_SERVICE_MAP() | |
54 | |
55 BEGIN_MSG_MAP(UrlmonUrlRequest) | |
56 CHAIN_MSG_MAP(TaskMarshaller) | |
57 END_MSG_MAP() | |
58 | |
59 // PluginUrlRequest implementation | |
60 virtual bool Start(); | |
61 virtual void Stop(); | |
62 virtual bool Read(int bytes_to_read); | |
63 | |
64 void TransferToHost(IUnknown* host); | |
65 | |
66 // IBindStatusCallback implementation | |
67 STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding); | |
68 STDMETHOD(GetPriority)(LONG* priority); | |
69 STDMETHOD(OnLowResource)(DWORD reserved); | |
70 STDMETHOD(OnProgress)(ULONG progress, ULONG max_progress, | |
71 ULONG status_code, LPCWSTR status_text); | |
72 STDMETHOD(OnStopBinding)(HRESULT result, LPCWSTR error); | |
73 STDMETHOD(GetBindInfo)(DWORD* bind_flags, BINDINFO* bind_info); | |
74 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc, | |
75 STGMEDIUM* storage); | |
76 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object); | |
77 | |
78 // IHttpNegotiate implementation | |
79 STDMETHOD(BeginningTransaction)(const wchar_t* url, | |
80 const wchar_t* current_headers, DWORD reserved, | |
81 wchar_t** additional_headers); | |
82 STDMETHOD(OnResponse)(DWORD dwResponseCode, const wchar_t* response_headers, | |
83 const wchar_t* request_headers, wchar_t** additional_headers); | |
84 | |
85 // IWindowForBindingUI implementation. This interface is used typically to | |
86 // query the window handle which URLMON uses as the parent of error dialogs. | |
87 STDMETHOD(GetWindow)(REFGUID guid_reason, HWND* parent_window); | |
88 | |
89 // IAuthenticate implementation. Used to return the parent window for the | |
90 // dialog displayed by IE for authenticating with a proxy. | |
91 STDMETHOD(Authenticate)(HWND* parent_window, LPWSTR* user_name, | |
92 LPWSTR* password); | |
93 | |
94 // IHttpSecurity implementation. | |
95 STDMETHOD(OnSecurityProblem)(DWORD problem); | |
96 | |
97 HRESULT ConnectToExistingMoniker(IMoniker* moniker, IBindCtx* context, | |
98 const std::wstring& url); | |
99 | |
100 void set_parent_window(HWND parent_window) { | |
101 parent_window_ = parent_window; | |
102 } | |
103 | |
104 // Needed to support PostTask. | |
105 static bool ImplementsThreadSafeReferenceCounting() { | |
106 return true; | |
107 } | |
108 | |
109 // URL requests are handled on this thread. | |
110 void set_worker_thread(base::Thread* worker_thread) { | |
111 worker_thread_ = worker_thread; | |
112 } | |
113 | |
114 virtual void OnFinalMessage(HWND window); | |
115 | |
116 protected: | |
117 // The following functions issue and handle Urlmon requests on the dedicated | |
118 // Urlmon thread. | |
119 void StartAsync(); | |
120 void StopAsync(); | |
121 void ReadAsync(int bytes_to_read); | |
122 void ReleaseBindings(); | |
123 | |
124 static const size_t kCopyChunkSize = 32 * 1024; | |
125 // URL requests are handled on this thread. | |
126 base::Thread* worker_thread_; | |
127 | |
128 // A fake stream class to make it easier to copy received data using | |
129 // IStream::CopyTo instead of allocating temporary buffers and keeping | |
130 // track of data copied so far. | |
131 class SendStream | |
132 : public CComObjectRoot, | |
133 public IStream { | |
134 public: | |
135 SendStream() { | |
136 } | |
137 | |
138 BEGIN_COM_MAP(SendStream) | |
139 COM_INTERFACE_ENTRY(IStream) | |
140 COM_INTERFACE_ENTRY(ISequentialStream) | |
141 END_COM_MAP() | |
142 | |
143 void Initialize(UrlmonUrlRequest* request) { | |
144 request_ = request; | |
145 } | |
146 | |
147 STDMETHOD(Read)(void* pv, ULONG cb, ULONG* read) { | |
148 DCHECK(false) << __FUNCTION__; | |
149 return E_NOTIMPL; | |
150 } | |
151 | |
152 STDMETHOD(Write)(const void * buffer, ULONG size, ULONG* size_written) { | |
153 DCHECK(request_); | |
154 int size_to_write = static_cast<int>( | |
155 std::min(static_cast<ULONG>(MAXINT), size)); | |
156 request_->OnReadComplete(buffer, size_to_write); | |
157 if (size_written) | |
158 *size_written = size_to_write; | |
159 return S_OK; | |
160 } | |
161 | |
162 STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos) { | |
163 DCHECK(false) << __FUNCTION__; | |
164 return E_NOTIMPL; | |
165 } | |
166 | |
167 STDMETHOD(SetSize)(ULARGE_INTEGER new_size) { | |
168 DCHECK(false) << __FUNCTION__; | |
169 return E_NOTIMPL; | |
170 } | |
171 | |
172 STDMETHOD(CopyTo)(IStream* stream, ULARGE_INTEGER cb, ULARGE_INTEGER* read, | |
173 ULARGE_INTEGER* written) { | |
174 DCHECK(false) << __FUNCTION__; | |
175 return E_NOTIMPL; | |
176 } | |
177 | |
178 STDMETHOD(Commit)(DWORD flags) { | |
179 DCHECK(false) << __FUNCTION__; | |
180 return E_NOTIMPL; | |
181 } | |
182 | |
183 STDMETHOD(Revert)() { | |
184 DCHECK(false) << __FUNCTION__; | |
185 return E_NOTIMPL; | |
186 } | |
187 | |
188 STDMETHOD(LockRegion)(ULARGE_INTEGER offset, ULARGE_INTEGER cb, | |
189 DWORD type) { | |
190 DCHECK(false) << __FUNCTION__; | |
191 return E_NOTIMPL; | |
192 } | |
193 | |
194 STDMETHOD(UnlockRegion)(ULARGE_INTEGER offset, ULARGE_INTEGER cb, | |
195 DWORD type) { | |
196 DCHECK(false) << __FUNCTION__; | |
197 return E_NOTIMPL; | |
198 } | |
199 | |
200 STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag) { | |
201 return E_NOTIMPL; | |
202 } | |
203 | |
204 STDMETHOD(Clone)(IStream** stream) { | |
205 DCHECK(false) << __FUNCTION__; | |
206 return E_NOTIMPL; | |
207 } | |
208 | |
209 protected: | |
210 scoped_refptr<UrlmonUrlRequest> request_; | |
211 DISALLOW_COPY_AND_ASSIGN(SendStream); | |
212 }; | |
213 | |
214 // Manage data caching. Note: this class supports cache | |
215 // size less than 2GB | |
216 class Cache { | |
217 public: | |
218 // Adds data to the end of the cache. | |
219 bool Append(IStream* source, size_t* bytes_copied); | |
220 | |
221 // Reads from the cache. | |
222 bool Read(IStream* dest, size_t size, size_t* bytes_copied); | |
223 | |
224 // Returns the size of the cache. | |
225 size_t Size() const; | |
226 | |
227 // Returns true if the cache has valid data. | |
228 bool is_valid() const { | |
229 return Size() != 0; | |
230 } | |
231 | |
232 protected: | |
233 std::vector<byte> cache_; | |
234 char read_buffer_[kCopyChunkSize]; | |
235 }; | |
236 | |
237 HRESULT StartAsyncDownload(); | |
238 // Sends over the response end notification to chrome, releases the bindings | |
239 // and releases the initial reference on the UrlmonUrlRequest object. | |
240 // After this function is called we should not attempt to access any members | |
241 // as the object could become invalid at any point. | |
242 void EndRequest(); | |
243 // Executes in the context of the UI thread and releases the outstanding | |
244 // reference to us. It also deletes the request mapping for this instance. | |
245 void EndRequestInternal(); | |
246 int GetHttpResponseStatus() const; | |
247 std::string GetHttpHeaders() const; | |
248 | |
249 static net::Error HresultToNetError(HRESULT hr); | |
250 | 33 |
251 private: | 34 private: |
252 std::wstring redirect_url_; | 35 struct MonikerForUrl { |
253 int redirect_status_; | 36 ScopedComPtr<IMoniker> moniker; |
254 ScopedComPtr<IBinding> binding_; | 37 ScopedComPtr<IBindCtx> bind_ctx; |
255 ScopedComPtr<IMoniker> moniker_; | 38 std::wstring url; |
256 ScopedComPtr<IBindCtx> bind_context_; | 39 }; |
257 Cache cached_data_; | |
258 size_t pending_read_size_; | |
259 URLRequestStatus status_; | |
260 | 40 |
261 PlatformThreadId thread_; | 41 friend class MessageLoop; |
262 static int instance_count_; | 42 friend struct RunnableMethodTraits<UrlmonUrlRequestManager>; |
263 HWND parent_window_; | 43 static bool ImplementsThreadSafeReferenceCounting() { return true; } |
264 // Set to true if a redirect notification was aborted. | 44 void AddRef() {} |
265 bool ignore_redirect_stop_binding_error_; | 45 void Release() {} |
266 | 46 |
267 DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest); | 47 // PluginUrlRequestManager implementation. |
| 48 virtual bool IsThreadSafe(); |
| 49 virtual void StartRequest(int request_id, |
| 50 const IPC::AutomationURLRequest& request_info); |
| 51 virtual void ReadRequest(int request_id, int bytes_to_read); |
| 52 virtual void EndRequest(int request_id); |
| 53 virtual void StopAll(); |
| 54 |
| 55 // PluginUrlRequestDelegate implementation |
| 56 virtual void OnResponseStarted(int request_id, const char* mime_type, |
| 57 const char* headers, int size, base::Time last_modified, |
| 58 const std::string& peristent_cookies, const std::string& redirect_url, |
| 59 int redirect_status); |
| 60 virtual void OnReadComplete(int request_id, const void* buffer, int len); |
| 61 virtual void OnResponseEnd(int request_id, const URLRequestStatus& status); |
| 62 |
| 63 // Methods executed in worker thread. |
| 64 void StartRequestWorker(int request_id, |
| 65 const IPC::AutomationURLRequest& request_info, |
| 66 MonikerForUrl* moniker_for_url); |
| 67 void ReadRequestWorker(int request_id, int bytes_to_read); |
| 68 void EndRequestWorker(int request_id); |
| 69 void StopAllWorker(); |
| 70 void StealMonikerFromRequestWorker(int request_id, IMoniker** moniker, |
| 71 base::WaitableEvent* done); |
| 72 |
| 73 // Map for (request_id <-> UrlmonUrlRequest) |
| 74 typedef std::map<int, scoped_refptr<UrlmonUrlRequest> > RequestMap; |
| 75 RequestMap request_map_; |
| 76 scoped_refptr<UrlmonUrlRequest> LookupRequest(int request_id); |
| 77 |
| 78 scoped_ptr<MonikerForUrl> moniker_for_url_; |
| 79 STAThread worker_thread_; |
| 80 base::WaitableEvent map_empty_; |
| 81 bool stopping_; |
268 }; | 82 }; |
269 | 83 |
270 #endif // CHROME_FRAME_URLMON_URL_REQUEST_H_ | 84 #endif // CHROME_FRAME_URLMON_URL_REQUEST_H_ |
271 | 85 |
OLD | NEW |