| OLD | NEW |
| (Empty) |
| 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. | |
| 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 | |
| 11 #include <string> | |
| 12 | |
| 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" | |
| 18 | |
| 19 class UrlmonUrlRequest | |
| 20 : public CComObjectRootEx<CComMultiThreadModel>, | |
| 21 public PluginUrlRequest, | |
| 22 public IServiceProviderImpl<UrlmonUrlRequest>, | |
| 23 public IBindStatusCallback, | |
| 24 public IHttpNegotiate, | |
| 25 public IAuthenticate, | |
| 26 public IHttpSecurity { | |
| 27 public: | |
| 28 virtual bool Start(); | |
| 29 virtual void Stop(); | |
| 30 virtual bool Read(int bytes_to_read); | |
| 31 | |
| 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); | |
| 36 | |
| 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); | |
| 43 | |
| 44 // Parent Window for UrlMon error dialogs | |
| 45 void set_parent_window(HWND parent_window) { | |
| 46 parent_window_ = parent_window; | |
| 47 } | |
| 48 | |
| 49 // This function passes information on whether ChromeFrame is running in | |
| 50 // privileged mode. | |
| 51 void set_privileged_mode(bool privileged_mode) { | |
| 52 privileged_mode_ = privileged_mode; | |
| 53 } | |
| 54 | |
| 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; | |
| 58 | |
| 59 protected: | |
| 60 UrlmonUrlRequest(); | |
| 61 ~UrlmonUrlRequest(); | |
| 62 | |
| 63 BEGIN_COM_MAP(UrlmonUrlRequest) | |
| 64 COM_INTERFACE_ENTRY(IHttpNegotiate) | |
| 65 COM_INTERFACE_ENTRY(IServiceProvider) | |
| 66 COM_INTERFACE_ENTRY(IBindStatusCallback) | |
| 67 COM_INTERFACE_ENTRY(IWindowForBindingUI) | |
| 68 COM_INTERFACE_ENTRY(IAuthenticate) | |
| 69 COM_INTERFACE_ENTRY(IHttpSecurity) | |
| 70 END_COM_MAP() | |
| 71 | |
| 72 BEGIN_SERVICE_MAP(UrlmonUrlRequest) | |
| 73 SERVICE_ENTRY(IID_IHttpNegotiate); | |
| 74 END_SERVICE_MAP() | |
| 75 | |
| 76 // IBindStatusCallback implementation | |
| 77 STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding); | |
| 78 STDMETHOD(GetPriority)(LONG* priority); | |
| 79 STDMETHOD(OnLowResource)(DWORD reserved); | |
| 80 STDMETHOD(OnProgress)(ULONG progress, ULONG max_progress, | |
| 81 ULONG status_code, LPCWSTR status_text); | |
| 82 STDMETHOD(OnStopBinding)(HRESULT result, LPCWSTR error); | |
| 83 STDMETHOD(GetBindInfo)(DWORD* bind_flags, BINDINFO* bind_info); | |
| 84 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc, | |
| 85 STGMEDIUM* storage); | |
| 86 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object); | |
| 87 | |
| 88 // IHttpNegotiate implementation | |
| 89 STDMETHOD(BeginningTransaction)(const wchar_t* url, | |
| 90 const wchar_t* current_headers, DWORD reserved, | |
| 91 wchar_t** additional_headers); | |
| 92 STDMETHOD(OnResponse)(DWORD dwResponseCode, const wchar_t* response_headers, | |
| 93 const wchar_t* request_headers, wchar_t** additional_headers); | |
| 94 | |
| 95 // IWindowForBindingUI implementation. This interface is used typically to | |
| 96 // query the window handle which URLMON uses as the parent of error dialogs. | |
| 97 STDMETHOD(GetWindow)(REFGUID guid_reason, HWND* parent_window); | |
| 98 | |
| 99 // IAuthenticate implementation. Used to return the parent window for the | |
| 100 // dialog displayed by IE for authenticating with a proxy. | |
| 101 STDMETHOD(Authenticate)(HWND* parent_window, LPWSTR* user_name, | |
| 102 LPWSTR* password); | |
| 103 | |
| 104 // IHttpSecurity implementation. | |
| 105 STDMETHOD(OnSecurityProblem)(DWORD problem); | |
| 106 | |
| 107 void set_pending(bool pending) { | |
| 108 pending_ = pending; | |
| 109 } | |
| 110 | |
| 111 bool pending() const { | |
| 112 return pending_; | |
| 113 } | |
| 114 | |
| 115 bool terminate_requested() const { | |
| 116 return !terminate_bind_callback_.is_null(); | |
| 117 } | |
| 118 | |
| 119 std::string response_headers() { | |
| 120 return response_headers_; | |
| 121 } | |
| 122 | |
| 123 protected: | |
| 124 void ReleaseBindings(); | |
| 125 | |
| 126 HRESULT StartAsyncDownload(); | |
| 127 void NotifyDelegateAndDie(); | |
| 128 void TerminateTransaction(); | |
| 129 static net::Error HresultToNetError(HRESULT hr); | |
| 130 | |
| 131 private: | |
| 132 size_t SendDataToDelegate(size_t bytes); | |
| 133 | |
| 134 // This class simplifies tracking the progress of operation. We have 3 main | |
| 135 // states: DONE, WORKING and ABORTING. | |
| 136 // When in [DONE] or [ABORTING] state, there is additional information | |
| 137 // about the result of operation. | |
| 138 // Start(), SetRedirected(), Cancel() and Done() methods trigger the state | |
| 139 // change. See comments bellow. | |
| 140 class Status { | |
| 141 public: | |
| 142 enum State {DONE, ABORTING, WORKING}; | |
| 143 struct Redirection { | |
| 144 Redirection() : http_code(0) { } | |
| 145 int http_code; | |
| 146 std::string utf8_url; | |
| 147 }; | |
| 148 | |
| 149 Status() : state_(Status::DONE) { | |
| 150 } | |
| 151 | |
| 152 State get_state() const { | |
| 153 return state_; | |
| 154 } | |
| 155 | |
| 156 // Switch from [DONE] to [WORKING]. | |
| 157 void Start() { | |
| 158 DCHECK_EQ(state_, DONE); | |
| 159 state_ = WORKING; | |
| 160 } | |
| 161 | |
| 162 // Save redirection information and switch to [ABORTING] state. | |
| 163 // Assumes binding_->Abort() will be called! | |
| 164 void SetRedirected(int http_code, const std::string& utf8_url) { | |
| 165 DCHECK_EQ(state_, WORKING); | |
| 166 DCHECK_EQ(result_.status(), net::URLRequestStatus::SUCCESS); | |
| 167 redirect_.utf8_url = utf8_url; | |
| 168 | |
| 169 // At times we receive invalid redirect codes like 0, 200, etc. We | |
| 170 // default to 302 in this case. | |
| 171 redirect_.http_code = http_code; | |
| 172 if (!net::HttpResponseHeaders::IsRedirectResponseCode(http_code)) | |
| 173 redirect_.http_code = 302; | |
| 174 | |
| 175 state_ = ABORTING; | |
| 176 } | |
| 177 | |
| 178 // Set the result as net::URLRequestStatus::CANCELED. | |
| 179 // Switch to [ABORTING] state (if not already in that state). | |
| 180 void Cancel() { | |
| 181 if (state_ == DONE) | |
| 182 return; | |
| 183 | |
| 184 if (state_ == WORKING) { | |
| 185 state_ = ABORTING; | |
| 186 } else { | |
| 187 // state_ == ABORTING | |
| 188 redirect_.http_code = 0; | |
| 189 redirect_.utf8_url.clear(); | |
| 190 } | |
| 191 | |
| 192 set_result(net::URLRequestStatus::CANCELED, 0); | |
| 193 } | |
| 194 | |
| 195 void Done() { | |
| 196 state_ = DONE; | |
| 197 } | |
| 198 | |
| 199 bool was_redirected() const { | |
| 200 return redirect_.http_code != 0; | |
| 201 } | |
| 202 | |
| 203 const Redirection& get_redirection() const { | |
| 204 return redirect_; | |
| 205 } | |
| 206 | |
| 207 const net::URLRequestStatus& get_result() const { | |
| 208 return result_; | |
| 209 } | |
| 210 | |
| 211 void set_result(net::URLRequestStatus::Status status, int error) { | |
| 212 result_.set_status(status); | |
| 213 result_.set_error(error); | |
| 214 } | |
| 215 | |
| 216 void set_result(HRESULT hr) { | |
| 217 result_.set_status(FAILED(hr)? net::URLRequestStatus::FAILED: | |
| 218 net::URLRequestStatus::SUCCESS); | |
| 219 result_.set_error(HresultToNetError(hr)); | |
| 220 } | |
| 221 | |
| 222 private: | |
| 223 Redirection redirect_; | |
| 224 State state_; | |
| 225 net::URLRequestStatus result_; | |
| 226 }; | |
| 227 | |
| 228 Status status_; | |
| 229 base::win::ScopedComPtr<IBinding> binding_; | |
| 230 base::win::ScopedComPtr<IMoniker> moniker_; | |
| 231 base::win::ScopedComPtr<IBindCtx> bind_context_; | |
| 232 base::win::ScopedComPtr<IStream> cache_; | |
| 233 base::win::ScopedComPtr<IStream> pending_data_; | |
| 234 | |
| 235 size_t pending_read_size_; | |
| 236 base::PlatformThreadId thread_; | |
| 237 HWND parent_window_; | |
| 238 bool headers_received_; | |
| 239 int calling_delegate_; // re-entrancy protection. | |
| 240 // Set to true if the ChromeFrame instance is running in privileged mode. | |
| 241 bool privileged_mode_; | |
| 242 bool pending_; | |
| 243 TerminateBindCallback terminate_bind_callback_; | |
| 244 std::string response_headers_; | |
| 245 // Defaults to true and indicates whether we want to keep the original | |
| 246 // transaction alive when we receive the last data notification from | |
| 247 // urlmon. | |
| 248 bool is_expecting_download_; | |
| 249 // Set to true if the Urlmon transaction object needs to be cleaned up | |
| 250 // when this object is destroyed. Happens if we return | |
| 251 // INET_E_TERMINATE_BIND from OnDataAvailable in the last data notification. | |
| 252 bool cleanup_transaction_; | |
| 253 // Copy of the request headers. | |
| 254 std::string request_headers_; | |
| 255 | |
| 256 DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest); | |
| 257 }; | |
| 258 | |
| 259 #endif // CHROME_FRAME_URLMON_URL_REQUEST_PRIVATE_H_ | |
| OLD | NEW |