Home | History | Annotate | Download | only in chrome_frame
      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:
     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:
     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 
     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 
     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:
    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 
    141     ~Progress() {
    142     }
    143 
    144     ULONG progress() const {
    145       return progress_;
    146     }
    147 
    148     ULONG progress_max() const {
    149       return progress_max_;
    150     }
    151 
    152     ULONG status_code() const {
    153       return status_code_;
    154     }
    155 
    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