JSAPI2_ExternalObject.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. #include "JSAPI2_ExternalObject.h"
  2. #include "JSAPI2_svc_apicreator.h"
  3. #include "JSAPI2_TransportAPI.h"
  4. #include "JSAPI2_PlayerAPI.h"
  5. #include "JSAPI2_Downloader.h"
  6. #include "JSAPI2_SecurityAPI.h"
  7. #include "JSAPI2_Security.h"
  8. #include "JSAPI2_Bookmarks.h"
  9. #include "JSAPI2_Application.h"
  10. #include "JSAPI2_SkinAPI.h"
  11. #include "JSAPI2_MediaCore.h"
  12. #include "JSAPI2_AsyncDownloader.h"
  13. #include "JSAPI.h"
  14. #include "api.h"
  15. #include "main.h"
  16. #include "../nu/AutoChar.h"
  17. #include "../nu/AutoCharFn.h"
  18. #include <api/service/waservicefactory.h>
  19. #include <shlwapi.h>
  20. /* benski: basic thoughts
  21. ExternalObject will be created "on demand" when ml_online loads a page
  22. so ExternalObjects will have a lifetime (unlike ExternalCOM which is a singleton)
  23. create wasabi services for creating window.external.* objects
  24. when a window.external.* function is requested, services are enumerated
  25. the key is passed to the object creator. The returned object will be treated
  26. as a singleton from ExternalObject's perspective. It will be Release()'d when
  27. the ExternalObject is destroyed.
  28. the basic layout will be
  29. window.external.API.method
  30. e.g.
  31. window.external.Transport.Play();
  32. any time that non-singleton objects need to be created (Config object,
  33. playlist object, etc) they will be created from a method within the API object
  34. e.g.
  35. var new_playlist = window.external.Playlist.Create();
  36. */
  37. JSAPI2::ExternalObject::ExternalObject(const wchar_t *_key)
  38. {
  39. hwnd=0;
  40. if (_key)
  41. key = _wcsdup(_key);
  42. else
  43. key = 0;
  44. refCount = 1;
  45. // create Config API now.
  46. ConfigCOM *configCOM;
  47. wchar_t szPath[MAX_PATH] = {0};
  48. PathCombineW(szPath, CONFIGDIR, L"jscfg.ini");
  49. if (SUCCEEDED(ConfigCOM::CreateInstanceW(key, AutoCharFn(szPath), &configCOM)))
  50. {
  51. AddDispatch(L"Config", configCOM);
  52. configCOM->Release();
  53. }
  54. }
  55. JSAPI2::ExternalObject::~ExternalObject()
  56. {
  57. for (JSAPI::DispatchTable::iterator itr = dispatchTable.begin(); itr != dispatchTable.end(); itr++)
  58. {
  59. //JSAPI::Dispatcher *entry = *itr;
  60. delete (*itr);
  61. }
  62. dispatchTable.clear();
  63. if (key) free(key);
  64. }
  65. DWORD JSAPI2::ExternalObject::AddDispatch(const wchar_t *name, IDispatch *object)
  66. {
  67. int id = (int) dispatchTable.size();
  68. dispatchTable.push_back(new JSAPI::Dispatcher(name, id, object));
  69. return id;
  70. }
  71. #define CHECK_ID(str, id)\
  72. if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, rgszNames[i], -1, L##str, -1))\
  73. { rgdispid[i] = id; continue; }
  74. HRESULT JSAPI2::ExternalObject::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  75. {
  76. bool unknowns = false;
  77. for (unsigned int i = 0;i != cNames;i++)
  78. {
  79. if (GetDispID(rgszNames[i], fdexNameCaseSensitive, &rgdispid[i]) == DISPID_UNKNOWN)
  80. unknowns=true;
  81. }
  82. if (unknowns)
  83. return DISP_E_UNKNOWNNAME;
  84. else
  85. return S_OK;
  86. }
  87. HRESULT JSAPI2::ExternalObject::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  88. {
  89. return E_NOTIMPL;
  90. }
  91. HRESULT JSAPI2::ExternalObject::GetTypeInfoCount(unsigned int FAR * pctinfo)
  92. {
  93. return E_NOTIMPL;
  94. }
  95. HRESULT JSAPI2::ExternalObject::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  96. {
  97. return InvokeEx(dispid, lcid, wFlags, pdispparams, pvarResult, pexecinfo, 0);
  98. }
  99. STDMETHODIMP JSAPI2::ExternalObject::QueryInterface(REFIID riid, PVOID *ppvObject)
  100. {
  101. if (!ppvObject)
  102. return E_POINTER;
  103. else if (IsEqualIID(riid, IID_IDispatch))
  104. *ppvObject = (IDispatch *)this;
  105. else if (IsEqualIID(riid, IID_IUnknown))
  106. *ppvObject = this;
  107. else if (IsEqualIID(riid, IID_IWasabiDispatchable))
  108. *ppvObject = (IWasabiDispatchable *)this;
  109. else
  110. {
  111. *ppvObject = NULL;
  112. return E_NOINTERFACE;
  113. }
  114. AddRef();
  115. return S_OK;
  116. }
  117. ULONG JSAPI2::ExternalObject::AddRef(void)
  118. {
  119. return InterlockedIncrement(&refCount);
  120. }
  121. ULONG JSAPI2::ExternalObject::Release(void)
  122. {
  123. LONG lRef = InterlockedDecrement(&refCount);
  124. if (lRef == 0) delete this;
  125. return lRef;
  126. }
  127. HRESULT JSAPI2::ExternalObject::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid)
  128. {
  129. *pid = DISP_E_UNKNOWNNAME;
  130. for (size_t entry=0;entry!=dispatchTable.size();entry++)
  131. {
  132. if (!wcscmp(bstrName, dispatchTable[entry]->name))
  133. {
  134. if (dispatchTable[entry]->object)
  135. {
  136. *pid = (DISPID)entry;
  137. return S_OK;
  138. }
  139. else
  140. {
  141. return DISPID_UNKNOWN;
  142. }
  143. }
  144. }
  145. // look it up in wasabi
  146. IDispatch *disp = 0;
  147. waServiceFactory *sf = 0;
  148. int n = 0;
  149. do
  150. {
  151. sf = WASABI_API_SVC->service_enumService(JSAPI2::svc_apicreator::getServiceType(), n++);
  152. if (!sf)
  153. break;
  154. if (sf)
  155. {
  156. JSAPI2::svc_apicreator *creator = (JSAPI2::svc_apicreator *)sf->getInterface();
  157. if (creator)
  158. {
  159. disp = creator->CreateAPI(bstrName, key, static_cast<JSAPI::ifc_info *>(this));
  160. }
  161. sf->releaseInterface(creator);
  162. }
  163. } while (sf && !disp);
  164. *pid = AddDispatch(bstrName, disp);
  165. if (!disp)
  166. {
  167. *pid = DISP_E_UNKNOWNNAME;
  168. return DISPID_UNKNOWN;
  169. }
  170. else
  171. return S_OK;
  172. }
  173. HRESULT JSAPI2::ExternalObject::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
  174. {
  175. if (id >= 0 && (size_t)id < dispatchTable.size())
  176. {
  177. IDispatch *disp = dispatchTable[id]->object;
  178. if (disp)
  179. disp->AddRef(); // I assume we're supposed to do this, but I'm not 100% sure
  180. JSAPI_INIT_RESULT(pvarRes, VT_DISPATCH);
  181. JSAPI_SET_RESULT(pvarRes, pdispVal, disp);
  182. return S_OK;
  183. }
  184. return DISP_E_MEMBERNOTFOUND;
  185. }
  186. HRESULT JSAPI2::ExternalObject::DeleteMemberByName(BSTR bstrName, DWORD grfdex)
  187. {
  188. return E_NOTIMPL;
  189. }
  190. HRESULT JSAPI2::ExternalObject::DeleteMemberByDispID(DISPID id)
  191. {
  192. return E_NOTIMPL;
  193. }
  194. HRESULT JSAPI2::ExternalObject::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
  195. {
  196. return E_NOTIMPL;
  197. }
  198. HRESULT JSAPI2::ExternalObject::GetMemberName(DISPID id, BSTR *pbstrName)
  199. {
  200. return E_NOTIMPL;
  201. }
  202. HRESULT JSAPI2::ExternalObject::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid)
  203. {
  204. return E_NOTIMPL;
  205. }
  206. HRESULT JSAPI2::ExternalObject::GetNameSpaceParent(IUnknown **ppunk)
  207. {
  208. return E_NOTIMPL;
  209. }
  210. HRESULT JSAPI2::ExternalObject::QueryDispatchable(REFIID riid, Dispatchable **ppDispatchable)
  211. {
  212. if (IsEqualIID(riid, JSAPI::IID_JSAPI_ifc_info))
  213. {
  214. *ppDispatchable = (JSAPI::ifc_info *)this;
  215. }
  216. else
  217. {
  218. *ppDispatchable = NULL;
  219. return E_NOINTERFACE;
  220. }
  221. (*ppDispatchable)->AddRef();
  222. return S_OK;
  223. }
  224. const wchar_t *JSAPI2::ExternalObject::GetUserAgent()
  225. {
  226. return L"JSAPI2";
  227. }
  228. void JSAPI2::ExternalObject::SetHWND(HWND hwnd)
  229. {
  230. this->hwnd = hwnd;
  231. }
  232. HWND JSAPI2::ExternalObject::GetHWND()
  233. {
  234. return hwnd;
  235. }
  236. void JSAPI2::ExternalObject::SetName(const wchar_t *name)
  237. {
  238. JSAPI2::security.AssociateName(key, name);
  239. }
  240. const wchar_t *JSAPI2::ExternalObject::GetName()
  241. {
  242. return JSAPI2::security.GetAssociatedName(key);
  243. }
  244. int JSAPI2::ExternalObject::AddAPI(const wchar_t *name, IDispatch *dispatch)
  245. {
  246. if (dispatch)
  247. {
  248. dispatch->AddRef();
  249. AddDispatch(name, dispatch);
  250. return 0;
  251. }
  252. return 1;
  253. }
  254. #define CBCLASS JSAPI2::ExternalObject
  255. START_DISPATCH;
  256. CB(JSAPI_IFC_INFO_GETUSERAGENT, GetUserAgent)
  257. VCB(JSAPI_IFC_INFO_SETHWND, SetHWND)
  258. CB(JSAPI_IFC_INFO_GETHWND, GetHWND)
  259. VCB(JSAPI_IFC_INFO_SETNAME, SetName)
  260. CB(JSAPI_IFC_INFO_GETNAME, GetName)
  261. CB(JSAPI_IFC_INFO_ADDAPI, AddAPI)
  262. END_DISPATCH;
  263. #undef CBCLASS