[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 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_BIND_STATUS_CALLBACK_H_ |
| 6 | #define CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ |
| 7 | |
| 8 | #include <atlbase.h> |
| 9 | #include <atlcom.h> |
| 10 | |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 11 | #include "base/memory/scoped_ptr.h" |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 12 | #include "chrome_frame/bind_status_callback_impl.h" |
| 13 | #include "chrome_frame/stream_impl.h" |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 14 | |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 15 | |
| 16 | // A fake stream class to serve cached data to arbitrary |
| 17 | // IBindStatusCallback |
| 18 | class CacheStream : public CComObjectRoot, public StreamImpl { |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 19 | public: |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 20 | BEGIN_COM_MAP(CacheStream) |
| 21 | COM_INTERFACE_ENTRY(IStream) |
| 22 | COM_INTERFACE_ENTRY(ISequentialStream) |
| 23 | END_COM_MAP() |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 24 | |
[email protected] | de5bc35 | 2010-04-16 01:38:48 | [diff] [blame] | 25 | CacheStream() : cache_(NULL), size_(0), position_(0), eof_(false) { |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 26 | } |
[email protected] | f1917ed | 2010-05-13 20:21:08 | [diff] [blame] | 27 | HRESULT Initialize(const char* cache, size_t size, bool eof); |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 28 | static HRESULT BSCBFeedData(IBindStatusCallback* bscb, const char* data, |
| 29 | size_t size, CLIPFORMAT clip_format, |
[email protected] | de5bc35 | 2010-04-16 01:38:48 | [diff] [blame] | 30 | size_t flags, bool eof); |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 31 | |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 32 | // IStream overrides |
| 33 | STDMETHOD(Read)(void* pv, ULONG cb, ULONG* read); |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 34 | |
| 35 | protected: |
[email protected] | f1917ed | 2010-05-13 20:21:08 | [diff] [blame] | 36 | scoped_ptr<char> cache_; |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 37 | size_t size_; |
| 38 | size_t position_; |
[email protected] | de5bc35 | 2010-04-16 01:38:48 | [diff] [blame] | 39 | bool eof_; |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 40 | |
| 41 | private: |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 42 | DISALLOW_COPY_AND_ASSIGN(CacheStream); |
| 43 | }; |
| 44 | |
| 45 | // Utility class for data sniffing |
| 46 | class SniffData { |
| 47 | public: |
[email protected] | de5bc35 | 2010-04-16 01:38:48 | [diff] [blame] | 48 | SniffData() : renderer_type_(OTHER), size_(0), eof_(false) {} |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 49 | |
| 50 | enum RendererType { |
| 51 | UNDETERMINED, |
| 52 | CHROME, |
| 53 | OTHER |
| 54 | }; |
| 55 | |
[email protected] | 040b800f | 2010-05-05 23:46:30 | [diff] [blame] | 56 | HRESULT InitializeCache(const std::wstring& url); |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 57 | HRESULT ReadIntoCache(IStream* stream, bool force_determination); |
| 58 | HRESULT DrainCache(IBindStatusCallback* bscb, DWORD bscf, |
| 59 | CLIPFORMAT clip_format); |
[email protected] | 37a3a4b | 2010-04-14 22:37:40 | [diff] [blame] | 60 | void DetermineRendererType(bool last_chance); |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 61 | |
| 62 | bool is_undetermined() const { |
| 63 | return (UNDETERMINED == renderer_type_); |
| 64 | } |
| 65 | bool is_chrome() const { |
| 66 | return (CHROME == renderer_type_); |
| 67 | } |
| 68 | |
| 69 | RendererType renderer_type() const { |
| 70 | return renderer_type_; |
| 71 | } |
| 72 | |
| 73 | size_t size() const { |
| 74 | return size_; |
| 75 | } |
| 76 | |
| 77 | bool is_cache_valid() { |
| 78 | return (size_ != 0); |
| 79 | } |
| 80 | |
[email protected] | 8ee65ba | 2011-04-12 20:53:23 | [diff] [blame] | 81 | base::win::ScopedComPtr<IStream> cache_; |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 82 | std::wstring url_; |
| 83 | RendererType renderer_type_; |
| 84 | size_t size_; |
| 85 | |
| 86 | static const size_t kMaxSniffSize = 2 * 1024; |
[email protected] | de5bc35 | 2010-04-16 01:38:48 | [diff] [blame] | 87 | bool eof_; |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 88 | |
| 89 | private: |
| 90 | DISALLOW_COPY_AND_ASSIGN(SniffData); |
| 91 | }; |
| 92 | |
| 93 | // A wrapper for bind status callback in IMoniker::BindToStorage |
| 94 | class BSCBStorageBind : public BSCBImpl { |
| 95 | public: |
| 96 | typedef BSCBImpl CallbackImpl; |
[email protected] | 74e9983a | 2010-05-14 02:27:34 | [diff] [blame] | 97 | BSCBStorageBind(); |
| 98 | ~BSCBStorageBind(); |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 99 | |
| 100 | BEGIN_COM_MAP(BSCBStorageBind) |
| 101 | COM_INTERFACE_ENTRY(IBindStatusCallback) |
| 102 | COM_INTERFACE_ENTRY_CHAIN(CallbackImpl) |
| 103 | END_COM_MAP() |
| 104 | |
[email protected] | 70277f6 | 2010-04-15 01:39:26 | [diff] [blame] | 105 | HRESULT Initialize(IMoniker* moniker, IBindCtx* bind_ctx); |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 106 | HRESULT MayPlayBack(DWORD flags); |
| 107 | |
| 108 | // IBindStatusCallback |
| 109 | STDMETHOD(OnProgress)(ULONG progress, ULONG progress_max, ULONG status_code, |
| 110 | LPCWSTR status_text); |
| 111 | STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* format_etc, |
| 112 | STGMEDIUM* stgmed); |
| 113 | STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR error); |
| 114 | |
| 115 | protected: |
[email protected] | b31b9ff | 2010-05-07 18:29:24 | [diff] [blame] | 116 | // is it a good time to start caching progress notifications |
| 117 | bool ShouldCacheProgress(ULONG status_code) const; |
| 118 | |
| 119 | protected: |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 120 | SniffData data_sniffer_; |
| 121 | |
[email protected] | 74e9983a | 2010-05-14 02:27:34 | [diff] [blame] | 122 | // A structure to cache the progress notifications. |
| 123 | class Progress { |
| 124 | public: |
| 125 | Progress(ULONG progress, ULONG progress_max, ULONG status_code, |
| 126 | const wchar_t* status_text) |
| 127 | : progress_(progress), |
| 128 | progress_max_(progress_max), |
| 129 | status_code_(status_code), |
| 130 | status_text_(NULL) { |
| 131 | if (status_text) { |
| 132 | int len = lstrlenW(status_text) + 1; |
| 133 | status_text_.reset(new wchar_t[len]); |
| 134 | if (status_text_.get()) { |
[email protected] | 77d7aee | 2010-05-14 20:31:55 | [diff] [blame] | 135 | lstrcpynW(status_text_.get(), status_text, len); |
[email protected] | 74e9983a | 2010-05-14 02:27:34 | [diff] [blame] | 136 | } else { |
| 137 | NOTREACHED(); |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | ~Progress() { |
| 143 | } |
| 144 | |
| 145 | ULONG progress() const { |
| 146 | return progress_; |
| 147 | } |
| 148 | |
| 149 | ULONG progress_max() const { |
| 150 | return progress_max_; |
| 151 | } |
| 152 | |
| 153 | ULONG status_code() const { |
| 154 | return status_code_; |
| 155 | } |
| 156 | |
| 157 | const wchar_t* status_text() const { |
| 158 | return status_text_.get(); |
| 159 | } |
| 160 | |
| 161 | protected: |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 162 | ULONG progress_; |
| 163 | ULONG progress_max_; |
| 164 | ULONG status_code_; |
[email protected] | 74e9983a | 2010-05-14 02:27:34 | [diff] [blame] | 165 | // We don't use std::wstring here since we want to be able to play |
| 166 | // progress notifications back exactly as we got them. NULL and L"" are |
| 167 | // not equal. |
| 168 | scoped_ptr<wchar_t> status_text_; |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 169 | }; |
| 170 | |
[email protected] | 77d7aee | 2010-05-14 20:31:55 | [diff] [blame] | 171 | typedef std::vector<Progress*> ProgressVector; |
| 172 | ProgressVector saved_progress_; |
[email protected] | 97965e1 | 2010-04-09 00:51:10 | [diff] [blame] | 173 | CLIPFORMAT clip_format_; |
| 174 | |
| 175 | private: |
| 176 | DISALLOW_COPY_AND_ASSIGN(BSCBStorageBind); |
[email protected] | 051236f | 2010-03-12 22:06:14 | [diff] [blame] | 177 | }; |
| 178 | |
| 179 | #endif // CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_ |