• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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_BIND_STATUS_CALLBACK_H_
6 #define CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_
7 
8 #include <atlbase.h>
9 #include <atlcom.h>
10 
11 #include "base/memory/scoped_ptr.h"
12 #include "chrome_frame/bind_status_callback_impl.h"
13 #include "chrome_frame/stream_impl.h"
14 
15 
16 // A fake stream class to serve cached data to arbitrary
17 // IBindStatusCallback
18 class CacheStream : public CComObjectRoot, public StreamImpl {
19  public:
BEGIN_COM_MAP(CacheStream)20   BEGIN_COM_MAP(CacheStream)
21     COM_INTERFACE_ENTRY(IStream)
22     COM_INTERFACE_ENTRY(ISequentialStream)
23   END_COM_MAP()
24 
25   CacheStream() : size_(0), position_(0), eof_(false) {
26   }
27   HRESULT Initialize(const char* cache, size_t size, bool eof);
28   static HRESULT BSCBFeedData(IBindStatusCallback* bscb, const char* data,
29                               size_t size, CLIPFORMAT clip_format,
30                               size_t flags, bool eof);
31 
32   // IStream overrides
33   STDMETHOD(Read)(void* pv, ULONG cb, ULONG* read);
34 
35  protected:
36   scoped_ptr<char[]> cache_;
37   size_t size_;
38   size_t position_;
39   bool eof_;
40 
41  private:
42   DISALLOW_COPY_AND_ASSIGN(CacheStream);
43 };
44 
45 // Utility class for data sniffing
46 class SniffData {
47  public:
SniffData()48   SniffData() : renderer_type_(OTHER), size_(0), eof_(false) {}
49 
50   enum RendererType {
51     UNDETERMINED,
52     CHROME,
53     OTHER
54   };
55 
56   HRESULT InitializeCache(const std::wstring& url);
57   HRESULT ReadIntoCache(IStream* stream, bool force_determination);
58   HRESULT DrainCache(IBindStatusCallback* bscb, DWORD bscf,
59                      CLIPFORMAT clip_format);
60   void DetermineRendererType(bool last_chance);
61 
is_undetermined()62   bool is_undetermined() const {
63     return (UNDETERMINED == renderer_type_);
64   }
is_chrome()65   bool is_chrome() const {
66     return (CHROME == renderer_type_);
67   }
68 
renderer_type()69   RendererType renderer_type() const {
70     return renderer_type_;
71   }
72 
size()73   size_t size() const {
74     return size_;
75   }
76 
is_cache_valid()77   bool is_cache_valid() {
78     return (size_ != 0);
79   }
80 
81   base::win::ScopedComPtr<IStream> cache_;
82   std::wstring url_;
83   RendererType renderer_type_;
84   size_t size_;
85 
86   static const size_t kMaxSniffSize = 2 * 1024;
87   bool eof_;
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;
97   BSCBStorageBind();
98   ~BSCBStorageBind();
99 
100 BEGIN_COM_MAP(BSCBStorageBind)
101   COM_INTERFACE_ENTRY(IBindStatusCallback)
102   COM_INTERFACE_ENTRY_CHAIN(CallbackImpl)
103 END_COM_MAP()
104 
105   HRESULT Initialize(IMoniker* moniker, IBindCtx* bind_ctx);
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:
116   // is it a good time to start caching progress notifications
117   bool ShouldCacheProgress(ULONG status_code) const;
118 
119  protected:
120   SniffData data_sniffer_;
121 
122   // A structure to cache the progress notifications.
123   class Progress {
124    public:
Progress(ULONG progress,ULONG progress_max,ULONG status_code,const wchar_t * status_text)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       if (status_text) {
131         int len = lstrlenW(status_text) + 1;
132         status_text_.reset(new wchar_t[len]);
133         if (status_text_.get()) {
134           lstrcpynW(status_text_.get(), status_text, len);
135         } else {
136           NOTREACHED();
137         }
138       }
139     }
140 
~Progress()141     ~Progress() {
142     }
143 
progress()144     ULONG progress() const {
145       return progress_;
146     }
147 
progress_max()148     ULONG progress_max() const {
149       return progress_max_;
150     }
151 
status_code()152     ULONG status_code() const {
153       return status_code_;
154     }
155 
status_text()156     const wchar_t* status_text() const {
157       return status_text_.get();
158     }
159 
160    protected:
161     ULONG progress_;
162     ULONG progress_max_;
163     ULONG status_code_;
164     // We don't use std::wstring here since we want to be able to play
165     // progress notifications back exactly as we got them.  NULL and L"" are
166     // not equal.
167     scoped_ptr<wchar_t[]> status_text_;
168   };
169 
170   typedef std::vector<Progress*> ProgressVector;
171   ProgressVector saved_progress_;
172   CLIPFORMAT clip_format_;
173 
174  private:
175   DISALLOW_COPY_AND_ASSIGN(BSCBStorageBind);
176 };
177 
178 #endif  // CHROME_FRAME_URLMON_BIND_STATUS_CALLBACK_H_
179