Guest User

Untitled

a guest
Jul 24th, 2015
367
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 49.61 KB | None | 0 0
  1.  
  2. #include "webpage.h"
  3.  
  4. #include <math.h>
  5.  
  6. #include <QApplication>
  7. #include <QDesktopServices>
  8. #include <QDateTime>
  9. #include <QDir>
  10. #include <QFileInfo>
  11. #include <QKeyEvent>
  12. #include <QMouseEvent>
  13. #include <QNetworkAccessManager>
  14. #include <QNetworkCookie>
  15. #include <QNetworkRequest>
  16. #include <QPainter>
  17. #include <QPrinter>
  18. #include <QWebHistory>
  19. #include <QWebHistoryItem>
  20. #include <QWebElement>
  21. #include <QWebFrame>
  22. #include <QWebPage>
  23. #include <QWebInspector>
  24. #include <QMapIterator>
  25. #include <QBuffer>
  26. #include <QDebug>
  27. #include <QImageWriter>
  28. #include <QUuid>
  29.  
  30. #include "networkaccessmanager.h"
  31. #include "utils.h"
  32. #include "config.h"
  33. #include "consts.h"
  34. #include "callback.h"
  35. #include "cookiejar.h"
  36. #include "system.h"
  37.  
  38.  
  39. #include "redispp.h"
  40.  
  41.  
  42. #ifdef Q_OS_WIN32
  43. #include <io.h>
  44. #include <fcntl.h>
  45. #endif
  46.  
  47. // Ensure we have at least head and body.
  48. #define BLANK_HTML "<html><head></head><body></body></html>"
  49. #define CALLBACKS_OBJECT_NAME ""
  50. #define CALLBACKS_OBJECT_PRESENT "typeof(window."CALLBACKS_OBJECT_NAME") !== \"undefined\";"
  51.  
  52. #define STDOUT_FILENAME "/dev/stdout"
  53. #define STDERR_FILENAME "/dev/stderr"
  54.  
  55.  
  56. /**
  57. * @class CustomPage
  58. */
  59. class CustomPage: public QWebPage
  60. {
  61. Q_OBJECT
  62.  
  63.  
  64. public:
  65. redispp::Connection con;
  66.  
  67.  
  68. CustomPage(WebPage* parent = 0)
  69. : QWebPage(parent)
  70. , m_webPage(parent)
  71. {
  72. m_userAgent = QWebPage::userAgentForUrl(QUrl());
  73. this->con = new redispp::Connection("127.0.0.1", "6379", "password", false) ;
  74. setForwardUnsupportedContent(true);
  75. }
  76.  
  77. bool extension(Extension extension, const ExtensionOption* option, ExtensionReturn* output)
  78. {
  79. Q_UNUSED(option);
  80.  
  81. if (extension == ChooseMultipleFilesExtension) {
  82. static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = m_uploadFiles;
  83. return true;
  84. } else {
  85. return false;
  86. }
  87. }
  88.  
  89. void setCookieJar(CookieJar* cookieJar)
  90. {
  91. m_cookieJar = cookieJar;
  92. }
  93.  
  94. public slots:
  95. bool shouldInterruptJavaScript()
  96. {
  97. m_webPage->javascriptInterrupt();
  98.  
  99. if (m_webPage->m_shouldInterruptJs) {
  100.  
  101. // reset our flag
  102. m_webPage->m_shouldInterruptJs = false;
  103. return true;
  104. }
  105. return false;
  106. }
  107.  
  108. protected:
  109. bool supportsExtension(Extension extension) const
  110. {
  111. return extension == ChooseMultipleFilesExtension;
  112. }
  113.  
  114. QString chooseFile(QWebFrame* originatingFrame, const QString& oldFile)
  115. {
  116. Q_UNUSED(originatingFrame);
  117.  
  118. // Check if User set a file via File Picker
  119. QString chosenFile = m_webPage->filePicker(oldFile);
  120. if (chosenFile == QString::null && m_uploadFiles.count() > 0) {
  121. // Check if instead User set a file via uploadFile API
  122. chosenFile = m_uploadFiles.first();
  123. }
  124.  
  125. // Return the value coming from the "filePicker" callback, IFF not null.
  126. qDebug() << "CustomPage - file chosen for upload:" << chosenFile;
  127. return chosenFile;
  128. }
  129.  
  130. void javaScriptAlert(QWebFrame* originatingFrame, const QString& msg)
  131. {
  132. Q_UNUSED(originatingFrame);
  133. emit m_webPage->javaScriptAlertSent(msg);
  134. }
  135.  
  136. bool javaScriptConfirm(QWebFrame* originatingFrame, const QString& msg)
  137. {
  138. Q_UNUSED(originatingFrame);
  139. return m_webPage->javaScriptConfirm(msg);
  140. }
  141.  
  142. bool javaScriptPrompt(QWebFrame* originatingFrame, const QString& msg, const QString& defaultValue, QString* result)
  143. {
  144. Q_UNUSED(originatingFrame);
  145. return m_webPage->javaScriptPrompt(msg, defaultValue, result);
  146. }
  147.  
  148. void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
  149. {
  150. Q_UNUSED(lineNumber);
  151. Q_UNUSED(sourceID);
  152. emit m_webPage->javaScriptConsoleMessageSent(message);
  153. }
  154.  
  155. void javaScriptError(const QString& message, int lineNumber, const QString& sourceID, const QString& stack)
  156. {
  157. emit m_webPage->javaScriptErrorSent(message, lineNumber, sourceID, stack);
  158. }
  159.  
  160. QString userAgentForUrl(const QUrl& url) const
  161. {
  162. Q_UNUSED(url);
  163. return m_userAgent;
  164. }
  165.  
  166. bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type)
  167. {
  168. bool isMainFrame = (frame == m_webPage->m_mainFrame);
  169.  
  170. QString navigationType = "Undefined";
  171. switch (type) {
  172. case NavigationTypeLinkClicked:
  173. navigationType = "LinkClicked";
  174. break;
  175. case NavigationTypeFormSubmitted:
  176. navigationType = "FormSubmitted";
  177. break;
  178. case NavigationTypeBackOrForward:
  179. navigationType = "BackOrForward";
  180. break;
  181. case NavigationTypeReload:
  182. navigationType = "Reload";
  183. break;
  184. case NavigationTypeFormResubmitted:
  185. navigationType = "FormResubmitted";
  186. break;
  187. case NavigationTypeOther:
  188. navigationType = "Other";
  189. break;
  190. }
  191. bool isNavigationLocked = m_webPage->navigationLocked();
  192.  
  193. emit m_webPage->navigationRequested(
  194. request.url(), //< Requested URL
  195. navigationType, //< Navigation Type
  196. !isNavigationLocked, //< Will navigate (not locked)?
  197. isMainFrame); //< Is main frame?
  198.  
  199. return !isNavigationLocked;
  200. }
  201.  
  202. QWebPage* createWindow(WebWindowType type)
  203. {
  204. Q_UNUSED(type);
  205. WebPage* newPage;
  206.  
  207. // Create a new "raw" WebPage object
  208. if (m_webPage->ownsPages()) {
  209. newPage = new WebPage(m_webPage);
  210. } else {
  211. newPage = new WebPage::instance());
  212. ::instance()->m_pages.append(newPage);
  213. }
  214. newPage->setCookieJar(m_cookieJar);
  215.  
  216. // Apply default settings
  217. newPage->applySettings::instance()->defaultPageSettings());
  218.  
  219. // Signal JS shim to catch, decorate and store this new child page
  220. emit m_webPage->rawPageCreated(newPage);
  221.  
  222. // Return the new QWebPage to the QWebKit backend
  223. return newPage->m_customWebPage;
  224. }
  225.  
  226. private:
  227. WebPage* m_webPage;
  228. QString m_userAgent;
  229. QStringList m_uploadFiles;
  230. friend class WebPage;
  231. CookieJar* m_cookieJar;
  232. };
  233.  
  234.  
  235. /**
  236. * Contains the Callback Objects used to regulate callback-traffic from the webpage internal context.
  237. * It's directly exposed within the webpage JS context,
  238. * and indirectly in the JS context.
  239. *
  240. * @class WebPageCallbacks
  241. */
  242. class WebpageCallbacks : public QObject
  243. {
  244. Q_OBJECT
  245.  
  246. public:
  247. WebpageCallbacks(QObject* parent = 0)
  248. : QObject(parent)
  249. , m_genericCallback(NULL)
  250. , m_filePickerCallback(NULL)
  251. , m_jsConfirmCallback(NULL)
  252. , m_jsPromptCallback(NULL)
  253. , m_jsInterruptCallback(NULL)
  254. {
  255. }
  256.  
  257. QObject* getGenericCallback()
  258. {
  259. qDebug() << "WebpageCallbacks - getGenericCallback";
  260.  
  261. if (!m_genericCallback) {
  262. m_genericCallback = new Callback(this);
  263. }
  264. return m_genericCallback;
  265. }
  266.  
  267. QObject* getFilePickerCallback()
  268. {
  269. qDebug() << "WebpageCallbacks - getFilePickerCallback";
  270.  
  271. if (!m_filePickerCallback) {
  272. m_filePickerCallback = new Callback(this);
  273. }
  274. return m_filePickerCallback;
  275. }
  276.  
  277. QObject* getJsConfirmCallback()
  278. {
  279. qDebug() << "WebpageCallbacks - getJsConfirmCallback";
  280.  
  281. if (!m_jsConfirmCallback) {
  282. m_jsConfirmCallback = new Callback(this);
  283. }
  284. return m_jsConfirmCallback;
  285. }
  286.  
  287. QObject* getJsPromptCallback()
  288. {
  289. qDebug() << "WebpageCallbacks - getJsConfirmCallback";
  290.  
  291. if (!m_jsPromptCallback) {
  292. m_jsPromptCallback = new Callback(this);
  293. }
  294. return m_jsPromptCallback;
  295. }
  296.  
  297. QObject* getJsInterruptCallback()
  298. {
  299. qDebug() << "WebpageCallbacks - getJsInterruptCallback";
  300.  
  301. if (!m_jsInterruptCallback) {
  302. m_jsInterruptCallback = new Callback(this);
  303. }
  304. return m_jsInterruptCallback;
  305. }
  306.  
  307. public slots:
  308. QVariant call(const QVariantList& arguments)
  309. {
  310. if (m_genericCallback) {
  311. return m_genericCallback->call(arguments);
  312. }
  313. return QVariant();
  314. }
  315.  
  316. private:
  317. Callback* m_genericCallback;
  318. Callback* m_filePickerCallback;
  319. Callback* m_jsConfirmCallback;
  320. Callback* m_jsPromptCallback;
  321. Callback* m_jsInterruptCallback;
  322.  
  323. friend class WebPage;
  324. };
  325. ///here
  326.  
  327.  
  328.  
  329. WebPage::WebPage(QObject* parent, const QUrl& baseUrl)
  330. : QObject(parent)
  331. , m_navigationLocked(false)
  332. , m_mousePos(QPoint(0, 0))
  333. , m_ownsPages(true)
  334. , m_loadingProgress(0)
  335. , m_shouldInterruptJs(false)
  336. , m_customWebPage
  337. {
  338. setObjectName("WebPage");
  339. m_callbacks = new WebpageCallbacks(this);
  340. m_customWebPage = new CustomPage(this);
  341.  
  342. // To grant universal access to a web page
  343. // attribute "WebSecurityEnabled" must be applied during the initializing
  344. // security context for Document instance. Setting up it later will not cause any effect
  345. // see <qt\src\3rdparty\webkit\Source\WebCore\dom\Document.cpp:4468>
  346. QWebSettings* settings = m_customWebPage->settings();
  347.  
  348. m_mainFrame = m_customWebPage->mainFrame();
  349. m_currentFrame = m_mainFrame;
  350. m_mainFrame->setHtml(BLANK_HTML, baseUrl);
  351.  
  352. // NOTE: below you can see that between all the event handlers
  353. // we listen for, "SLOT(setupFrame())" is connected to 2 signals:
  354. // 1. page.loadFinished
  355. // 2. mainFrame.javaScriptWindowObjectCleared
  356. // We have found out that, despite our understanding, the event #1 above
  357. // fires BEFORE the event #2 when loading a url.
  358. // But, if no page load is requested, #2 is the only one to fire.
  359. //
  360. // So, we call the slot twice to setup the main frame
  361. // (no parameter == main frame) but we make sure to do the setup only once.
  362. //
  363. // @see WebPage::setupFrame(QWebFrame *) for details.
  364. connect(m_mainFrame, SIGNAL(loadStarted()), this, SLOT(switchToMainFrame()), Qt::QueuedConnection);
  365. connect(m_mainFrame, SIGNAL(loadFinished(bool)), this, SLOT(setupFrame()), Qt::QueuedConnection);
  366. connect(m_customWebPage, SIGNAL(frameCreated(QWebFrame*)), this, SLOT(setupFrame(QWebFrame*)), Qt::DirectConnection);
  367. connect(m_mainFrame, SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(setupFrame()));
  368. connect(m_mainFrame, SIGNAL(javaScriptWindowObjectCleared()), SIGNAL(initialized()));
  369. connect(m_mainFrame, SIGNAL(urlChanged(QUrl)), SIGNAL(urlChanged(QUrl)));
  370. connect(m_customWebPage, SIGNAL(loadStarted()), SIGNAL(loadStarted()), Qt::QueuedConnection);
  371. connect(m_customWebPage, SIGNAL(loadFinished(bool)), SLOT(finish(bool)), Qt::QueuedConnection);
  372. connect(m_customWebPage, SIGNAL(windowCloseRequested()), this, SLOT(close()), Qt::QueuedConnection);
  373. connect(m_customWebPage, SIGNAL(loadProgress(int)), this, SLOT(updateLoadingProgress(int)));
  374. connect(m_customWebPage, SIGNAL(repaintRequested(QRect)), this, SLOT(handleRepaintRequested(QRect)), Qt::QueuedConnection);
  375.  
  376.  
  377. // Start with transparent background.
  378. QPalette palette = m_customWebPage->palette();
  379. palette.setBrush(QPalette::Base, Qt::transparent);
  380. m_customWebPage->setPalette(palette);
  381.  
  382. // Set the page Library path
  383. setLibraryPath(QFileInfo(->scriptFile()).dir().absolutePath());
  384.  
  385. // Page size does not need to take scrollbars into account.
  386. m_mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
  387. m_mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
  388.  
  389. m_customWebPage->settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
  390. m_customWebPage->settings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, true);
  391. m_customWebPage->settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, true);
  392.  
  393. m_customWebPage->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
  394. m_customWebPage->settings()->setLocalStoragePath(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
  395.  
  396. // Custom network access manager to allow traffic monitoring.
  397. m_networkAccessManager = new NetworkAccessManager(this, );
  398. m_customWebPage->setNetworkAccessManager(m_networkAccessManager);
  399. connect(m_networkAccessManager, SIGNAL(resourceRequested(QVariant, QObject*)),
  400. SIGNAL(resourceRequested(QVariant, QObject*)));
  401. connect(m_networkAccessManager, SIGNAL(resourceReceived(QVariant)),
  402. SIGNAL(resourceReceived(QVariant)));
  403. connect(m_networkAccessManager, SIGNAL(resourceError(QVariant)),
  404. SIGNAL(resourceError(QVariant)));
  405. connect(m_networkAccessManager, SIGNAL(resourceTimeout(QVariant)),
  406. SIGNAL(resourceTimeout(QVariant)));
  407.  
  408. m_customWebPage->setViewportSize(QSize(400, 300));
  409. }
  410.  
  411. WebPage::~WebPage()
  412. {
  413. emit closing(this);
  414. }
  415.  
  416. QWebFrame* WebPage::mainFrame()
  417. {
  418. return m_mainFrame;
  419. }
  420.  
  421. QString WebPage::content() const
  422. {
  423. return m_mainFrame->toHtml();
  424. }
  425.  
  426. QString WebPage::frameContent() const
  427. {
  428. return m_currentFrame->toHtml();
  429. }
  430.  
  431. void WebPage::setContent(const QString& content)
  432. {
  433. m_mainFrame->setHtml(content);
  434. }
  435.  
  436. void WebPage::setContent(const QString& content, const QString& baseUrl)
  437. {
  438. if (baseUrl == "about:blank") {
  439. m_mainFrame->setHtml(BLANK_HTML);
  440. } else {
  441. m_mainFrame->setHtml(content, QUrl(baseUrl));
  442. }
  443. }
  444.  
  445.  
  446. void WebPage::setFrameContent(const QString& content)
  447. {
  448. m_currentFrame->setHtml(content);
  449. }
  450.  
  451. QString WebPage::title() const
  452. {
  453. return m_mainFrame->title();
  454. }
  455.  
  456. QString WebPage::frameTitle() const
  457. {
  458. return m_currentFrame->title();
  459. }
  460.  
  461. QString WebPage::url() const
  462. {
  463. return m_mainFrame->url().toString();
  464. }
  465.  
  466. QString WebPage::frameUrl() const
  467. {
  468. return m_currentFrame->url().toString();
  469. }
  470.  
  471. bool WebPage::loading() const
  472. {
  473. // Return "true" if Load Progress is "]0, 100["
  474. return (0 < m_loadingProgress && m_loadingProgress < 100);
  475. }
  476.  
  477. int WebPage::loadingProgress() const
  478. {
  479. return m_loadingProgress;
  480. }
  481.  
  482. bool WebPage::canGoBack()
  483. {
  484. return m_customWebPage->history()->canGoBack();
  485. }
  486.  
  487. bool WebPage::goBack()
  488. {
  489. if (canGoBack()) {
  490. m_customWebPage->history()->back();
  491. return true;
  492. }
  493. return false;
  494. }
  495.  
  496. bool WebPage::canGoForward()
  497. {
  498. return m_customWebPage->history()->canGoForward();
  499. }
  500.  
  501. bool WebPage::goForward()
  502. {
  503. if (canGoForward()) {
  504. m_customWebPage->history()->forward();
  505. return true;
  506. }
  507. return false;
  508. }
  509.  
  510. bool WebPage::go(int historyItemRelativeIndex)
  511. {
  512. // Convert the relative index to absolute
  513. int historyItemIndex = m_customWebPage->history()->currentItemIndex() + historyItemRelativeIndex;
  514.  
  515. // Fetch the right item from the history
  516. QWebHistoryItem historyItem = m_customWebPage->history()->itemAt(historyItemIndex);
  517.  
  518. // Go to the history item, if it's valid
  519. if (historyItem.isValid()) {
  520. m_customWebPage->history()->goToItem(historyItem);
  521. return true;
  522. }
  523.  
  524. return false;
  525. }
  526.  
  527. void WebPage::reload()
  528. {
  529. m_customWebPage->triggerAction(QWebPage::Reload);
  530. }
  531.  
  532. void WebPage::stop()
  533. {
  534. m_customWebPage->triggerAction(QWebPage::Stop);
  535. }
  536.  
  537.  
  538. QString WebPage::plainText() const
  539. {
  540. return m_mainFrame->toPlainText();
  541. }
  542.  
  543. QString WebPage::framePlainText() const
  544. {
  545. return m_currentFrame->toPlainText();
  546. }
  547.  
  548. QString WebPage::libraryPath() const
  549. {
  550. return m_libraryPath;
  551. }
  552.  
  553. void WebPage::setLibraryPath(const QString& libraryPath)
  554. {
  555. m_libraryPath = libraryPath;
  556. }
  557.  
  558. QString WebPage::offlineStoragePath() const
  559. {
  560. return m_customWebPage->settings()->offlineStoragePath();
  561. }
  562.  
  563. int WebPage::offlineStorageQuota() const
  564. {
  565. return m_customWebPage->settings()->offlineStorageDefaultQuota();
  566. }
  567.  
  568. void WebPage::showInspector(const int port)
  569. {
  570. m_customWebPage->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
  571. m_inspector = new QWebInspector;
  572. m_inspector->setPage(m_customWebPage);
  573.  
  574. if (port == -1) {
  575. m_inspector->setVisible(true);
  576. } else {
  577. m_customWebPage->setProperty("_q_webInspectorServerPort", port);
  578. }
  579. }
  580.  
  581. void WebPage::applySettings(const QVariantMap& def)
  582. {
  583. QWebSettings* opt = m_customWebPage->settings();
  584.  
  585. opt->setAttribute(QWebSettings::AutoLoadImages, def[PAGE_SETTINGS_LOAD_IMAGES].toBool());
  586. opt->setAttribute(QWebSettings::JavascriptEnabled, def[PAGE_SETTINGS_JS_ENABLED].toBool());
  587. opt->setAttribute(QWebSettings::XSSAuditingEnabled, def[PAGE_SETTINGS_XSS_AUDITING].toBool());
  588. opt->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, def[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE].toBool());
  589. opt->setAttribute(QWebSettings::WebSecurityEnabled, def[PAGE_SETTINGS_WEB_SECURITY_ENABLED].toBool());
  590. opt->setAttribute(QWebSettings::JavascriptCanOpenWindows, def[PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS].toBool());
  591. opt->setAttribute(QWebSettings::JavascriptCanCloseWindows, def[PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS].toBool());
  592.  
  593. if (def.contains(PAGE_SETTINGS_USER_AGENT)) {
  594. m_customWebPage->m_userAgent = def[PAGE_SETTINGS_USER_AGENT].toString();
  595. }
  596.  
  597. if (def.contains(PAGE_SETTINGS_USERNAME)) {
  598. m_networkAccessManager->setUserName(def[PAGE_SETTINGS_USERNAME].toString());
  599. }
  600.  
  601. if (def.contains(PAGE_SETTINGS_PASSWORD)) {
  602. m_networkAccessManager->setPassword(def[PAGE_SETTINGS_PASSWORD].toString());
  603. }
  604.  
  605. if (def.contains(PAGE_SETTINGS_MAX_AUTH_ATTEMPTS)) {
  606. m_networkAccessManager->setMaxAuthAttempts(def[PAGE_SETTINGS_MAX_AUTH_ATTEMPTS].toInt());
  607. }
  608.  
  609. if (def.contains(PAGE_SETTINGS_RESOURCE_TIMEOUT)) {
  610. m_networkAccessManager->setResourceTimeout(def[PAGE_SETTINGS_RESOURCE_TIMEOUT].toInt());
  611. }
  612.  
  613. }
  614.  
  615. QString WebPage::userAgent() const
  616. {
  617. return m_customWebPage->m_userAgent;
  618. }
  619.  
  620. void WebPage::setNavigationLocked(bool lock)
  621. {
  622. m_navigationLocked = lock;
  623. }
  624.  
  625. bool WebPage::navigationLocked()
  626. {
  627. return m_navigationLocked;
  628. }
  629.  
  630. void WebPage::setViewportSize(const QVariantMap& size)
  631. {
  632. int w = size.value("width").toInt();
  633. int h = size.value("height").toInt();
  634. if (w > 0 && h > 0) {
  635. m_customWebPage->setViewportSize(QSize(w, h));
  636. }
  637. }
  638.  
  639. QVariantMap WebPage::viewportSize() const
  640. {
  641. QVariantMap result;
  642. QSize size = m_customWebPage->viewportSize();
  643. result["width"] = size.width();
  644. result["height"] = size.height();
  645. return result;
  646. }
  647.  
  648. void WebPage::setClipRect(const QVariantMap& size)
  649. {
  650. int w = size.value("width").toInt();
  651. int h = size.value("height").toInt();
  652. int top = size.value("top").toInt();
  653. int left = size.value("left").toInt();
  654.  
  655. if (w >= 0 && h >= 0) {
  656. m_clipRect = QRect(left, top, w, h);
  657. }
  658. }
  659.  
  660. QVariantMap WebPage::clipRect() const
  661. {
  662. QVariantMap result;
  663. result["width"] = m_clipRect.width();
  664. result["height"] = m_clipRect.height();
  665. result["top"] = m_clipRect.top();
  666. result["left"] = m_clipRect.left();
  667. return result;
  668. }
  669.  
  670.  
  671. void WebPage::setScrollPosition(const QVariantMap& size)
  672. {
  673. int top = size.value("top").toInt();
  674. int left = size.value("left").toInt();
  675. m_scrollPosition = QPoint(left, top);
  676. m_mainFrame->setScrollPosition(m_scrollPosition);
  677. }
  678.  
  679. QVariantMap WebPage::scrollPosition() const
  680. {
  681. QVariantMap result;
  682. result["top"] = m_scrollPosition.y();
  683. result["left"] = m_scrollPosition.x();
  684. return result;
  685. }
  686.  
  687. void WebPage::setPaperSize(const QVariantMap& size)
  688. {
  689. m_paperSize = size;
  690. }
  691.  
  692. QVariantMap WebPage::paperSize() const
  693. {
  694. return m_paperSize;
  695. }
  696.  
  697. QVariant WebPage::evaluateJavaScript(const QString& code)
  698. {
  699. QVariant evalResult;
  700. QString function = "(" + code + ")()";
  701.  
  702. qDebug() << "WebPage - evaluateJavaScript" << function;
  703.  
  704. evalResult = m_currentFrame->evaluateJavaScript(
  705. function, //< function evaluated
  706. QString("://webpage.evaluate()")); //< reference source file
  707.  
  708. qDebug() << "WebPage - evaluateJavaScript result" << evalResult;
  709.  
  710. return evalResult;
  711. }
  712.  
  713. QString WebPage::filePicker(const QString& oldFile)
  714. {
  715. qDebug() << "WebPage - filePicker" << "- old file:" << oldFile;
  716.  
  717. if (m_callbacks->m_filePickerCallback) {
  718. QVariant res = m_callbacks->m_filePickerCallback->call(QVariantList() << oldFile);
  719.  
  720. if (res.canConvert<QString>()) {
  721. QString filePath = res.toString();
  722. qDebug() << "WebPage - filePicker" << "- new file:" << filePath;
  723. // Return this value only if the file actually exists
  724. if (QFile::exists(filePath)) {
  725. return filePath;
  726. }
  727. }
  728. }
  729. return QString::null;
  730. }
  731.  
  732. bool WebPage::javaScriptConfirm(const QString& msg)
  733. {
  734. if (m_callbacks->m_jsConfirmCallback) {
  735. QVariant res = m_callbacks->m_jsConfirmCallback->call(QVariantList() << msg);
  736. if (res.canConvert<bool>()) {
  737. return res.toBool();
  738. }
  739. }
  740. return false;
  741. }
  742.  
  743. bool WebPage::javaScriptPrompt(const QString& msg, const QString& defaultValue, QString* result)
  744. {
  745. if (m_callbacks->m_jsPromptCallback) {
  746. QVariant res = m_callbacks->m_jsPromptCallback->call(QVariantList() << msg << defaultValue);
  747. if (!res.isNull() && res.canConvert<QString>()) {
  748. result->append(res.toString());
  749. return true;
  750. }
  751. }
  752. return false;
  753. }
  754.  
  755. void WebPage::javascriptInterrupt()
  756. {
  757. if (m_callbacks->m_jsInterruptCallback) {
  758. QVariant res = m_callbacks->m_jsInterruptCallback->call(QVariantList());
  759.  
  760. if (res.canConvert<bool>()) {
  761. m_shouldInterruptJs = res.toBool();
  762. }
  763. }
  764. }
  765.  
  766. void WebPage::finish(bool ok)
  767. {
  768. QString status = ok ? "success" : "fail";
  769. emit loadFinished(status);
  770. }
  771.  
  772. void WebPage::setCustomHeaders(const QVariantMap& headers)
  773. {
  774. m_networkAccessManager->setCustomHeaders(headers);
  775. }
  776.  
  777. QVariantMap WebPage::customHeaders() const
  778. {
  779. return m_networkAccessManager->customHeaders();
  780. }
  781.  
  782. QStringList WebPage::captureContent() const
  783. {
  784. return m_networkAccessManager->captureContent();
  785. }
  786.  
  787. void WebPage::setCaptureContent(const QStringList& patterns)
  788. {
  789. m_networkAccessManager->setCaptureContent(patterns);
  790. }
  791.  
  792. void WebPage::setCookieJar(CookieJar* cookieJar)
  793. {
  794. m_cookieJar = cookieJar;
  795. m_customWebPage->setCookieJar(m_cookieJar);
  796. m_networkAccessManager->setCookieJar(m_cookieJar);
  797. }
  798.  
  799. void WebPage::setCookieJarFromQObject(QObject* cookieJar)
  800. {
  801. setCookieJar(qobject_cast<CookieJar*>(cookieJar));
  802. }
  803.  
  804. CookieJar* WebPage::cookieJar()
  805. {
  806. return m_cookieJar;
  807. }
  808.  
  809. bool WebPage::setCookies(const QVariantList& cookies)
  810. {
  811. // Delete all the cookies for this URL
  812. m_cookieJar->deleteCookies(this->url());
  813. // Add a new set of cookies foor this URL
  814. return m_cookieJar->addCookiesFromMap(cookies, this->url());
  815. }
  816.  
  817. QVariantList WebPage::cookies() const
  818. {
  819. // Return all the Cookies visible to this Page, as a list of Maps (aka JSON in JS space)
  820. return m_cookieJar->cookiesToMap(this->url());
  821. }
  822.  
  823. bool WebPage::addCookie(const QVariantMap& cookie)
  824. {
  825. return m_cookieJar->addCookieFromMap(cookie, this->url());
  826. }
  827.  
  828. bool WebPage::deleteCookie(const QString& cookieName)
  829. {
  830. if (!cookieName.isEmpty()) {
  831. return m_cookieJar->deleteCookie(cookieName, this->url());
  832. }
  833. return false;
  834. }
  835.  
  836. bool WebPage::clearCookies()
  837. {
  838. return m_cookieJar->deleteCookies(this->url());
  839. }
  840.  
  841. void WebPage::openUrl(const QString& address, const QVariant& op, const QVariantMap& settings)
  842. {
  843. QString operation;
  844. QByteArray body;
  845. QNetworkRequest request;
  846.  
  847. applySettings(settings);
  848. m_customWebPage->triggerAction(QWebPage::Stop);
  849.  
  850. if (op.type() == QVariant::String) {
  851. operation = op.toString();
  852. }
  853.  
  854. if (op.type() == QVariant::Map) {
  855. QVariantMap settingsMap = op.toMap();
  856. operation = settingsMap.value("operation").toString();
  857. QString bodyString = settingsMap.value("data").toString();
  858. QString encoding = settingsMap.value("encoding").toString().toLower();
  859. body = encoding == "utf-8" || encoding == "utf8" ? bodyString.toUtf8() : bodyString.toLatin1();
  860. if (settingsMap.contains("headers")) {
  861. QMapIterator<QString, QVariant> i(settingsMap.value("headers").toMap());
  862. while (i.hasNext()) {
  863. i.next();
  864. request.setRawHeader(i.key().toUtf8(), i.value().toString().toUtf8());
  865. }
  866. }
  867. }
  868.  
  869. if (operation.isEmpty()) {
  870. operation = "get";
  871. }
  872.  
  873. QNetworkAccessManager::Operation networkOp = QNetworkAccessManager::UnknownOperation;
  874. operation = operation.toLower();
  875. if (operation == "get") {
  876. networkOp = QNetworkAccessManager::GetOperation;
  877. } else if (operation == "head") {
  878. networkOp = QNetworkAccessManager::HeadOperation;
  879. } else if (operation == "put") {
  880. networkOp = QNetworkAccessManager::PutOperation;
  881. } else if (operation == "post") {
  882. networkOp = QNetworkAccessManager::PostOperation;
  883. } else if (operation == "delete") {
  884. networkOp = QNetworkAccessManager::DeleteOperation;
  885. }
  886.  
  887. if (networkOp == QNetworkAccessManager::UnknownOperation) {
  888. m_mainFrame->evaluateJavaScript("console.error('Unknown network operation: " + operation + "');", QString());
  889. return;
  890. }
  891.  
  892. if (address == "about:blank") {
  893. m_mainFrame->setHtml(BLANK_HTML);
  894. } else {
  895. QUrl url = QUrl::fromEncoded(QByteArray(address.toLatin1()));
  896.  
  897. // Assume local file if scheme is empty
  898. if (url.scheme().isEmpty()) {
  899. url.setPath(QFileInfo(url.toString()).absoluteFilePath().prepend("/"));
  900. url.setScheme("file");
  901. }
  902.  
  903. request.setUrl(url);
  904. m_mainFrame->load(request, networkOp, body);
  905. }
  906. }
  907.  
  908. void WebPage::release()
  909. {
  910. close();
  911. }
  912.  
  913. void WebPage::close()
  914. {
  915. deleteLater();
  916. }
  917.  
  918. void WebPage::connectRedis()
  919. {
  920.  
  921. }
  922.  
  923. void WebPage::redisSet(const QString& key,const QString& value)
  924. {
  925. conn.set(key, value);
  926. }
  927.  
  928.  
  929.  
  930.  
  931.  
  932. bool WebPage::render(const QString& fileName, const QVariantMap& option)
  933. {
  934. if (m_mainFrame->contentsSize().isEmpty()) {
  935. return false;
  936. }
  937.  
  938. QString outFileName = fileName;
  939. QString tempFileName = "";
  940.  
  941. QString format = "";
  942. int quality = -1; // QImage#save default
  943.  
  944. if (fileName == STDOUT_FILENAME || fileName == STDERR_FILENAME) {
  945. if (!QFile::exists(fileName)) {
  946. // create temporary file for OS that have no /dev/stdout or /dev/stderr. (ex. windows)
  947. tempFileName = QDir::tempPath() + "/temp" + QUuid::createUuid().toString();
  948. outFileName = tempFileName;
  949. }
  950.  
  951. format = "png"; // default format for stdout and stderr
  952. } else {
  953. QFileInfo fileInfo(outFileName);
  954. QDir dir;
  955. dir.mkpath(fileInfo.absolutePath());
  956. }
  957.  
  958. if (option.contains("format")) {
  959. format = option.value("format").toString();
  960. } else if (fileName.endsWith(".pdf", Qt::CaseInsensitive)) {
  961. format = "pdf";
  962. }
  963.  
  964. if (option.contains("quality")) {
  965. quality = option.value("quality").toInt();
  966. }
  967.  
  968. bool retval = true;
  969. if (format == "pdf") {
  970. retval = renderPdf(outFileName);
  971. } else {
  972. QImage rawPageRendering = renderImage();
  973.  
  974. const char* f = 0; // 0 is QImage#save default
  975. if (format != "") {
  976. f = format.toLocal8Bit().constData();
  977. }
  978.  
  979. retval = rawPageRendering.save(outFileName, f, quality);
  980. }
  981.  
  982. if (tempFileName != "") {
  983. // cleanup temporary file and render to stdout or stderr
  984. QFile i(tempFileName);
  985. i.open(QIODevice::ReadOnly);
  986.  
  987. QByteArray ba = i.readAll();
  988.  
  989. System* system = (System*::instance()->createSystem();
  990. if (fileName == STDOUT_FILENAME) {
  991. #ifdef Q_OS_WIN32
  992. _setmode(_fileno(stdout), O_BINARY);
  993. #endif
  994.  
  995. ((File*)system->_stdout())->write(QString::fromLatin1(ba.constData(), ba.size()));
  996.  
  997. #ifdef Q_OS_WIN32
  998. _setmode(_fileno(stdout), O_TEXT);
  999. #endif
  1000. } else if (fileName == STDERR_FILENAME) {
  1001. #ifdef Q_OS_WIN32
  1002. _setmode(_fileno(stderr), O_BINARY);
  1003. #endif
  1004.  
  1005. ((File*)system->_stderr())->write(QString::fromLatin1(ba.constData(), ba.size()));
  1006.  
  1007. #ifdef Q_OS_WIN32
  1008. _setmode(_fileno(stderr), O_TEXT);
  1009. #endif
  1010. }
  1011.  
  1012. i.close();
  1013.  
  1014. QFile::remove(tempFileName);
  1015. }
  1016.  
  1017. return retval;
  1018. }
  1019.  
  1020. QString WebPage::renderBase64(const QByteArray& format)
  1021. {
  1022. QByteArray nformat = format.toLower();
  1023.  
  1024. // Check if the given format is supported
  1025. if (QImageWriter::supportedImageFormats().contains(nformat)) {
  1026. QImage rawPageRendering = renderImage();
  1027.  
  1028. // Prepare buffer for writing
  1029. QByteArray bytes;
  1030. QBuffer buffer(&bytes);
  1031. buffer.open(QIODevice::WriteOnly);
  1032.  
  1033. // Writing image to the buffer, using PNG encoding
  1034. rawPageRendering.save(&buffer, nformat);
  1035.  
  1036. return bytes.toBase64();
  1037. }
  1038.  
  1039. // Return an empty string in case an unsupported format was provided
  1040. return "";
  1041. }
  1042.  
  1043. QImage WebPage::renderImage()
  1044. {
  1045. QSize contentsSize = m_mainFrame->contentsSize();
  1046. contentsSize -= QSize(m_scrollPosition.x(), m_scrollPosition.y());
  1047. QRect frameRect = QRect(QPoint(0, 0), contentsSize);
  1048. if (!m_clipRect.isNull()) {
  1049. frameRect = m_clipRect;
  1050. }
  1051.  
  1052. QSize viewportSize = m_customWebPage->viewportSize();
  1053. m_customWebPage->setViewportSize(contentsSize);
  1054.  
  1055. #ifdef Q_OS_WIN32
  1056. QImage::Format format = QImage::Format_ARGB32_Premultiplied;
  1057. #else
  1058. QImage::Format format = QImage::Format_ARGB32;
  1059. #endif
  1060.  
  1061. QImage buffer(frameRect.size(), format);
  1062. buffer.fill(Qt::transparent);
  1063.  
  1064. QPainter painter;
  1065.  
  1066. // We use tiling approach to work-around Qt software rasterizer bug
  1067. // when dealing with very large paint device.
  1068. // See http://code.google.com/p//issues/detail?id=54.
  1069. const int tileSize = 4096;
  1070. int htiles = (buffer.width() + tileSize - 1) / tileSize;
  1071. int vtiles = (buffer.height() + tileSize - 1) / tileSize;
  1072. for (int x = 0; x < htiles; ++x) {
  1073. for (int y = 0; y < vtiles; ++y) {
  1074.  
  1075. QImage tileBuffer(tileSize, tileSize, format);
  1076. tileBuffer.fill(Qt::transparent);
  1077.  
  1078. // Render the web page onto the small tile first
  1079. painter.begin(&tileBuffer);
  1080. painter.setRenderHint(QPainter::Antialiasing, true);
  1081. painter.setRenderHint(QPainter::TextAntialiasing, true);
  1082. painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
  1083. painter.translate(-frameRect.left(), -frameRect.top());
  1084. painter.translate(-x * tileSize, -y * tileSize);
  1085. m_mainFrame->render(&painter, QRegion(frameRect));
  1086. painter.end();
  1087.  
  1088. // Copy the tile to the main buffer
  1089. painter.begin(&buffer);
  1090. painter.setCompositionMode(QPainter::CompositionMode_Source);
  1091. painter.drawImage(x * tileSize, y * tileSize, tileBuffer);
  1092. painter.end();
  1093. }
  1094. }
  1095.  
  1096. m_customWebPage->setViewportSize(viewportSize);
  1097. return buffer;
  1098. }
  1099.  
  1100. #define _PDF_DPI 72 // Different defaults. OSX: 72, X11: 75(?), Windows: 96
  1101.  
  1102. qreal stringToPointSize(const QString& string)
  1103. {
  1104. static const struct {
  1105. QString unit;
  1106. qreal factor;
  1107. } units[] = {
  1108. { "mm", 72 / 25.4 },
  1109. { "cm", 72 / 2.54 },
  1110. { "in", 72 },
  1111. { "px", 72.0 / _PDF_DPI },
  1112. { "", 72.0 / _PDF_DPI }
  1113. };
  1114. for (uint i = 0; i < sizeof(units) / sizeof(units[0]); ++i) {
  1115. if (string.endsWith(units[i].unit)) {
  1116. QString value = string;
  1117. value.chop(units[i].unit.length());
  1118. return value.toDouble() * units[i].factor;
  1119. }
  1120. }
  1121. return 0;
  1122. }
  1123.  
  1124. qreal printMargin(const QVariantMap& map, const QString& key)
  1125. {
  1126. const QVariant margin = map.value(key);
  1127. if (margin.isValid() && margin.canConvert(QVariant::String)) {
  1128. return stringToPointSize(margin.toString());
  1129. } else {
  1130. return 0;
  1131. }
  1132. }
  1133.  
  1134. bool WebPage::renderPdf(const QString& fileName)
  1135. {
  1136. QPrinter printer;
  1137. printer.setOutputFormat(QPrinter::PdfFormat);
  1138. printer.setOutputFileName(fileName);
  1139. printer.setResolution(_PDF_DPI);
  1140. QVariantMap paperSize = m_paperSize;
  1141.  
  1142. if (paperSize.isEmpty()) {
  1143. const QSize pageSize = m_mainFrame->contentsSize();
  1144. paperSize.insert("width", QString::number(pageSize.width()) + "px");
  1145. paperSize.insert("height", QString::number(pageSize.height()) + "px");
  1146. paperSize.insert("margin", "0px");
  1147. }
  1148.  
  1149. if (paperSize.contains("width") && paperSize.contains("height")) {
  1150. const QSizeF sizePt(ceil(stringToPointSize(paperSize.value("width").toString())),
  1151. ceil(stringToPointSize(paperSize.value("height").toString())));
  1152. printer.setPaperSize(sizePt, QPrinter::Point);
  1153. } else if (paperSize.contains("format")) {
  1154. const QPrinter::Orientation orientation = paperSize.contains("orientation")
  1155. && paperSize.value("orientation").toString().compare("landscape", Qt::CaseInsensitive) == 0 ?
  1156. QPrinter::Landscape : QPrinter::Portrait;
  1157. printer.setOrientation(orientation);
  1158. static const struct {
  1159. QString format;
  1160. QPrinter::PaperSize paperSize;
  1161. } formats[] = {
  1162. { "A0", QPrinter::A0 },
  1163. { "A1", QPrinter::A1 },
  1164. { "A2", QPrinter::A2 },
  1165. { "A3", QPrinter::A3 },
  1166. { "A4", QPrinter::A4 },
  1167. { "A5", QPrinter::A5 },
  1168. { "A6", QPrinter::A6 },
  1169. { "A7", QPrinter::A7 },
  1170. { "A8", QPrinter::A8 },
  1171. { "A9", QPrinter::A9 },
  1172. { "B0", QPrinter::B0 },
  1173. { "B1", QPrinter::B1 },
  1174. { "B2", QPrinter::B2 },
  1175. { "B3", QPrinter::B3 },
  1176. { "B4", QPrinter::B4 },
  1177. { "B5", QPrinter::B5 },
  1178. { "B6", QPrinter::B6 },
  1179. { "B7", QPrinter::B7 },
  1180. { "B8", QPrinter::B8 },
  1181. { "B9", QPrinter::B9 },
  1182. { "B10", QPrinter::B10 },
  1183. { "C5E", QPrinter::C5E },
  1184. { "Comm10E", QPrinter::Comm10E },
  1185. { "DLE", QPrinter::DLE },
  1186. { "Executive", QPrinter::Executive },
  1187. { "Folio", QPrinter::Folio },
  1188. { "Ledger", QPrinter::Ledger },
  1189. { "Legal", QPrinter::Legal },
  1190. { "Letter", QPrinter::Letter },
  1191. { "Tabloid", QPrinter::Tabloid }
  1192. };
  1193. printer.setPaperSize(QPrinter::A4); // Fallback
  1194. for (uint i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) {
  1195. if (paperSize.value("format").toString().compare(formats[i].format, Qt::CaseInsensitive) == 0) {
  1196. printer.setPaperSize(formats[i].paperSize);
  1197. break;
  1198. }
  1199. }
  1200. } else {
  1201. return false;
  1202. }
  1203.  
  1204. if (paperSize.contains("border") && !paperSize.contains("margin")) {
  1205. // backwards compatibility
  1206. paperSize["margin"] = paperSize["border"];
  1207. }
  1208.  
  1209. qreal marginLeft = 0;
  1210. qreal marginTop = 0;
  1211. qreal marginRight = 0;
  1212. qreal marginBottom = 0;
  1213.  
  1214. if (paperSize.contains("margin")) {
  1215. const QVariant margins = paperSize["margin"];
  1216. if (margins.canConvert(QVariant::Map)) {
  1217. const QVariantMap map = margins.toMap();
  1218. marginLeft = printMargin(map, "left");
  1219. marginTop = printMargin(map, "top");
  1220. marginRight = printMargin(map, "right");
  1221. marginBottom = printMargin(map, "bottom");
  1222. } else if (margins.canConvert(QVariant::String)) {
  1223. const qreal margin = stringToPointSize(margins.toString());
  1224. marginLeft = margin;
  1225. marginTop = margin;
  1226. marginRight = margin;
  1227. marginBottom = margin;
  1228. }
  1229. }
  1230.  
  1231. printer.setPageMargins(marginLeft, marginTop, marginRight, marginBottom, QPrinter::Point);
  1232.  
  1233. m_mainFrame->print(&printer, this);
  1234. return true;
  1235. }
  1236.  
  1237. void WebPage::setZoomFactor(qreal zoom)
  1238. {
  1239. m_mainFrame->setZoomFactor(zoom);
  1240. }
  1241.  
  1242. qreal WebPage::zoomFactor() const
  1243. {
  1244. return m_mainFrame->zoomFactor();
  1245. }
  1246.  
  1247. QString WebPage::windowName() const
  1248. {
  1249. return m_mainFrame->evaluateJavaScript("window.name;").toString();
  1250. }
  1251.  
  1252. qreal getHeight(const QVariantMap& map, const QString& key)
  1253. {
  1254. QVariant footer = map.value(key);
  1255. if (!footer.canConvert(QVariant::Map)) {
  1256. return 0;
  1257. }
  1258. QVariant height = footer.toMap().value("height");
  1259. if (!height.canConvert(QVariant::String)) {
  1260. return 0;
  1261. }
  1262. return stringToPointSize(height.toString());
  1263. }
  1264.  
  1265. qreal WebPage::footerHeight() const
  1266. {
  1267. return getHeight(m_paperSize, "footer");
  1268. }
  1269.  
  1270. qreal WebPage::headerHeight() const
  1271. {
  1272. return getHeight(m_paperSize, "header");
  1273. }
  1274.  
  1275. QString getHeaderFooter(const QVariantMap& map, const QString& key, QWebFrame* frame, int page, int numPages)
  1276. {
  1277. QVariant header = map.value(key);
  1278. if (!header.canConvert(QVariant::Map)) {
  1279. return QString();
  1280. }
  1281. QVariant callback = header.toMap().value("contents");
  1282. if (callback.canConvert<QObject*>()) {
  1283. Callback* caller = qobject_cast<Callback*>(callback.value<QObject*>());
  1284. if (caller) {
  1285. QVariant ret = caller->call(QVariantList() << page << numPages);
  1286. if (ret.canConvert(QVariant::String)) {
  1287. return ret.toString();
  1288. }
  1289. }
  1290. }
  1291. frame->evaluateJavaScript("console.error('Bad header callback given, use.callback);", QString());
  1292. return QString();
  1293. }
  1294.  
  1295. QString WebPage::header(int page, int numPages)
  1296. {
  1297. return getHeaderFooter(m_paperSize, "header", m_mainFrame, page, numPages);
  1298. }
  1299.  
  1300. QString WebPage::footer(int page, int numPages)
  1301. {
  1302. return getHeaderFooter(m_paperSize, "footer", m_mainFrame, page, numPages);
  1303. }
  1304.  
  1305. void WebPage::_uploadFile(const QString& selector, const QStringList& fileNames)
  1306. {
  1307. QWebElement el = m_currentFrame->findFirstElement(selector);
  1308. if (el.isNull()) {
  1309. return;
  1310. }
  1311.  
  1312. // Filter out "fileNames" that don't actually exist
  1313. m_customWebPage->m_uploadFiles.clear();
  1314. for (int i = 0, ilen = fileNames.length(); i < ilen; ++i) {
  1315. if (QFile::exists(fileNames[i])) {
  1316. m_customWebPage->m_uploadFiles.append(fileNames[i]);
  1317. }
  1318. }
  1319.  
  1320. el.evaluateJavaScript(JS_ELEMENT_CLICK);
  1321. }
  1322.  
  1323. bool WebPage::injectJs(const QString& jsFilePath)
  1324. {
  1325. return Utils::injectJsInFrame(jsFilePath, m_libraryPath, m_currentFrame);
  1326. }
  1327.  
  1328. void WebPage::_appendScriptElement(const QString& scriptUrl)
  1329. {
  1330. m_currentFrame->evaluateJavaScript(QString(JS_APPEND_SCRIPT_ELEMENT).arg(scriptUrl), scriptUrl);
  1331. }
  1332.  
  1333. QObject* WebPage::_getGenericCallback()
  1334. {
  1335. if (!m_callbacks) {
  1336. m_callbacks = new WebpageCallbacks(this);
  1337. }
  1338.  
  1339. return m_callbacks->getGenericCallback();
  1340. }
  1341.  
  1342. QObject* WebPage::_getFilePickerCallback()
  1343. {
  1344. if (!m_callbacks) {
  1345. m_callbacks = new WebpageCallbacks(this);
  1346. }
  1347.  
  1348. return m_callbacks->getFilePickerCallback();
  1349. }
  1350.  
  1351. QObject* WebPage::_getJsConfirmCallback()
  1352. {
  1353. if (!m_callbacks) {
  1354. m_callbacks = new WebpageCallbacks(this);
  1355. }
  1356.  
  1357. return m_callbacks->getJsConfirmCallback();
  1358. }
  1359.  
  1360. QObject* WebPage::_getJsPromptCallback()
  1361. {
  1362. if (!m_callbacks) {
  1363. m_callbacks = new WebpageCallbacks(this);
  1364. }
  1365.  
  1366. return m_callbacks->getJsPromptCallback();
  1367. }
  1368.  
  1369. QObject* WebPage::_getJsInterruptCallback()
  1370. {
  1371. if (!m_callbacks) {
  1372. m_callbacks = new WebpageCallbacks(this);
  1373. }
  1374.  
  1375. return m_callbacks->getJsInterruptCallback();
  1376. }
  1377.  
  1378. void WebPage::sendEvent(const QString& type, const QVariant& arg1, const QVariant& arg2, const QString& mouseButton, const QVariant& modifierArg)
  1379. {
  1380. Qt::KeyboardModifiers keyboardModifiers(modifierArg.toInt());
  1381. // Normalize the event "type" to lowercase
  1382. const QString eventType = type.toLower();
  1383.  
  1384. // single keyboard events
  1385. if (eventType == "keydown" || eventType == "keyup") {
  1386. QKeyEvent::Type keyEventType = QEvent::None;
  1387. if (eventType == "keydown") {
  1388. keyEventType = QKeyEvent::KeyPress;
  1389. }
  1390. if (eventType == "keyup") {
  1391. keyEventType = QKeyEvent::KeyRelease;
  1392. }
  1393. Q_ASSERT(keyEventType != QEvent::None);
  1394.  
  1395. int key = 0;
  1396. QString text;
  1397. if (arg1.type() == QVariant::Char) {
  1398. // a single char was given
  1399. text = arg1.toChar();
  1400. key = text.at(0).toUpper().unicode();
  1401. } else if (arg1.type() == QVariant::String) {
  1402. // javascript invokation of a single char
  1403. text = arg1.toString();
  1404. if (!text.isEmpty()) {
  1405. key = text.at(0).toUpper().unicode();
  1406. }
  1407. } else {
  1408. // assume a raw integer char code was given
  1409. key = arg1.toInt();
  1410. }
  1411. QKeyEvent* keyEvent = new QKeyEvent(keyEventType, key, keyboardModifiers, text);
  1412. QApplication::postEvent(m_customWebPage, keyEvent);
  1413. QApplication::processEvents();
  1414. return;
  1415. }
  1416.  
  1417. // sequence of key events: will generate all the single keydown/keyup events
  1418. if (eventType == "keypress") {
  1419. if (arg1.type() == QVariant::String) {
  1420. // this is the case for e.g. sendEvent("...", 'A')
  1421. // but also works with sendEvent("...", "ABCD")
  1422. foreach(const QChar typeChar, arg1.toString()) {
  1423. sendEvent("keydown", typeChar, QVariant(), QString(), modifierArg);
  1424. sendEvent("keyup", typeChar, QVariant(), QString(), modifierArg);
  1425. }
  1426. } else {
  1427. // otherwise we assume a raw integer char-code was given
  1428. sendEvent("keydown", arg1.toInt(), QVariant(), QString(), modifierArg);
  1429. sendEvent("keyup", arg1.toInt(), QVariant(), QString(), modifierArg);
  1430. }
  1431. return;
  1432. }
  1433.  
  1434. // mouse events
  1435. if (eventType == "mousedown" ||
  1436. eventType == "mouseup" ||
  1437. eventType == "mousemove" ||
  1438. eventType == "mousedoubleclick") {
  1439. QMouseEvent::Type mouseEventType = QEvent::None;
  1440.  
  1441. // Which mouse button (if it's a click)
  1442. Qt::MouseButton button = Qt::LeftButton;
  1443. Qt::MouseButton buttons = Qt::LeftButton;
  1444. if (mouseButton.toLower() == "middle") {
  1445. button = Qt::MiddleButton;
  1446. buttons = Qt::MiddleButton;
  1447. } else if (mouseButton.toLower() == "right") {
  1448. button = Qt::RightButton;
  1449. buttons = Qt::RightButton;
  1450. }
  1451.  
  1452. // Which mouse event
  1453. if (eventType == "mousedown") {
  1454. mouseEventType = QEvent::MouseButtonPress;
  1455. } else if (eventType == "mouseup") {
  1456. mouseEventType = QEvent::MouseButtonRelease;
  1457. } else if (eventType == "mousedoubleclick") {
  1458. mouseEventType = QEvent::MouseButtonDblClick;
  1459. } else if (eventType == "mousemove") {
  1460. mouseEventType = QEvent::MouseMove;
  1461. button = Qt::NoButton;
  1462. buttons = Qt::NoButton;
  1463. }
  1464. Q_ASSERT(mouseEventType != QEvent::None);
  1465.  
  1466. // Gather coordinates
  1467. if (arg1.isValid() && arg2.isValid()) {
  1468. m_mousePos.setX(arg1.toInt());
  1469. m_mousePos.setY(arg2.toInt());
  1470. }
  1471.  
  1472. // Prepare the Mouse event
  1473. qDebug() << "Mouse Event:" << eventType << "(" << mouseEventType << ")" << m_mousePos << ")" << button << buttons;
  1474. QMouseEvent* event = new QMouseEvent(mouseEventType, m_mousePos, button, buttons, keyboardModifiers);
  1475.  
  1476. // Post and process events
  1477. QApplication::postEvent(m_customWebPage, event);
  1478. QApplication::processEvents();
  1479. return;
  1480. }
  1481.  
  1482. // mouse click events: Qt doesn't provide this as a separate events,
  1483. // so we compose it with a mousedown/mouseup sequence
  1484. // mouse doubleclick events: It is not enough to simply send a
  1485. // MouseButtonDblClick event by itself; it must be accompanied
  1486. // by a preceding press-release, and a following release.
  1487. if (type == "click" || type == "doubleclick") {
  1488. sendEvent("mousedown", arg1, arg2, mouseButton, modifierArg);
  1489. sendEvent("mouseup", arg1, arg2, mouseButton, modifierArg);
  1490. if (type == "doubleclick") {
  1491. sendEvent("mousedoubleclick", arg1, arg2, mouseButton, modifierArg);
  1492. sendEvent("mouseup", arg1, arg2, mouseButton, modifierArg);
  1493. }
  1494. return;
  1495. }
  1496. }
  1497.  
  1498. QObjectList WebPage::pages() const
  1499. {
  1500. QObjectList pages;
  1501.  
  1502. QList<WebPage*> childPages = this->findChildren<WebPage*>();
  1503. for (int i = childPages.length() - 1; i >= 0; --i) {
  1504. pages << childPages.at(i);
  1505. }
  1506.  
  1507. return pages;
  1508. }
  1509.  
  1510. QStringList WebPage::pagesWindowName() const
  1511. {
  1512. QStringList pagesWindowName;
  1513.  
  1514. foreach(const WebPage * p, this->findChildren<WebPage*>()) {
  1515. pagesWindowName << p->windowName();
  1516. }
  1517.  
  1518. return pagesWindowName;
  1519. }
  1520.  
  1521. QObject* WebPage::getPage(const QString& windowName) const
  1522. {
  1523. QList<WebPage*> childPages = this->findChildren<WebPage*>();
  1524. for (int i = childPages.length() - 1; i >= 0; --i) {
  1525. if (childPages.at(i)->windowName() == windowName) {
  1526. return childPages.at(i);
  1527. }
  1528. }
  1529. return NULL;
  1530. }
  1531.  
  1532. bool WebPage::ownsPages() const
  1533. {
  1534. return m_ownsPages;
  1535. }
  1536.  
  1537. void WebPage::setOwnsPages(const bool owns)
  1538. {
  1539. m_ownsPages = owns;
  1540. }
  1541.  
  1542. int WebPage::framesCount() const
  1543. {
  1544. return m_currentFrame->childFrames().count();
  1545. }
  1546.  
  1547. int WebPage::childFramesCount() const //< deprecated
  1548. {
  1549. return this->framesCount();
  1550. }
  1551.  
  1552. QStringList WebPage::framesName() const
  1553. {
  1554. QStringList framesName;
  1555.  
  1556. foreach(const QWebFrame * f, m_currentFrame->childFrames()) {
  1557. framesName << f->frameName();
  1558. }
  1559. return framesName;
  1560. }
  1561.  
  1562. QStringList WebPage::childFramesName() const //< deprecated
  1563. {
  1564. return this->framesName();
  1565. }
  1566.  
  1567. void WebPage::changeCurrentFrame(QWebFrame* const frame)
  1568. {
  1569. if (frame != m_currentFrame) {
  1570. qDebug() << "WebPage - changeCurrentFrame" << "from" << (m_currentFrame == NULL ? "Undefined" : m_currentFrame->frameName()) << "to" << frame->frameName();
  1571. m_currentFrame = frame;
  1572. }
  1573. }
  1574.  
  1575. bool WebPage::switchToFrame(const QString& frameName)
  1576. {
  1577. QList<QWebFrame*> childFrames = m_currentFrame->childFrames();
  1578. for (int i = childFrames.length() - 1; i >= 0; --i) {
  1579. if (childFrames.at(i)->frameName() == frameName) {
  1580. this->changeCurrentFrame(childFrames.at(i));
  1581. return true;
  1582. }
  1583. }
  1584. return false;
  1585. }
  1586.  
  1587. bool WebPage::switchToChildFrame(const QString& frameName) //< deprecated
  1588. {
  1589. return this->switchToFrame(frameName);
  1590. }
  1591.  
  1592. bool WebPage::switchToFrame(const int framePosition)
  1593. {
  1594. QList<QWebFrame*> childFrames = m_currentFrame->childFrames();
  1595. if (framePosition >= 0 && framePosition < childFrames.size()) {
  1596. this->changeCurrentFrame(childFrames.at(framePosition));
  1597. return true;
  1598. }
  1599. return false;
  1600. }
  1601.  
  1602. bool WebPage::switchToChildFrame(const int framePosition) //< deprecated
  1603. {
  1604. return this->switchToFrame(framePosition);
  1605. }
  1606.  
  1607. void WebPage::switchToMainFrame()
  1608. {
  1609. if (m_currentFrame != m_mainFrame) {
  1610. this->changeCurrentFrame(m_mainFrame);
  1611. }
  1612. }
  1613.  
  1614. bool WebPage::switchToParentFrame()
  1615. {
  1616. if (m_currentFrame->parentFrame() != NULL) {
  1617. this->changeCurrentFrame(m_currentFrame->parentFrame());
  1618. return true;
  1619. }
  1620. return false;
  1621. }
  1622.  
  1623. void WebPage::switchToFocusedFrame()
  1624. {
  1625. this->changeCurrentFrame(m_customWebPage->currentFrame());
  1626. }
  1627.  
  1628. QString WebPage::frameName() const
  1629. {
  1630. return m_currentFrame->frameName();
  1631. }
  1632.  
  1633. QString WebPage::currentFrameName() const //< deprecated
  1634. {
  1635. return this->frameName();
  1636. }
  1637.  
  1638. QString WebPage::focusedFrameName() const
  1639. {
  1640. return m_customWebPage->currentFrame()->frameName();
  1641. }
  1642.  
  1643. static void injectCallbacksObjIntoFrame(QWebFrame* frame, WebpageCallbacks* callbacksObject)
  1644. {
  1645. // Inject object only if it's not already present
  1646. if (frame->evaluateJavaScript(CALLBACKS_OBJECT_PRESENT).toBool() == false) {
  1647. // Decorate the window object in this frame (object ownership left to the creator/parent)
  1648. frame->addToJavaScriptWindowObject(CALLBACKS_OBJECT_NAME, callbacksObject, QWebFrame::QtOwnership);
  1649. frame->evaluateJavaScript(CALLBACKS_OBJECT_INJECTION);
  1650. }
  1651. }
  1652.  
  1653. void WebPage::setupFrame(QWebFrame* frame)
  1654. {
  1655. qDebug() << "WebPage - setupFrame" << (frame == NULL ? "" : frame->frameName());
  1656.  
  1657. // Inject the Callbacks object in the main frame
  1658. injectCallbacksObjIntoFrame(frame == NULL ? m_mainFrame : frame, m_callbacks);
  1659. }
  1660.  
  1661. void WebPage::updateLoadingProgress(int progress)
  1662. {
  1663. qDebug() << "WebPage - updateLoadingProgress:" << progress;
  1664. m_loadingProgress = progress;
  1665. }
  1666.  
  1667. void WebPage::handleRepaintRequested(const QRect& dirtyRect)
  1668. {
  1669. emit repaintRequested(dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height());
  1670. }
  1671.  
  1672.  
  1673. void WebPage::stopJavaScript()
  1674. {
  1675. m_shouldInterruptJs = true;
  1676. }
  1677.  
  1678. void WebPage::clearMemoryCache()
  1679. {
  1680. QWebSettings::clearMemoryCaches();
  1681. }
  1682.  
  1683. #include "webpage.moc"
Add Comment
Please, Sign In to add comment