FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
IDispatchAPI.cpp
1 /**********************************************************\
2 Original Author: Richard Bateman (taxilian)
3 
4 Created: Nov 4, 2009
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2009 Richard Bateman, Firebreath development team
13 \**********************************************************/
14 
15 #include "win_targetver.h"
16 #include <boost/bind.hpp>
17 #include <boost/scoped_array.hpp>
18 #include <dispex.h>
19 #include "utf8_tools.h"
20 #include "JSAPI_IDispatchEx.h"
21 #include "axutil.h"
22 
23 #include "precompiled_headers.h" // On windows, everything above this line in PCH
24 #include "IDispatchAPI.h"
25 
26 using namespace FB::ActiveX;
27 
28 boost::shared_ptr<FB::ActiveX::IDispatchAPI> IDispatchAPI::create(IDispatch * obj, const ActiveXBrowserHostPtr& host)
29 {
30  return boost::shared_ptr<IDispatchAPI>(new IDispatchAPI(obj, host));
31 }
32 
33 FB::ActiveX::IDispatchAPI::IDispatchAPI(IDispatch * obj, const ActiveXBrowserHostPtr& host) :
34  FB::JSObject(host), m_browser(host), m_obj(host->getIDispatchRef(obj)), is_JSAPI(false)
35 {
36  FB::JSAPIPtr ptr(getJSAPI());
37 
38  if (ptr) {
39  // This is a JSAPI object wrapped in an IDispatch object; we'll call it
40  // directly(ish)
41  is_JSAPI = true;
42  inner = ptr;
43  }
44 }
45 
46 IDispatchAPI::~IDispatchAPI(void)
47 {
48  if (!m_browser.expired())
49  getHost()->deferred_release(m_obj);
50  m_obj.reset();
51 }
52 
53 void IDispatchAPI::getMemberNames(std::vector<std::string> &nameVector) const
54 {
55  if (m_browser.expired() || m_obj.expired())
56  return;
57 
58  ActiveXBrowserHostPtr browser(getHost());
59  if (!browser->isMainThread()) {
60  typedef void (FB::JSAPI::*getMemberNamesType)(std::vector<std::string> *nameVector) const;
61  browser->CallOnMainThread(boost::bind((getMemberNamesType)&FB::JSAPI::getMemberNames, this, &nameVector));
62  return;
63  }
64  if (is_JSAPI) {
65  FB::JSAPIPtr tmp = inner.lock();
66  if (tmp)
67  tmp->getMemberNames(nameVector);
68  return;
69  }
70 
71  try {
72  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
73  if (!dispatchEx) {
74  throw FB::script_error("Cannot enumerate members; IDispatchEx not supported");
75  }
76 
77  DISPID dispid = DISPID_STARTENUM;
78  while (dispatchEx->GetNextDispID(fdexEnumAll, dispid, &dispid) != S_FALSE) {
79  if (dispid < 0) {
80  continue;
81  }
82  CComBSTR memberName;
83  if (SUCCEEDED(dispatchEx->GetMemberName(dispid, &memberName))) {
84  std::wstring name(memberName);
85  nameVector.push_back(FB::wstring_to_utf8(name));
86  }
87  }
88  } catch(...) {}
89 }
90 
91 size_t IDispatchAPI::getMemberCount() const
92 {
93  if (m_browser.expired() || m_obj.expired())
94  return 0;
95 
96  ActiveXBrowserHostPtr browser(getHost());
97  if (!browser->isMainThread()) {
98  return browser->CallOnMainThread(boost::bind(&IDispatchAPI::getMemberCount, this));
99  }
100 
101  if (is_JSAPI) {
102  FB::JSAPIPtr tmp = inner.lock();
103  if (!tmp) {
104  // TODO: check if this should be -1
105  return 0;
106  }
107  return tmp->getMemberCount();
108  }
109 
110  size_t count = 0;
111  try {
112  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
113  if (!dispatchEx) {
114  return -1;
115  }
116 
117  DISPID dispid = DISPID_STARTENUM;
118  while (dispatchEx->GetNextDispID(fdexEnumAll, dispid, &dispid) != S_FALSE) {
119  if (dispid >= 0) {
120  ++count;
121  }
122  }
123  } catch (...) {}
124 
125  return count;
126 }
127 
128 DISPID IDispatchAPI::getIDForName(const std::wstring& name) const
129 {
130  if (m_browser.expired() || m_obj.expired())
131  return DISPID_UNKNOWN;
132 
133  ActiveXBrowserHostPtr browser(getHost());
134  if (!browser->isMainThread()) {
135  return browser->CallOnMainThread(boost::bind(&IDispatchAPI::getIDForName, this, name));
136  }
137 
138  if (name.empty()) {
139  return DISPID_VALUE;
140  }
141 
142  HRESULT hr = E_NOTIMPL;
143  DISPID dispId = DISPID_UNKNOWN;
144  try {
145  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
146  if (dispatchEx) {
147  hr = dispatchEx->GetDispID(CComBSTR(name.c_str()),
148  fdexNameEnsure | fdexNameCaseSensitive | 0x10000000, &dispId);
149  } else {
150  const wchar_t* p = name.c_str();
151  hr = getIDispatch()->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&p), 1, LOCALE_SYSTEM_DEFAULT, &dispId);
152  }
153 
154  if (FAILED(hr)) {
155  if (hr == E_NOTIMPL) {
156  return AxIdMap.getIdForValue(name); // Makes events possible
157  }
158  return DISPID_UNKNOWN;
159  }
160  } catch (...) {}
161  return dispId;
162 }
163 
164 bool IDispatchAPI::HasMethod(const std::wstring& methodName) const
165 {
166  // This will actually just return true if the specified member exists; IDispatch doesn't really
167  // differentiate further than that
168  return getIDForName(methodName) != -1;
169 }
170 
171 bool IDispatchAPI::HasMethod(const std::string& methodName) const
172 {
173  if (m_browser.expired() || m_obj.expired())
174  return false;
175 
176  ActiveXBrowserHostPtr browser(getHost());
177  if (!browser->isMainThread()) {
178  typedef bool (IDispatchAPI::*curtype)(const std::string&) const;
179  return browser->CallOnMainThread(boost::bind((curtype)&IDispatchAPI::HasMethod, this, methodName));
180  }
181 
182  if (is_JSAPI) {
183  FB::JSAPIPtr tmp = inner.lock();
184  if (!tmp) {
185  return false;
186  }
187  return tmp->HasMethod(methodName);
188  }
189 
190  // This will actually just return true if the specified member exists; IDispatch doesn't really
191  // differentiate further than that
192  return getIDForName(FB::utf8_to_wstring(methodName)) != -1 && !HasProperty(methodName);
193 }
194 
195 bool IDispatchAPI::HasProperty(const std::wstring& propertyName) const
196 {
197  return HasProperty(FB::wstring_to_utf8(propertyName));
198 }
199 
200 bool IDispatchAPI::HasProperty(const std::string& propertyName) const
201 {
202  if (m_browser.expired() || m_obj.expired())
203  return false;
204 
205  ActiveXBrowserHostPtr browser(getHost());
206  if (!browser->isMainThread()) {
207  typedef bool (IDispatchAPI::*HasPropertyType)(const std::string&) const;
208  return browser->CallOnMainThread(boost::bind((HasPropertyType)&IDispatchAPI::HasProperty, this, propertyName));
209  }
210 
211  if (is_JSAPI) {
212  FB::JSAPIPtr tmp = inner.lock();
213  if (!tmp) {
214  return false;
215  }
216  return tmp->HasProperty(propertyName);
217  }
218 
219  DISPID dispId = getIDForName(FB::utf8_to_wstring(propertyName));
220  if (dispId == DISPID_UNKNOWN && propertyName != "toString") {
221  return false;
222  }
223 
224  DISPPARAMS params;
225  params.cArgs = 0;
226  params.cNamedArgs = 0;
227 
228  // the only way to find out if the property actually exists or not is to try to get it
229  HRESULT hr;
230  CComVariant result;
231  CComExcepInfo exceptionInfo;
232  try {
233  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
234  if (dispatchEx) {
235  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT,
236  DISPATCH_PROPERTYGET, &params, &result, &exceptionInfo, NULL);
237  } else {
238  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
239  DISPATCH_PROPERTYGET, &params, &result, &exceptionInfo, NULL);
240  }
241  return SUCCEEDED(hr);
242  } catch (...) { return false; }
243 }
244 
245 bool IDispatchAPI::HasProperty(int idx) const
246 {
247  FB::variant name(idx);
248  return getIDForName(name.convert_cast<std::wstring>()) != -1;
249 }
250 
251 // Methods to manage properties on the API
252 FB::variant IDispatchAPI::GetProperty(const std::string& propertyName)
253 {
254  if (m_browser.expired() || m_obj.expired())
255  return FB::FBVoid();
256 
257  ActiveXBrowserHostPtr browser(getHost());
258  if (!browser->isMainThread()) {
259  return browser->CallOnMainThread(boost::bind((FB::GetPropertyType)&IDispatchAPI::GetProperty, this, propertyName));
260  }
261 
262  if (is_JSAPI) {
263  FB::JSAPIPtr tmp = inner.lock();
264  if (!tmp) {
265  return false;
266  }
267  return tmp->GetProperty(propertyName);
268  }
269 
270  DISPID dispId = getIDForName(FB::utf8_to_wstring(propertyName));
271  if (dispId == DISPID_UNKNOWN && propertyName != "toString") {
272  throw FB::script_error("Could not get property");
273  }
274 
275  // TODO: how can toString == DISPID_UNKNOWN work?
276 
277  DISPPARAMS params;
278  params.cArgs = 0;
279  params.cNamedArgs = 0;
280 
281  HRESULT hr;
282  CComVariant result;
283  CComExcepInfo exceptionInfo;
284  try {
285  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
286  if (dispatchEx) {
287  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params,
288  &result, &exceptionInfo, NULL);
289  } else {
290  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
291  DISPATCH_PROPERTYGET, &params, &result, &exceptionInfo, NULL);
292  }
293 
294  if (FAILED(hr)) {
295  throw FB::script_error("Could not get property");
296  }
297 
298  return browser->getVariant(&result);
299  } catch (...) {
300  throw FB::script_error("Could not get property");
301  }
302 }
303 
304 void IDispatchAPI::SetProperty(const std::string& propertyName, const FB::variant& value)
305 {
306  if (m_browser.expired() || m_obj.expired())
307  return;
308 
309  ActiveXBrowserHostPtr browser(getHost());
310  if (!browser->isMainThread()) {
311  browser->CallOnMainThread(boost::bind((FB::SetPropertyType)&IDispatchAPI::SetProperty, this, propertyName, value));
312  return;
313  }
314 
315  if (is_JSAPI) {
316  FB::JSAPIPtr tmp = inner.lock();
317  if (tmp)
318  tmp->SetProperty(propertyName, value);
319  return;
320  }
321 
322  DISPID dispId = getIDForName(FB::utf8_to_wstring(propertyName));
323  if (dispId == DISPID_UNKNOWN) {
324  throw FB::script_error("Could not set property");
325  }
326 
327  CComVariant arg[1];
328  VARIANTARG rawArg[1];
329  DISPID namedArg[1];
330  DISPPARAMS params;
331  params.cArgs = 1;
332  params.cNamedArgs = 1;
333  params.rgdispidNamedArgs = namedArg;
334  params.rgvarg = rawArg;
335 
336  browser->getComVariant(&arg[0], value);
337  rawArg[0] = arg[0];
338  namedArg[0] = DISPID_PROPERTYPUT;
339 
340  HRESULT hr;
341  CComVariant result;
342  CComExcepInfo exceptionInfo;
343  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
344  if (dispatchEx) {
345  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &params,
346  &result, &exceptionInfo, NULL);
347  if (hr == DISP_E_MEMBERNOTFOUND) {
348  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params,
349  NULL, &exceptionInfo, NULL);
350  }
351  } else {
352  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
353  DISPATCH_PROPERTYPUT, &params, &result, &exceptionInfo, NULL);
354  }
355 
356  if (FAILED(hr)) {
357  throw FB::script_error("Could not set property");
358  }
359 }
360 
361 void IDispatchAPI::RemoveProperty(const std::string& propertyName)
362 {
363  if (m_browser.expired())
364  return;
365 
366  ActiveXBrowserHostPtr browser(getHost());
367  if (!browser->isMainThread()) {
368  browser->CallOnMainThread(boost::bind((FB::RemovePropertyType)&IDispatchAPI::RemoveProperty, this, propertyName));
369  return;
370  }
371 
372  if (is_JSAPI) {
373  FB::JSAPIPtr tmp = inner.lock();
374  if (tmp)
375  RemoveProperty(propertyName);
376  return;
377  }
378 
379  DISPID dispId = getIDForName(FB::utf8_to_wstring(propertyName));
380  if (dispId == DISPID_UNKNOWN) {
381  return;
382  }
383 
384  HRESULT hr;
385  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
386  if (dispatchEx) {
387  hr = dispatchEx->DeleteMemberByDispID(dispId);
388  } else {
389  // todo: IDispatch does not support removing properties. Do SetProperty(propertyName, undefined); instead?
390  throw FB::script_error("Could not remove property");
391  }
392 
393  if (FAILED(hr)) {
394  return;
395  } else {
396  // todo: we should probably remove the name from the afxmap, but this is a bit hairy as described at
397  // http://msdn.microsoft.com/en-us/library/sky96ah7(v=vs.94).aspx . So we'll ignore it for now.
398  }
399 }
400 
401 
402 FB::variant IDispatchAPI::GetProperty(int idx)
403 {
404  FB::variant sIdx(idx);
405  return GetProperty(sIdx.convert_cast<std::string>());
406 }
407 
408 void IDispatchAPI::RemoveProperty(int idx)
409 {
410  if (is_JSAPI) {
411  FB::JSAPIPtr tmp = inner.lock();
412  if (tmp)
413  RemoveProperty(idx);
414  }
415 
416  FB::variant sIdx(idx);
417  RemoveProperty(sIdx.convert_cast<std::string>());
418 }
419 
420 void IDispatchAPI::SetProperty(int idx, const FB::variant& value)
421 {
422  if (is_JSAPI) {
423  FB::JSAPIPtr tmp = inner.lock();
424  if (tmp)
425  tmp->SetProperty(idx, value);
426  }
427 
428  FB::variant sIdx(idx);
429  SetProperty(sIdx.convert_cast<std::string>(), value);
430 }
431 
432 
433 // Methods to manage methods on the API
434 FB::variant IDispatchAPI::Invoke(const std::string& methodName, const std::vector<FB::variant>& args)
435 {
436  if (m_browser.expired() || m_obj.expired())
437  return FB::FBVoid();
438 
439  ActiveXBrowserHostPtr browser(getHost());
440  if (!browser->isMainThread()) {
441  return browser->CallOnMainThread(boost::bind((FB::InvokeType)&IDispatchAPI::Invoke, this, methodName, args));
442  }
443 
444  DISPID dispId = getIDForName(FB::utf8_to_wstring(methodName));
445  if (dispId == DISPID_UNKNOWN) {
446  throw FB::script_error("Method invoke failed");
447  }
448 
449  size_t argCount(args.size());
450  boost::scoped_array<CComVariant> comArgs(new CComVariant[argCount + 1]);
451  boost::scoped_array<VARIANTARG> rawComArgs(new VARIANTARG[argCount + 1]);
452  DISPPARAMS params;
453  DISPID tid = DISPID_THIS;
454  params.cArgs = args.size() + 1;
455  params.cNamedArgs = 1;
456  params.rgvarg = rawComArgs.get();
457  params.rgdispidNamedArgs = &tid; // Needed for IE9
458 
459  for (size_t i = 0; i < argCount; i++) {
460  browser->getComVariant(&comArgs[argCount - i], args[i]);
461  // We copy w/out adding a ref so that comArgs will still clean up the values when it goes away
462  rawComArgs[argCount - i] = comArgs[argCount - i];
463  }
464  comArgs[0] = getIDispatch(); // Needed for IE 9
465  rawComArgs[0] = comArgs[0];
466 
467  CComVariant result;
468  CComExcepInfo exceptionInfo;
469  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
470  HRESULT hr;
471  if (!dispatchEx) {
472  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
473  DISPATCH_METHOD, &params, &result, &exceptionInfo, NULL);
474  } else {
475  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT,
476  DISPATCH_METHOD, &params, &result, &exceptionInfo, NULL);
477  }
478  if (FAILED(hr)) {
479  throw FB::script_error("Method invoke failed");
480  }
481 
482  return browser->getVariant(&result);
483 }
484 
485 void IDispatchAPI::callMultipleFunctions( const std::string& name, const FB::VariantList& args,
486  const std::vector<FB::JSObjectPtr>& direct, const std::vector<FB::JSObjectPtr>& ifaces )
487 {
488  if (!isValid())
489  throw FB::script_error("Error calling handlers");
490 
491  ActiveXBrowserHostPtr browser(getHost());
492  if (!browser->isMainThread()) {
493  return browser->ScheduleOnMainThread(shared_from_this(), boost::bind(&IDispatchAPI::callMultipleFunctions, this, name, args, direct, ifaces));
494  }
495 
496  size_t argCount(args.size());
497  boost::scoped_array<CComVariant> comArgs(new CComVariant[argCount + 1]);
498  boost::scoped_array<VARIANTARG> rawComArgs(new VARIANTARG[argCount + 1]);
499  DISPPARAMS params;
500  DISPID tid = DISPID_THIS;
501  params.cArgs = args.size() + 1;
502  params.cNamedArgs = 1;
503  params.rgvarg = rawComArgs.get();
504  params.rgdispidNamedArgs = &tid; // Needed for IE9
505 
506  for (size_t i = 0; i < argCount; i++) {
507  browser->getComVariant(&comArgs[argCount - i], args[i]);
508  // We copy w/out adding a ref so that comArgs will still clean up the values when it goes away
509  rawComArgs[argCount - i] = comArgs[argCount - i];
510  }
511  comArgs[0] = getIDispatch(); // Needed for IE 9
512  rawComArgs[0] = comArgs[0];
513 
514  CComVariant result;
515  CComExcepInfo exceptionInfo;
516  std::vector<FB::JSObjectPtr>::const_iterator it(direct.begin());
517  std::vector<FB::JSObjectPtr>::const_iterator endit(direct.end());
518  for (it; it != endit; ++it) {
519  IDispatchAPIPtr ptr(boost::static_pointer_cast<IDispatchAPI>(*it));
520  DISPID dispId = ptr->getIDForName(std::wstring(L""));
521  if (dispId == DISPID_UNKNOWN) {
522  continue;
523  }
524  CComQIPtr<IDispatchEx> dispatchEx(ptr->getIDispatch());
525  HRESULT hr;
526  if (!dispatchEx) {
527  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
528  DISPATCH_METHOD, &params, &result, &exceptionInfo, NULL);
529  } else {
530  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT,
531  DISPATCH_METHOD, &params, &result, &exceptionInfo, NULL);
532  }
533  }
534  it = ifaces.begin();
535  endit = ifaces.end();
536  for (it; it != endit; ++it) {
537  IDispatchAPIPtr ptr(boost::static_pointer_cast<IDispatchAPI>(*it));
538  DISPID dispId = getIDForName(FB::utf8_to_wstring(name));
539  if (dispId == DISPID_UNKNOWN) {
540  continue;
541  }
542  CComQIPtr<IDispatchEx> dispatchEx(ptr->getIDispatch());
543  HRESULT hr;
544  if (!dispatchEx) {
545  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
546  DISPATCH_METHOD, &params, &result, &exceptionInfo, NULL);
547  } else {
548  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT,
549  DISPATCH_METHOD, &params, &result, &exceptionInfo, NULL);
550  }
551  }
552 }
553 
554 FB::variant IDispatchAPI::Construct(const std::vector<FB::variant>& args)
555 {
556  if (m_browser.expired())
557  return FB::FBVoid();
558 
559  ActiveXBrowserHostPtr browser(getHost());
560  if (!browser->isMainThread()) {
561  return browser->CallOnMainThread(boost::bind((FB::ConstructType)&IDispatchAPI::Construct, this, args));
562 
563  }
564 
565  DISPID dispId = getIDForName(FB::utf8_to_wstring(""));
566  if (dispId == DISPID_UNKNOWN) {
567  throw FB::script_error("Constructor invoke failed");
568  }
569 
570  size_t argCount(args.size());
571  boost::scoped_array<CComVariant> comArgs(new CComVariant[argCount + 1]);
572  boost::scoped_array<VARIANTARG> rawComArgs(new VARIANTARG[argCount + 1]);
573  DISPPARAMS params;
574  DISPID tid = DISPID_THIS;
575  params.cArgs = args.size() + 1;
576  params.cNamedArgs = 1;
577  params.rgvarg = rawComArgs.get();
578  params.rgdispidNamedArgs = &tid; // Needed for IE9
579 
580  for (size_t i = 0; i < argCount; i++) {
581  browser->getComVariant(&comArgs[argCount - i], args[i]);
582  // We copy w/out adding a ref so that comArgs will still clean up the values when it goes away
583  rawComArgs[argCount - i] = comArgs[argCount - i];
584  }
585  comArgs[0] = getIDispatch(); // Needed for IE 9
586  rawComArgs[0] = comArgs[0];
587 
588  CComVariant result;
589  CComExcepInfo exceptionInfo;
590  CComQIPtr<IDispatchEx> dispatchEx(getIDispatch());
591  HRESULT hr;
592  if (!dispatchEx) {
593  hr = getIDispatch()->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT,
594  DISPATCH_CONSTRUCT, &params, &result, &exceptionInfo, NULL);
595  } else {
596  hr = dispatchEx->InvokeEx(dispId, LOCALE_USER_DEFAULT,
597  DISPATCH_CONSTRUCT, &params, &result, &exceptionInfo, NULL);
598  }
599  if (FAILED(hr)) {
600  throw FB::script_error("Method invoke failed");
601  }
602 
603  return browser->getVariant(&result);
604 }
605 
606 FB::JSAPIPtr IDispatchAPI::getJSAPI() const
607 {
608  if (m_browser.expired() || m_obj.expired()) {
609  return FB::JSAPIPtr();
610  }
611  JSAPI_IDispatchExBase* p(NULL);
612  try {
613  CComQIPtr<IFireBreathObject> fbObj(getIDispatch());
614  // If it's our own element then both of these will pass! This means it isn't us!
615  CComQIPtr<IHTMLElement> testObj(getIDispatch());
616  if (!testObj && fbObj && (p = dynamic_cast<JSAPI_IDispatchExBase*>(getIDispatch()))) {
617  return p->getAPI();
618  }
619  } catch (...) {}
620 
621  return FB::JSAPIPtr();
622 }
623 
variant(JSAPI::* InvokeType)(const std::string &, const std::vector< variant > &)
Defines an alias representing a function pointer to JSAPI::Invoke.
Definition: APITypes.h:172
Provide a JSObject implementation to wrap a IDispatch ActiveX object.
Definition: IDispatchAPI.h:33
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
variant(JSAPI::* GetPropertyType)(const std::string &)
Defines an alias representing a function pointer to JSAPI::GetProperty.
Definition: APITypes.h:178
std::vector< variant > VariantList
Defines an alias representing list of variants.
Definition: APITypes.h:64
variant(JSAPI::* ConstructType)(const std::vector< variant > &)
Defines an alias representing a function pointer to JSAPI::Invoke.
Definition: APITypes.h:174
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
Exception type; when thrown in a JSAPI method, a javascript exception will be thrown.
Definition: JSExceptions.h:28
void(JSAPI::* RemovePropertyType)(const std::string &)
Defines an alias representing a function pointer to JSAPI::GetProperty.
Definition: APITypes.h:180
std::string wstring_to_utf8(const std::wstring &src)
Accepts a std::wstring and returns a UTF8-encoded std::string.
Definition: utf8_tools.cpp:37
void(JSAPI::* SetPropertyType)(const std::string &, const variant &)
Defines an alias representing a function pointer to JSAPI::SetProperty.
Definition: APITypes.h:176
JavaScript API class – provides a javascript interface that can be exposed to the browser...
Definition: JSAPI.h:56
std::wstring utf8_to_wstring(const std::string &src)
Accepts a UTF8-encoded std::string and returns a std::wstring.
Definition: utf8_tools.cpp:50