iebrowser.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. #include <precomp.h>
  2. #include "iebrowser.h"
  3. #include "mbsvc.h"
  4. #include "main.h"
  5. #include "../nu/ns_wc.h"
  6. #include "../Winamp/buildtype.h"
  7. #include <api/config/items/cfgitem.h>
  8. #include <wa2frontend.h>
  9. #include <windows.h>
  10. #include <Mshtml.h>
  11. #include "minibrowserCOM.h"
  12. class BrowserMsgProc: public ifc_messageprocessor
  13. {
  14. public:
  15. BrowserMsgProc(BrowserWnd *pBrowser) : pTarget(pBrowser) {}
  16. ~BrowserMsgProc(void) {}
  17. public:
  18. bool ProcessMessage(MSG *pMsg)
  19. {
  20. if (WM_KEYFIRST <= pMsg->message && WM_KEYLAST >= pMsg->message)
  21. {
  22. HWND hwndHost;
  23. hwndHost = pTarget->gethWnd();
  24. if ((hwndHost == pMsg->hwnd || IsChild(hwndHost, pMsg->hwnd)) && IsWindowVisible(pMsg->hwnd))
  25. {
  26. if (!(GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_MENU)&0x8000))
  27. {
  28. if (pTarget->TranslateKey(pMsg)) return true;
  29. }
  30. switch(pMsg->message)
  31. {
  32. case WM_KEYDOWN:
  33. case WM_SYSKEYDOWN:
  34. case WM_KEYUP:
  35. case WM_SYSKEYUP:
  36. switch(pMsg->wParam)
  37. {
  38. case VK_F1:
  39. if (!(GetAsyncKeyState(VK_SHIFT)&0x8000)) pMsg->hwnd = plugin.hwndParent;
  40. break;
  41. case VK_F4:
  42. if ((pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) && (GetAsyncKeyState(VK_MENU)&0x8000))
  43. SendMessageW(plugin.hwndParent, WM_CLOSE, 0, 0);
  44. pMsg->message = WM_NULL;
  45. break;
  46. case 'P':
  47. case 'K':
  48. case 'H':
  49. case VK_TAB:
  50. if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_MENU)&0x8000)) pMsg->hwnd = plugin.hwndParent;
  51. break;
  52. case '3':
  53. case VK_UP:
  54. case VK_DOWN:
  55. break;
  56. default:
  57. if ((GetAsyncKeyState(VK_MENU)&0x8000) && !(GetAsyncKeyState(VK_CONTROL)&0x8000)) pMsg->hwnd = plugin.hwndParent;
  58. break;
  59. }
  60. break;
  61. }
  62. }
  63. }
  64. return /*(IsDialogMessageW(pTarget->gethWnd(), pMsg)) ? true :*/ false;
  65. }
  66. protected:
  67. BrowserWnd *pTarget;
  68. RECVS_DISPATCH;
  69. };
  70. extern HINSTANCE hInstance;
  71. STDAPI WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc)
  72. {
  73. *pstrDest = SysAllocString( szSrc );
  74. if ( !(*pstrDest) ) return E_OUTOFMEMORY;
  75. return NOERROR;
  76. }
  77. STDAPI FreeBSTR(BSTR* pstr)
  78. {
  79. if ( *pstr == NULL ) return S_FALSE;
  80. SysFreeString( *pstr );
  81. return NOERROR;
  82. }
  83. HRESULT writeBString(BSTR* psz, const char *str)
  84. {
  85. WCHAR WideStr[WA_MAX_PATH] = {0};
  86. String s = str;
  87. if (s.isempty()) s = "";
  88. MultiByteToWideCharSZ(CP_ACP, 0, s, -1, WideStr, WA_MAX_PATH);
  89. return WriteBSTR(psz, WideStr);
  90. }
  91. BrowserWnd::BrowserWnd() : HTMLContainer2(NULL, NULL), processor(NULL)
  92. {
  93. setVirtual(0);
  94. oleOk = FALSE;
  95. homepage = L"about:blank";
  96. timerset1 = 0;
  97. timerset2 = 0;
  98. cancelIEErrorPage = false;
  99. scrollbarsflag = BROWSER_SCROLLBARS_DEFAULT;
  100. }
  101. BrowserWnd::~BrowserWnd()
  102. {
  103. if (processor)
  104. {
  105. if (WASABI_API_APP) WASABI_API_APP->app_removeMessageProcessor(processor);
  106. free(processor);
  107. processor = NULL;
  108. }
  109. if (timerset1)
  110. {
  111. killTimer(MB_TIMERID1);
  112. timerset1 = 0;
  113. }
  114. if (timerset2)
  115. {
  116. killTimer(MB_TIMERID2);
  117. timerset2 = 0;
  118. }
  119. freeBrowserStuff();
  120. }
  121. bool BrowserWnd::InitializeLibrary()
  122. {
  123. return (FALSE != HTMLContainer2_Initialize());
  124. }
  125. void BrowserWnd::UninitializeLibrary()
  126. {
  127. HTMLContainer2_Uninitialize();
  128. }
  129. int BrowserWnd::onInit()
  130. {
  131. BROWSER_PARENT::onInit();
  132. if (isVisible())
  133. onSetVisible(1);
  134. updateScrollbars();
  135. return 1;
  136. }
  137. void BrowserWnd::onSetVisible(int show)
  138. {
  139. if (show) initBrowserStuff();
  140. }
  141. int BrowserWnd::initBrowserStuff()
  142. {
  143. if (pUnk) return 1;
  144. if (SUCCEEDED(OleInitialize(NULL))) oleOk = TRUE;
  145. if (!oleOk) return 1;
  146. // {280876CF-48C0-40bc-8E86-73CE6BB462E5}
  147. const GUID options_guid =
  148. { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
  149. hParent = gethWnd();
  150. int usemozilla = 0;
  151. #ifdef WASABI_COMPILE_CONFIG
  152. usemozilla = _intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid), L"Use Mozilla instead of IE for minibrowser");
  153. #endif
  154. if (SUCCEEDED(Initialize()))
  155. {
  156. HRESULT hr;
  157. IWebBrowser2 *pWeb2;
  158. hr = GetIWebBrowser2(&pWeb2);
  159. if (SUCCEEDED(hr))
  160. {
  161. pWeb2->put_RegisterAsBrowser(VARIANT_TRUE);
  162. if (deferednavigate.isempty())
  163. {
  164. if (!homepage.isempty())
  165. minibrowser_navigateUrl(homepage);
  166. else
  167. minibrowser_navigateUrl(L"about:blank");
  168. }
  169. else minibrowser_navigateUrl(deferednavigate);
  170. }
  171. }
  172. if (!processor && WASABI_API_APP)
  173. {
  174. processor = new BrowserMsgProc(this);
  175. WASABI_API_APP->app_addMessageProcessor(processor);
  176. }
  177. ShowWindow(hParent, SW_SHOWNA);
  178. return 1;
  179. }
  180. void BrowserWnd::freeBrowserStuff()
  181. {
  182. if (oleOk)
  183. {
  184. Finish();
  185. OleUninitialize();
  186. oleOk = FALSE;
  187. #ifndef WASABINOMAINAPI
  188. api->hint_garbageCollect();
  189. #endif
  190. }
  191. }
  192. int BrowserWnd::minibrowser_navigateUrl(const wchar_t *url)
  193. {
  194. HRESULT hr;
  195. curpage = url;
  196. hr = NavigateToName(url, 0);
  197. if (FAILED(hr))
  198. {
  199. deferednavigate = url;
  200. return 0;
  201. }
  202. return 1;
  203. }
  204. int BrowserWnd::minibrowser_back()
  205. {
  206. HRESULT hr;
  207. IWebBrowser2 *pWeb2;
  208. hr = GetIWebBrowser2(&pWeb2);
  209. if (SUCCEEDED(hr))
  210. {
  211. pWeb2->GoBack();
  212. pWeb2->Release();
  213. }
  214. return 1;
  215. }
  216. int BrowserWnd::minibrowser_forward()
  217. {
  218. HRESULT hr;
  219. IWebBrowser2 *pWeb2;
  220. hr = GetIWebBrowser2(&pWeb2);
  221. if (SUCCEEDED(hr))
  222. {
  223. pWeb2->GoForward();
  224. pWeb2->Release();
  225. }
  226. return 1;
  227. }
  228. int BrowserWnd::minibrowser_refresh()
  229. {
  230. HRESULT hr;
  231. IWebBrowser2 *pWeb2;
  232. hr = GetIWebBrowser2(&pWeb2);
  233. if (SUCCEEDED(hr))
  234. {
  235. pWeb2->Refresh();
  236. pWeb2->Release();
  237. }
  238. return 1;
  239. }
  240. int BrowserWnd::minibrowser_home()
  241. {
  242. minibrowser_navigateUrl(homepage);
  243. return 1;
  244. }
  245. int BrowserWnd::minibrowser_stop()
  246. {
  247. HRESULT hr;
  248. IWebBrowser2 *pWeb2;
  249. hr = GetIWebBrowser2(&pWeb2);
  250. if (SUCCEEDED(hr))
  251. {
  252. pWeb2->Stop();
  253. pWeb2->Release();
  254. }
  255. return 1;
  256. }
  257. HWND BrowserWnd::getOSHandle()
  258. {
  259. return ::GetWindow(gethWnd(), GW_CHILD); // assumes setVirtual(0) in constructor
  260. }
  261. void BrowserWnd::onTargetNameTimer()
  262. {
  263. updateTargetName();
  264. }
  265. void BrowserWnd::onScrollbarsFlagTimer()
  266. {
  267. updateScrollbars();
  268. }
  269. void BrowserWnd::timerCallback(int id)
  270. {
  271. switch (id)
  272. {
  273. case MB_TIMERID1:
  274. onTargetNameTimer();
  275. return ;
  276. case MB_TIMERID2:
  277. onScrollbarsFlagTimer();
  278. return ;
  279. }
  280. BROWSER_PARENT::timerCallback(id);
  281. }
  282. void BrowserWnd::minibrowser_setTargetName(const wchar_t *name)
  283. {
  284. targetname = name;
  285. updateTargetName();
  286. }
  287. void BrowserWnd::updateTargetName()
  288. {
  289. if (!doSetTargetName(targetname))
  290. {
  291. if (!timerset1) { setTimer(MB_TIMERID1, 100); timerset1 = 1; }
  292. return ;
  293. }
  294. else
  295. {
  296. if (timerset1) { killTimer(MB_TIMERID1); timerset1 = 0; }
  297. }
  298. }
  299. int BrowserWnd::doSetTargetName(const wchar_t *name)
  300. {
  301. HRESULT hr;
  302. IWebBrowser2 *pWeb2;
  303. IDispatch *id;
  304. hr = GetIWebBrowser2(&pWeb2);
  305. if (FAILED(hr)) return FALSE;
  306. if (SUCCEEDED(pWeb2->get_Document(&id)) && id)
  307. {
  308. IHTMLDocument2 *doc;
  309. if (SUCCEEDED(id->QueryInterface(IID_IHTMLDocument2, (void **)&doc)) && doc)
  310. {
  311. IHTMLWindow2 *w;
  312. if (SUCCEEDED(doc->get_parentWindow(&w)) && w)
  313. {
  314. w->put_name(SysAllocString(targetname.getValue()));
  315. w->Release();
  316. doc->Release();
  317. id->Release();
  318. pWeb2->Release();
  319. return 1;
  320. }
  321. doc->Release();
  322. }
  323. id->Release();
  324. }
  325. pWeb2->Release();
  326. return 0;
  327. }
  328. const wchar_t *BrowserWnd::minibrowser_getTargetName()
  329. {
  330. return targetname;
  331. }
  332. void BrowserWnd::OnBeforeNavigate(IDispatch *pDispatch, VARIANT *URL, VARIANT *Flags, VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers, VARIANT_BOOL *Cancel)
  333. {
  334. int i = 0;
  335. foreach(callbacks)
  336. int r = callbacks.getfor()->minibrowsercb_onBeforeNavigate(URL->bstrVal, Flags->intVal, TargetFrameName->bstrVal);
  337. if (i++ == 0) *Cancel = (r) ? VARIANT_TRUE : VARIANT_FALSE;
  338. endfor;
  339. updateScrollbars();
  340. }
  341. void BrowserWnd::minibrowser_setScrollbarsFlag(int a)
  342. {
  343. scrollbarsflag = a;
  344. updateScrollbars();
  345. }
  346. void BrowserWnd::updateScrollbars()
  347. {
  348. if (!doSetScrollbars())
  349. {
  350. if (!timerset2) { setTimer(MB_TIMERID2, 100); timerset2 = 1; }
  351. return ;
  352. }
  353. else
  354. {
  355. if (timerset2) { killTimer(MB_TIMERID2); timerset2 = 0; }
  356. }
  357. }
  358. void BrowserWnd::OnDocumentComplete(IDispatch *pDispatch, VARIANT *URL)
  359. {
  360. if (!targetname.isempty())
  361. minibrowser_setTargetName(targetname);
  362. foreach(callbacks)
  363. callbacks.getfor()->minibrowsercb_onDocumentComplete(URL->bstrVal);
  364. endfor;
  365. updateScrollbars();
  366. }
  367. void BrowserWnd::OnDocumentReady(IDispatch *pDispatch, VARIANT *URL)
  368. {
  369. if (!targetname.isempty())
  370. minibrowser_setTargetName(targetname);
  371. foreach(callbacks)
  372. callbacks.getfor()->minibrowsercb_onDocumentReady(URL->bstrVal);
  373. endfor;
  374. updateScrollbars();
  375. }
  376. void BrowserWnd::OnNavigateError(IDispatch *pDispatch, VARIANT *URL, VARIANT *TargetFrameName, VARIANT *StatusCode, VARIANT_BOOL *Cancel)
  377. {
  378. if (TargetFrameName->bstrVal != NULL)
  379. return; //TODO: send targetframe via api to script
  380. foreach(callbacks)
  381. callbacks.getfor()->minibrowsercb_onNavigateError(URL->bstrVal, StatusCode->intVal);
  382. endfor;
  383. if (cancelIEErrorPage) *Cancel = -1;
  384. }
  385. const wchar_t* BrowserWnd::messageToMaki(wchar_t* str1, wchar_t* str2, int i1, int i2, int i3)
  386. {
  387. const wchar_t* ret = 0;
  388. foreach(callbacks)
  389. ret = callbacks.getfor()->minibrowsercb_messageToMaki(str1, str2, i1, i2, i3);
  390. if (ret) break;
  391. endfor;
  392. return ret;
  393. }
  394. const wchar_t* BrowserWnd::minibrowser_messageToJS(const wchar_t* str1, const wchar_t* str2, int i1, int i2, int i3)
  395. {
  396. // TODO feed JS w/ this info
  397. return 0;
  398. }
  399. void BrowserWnd::minibrowser_scrape()
  400. {
  401. IWebBrowser2 *browser=0;
  402. GetIWebBrowser2(&browser);
  403. IDispatch *docDisp=0;
  404. IHTMLDocument2 *document = 0;
  405. if (browser)
  406. {
  407. browser->get_Document(&docDisp);
  408. if (docDisp)
  409. {
  410. docDisp->QueryInterface(&document);
  411. docDisp->Release();
  412. }
  413. browser->Release();
  414. }
  415. if (document)
  416. {
  417. IHTMLElementCollection *links=0;
  418. document->get_all(&links);
  419. if (links)
  420. {
  421. IDispatch *anchorDisp=0;
  422. VARIANT index;
  423. VariantInit(&index);
  424. index.vt = VT_I4;
  425. index.intVal = 0;
  426. links->item(index, index, &anchorDisp);
  427. while (anchorDisp)
  428. {
  429. IHTMLAnchorElement *anchor=0;
  430. anchorDisp->QueryInterface(&anchor);
  431. if (anchor)
  432. {
  433. BSTR href=0;
  434. anchor->get_href(&href);
  435. if (href && (wa2.CanPlay(href) || wa2.IsPlaylist(href)))
  436. {
  437. foreach(callbacks)
  438. callbacks.getfor()->minibrowsercb_onMediaLink(href);
  439. endfor;
  440. }
  441. SysFreeString(href);
  442. anchor->Release();
  443. }
  444. index.intVal++;
  445. anchorDisp->Release();
  446. links->item(index, index, &anchorDisp);
  447. }
  448. links->Release();
  449. }
  450. document->Release();
  451. }
  452. }
  453. void BrowserWnd::minibrowser_getDocumentTitle(wchar_t *str, size_t len)
  454. {
  455. IWebBrowser2 *browser=0;
  456. GetIWebBrowser2(&browser);
  457. IDispatch *docDisp=0;
  458. IHTMLDocument2 *document = 0;
  459. if (browser)
  460. {
  461. browser->get_Document(&docDisp);
  462. if (docDisp)
  463. {
  464. docDisp->QueryInterface(&document);
  465. docDisp->Release();
  466. }
  467. browser->Release();
  468. }
  469. if (document)
  470. {
  471. BSTR title_bstr;
  472. document->get_title(&title_bstr);
  473. document->Release();
  474. WCSCPYN(str, title_bstr, len);
  475. // the COM object SysAllocString'd this for us, so we need to free it via COM also
  476. SysFreeString(title_bstr);
  477. }
  478. else
  479. str[0]=0;
  480. }
  481. void BrowserWnd::minibrowser_setCancelIEErrorPage (bool cancel)
  482. {
  483. cancelIEErrorPage = cancel;
  484. }
  485. int BrowserWnd::doSetScrollbars()
  486. {
  487. HRESULT hr;
  488. IWebBrowser2 *pWeb2;
  489. IDispatch *id;
  490. hr = GetIWebBrowser2(&pWeb2);
  491. if (FAILED(hr)) return 0;
  492. if (scrollbarsflag == BROWSER_SCROLLBARS_DEFAULT) return 1;
  493. if (SUCCEEDED(pWeb2->get_Document(&id)) && id)
  494. {
  495. IHTMLDocument2 *doc;
  496. if (SUCCEEDED(id->QueryInterface(IID_IHTMLDocument2, (void **)&doc)) && doc)
  497. {
  498. IHTMLElement *e;
  499. if (SUCCEEDED(doc->get_body(&e)))
  500. {
  501. IHTMLStyle *s;
  502. if (SUCCEEDED(e->get_style(&s)))
  503. {
  504. BSTR a;
  505. switch (scrollbarsflag)
  506. {
  507. case BROWSER_SCROLLBARS_ALWAYS:
  508. writeBString(&a, "scroll");
  509. break;
  510. case BROWSER_SCROLLBARS_AUTO:
  511. writeBString(&a, "auto");
  512. break;
  513. case BROWSER_SCROLLBARS_NEVER:
  514. writeBString(&a, "hidden");
  515. break;
  516. default:
  517. a = NULL;
  518. break;
  519. }
  520. if (a) s->put_overflow(a);
  521. FreeBSTR(&a);
  522. s->Release();
  523. pWeb2->Release();
  524. return 1;
  525. }
  526. e->Release();
  527. }
  528. doc->Release();
  529. }
  530. id->Release();
  531. }
  532. pWeb2->Release();
  533. return 0;
  534. }
  535. const wchar_t *BrowserWnd::minibrowser_getCurrentUrl()
  536. {
  537. return curpage;
  538. }
  539. STDMETHODIMP BrowserWnd::GetExternal(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
  540. {
  541. *ppDispatch = (IDispatch*) new MinibrowserCOM(this); //TODO we might need to delete this as well!
  542. return S_OK;
  543. }
  544. DWORD BrowserWnd::OnGetDownlodFlags(void)
  545. {
  546. return DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_PRAGMA_NO_CACHE
  547. #ifdef WINAMP_FINAL_BUILD
  548. |DLCTL_SILENT
  549. #endif
  550. ;
  551. }
  552. #define CBCLASS BrowserMsgProc
  553. START_DISPATCH;
  554. CB(IFC_MESSAGEPROCESSOR_PROCESS_MESSAGE, ProcessMessage)
  555. END_DISPATCH;
  556. #undef CBCLASS