- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / com_type_info_holder.h
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_COM_TYPE_INFO_HOLDER_H_
6 #define CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_
7
8 #include <map>
9 #include <ocidl.h>  // IProvideClassInfo2
10
11 #include "base/synchronization/lock.h"
12 #include "base/win/scoped_comptr.h"
13
14 #define NO_VTABLE __declspec(novtable)
15
16 namespace com_util {
17
18 // A map from a name hash (32 bit value) to a DISPID.
19 // Used as a caching layer before looking the name up in a type lib.
20 class NameToDispIdCache {
21  public:
22   typedef uint32 HashType;
23
24   bool Lookup(HashType hash, DISPID* dispid) const;
25   void Add(HashType hash, DISPID dispid);
26
27   // Hashes the name by calling LHashValOfName.
28   // The returned hash value is independent of the case of the characters
29   // in |name|.
30   static HashType Hash(const wchar_t* name);
31
32  protected:
33   typedef std::map<HashType, DISPID> DispidMap;
34   DispidMap map_;
35   mutable base::Lock lock_;
36 };
37
38 // Wraps an instance of ITypeInfo and builds+maintains a cache of names
39 // to dispids.  Also offers an Invoke method that simply forwards the call
40 // to ITypeInfo::Invoke.
41 class TypeInfoNameCache {
42  public:
43   // Loads the module's type library and fetches the ITypeInfo object for
44   // the specified interface ID.
45   HRESULT Initialize(const IID& iid);
46
47   // Fetches the id's of the given names.  If there's a cache miss, the results
48   // are fetched from the underlying ITypeInfo and then cached.
49   HRESULT GetIDsOfNames(OLECHAR** names, uint32 count, DISPID* dispids);
50
51   // Calls ITypeInfo::Invoke.
52   HRESULT Invoke(IDispatch* p, DISPID dispid, WORD flags, DISPPARAMS* params,
53                  VARIANT* result, EXCEPINFO* excepinfo, UINT* arg_err);
54
55   inline ITypeInfo* CopyTypeInfo() {
56     ITypeInfo* ti = type_info_.get();
57     if (ti)
58       ti->AddRef();
59     return ti;
60   }
61
62  protected:
63   base::win::ScopedComPtr<ITypeInfo> type_info_;
64   NameToDispIdCache cache_;
65 };
66
67 // The root class for type lib access.
68 // This class has only one instance that should be accessed via the
69 // Singleton method.
70 class TypeInfoCache {
71  public:
72   TypeInfoCache() {
73   }
74
75   ~TypeInfoCache();
76
77   // Looks up a previously cached TypeInfoNameCache instance or creates and
78   // caches a new one.
79   TypeInfoNameCache* Lookup(const IID* iid);
80
81   // Call to get access to the singleton instance of TypeInfoCache.
82   static TypeInfoCache* Singleton();
83
84  protected:
85   typedef std::map<const IID*, TypeInfoNameCache*> CacheMap;
86   base::Lock lock_;
87   CacheMap cache_;
88 };
89
90 // Holds a pointer to the type info of a given COM interface.
91 // The type info is loaded once on demand and after that cached.
92 // NOTE: This class only supports loading the first typelib from the
93 // current module.
94 template <const IID& iid>
95 class TypeInfoHolder {
96  public:
97   TypeInfoHolder() : type_info_(NULL) {
98   }
99
100   bool EnsureTI() {
101     if (!type_info_)
102       type_info_ = TypeInfoCache::Singleton()->Lookup(&iid);
103     return type_info_ != NULL;
104   }
105
106   HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** info) {
107     if (EnsureTI()) {
108       *info = type_info_->CopyTypeInfo();
109       return S_OK;
110     }
111
112     return E_UNEXPECTED;
113   }
114
115   HRESULT GetIDsOfNames(REFIID riid, OLECHAR** names, UINT count, LCID lcid,
116                         DISPID* dispids) {
117     if (!EnsureTI())
118       return E_UNEXPECTED;
119     return type_info_->GetIDsOfNames(names, count, dispids);
120   }
121
122   HRESULT Invoke(IDispatch* p, DISPID dispid, REFIID riid, LCID lcid,
123                  WORD flags, DISPPARAMS* params, VARIANT* result,
124                  EXCEPINFO* excepinfo, UINT* arg_err) {
125     if (!EnsureTI())
126       return E_UNEXPECTED;
127
128     return type_info_->Invoke(p, dispid, flags, params, result, excepinfo,
129                               arg_err);
130   }
131
132  protected:
133   TypeInfoNameCache* type_info_;
134 };
135
136 // Implements IDispatch part of T (where T is an IDispatch derived interface).
137 // The class assumes that the type info of T is available in a typelib of the
138 // current module.
139 template <class T, const IID& iid = __uuidof(T)>
140 class NO_VTABLE IDispatchImpl : public T {
141  public:
142   STDMETHOD(GetTypeInfoCount)(UINT* count) {
143     if (count == NULL)
144       return E_POINTER;
145     *count = 1;
146     return S_OK;
147   }
148
149   STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) {
150     return type_info_.GetTypeInfo(itinfo, lcid, pptinfo);
151   }
152
153   STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* names, UINT count,
154                            LCID lcid, DISPID* dispids) {
155     return type_info_.GetIDsOfNames(riid, names, count, lcid, dispids);
156   }
157   STDMETHOD(Invoke)(DISPID dispid, REFIID riid, LCID lcid, WORD flags,
158                     DISPPARAMS* params, VARIANT* result, EXCEPINFO* excepinfo,
159                     UINT* arg_err) {
160     return type_info_.Invoke(static_cast<IDispatch*>(this), dispid, riid, lcid,
161                              flags, params, result, excepinfo, arg_err);
162   }
163
164  protected:
165   TypeInfoHolder<iid> type_info_;
166 };
167
168 // Simple implementation of IProvideClassInfo[2].
169 template <const CLSID& class_id, const IID& source_iid>
170 class NO_VTABLE IProvideClassInfo2Impl : public IProvideClassInfo2 {
171  public:
172   STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo) {
173     return type_info_.GetTypeInfo(0, LANG_NEUTRAL, pptinfo);
174   }
175
176   STDMETHOD(GetGUID)(DWORD guid_kind, GUID* guid) {
177     if (guid == NULL || guid_kind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
178       return E_INVALIDARG;
179
180     *guid = source_iid;
181
182     return S_OK;
183   }
184
185  protected:
186   TypeInfoHolder<class_id> type_info_;
187 };
188
189 }  // namespace com_util
190
191 #endif  // CHROME_FRAME_COM_TYPE_INFO_HOLDER_H_