FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
ComVariantUtil.h
1 
2 /**********************************************************\
3  Original Author: Georg Fritzsche
4 
5  Created: Nov 7, 2010
6  License: Dual license model; choose one of two:
7  New BSD License
8  http://www.opensource.org/licenses/bsd-license.php
9  - or -
10  GNU Lesser General Public License, version 2.1
11  http://www.gnu.org/licenses/lgpl-2.1.html
12 
13  Copyright 20100 Georg Fritzsche, Firebreath development team
14  \**********************************************************/
15 
16 #pragma once
17 #ifndef FB_H_CComVariantUTIL
18 #define FB_H_CComVariantUTIL
19 
20 #include <map>
21 #include <string>
22 #include <typeinfo>
23 
24 #include <boost/assign/list_of.hpp>
25 #include <boost/type_traits/is_arithmetic.hpp>
26 #include <boost/type_traits/is_integral.hpp>
27 #include <boost/type_traits/is_same.hpp>
28 #include <boost/type_traits/is_floating_point.hpp>
29 #include <boost/integer_traits.hpp>
30 
31 #include "FactoryBase.h"
32 #include "ActiveXBrowserHost.h"
33 #include "DOM/Document.h"
34 #include "DOM/Window.h"
35 #include "AXDOM/Window.h"
36 #include "AXDOM/Document.h"
37 #include "AXDOM/Element.h"
38 #include "AXDOM/Node.h"
39 #include <atlsafe.h>
40 
41 namespace FB { namespace ActiveX
42 {
43  struct type_info_less
44  {
45  bool operator() (const std::type_info* const lhs, const std::type_info* const rhs) const
46  {
47  return lhs->before(*rhs) ? true : false;
48  }
49  };
50 
51  typedef CComVariant (*ComVariantBuilder)(const ActiveXBrowserHostPtr&, const FB::variant&);
52  typedef std::map<std::type_info const*, ComVariantBuilder, type_info_less> ComVariantBuilderMap;
53 
54  namespace {
55  ComVariantBuilderMap comVariantBuilderMap;
56  boost::once_flag init_flag = BOOST_ONCE_INIT;
57  }
58 
59  // GJS ---
60  // I would probably put the ComVariantBuilderMap code into ComVariantUtil.cpp?
61  template<class T>
62  inline ComVariantBuilderMap::value_type makeBuilderEntry()
63  {
64  return ComVariantBuilderMap::value_type(&typeid(T), select_ccomvariant_builder::select<T>());
65  }
66 
67  inline void makeComVariantBuilderMap(ComVariantBuilderMap& tdm)
68  {
69  tdm.insert(makeBuilderEntry<bool>());
70  tdm.insert(makeBuilderEntry<char>());
71  tdm.insert(makeBuilderEntry<unsigned char>());
72  tdm.insert(makeBuilderEntry<short>());
73  tdm.insert(makeBuilderEntry<unsigned short>());
74  tdm.insert(makeBuilderEntry<int>());
75  tdm.insert(makeBuilderEntry<unsigned int>());
76  tdm.insert(makeBuilderEntry<long>());
77  tdm.insert(makeBuilderEntry<unsigned long>());
78 
79 #ifndef BOOST_NO_LONG_LONG
80  tdm.insert(makeBuilderEntry<long long>());
81  tdm.insert(makeBuilderEntry<unsigned long long>());
82 #endif
83 
84  tdm.insert(makeBuilderEntry<float>());
85  tdm.insert(makeBuilderEntry<double>());
86 
87  tdm.insert(makeBuilderEntry<std::string>());
88  tdm.insert(makeBuilderEntry<std::wstring>());
89 
90  tdm.insert(makeBuilderEntry<FB::VariantList>());
91  tdm.insert(makeBuilderEntry<FB::VariantMap>());
92  tdm.insert(makeBuilderEntry<FB::JSAPIPtr>());
93  tdm.insert(makeBuilderEntry<FB::JSAPIWeakPtr>());
94  tdm.insert(makeBuilderEntry<FB::JSObjectPtr>());
95 
96  tdm.insert(makeBuilderEntry<FB::FBVoid>());
97  tdm.insert(makeBuilderEntry<FB::FBNull>());
98  }
99 
100  inline const ComVariantBuilderMap& getComVariantBuilderMap()
101  {
102  // Thread safety is required because IE10+ can run
103  // plug-ins in multiple threads within a single process.
104  boost::call_once(init_flag, boost::bind(&makeComVariantBuilderMap, boost::ref(comVariantBuilderMap)));
105 
106  return comVariantBuilderMap;
107  }
108  // GJS ---
109 
110  template<class T>
111  inline CComVariant makeArithmeticComVariant(const ActiveXBrowserHostPtr& host, const FB::variant& var)
112  {
113  return var.convert_cast<T>();
114  }
115 
116  template<> inline
117  CComVariant makeArithmeticComVariant<char>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
118  {
119  return var.cast<char>();
120  }
121 
122  template<> inline
123  CComVariant makeArithmeticComVariant<unsigned char>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
124  {
125  return var.cast<unsigned char>();
126  }
127 
128  template<class T>
129  CComVariant makeComVariant(const ActiveXBrowserHostPtr& host, const FB::variant& var)
130  {
131  CComVariant out;
132  out.ChangeType(VT_NULL);
133  return out;
134  }
135 
136  template<> inline
137  CComVariant makeComVariant<FB::FBNull>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
138  {
139  CComVariant out;
140  out.ChangeType(VT_NULL);
141  return out;
142  }
143 
144  template<> inline
145  CComVariant makeComVariant<FB::FBVoid>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
146  {
147  CComVariant out; // Just leave it at VT_EMPTY
148  return out;
149  }
150 
151  template<> inline
152  CComVariant makeComVariant<std::string>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
153  {
154  std::wstring wstr = var.convert_cast<std::wstring>();
155  CComBSTR bStr(wstr.c_str());
156  return bStr;
157  }
158 
159  template<> inline
160  CComVariant makeComVariant<std::wstring>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
161  {
162  std::wstring wstr = var.convert_cast<std::wstring>();
163  CComBSTR bStr(wstr.c_str());
164  return bStr;
165  }
166 
167  template<> inline
168  CComVariant makeComVariant<FB::VariantList>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
169  {
170  // GJS ---
171  CComVariant outVar;
172  FB::VariantList inArr = var.cast<FB::VariantList>();
173  if (host->hasHTMLWindow())
174  {
175  FB::JSObjectPtr outArr = host->getDOMWindow()->createArray();
176  for (FB::VariantList::iterator it = inArr.begin(); it != inArr.end(); ++it) {
177  FB::VariantList vl = boost::assign::list_of(*it);
178  outArr->Invoke("push", vl);
179  }
180  IDispatchAPIPtr api = ptr_cast<IDispatchAPI>(outArr);
181  if (api) {
182  return api->getIDispatch();
183  }
184  }
185  else
186  {
187  CComSafeArray<VARIANT> sa;
188  sa.Create();
189  const ComVariantBuilderMap& builderMap = getComVariantBuilderMap();
190  for (FB::VariantList::iterator itr = inArr.begin(); itr != inArr.end(); ++itr) {
191  const std::type_info& type = itr->get_type();
192  ComVariantBuilderMap::const_iterator found = builderMap.find(&type);
193 
194  if (found == builderMap.end())
195  continue;
196 
197  CComVariant var = (found->second)(host, *itr);
198  sa.Add(var);
199  }
200 
201  outVar = sa.Detach();
202  }
203  return outVar;
204  // GJS ---
205  }
206 
207  template<> inline
208  CComVariant makeComVariant<FB::VariantMap>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
209  {
210  // GJS ---
211  CComVariant outVar;
212  FB::VariantMap inMap = var.cast<FB::VariantMap>();
213  if (host->hasHTMLWindow())
214  {
215  FB::JSObjectPtr out = host->getDOMWindow()->createMap();
216  for (FB::VariantMap::iterator it = inMap.begin(); it != inMap.end(); ++it) {
217  out->SetProperty(it->first, it->second);
218  }
219  IDispatchAPIPtr api = ptr_cast<IDispatchAPI>(out);
220  if (api) {
221  outVar = api->getIDispatch();
222  }
223  }
224  else
225  {
226  CComSafeArray<VARIANT> sa;
227  sa.Create();
228  const ComVariantBuilderMap& builderMap = getComVariantBuilderMap();
229  for (FB::VariantMap::iterator itr = inMap.begin(); itr != inMap.end(); ++itr) {
230  const std::type_info& valType = itr->second.get_type();
231  ComVariantBuilderMap::const_iterator valTypeFound = builderMap.find(&valType);
232  if (valTypeFound == builderMap.end())
233  continue;
234 
235  CComSafeArray<VARIANT> sa2;
236  CComVariant key = makeComVariant<std::string>(host, itr->first);
237  CComVariant val = (valTypeFound->second)(host, itr->second);
238  sa2.Add(key);
239  sa2.Add(val);
240  sa.Add(sa2.Detach());
241  }
242  outVar = sa.Detach();
243  }
244  return outVar;
245  // GJS ---
246  }
247 
248  template<> inline
249  CComVariant makeComVariant<FB::JSAPIPtr>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
250  {
251  CComVariant outVar;
252 
253  FB::JSAPIPtr obj(var.cast<FB::JSAPIPtr>());
254  IDispatchAPIPtr api = ptr_cast<IDispatchAPI>(obj);
255  if (api) {
256  outVar = api->getIDispatch();
257  } else {
258  if (obj) {
259  // Add obj to the list of shared_ptrs that browserhost keeps
260  outVar = host->getJSAPIWrapper(obj, true);
261  outVar.pdispVal->Release();
262  } else {
263  outVar.ChangeType(VT_NULL);
264  }
265  }
266 
267  return outVar;
268  }
269 
270  template<> inline
271  CComVariant makeComVariant<FB::JSAPIWeakPtr>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
272  {
273  CComVariant outVar;
274 
275  FB::JSAPIPtr obj(var.convert_cast<FB::JSAPIPtr>());
276  IDispatchAPIPtr api = ptr_cast<IDispatchAPI>(obj);
277  if (api) {
278  outVar = api->getIDispatch();
279  } else {
280  if (obj) {
281  outVar = host->getJSAPIWrapper(obj, false);
282  outVar.pdispVal->Release();
283  } else {
284  outVar.ChangeType(VT_NULL);
285  }
286  }
287 
288  return outVar;
289  }
290 
291  template<> inline
292  CComVariant makeComVariant<FB::JSObjectPtr>(const ActiveXBrowserHostPtr& host, const FB::variant& var)
293  {
294  CComVariant outVar;
295 
296  FB::JSObjectPtr obj(var.cast<FB::JSObjectPtr>());
297  IDispatchAPIPtr api = ptr_cast<IDispatchAPI>(obj);
298  if (api) {
299  outVar = api->getIDispatch();
300  } else {
301  if (obj) {
302  FB::JSAPIPtr ptr(var.convert_cast<FB::JSAPIPtr>());
303  outVar = getFactoryInstance()->createCOMJSObject(host, ptr, true);
304  outVar.pdispVal->Release();
305  } else {
306  outVar.ChangeType(VT_NULL);
307  }
308  }
309 
310  return outVar;
311  }
312 
313  namespace select_ccomvariant_builder
314  {
315  template<class T>
316  ComVariantBuilder isArithmetic(const boost::true_type& /* is_arithmetic */)
317  {
318  return &makeArithmeticComVariant<T>;
319  }
320 
321  template<class T>
322  ComVariantBuilder isArithmetic(const boost::false_type& /* is_arithmetic */)
323  {
324  return &makeComVariant<T>;
325  }
326 
327  template<class T>
328  ComVariantBuilder select()
329  {
330  return isArithmetic<T>(boost::is_arithmetic<T>());
331  }
332  }
333 } }
334 
335 #endif
336 
boost::shared_ptr< FB::JSObject > JSObjectPtr
Defines an alias representing a JSObject shared_ptr (you should never use a JSObject* directly) ...
Definition: APITypes.h:109
const T convert_cast() const
Converts the stored value to the requested type if possible and returns the resulting value...
Definition: variant.h:667
Accepts any datatype, used in all interactions with javascript. Provides tools for getting back out t...
Definition: variant.h:198
boost::shared_ptr< T > ptr_cast(boost::shared_ptr< U > const &r)
Convenience function for doing a dynamic cast of one boost::shared_ptr to another.
Definition: APITypes.h:339
std::vector< variant > VariantList
Defines an alias representing list of variants.
Definition: APITypes.h:64
boost::shared_ptr< FB::JSAPI > JSAPIPtr
Defines an alias for a JSAPI shared_ptr (you should never use a JSAPI* directly)
Definition: APITypes.h:94
std::map< std::string, variant > VariantMap
Defines an alias representing a string -> variant map.
Definition: APITypes.h:72
T cast() const
returns the value cast as the given type; throws bad_variant_type if that type is not the type of the...
Definition: variant.h:370