/*
* Copyright (C) 2015-2018 Département de l'Instruction Publique (DIP-SEM)
*
* Copyright (C) 2013 Open Education Foundation
*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour
* l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of OpenBoard.
*
* OpenBoard is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License,
* with a specific linking exception for the OpenSSL project's
* "OpenSSL" library (or with modified versions of it that use the
* same license as the "OpenSSL" library).
*
* OpenBoard is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenBoard. If not, see .
*/
#include
#include
#include
#include
#include
#include "frameworks/UBPlatformUtils.h"
#include "UBWebController.h"
#include "UBOEmbedParser.h"
#include "UBTrapFlashController.h"
#include "web/browser/WBBrowserWindow.h"
#include "web/browser/WBWebView.h"
#include "web/browser/WBDownloadManager.h"
#include "web/browser/WBTabWidget.h"
#include "network/UBServerXMLHttpRequest.h"
#include "network/UBNetworkAccessManager.h"
#include "gui/UBWidgetMirror.h"
#include "gui/UBMainWindow.h"
#include "gui/UBWebToolsPalette.h"
#include "gui/UBKeyboardPalette.h"
#include "core/UBSettings.h"
#include "core/UBSetting.h"
#include "core/UBApplication.h"
#include "core/UBApplicationController.h"
#include "core/UBDisplayManager.h"
#include "board/UBBoardController.h"
#include "board/UBDrawingController.h"
#include "domain/UBGraphicsScene.h"
#include "desktop/UBCustomCaptureWindow.h"
#include "board/UBBoardPaletteManager.h"
#include "core/memcheck.h"
UBWebController::UBWebController(UBMainWindow* mainWindow)
: QObject(mainWindow->centralWidget())
, mMainWindow(mainWindow)
, mCurrentWebBrowser(0)
, mBrowserWidget(0)
, mTrapFlashController(0)
, mToolsCurrentPalette(0)
, mToolsPalettePositionned(false)
, mDownloadViewIsVisible(false)
{
connect(&mOEmbedParser, SIGNAL(oembedParsed(QVector)), this, SLOT(onOEmbedParsed(QVector)));
// TODO : Comment the next line to continue the Youtube button bugfix
initialiazemOEmbedProviders();
connect(mMainWindow->actionOpenTutorial,SIGNAL(triggered()),this, SLOT(onOpenTutorial()));
}
UBWebController::~UBWebController()
{
// NOOP
}
void UBWebController::onOpenTutorial()
{
loadUrl(QUrl(UBSettings::settings()->tutorialUrl->get().toString()));
}
void UBWebController::initialiazemOEmbedProviders()
{
mOEmbedProviders << "5min.com";
mOEmbedProviders << "amazon.com";
mOEmbedProviders << "flickr";
mOEmbedProviders << "video.google.";
mOEmbedProviders << "hulu.com";
mOEmbedProviders << "imdb.com";
mOEmbedProviders << "metacafe.com";
mOEmbedProviders << "qik.com";
mOEmbedProviders << "slideshare";
mOEmbedProviders << "5min.com";
mOEmbedProviders << "twitpic.com";
mOEmbedProviders << "viddler.com";
mOEmbedProviders << "vimeo.com";
mOEmbedProviders << "wikipedia.org";
mOEmbedProviders << "wordpress.com";
mOEmbedProviders << "youtube.com";
}
void UBWebController::webBrowserInstance()
{
QString webHomePage = UBSettings::settings()->webHomePage->get().toString();
QUrl currentUrl = WBBrowserWindow::guessUrlFromString(webHomePage);
if (UBSettings::settings()->webUseExternalBrowser->get().toBool())
{
QDesktopServices::openUrl(currentUrl);
}
else
{
if (!mCurrentWebBrowser)
{
mCurrentWebBrowser = new WBBrowserWindow(mMainWindow->centralWidget(), mMainWindow);
mMainWindow->addWebWidget(mCurrentWebBrowser);
connect(mCurrentWebBrowser, SIGNAL(activeViewChange(QWidget*)), this, SLOT(setSourceWidget(QWidget*)));
WBBrowserWindow::downloadManager()->setParent(mCurrentWebBrowser, Qt::Tool);
UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->webToolBar, mMainWindow->actionBoard, 32);
UBApplication::app()->decorateActionMenu(mMainWindow->actionMenu);
showTabAtTop(UBSettings::settings()->appToolBarPositionedAtTop->get().toBool());
adaptToolBar();
mTrapFlashController = new UBTrapFlashController(mCurrentWebBrowser);
connect(mCurrentWebBrowser, SIGNAL(activeViewPageChanged()), this, SLOT(activePageChanged()));
mCurrentWebBrowser->loadUrl(currentUrl);
mCurrentWebBrowser->tabWidget()->tabBar()->show();
mCurrentWebBrowser->tabWidget()->lineEdits()->show();
}
UBApplication::applicationController->setMirrorSourceWidget(mCurrentWebBrowser->paintWidget());
mMainWindow->switchToWebWidget();
setupPalettes();
screenLayoutChanged();
bool mirroring = UBSettings::settings()->webShowPageImmediatelyOnMirroredScreen->get().toBool();
UBApplication::mainWindow->actionWebShowHideOnDisplay->setChecked(mirroring);
mToolsCurrentPalette->show();
}
if (mDownloadViewIsVisible)
WBBrowserWindow::downloadManager()->show();
}
void UBWebController::show()
{
webBrowserInstance();
}
void UBWebController::setSourceWidget(QWidget* pWidget)
{
mBrowserWidget = pWidget;
UBApplication::applicationController->setMirrorSourceWidget(pWidget);
}
void UBWebController::trapFlash()
{
mTrapFlashController->showTrapFlash();
activePageChanged();
}
void UBWebController::activePageChanged()
{
if (mCurrentWebBrowser && mCurrentWebBrowser->currentTabWebView())
{
if (mTrapFlashController && mCurrentWebBrowser->currentTabWebView()->page())
mTrapFlashController->updateTrapFlashFromPage(mCurrentWebBrowser->currentTabWebView()->page()->currentFrame());
mMainWindow->actionWebTrap->setChecked(false);
QUrl latestUrl = mCurrentWebBrowser->currentTabWebView()->url();
// TODO : Uncomment the next line to continue the youtube button bugfix
//UBApplication::mainWindow->actionWebOEmbed->setEnabled(hasEmbeddedContent());
// And remove this line once the previous one is uncommented
UBApplication::mainWindow->actionWebOEmbed->setEnabled(isOEmbedable(latestUrl));
UBApplication::mainWindow->actionEduMedia->setEnabled(isEduMedia(latestUrl));
emit activeWebPageChanged(mCurrentWebBrowser->currentTabWebView());
}
}
bool UBWebController::hasEmbeddedContent()
{
bool bHasContent = false;
if(mCurrentWebBrowser){
QString html = mCurrentWebBrowser->currentTabWebView()->webPage()->mainFrame()->toHtml();
// search the presence of "+oembed"
QString query = "\\+oembed([^>]*)>";
QRegExp exp(query);
exp.indexIn(html);
QStringList results = exp.capturedTexts();
if(2 <= results.size() && "" != results.at(1)){
// An embedded content has been found, no need to check the other ones
bHasContent = true;
}else{
QList contentUrls;
lookForEmbedContent(&html, "embed", "src", &contentUrls);
lookForEmbedContent(&html, "video", "src", &contentUrls);
lookForEmbedContent(&html, "object", "data", &contentUrls);
// TODO: check the hidden iFrame
if(!contentUrls.empty()){
bHasContent = true;
}
}
}
return bHasContent;
}
QPixmap UBWebController::captureCurrentPage()
{
QPixmap pix;
if (mCurrentWebBrowser
&& mCurrentWebBrowser->currentTabWebView()
&& mCurrentWebBrowser->currentTabWebView()->page()
&& mCurrentWebBrowser->currentTabWebView()->page()->mainFrame())
{
QWebFrame* frame = mCurrentWebBrowser->currentTabWebView()->page()->mainFrame();
QSize size = frame->contentsSize();
qDebug() << size;
QVariant top = frame->evaluateJavaScript("document.getElementsByTagName('body')[0].clientTop");
QVariant left = frame->evaluateJavaScript("document.getElementsByTagName('body')[0].clientLeft");
QVariant width = frame->evaluateJavaScript("document.getElementsByTagName('body')[0].clientWidth");
QVariant height = frame->evaluateJavaScript("document.getElementsByTagName('body')[0].clientHeight");
QSize vieportSize = mCurrentWebBrowser->currentTabWebView()->page()->viewportSize();
mCurrentWebBrowser->currentTabWebView()->page()->setViewportSize(frame->contentsSize());
pix = QPixmap(frame->geometry().width(), frame->geometry().height());
{
QPainter p(&pix);
frame->render(&p);
}
if (left.isValid() && top.isValid() && width.isValid() && height.isValid())
{
bool okLeft, okTop, okWidth, okHeight;
int iLeft = left.toInt(&okLeft) * frame->zoomFactor();
int iTop = top.toInt(&okTop) * frame->zoomFactor();
int iWidth = width.toInt(&okWidth) * frame->zoomFactor();
int iHeight = height.toInt(&okHeight) * frame->zoomFactor();
if(okLeft && okTop && okWidth && okHeight)
{
pix = pix.copy(iLeft, iTop, iWidth, iHeight);
}
}
mCurrentWebBrowser->currentTabWebView()->page()->setViewportSize(vieportSize);
}
return pix;
}
void UBWebController::setupPalettes()
{
if(!mToolsCurrentPalette)
{
mToolsCurrentPalette = new UBWebToolsPalette(UBApplication::mainWindow);
UBApplication::boardController->paletteManager()->setCurrentWebToolsPalette(mToolsCurrentPalette);
#ifndef Q_OS_WIN
if (UBPlatformUtils::hasVirtualKeyboard() && UBApplication::boardController->paletteManager()->mKeyboardPalette)
connect(UBApplication::boardController->paletteManager()->mKeyboardPalette, SIGNAL(closed()),
UBApplication::boardController->paletteManager()->mKeyboardPalette, SLOT(onDeactivated()));
#endif
connect(mMainWindow->actionWebTrapFlash, SIGNAL(triggered()), this, SLOT(trapFlash()));
connect(mMainWindow->actionWebCustomCapture, SIGNAL(triggered()), this, SLOT(customCapture()));
connect(mMainWindow->actionWebWindowCapture, SIGNAL(triggered()), this, SLOT(captureWindow()));
connect(mMainWindow->actionWebOEmbed, SIGNAL(triggered()), this, SLOT(captureoEmbed()));
connect(mMainWindow->actionEduMedia, SIGNAL(triggered()), this, SLOT(captureEduMedia()));
connect(mMainWindow->actionWebShowHideOnDisplay, SIGNAL(toggled(bool)), this, SLOT(toogleMirroring(bool)));
connect(mMainWindow->actionWebTrap, SIGNAL(toggled(bool)), this, SLOT(toggleWebTrap(bool)));
mToolsCurrentPalette->hide();
mToolsCurrentPalette->adjustSizeAndPosition();
if (controlView()){
int left = controlView()->width() - 20 - mToolsCurrentPalette->width();
int top = (controlView()->height() - mToolsCurrentPalette->height()) / 2;
mToolsCurrentPalette->setCustomPosition(true);
mToolsCurrentPalette->move(left, top);
}
mMainWindow->actionWebTools->trigger();
}
}
void UBWebController::toggleWebTrap(bool checked)
{
if (mCurrentWebBrowser && mCurrentWebBrowser->currentTabWebView())
mCurrentWebBrowser->currentTabWebView()->setIsTrapping(checked);
}
void UBWebController::captureWindow()
{
QPixmap webPagePixmap = captureCurrentPage();
if (!webPagePixmap.isNull())
emit imageCaptured(webPagePixmap, true, mCurrentWebBrowser->currentTabWebView()->url());
}
void UBWebController::customCapture()
{
mToolsCurrentPalette->setVisible(false);
qApp->processEvents();
UBCustomCaptureWindow customCaptureWindow(mCurrentWebBrowser);
customCaptureWindow.show();
if (customCaptureWindow.execute(getScreenPixmap()) == QDialog::Accepted)
{
QPixmap selectedPixmap = customCaptureWindow.getSelectedPixmap();
emit imageCaptured(selectedPixmap, false, mCurrentWebBrowser->currentTabWebView()->url());
}
mToolsCurrentPalette->setVisible(true);
}
void UBWebController::toogleMirroring(bool checked)
{
UBApplication::applicationController->mirroringEnabled(checked);
}
QPixmap UBWebController::getScreenPixmap()
{
QDesktopWidget *desktop = QApplication::desktop();
// we capture the screen in which the mouse is.
const QRect primaryScreenRect = desktop->screenGeometry(QCursor::pos());
QCoreApplication::flush ();
return QPixmap::grabWindow(desktop->winId(),
primaryScreenRect.x(), primaryScreenRect.y(),
primaryScreenRect.width(), primaryScreenRect.height());
}
void UBWebController::screenLayoutChanged()
{
bool hasDisplay = (UBApplication::applicationController &&
UBApplication::applicationController->displayManager() &&
UBApplication::applicationController->displayManager()->hasDisplay());
UBApplication::mainWindow->actionWebShowHideOnDisplay->setVisible(hasDisplay);
}
void UBWebController::closing()
{
//NOOP
}
void UBWebController::adaptToolBar()
{
bool highResolution = mMainWindow->width() > 1024;
mMainWindow->actionWebReload->setVisible(highResolution);
mMainWindow->actionStopLoading->setVisible(highResolution);
if(mCurrentWebBrowser )
mCurrentWebBrowser->adaptToolBar(highResolution);
}
void UBWebController::showTabAtTop(bool attop)
{
if (mCurrentWebBrowser)
mCurrentWebBrowser->showTabAtTop(attop);
}
void UBWebController::captureoEmbed()
{
if ( mCurrentWebBrowser && mCurrentWebBrowser->currentTabWebView()){
// TODO : Uncomment the next lines to continue the youtube button bugfix
// getEmbeddableContent();
// And comment from here
QWebView* webView = mCurrentWebBrowser->currentTabWebView();
QUrl currentUrl = webView->url();
if (isOEmbedable(currentUrl))
{
UBGraphicsW3CWidgetItem * widget = UBApplication::boardController->activeScene()->addOEmbed(currentUrl);
if(widget)
{
UBApplication::applicationController->showBoard();
UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector);
}
}
// --> Until here
}
}
void UBWebController::lookForEmbedContent(QString* pHtml, QString tag, QString attribute, QList *pList)
{
if(NULL != pHtml && NULL != pList){
QVector urlsFound;
// Check for