| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // 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 | 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_BIND_STATUS_CALLBACK_H_ | 5 #ifndef CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ |
| 6 #define CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ | 6 #define CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ |
| 7 | 7 |
| 8 #include <atlbase.h> | 8 #include <atlbase.h> |
| 9 #include <atlcom.h> | 9 #include <atlcom.h> |
| 10 | 10 |
| 11 #include "chrome_frame/urlmon_moniker.h" | 11 #include "chrome_frame/bind_status_callback_impl.h" |
| 12 #include "chrome_frame/stream_impl.h" |
| 12 | 13 |
| 13 // Our implementation of IBindStatusCallback that allows us to sit on the | 14 |
| 14 // sidelines and cache all the data that passes by (using the RequestData | 15 // A fake stream class to serve cached data to arbitrary |
| 15 // class). That cache can then be used by other monikers for the same URL | 16 // IBindStatusCallback |
| 16 // that immediately follow. | 17 class CacheStream : public CComObjectRoot, public StreamImpl { |
| 17 class CFUrlmonBindStatusCallback | |
| 18 : public CComObjectRootEx<CComMultiThreadModel>, | |
| 19 public IBindStatusCallbackEx, | |
| 20 public IHttpNegotiate3, | |
| 21 public IServiceProvider { | |
| 22 public: | 18 public: |
| 23 CFUrlmonBindStatusCallback(); | 19 BEGIN_COM_MAP(CacheStream) |
| 24 ~CFUrlmonBindStatusCallback(); | 20 COM_INTERFACE_ENTRY(IStream) |
| 21 COM_INTERFACE_ENTRY(ISequentialStream) |
| 22 END_COM_MAP() |
| 25 | 23 |
| 26 // used for logging. | 24 CacheStream() : cache_(NULL), size_(0), position_(0) { |
| 27 std::string me(); | 25 } |
| 26 void Initialize(const char* cache, size_t size); |
| 27 static HRESULT BSCBFeedData(IBindStatusCallback* bscb, const char* data, |
| 28 size_t size, CLIPFORMAT clip_format, |
| 29 size_t flags); |
| 28 | 30 |
| 29 BEGIN_COM_MAP(CFUrlmonBindStatusCallback) | 31 // IStream overrides |
| 32 STDMETHOD(Read)(void* pv, ULONG cb, ULONG* read); |
| 33 |
| 34 protected: |
| 35 const char* cache_; |
| 36 size_t size_; |
| 37 size_t position_; |
| 38 |
| 39 private: |
| 40 DISALLOW_COPY_AND_ASSIGN(CacheStream); |
| 41 }; |
| 42 |
| 43 // Utility class for data sniffing |
| 44 class SniffData { |
| 45 public: |
| 46 SniffData() : renderer_type_(OTHER), size_(0) {} |
| 47 |
| 48 enum RendererType { |
| 49 UNDETERMINED, |
| 50 CHROME, |
| 51 OTHER |
| 52 }; |
| 53 |
| 54 bool InitializeCache(const std::wstring& url); |
| 55 HRESULT ReadIntoCache(IStream* stream, bool force_determination); |
| 56 HRESULT DrainCache(IBindStatusCallback* bscb, DWORD bscf, |
| 57 CLIPFORMAT clip_format); |
| 58 void DetermineRendererType(); |
| 59 |
| 60 bool is_undetermined() const { |
| 61 return (UNDETERMINED == renderer_type_); |
| 62 } |
| 63 bool is_chrome() const { |
| 64 return (CHROME == renderer_type_); |
| 65 } |
| 66 |
| 67 RendererType renderer_type() const { |
| 68 return renderer_type_; |
| 69 } |
| 70 |
| 71 size_t size() const { |
| 72 return size_; |
| 73 } |
| 74 |
| 75 bool is_cache_valid() { |
| 76 return (size_ != 0); |
| 77 } |
| 78 |
| 79 ScopedComPtr<IStream> cache_; |
| 80 std::wstring url_; |
| 81 RendererType renderer_type_; |
| 82 size_t size_; |
| 83 |
| 84 static const size_t kMaxSniffSize = 2 * 1024; |
| 85 |
| 86 private: |
| 87 DISALLOW_COPY_AND_ASSIGN(SniffData); |
| 88 }; |
| 89 |
| 90 // A wrapper for bind status callback in IMoniker::BindToStorage |
| 91 class BSCBStorageBind : public BSCBImpl { |
| 92 public: |
| 93 typedef BSCBImpl CallbackImpl; |
| 94 BSCBStorageBind() : clip_format_(CF_NULL) {} |
| 95 |
| 96 BEGIN_COM_MAP(BSCBStorageBind) |
| 30 COM_INTERFACE_ENTRY(IBindStatusCallback) | 97 COM_INTERFACE_ENTRY(IBindStatusCallback) |
| 31 COM_INTERFACE_ENTRY(IHttpNegotiate) | 98 COM_INTERFACE_ENTRY_CHAIN(CallbackImpl) |
| 32 COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(IBindStatusCallbackEx) | |
| 33 COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(IHttpNegotiate2) | |
| 34 COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(IHttpNegotiate3) | |
| 35 COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(IServiceProvider) | |
| 36 COM_INTERFACE_ENTRY_FUNC_BLIND(0, DelegateQI) | |
| 37 END_COM_MAP() | 99 END_COM_MAP() |
| 38 | 100 |
| 39 static STDMETHODIMP DelegateQI(void* obj, REFIID iid, void** ret, | 101 HRESULT Initialize(IMoniker* moniker, IBindCtx* bind_ctx); |
| 40 DWORD cookie); | 102 HRESULT MayPlayBack(DWORD flags); |
| 41 | |
| 42 HRESULT Initialize(IBindCtx* bind_ctx, RequestHeaders* headers); | |
| 43 | |
| 44 // For the COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS macro. | |
| 45 IBindStatusCallback* delegate() const { | |
| 46 return delegate_; | |
| 47 } | |
| 48 | |
| 49 RequestData* request_data() { | |
| 50 return data_; | |
| 51 } | |
| 52 | |
| 53 // IServiceProvider | |
| 54 STDMETHOD(QueryService)(REFGUID service, REFIID iid, void** object); | |
| 55 | 103 |
| 56 // IBindStatusCallback | 104 // IBindStatusCallback |
| 57 STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding); | |
| 58 STDMETHOD(GetPriority)(LONG* priority); | |
| 59 STDMETHOD(OnLowResource)(DWORD reserved); | |
| 60 STDMETHOD(OnProgress)(ULONG progress, ULONG progress_max, ULONG status_code, | 105 STDMETHOD(OnProgress)(ULONG progress, ULONG progress_max, ULONG status_code, |
| 61 LPCWSTR status_text); | 106 LPCWSTR status_text); |
| 107 STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* format_etc, |
| 108 STGMEDIUM* stgmed); |
| 62 STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR error); | 109 STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR error); |
| 63 STDMETHOD(GetBindInfo)(DWORD* bindf, BINDINFO* bind_info); | |
| 64 STDMETHOD(OnDataAvailable)(DWORD bscf, DWORD size, FORMATETC* format_etc, | |
| 65 STGMEDIUM* stgmed); | |
| 66 STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* unk); | |
| 67 | |
| 68 // IBindStatusCallbackEx | |
| 69 STDMETHOD(GetBindInfoEx)(DWORD* bindf, BINDINFO* bind_info, DWORD* bindf2, | |
| 70 DWORD* reserved); | |
| 71 | |
| 72 // IHttpNegotiate | |
| 73 STDMETHOD(BeginningTransaction)(LPCWSTR url, LPCWSTR headers, DWORD reserved, | |
| 74 LPWSTR* additional_headers); | |
| 75 STDMETHOD(OnResponse)(DWORD response_code, LPCWSTR response_headers, | |
| 76 LPCWSTR request_headers, LPWSTR* additional_headers); | |
| 77 | |
| 78 // IHttpNegotiate2 | |
| 79 STDMETHOD(GetRootSecurityId)(BYTE* security_id, DWORD* security_id_size, | |
| 80 DWORD_PTR reserved); | |
| 81 | |
| 82 // IHttpNegotiate3 | |
| 83 STDMETHOD(GetSerializedClientCertContext)(BYTE** cert, DWORD* cert_size); | |
| 84 | 110 |
| 85 protected: | 111 protected: |
| 86 ScopedComPtr<IBindStatusCallback> delegate_; | 112 SniffData data_sniffer_; |
| 87 ScopedComPtr<IBindCtx> bind_ctx_; | 113 |
| 88 ScopedComPtr<SimpleBindingImpl, &GUID_NULL> binding_delegate_; | 114 // A structure to cache the progress notifications |
| 89 bool only_buffer_; | 115 struct Progress { |
| 90 scoped_refptr<RequestData> data_; | 116 ULONG progress_; |
| 91 std::wstring redirected_url_; | 117 ULONG progress_max_; |
| 118 ULONG status_code_; |
| 119 std::wstring status_text_; |
| 120 }; |
| 121 |
| 122 std::vector<Progress> saved_progress_; |
| 123 CLIPFORMAT clip_format_; |
| 92 | 124 |
| 93 private: | 125 private: |
| 94 DISALLOW_COPY_AND_ASSIGN(CFUrlmonBindStatusCallback); | 126 DISALLOW_COPY_AND_ASSIGN(BSCBStorageBind); |
| 95 }; | 127 }; |
| 96 | 128 |
| 97 #endif // CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ | 129 #endif // CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ |
| 98 | |
| OLD | NEW |