1 /* 2 Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) 3 Copyright (C) 2007 Staikos Computing Services Inc. 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public License 16 along with this library; see the file COPYING.LIB. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 #include "qwebframe.h" 23 24 #if USE(JSC) 25 #include "BridgeJSC.h" 26 #include "CallFrame.h" 27 #elif USE(V8) 28 #include "V8Binding.h" 29 #endif 30 #include "Document.h" 31 #include "DocumentLoader.h" 32 #include "DragData.h" 33 #include "Element.h" 34 #include "FocusController.h" 35 #include "Frame.h" 36 #include "FrameLoaderClientQt.h" 37 #include "FrameTree.h" 38 #include "FrameView.h" 39 #if USE(JSC) 40 #include "GCController.h" 41 #elif USE(V8) 42 #include "V8GCController.h" 43 #endif 44 #include "GraphicsContext.h" 45 #include "HTMLMetaElement.h" 46 #include "HitTestResult.h" 47 #include "HTTPParsers.h" 48 #include "IconDatabase.h" 49 #include "InspectorController.h" 50 #if USE(JSC) 51 #include "JSDOMBinding.h" 52 #include "JSDOMWindowBase.h" 53 #include "JSLock.h" 54 #include "JSObject.h" 55 #elif USE(V8) 56 #include "V8DOMWrapper.h" 57 #include "V8DOMWindowShell.h" 58 #endif 59 #include "NetworkingContext.h" 60 #include "NodeList.h" 61 #include "Page.h" 62 #include "PlatformMouseEvent.h" 63 #include "PlatformWheelEvent.h" 64 #include "PrintContext.h" 65 #if USE(JSC) 66 #include "PutPropertySlot.h" 67 #endif 68 #include "RenderLayer.h" 69 #include "RenderTreeAsText.h" 70 #include "RenderView.h" 71 #include "ResourceRequest.h" 72 #include "ScriptController.h" 73 #include "ScriptSourceCode.h" 74 #include "ScriptValue.h" 75 #include "Scrollbar.h" 76 #include "Settings.h" 77 #include "SelectionController.h" 78 #include "SubstituteData.h" 79 #include "SVGSMILElement.h" 80 #include "TiledBackingStore.h" 81 #include "htmlediting.h" 82 #include "markup.h" 83 #if USE(JSC) 84 #include "qt_instance.h" 85 #include "qt_runtime.h" 86 #endif 87 #include "qwebelement.h" 88 #include "qwebframe_p.h" 89 #include "qwebpage.h" 90 #include "qwebpage_p.h" 91 #include "qwebsecurityorigin.h" 92 #include "qwebsecurityorigin_p.h" 93 #include "qwebscriptworld.h" 94 #include "qwebscriptworld_p.h" 95 #if USE(JSC) 96 #include "runtime_object.h" 97 #include "runtime_root.h" 98 #endif 99 #if USE(TEXTURE_MAPPER) 100 #include "texmap/TextureMapper.h" 101 #include "texmap/TextureMapperPlatformLayer.h" 102 #endif 103 #include "wtf/HashMap.h" 104 #include <QMultiMap> 105 #include <qdebug.h> 106 #include <qevent.h> 107 #include <qfileinfo.h> 108 #include <qpainter.h> 109 #include <qprinter.h> 110 #include <qregion.h> 111 #include <qnetworkrequest.h> 112 113 using namespace WebCore; 114 115 // from text/qfont.cpp 116 QT_BEGIN_NAMESPACE 117 extern Q_GUI_EXPORT int qt_defaultDpi(); 118 QT_END_NAMESPACE 119 120 bool QWEBKIT_EXPORT qtwebkit_webframe_scrollOverflow(QWebFrame* qFrame, int dx, int dy, const QPoint& pos) 121 { 122 WebCore::Frame* frame = QWebFramePrivate::core(qFrame); 123 if (!frame || !frame->document() || !frame->view() || !frame->eventHandler()) 124 return false; 125 126 QPoint contentsPos = frame->view()->windowToContents(pos); 127 Node* node = frame->document()->elementFromPoint(contentsPos.x(), contentsPos.y()); 128 if (!node) 129 return false; 130 131 RenderObject* renderer = node->renderer(); 132 if (!renderer) 133 return false; 134 135 if (renderer->isListBox()) 136 return false; 137 138 RenderLayer* renderLayer = renderer->enclosingLayer(); 139 if (!renderLayer) 140 return false; 141 142 bool scrolledHorizontal = false; 143 bool scrolledVertical = false; 144 145 do { 146 if (dx > 0) 147 scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); 148 else if (dx < 0) 149 scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); 150 151 if (dy > 0) 152 scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); 153 else if (dy < 0) 154 scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); 155 156 if (scrolledHorizontal || scrolledVertical) 157 return true; 158 159 renderLayer = renderLayer->parent(); 160 } while (renderLayer); 161 162 return false; 163 } 164 165 166 /*! 167 \internal 168 Scrolls nested frames starting at this frame, \a dx pixels to the right 169 and \a dy pixels downward. Both \a dx and \a dy may be negative. First attempts 170 to scroll elements with CSS overflow at position pos, followed by this frame. If this 171 frame doesn't scroll, attempts to scroll the parent 172 */ 173 void QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy, const QPoint& pos) 174 { 175 if (!qFrame) 176 return; 177 178 if (qtwebkit_webframe_scrollOverflow(qFrame, dx, dy, pos)) 179 return; 180 181 bool scrollHorizontal = false; 182 bool scrollVertical = false; 183 184 do { 185 if (dx > 0) // scroll right 186 scrollHorizontal = qFrame->scrollBarValue(Qt::Horizontal) < qFrame->scrollBarMaximum(Qt::Horizontal); 187 else if (dx < 0) // scroll left 188 scrollHorizontal = qFrame->scrollBarValue(Qt::Horizontal) > qFrame->scrollBarMinimum(Qt::Horizontal); 189 190 if (dy > 0) // scroll down 191 scrollVertical = qFrame->scrollBarValue(Qt::Vertical) < qFrame->scrollBarMaximum(Qt::Vertical); 192 else if (dy < 0) //scroll up 193 scrollVertical = qFrame->scrollBarValue(Qt::Vertical) > qFrame->scrollBarMinimum(Qt::Vertical); 194 195 if (scrollHorizontal || scrollVertical) { 196 qFrame->scroll(dx, dy); 197 return; 198 } 199 200 qFrame = qFrame->parentFrame(); 201 } while (qFrame); 202 } 203 204 static inline ResourceRequestCachePolicy cacheLoadControlToCachePolicy(uint cacheLoadControl) 205 { 206 switch (cacheLoadControl) { 207 case QNetworkRequest::AlwaysNetwork: 208 return WebCore::ReloadIgnoringCacheData; 209 case QNetworkRequest::PreferCache: 210 return WebCore::ReturnCacheDataElseLoad; 211 case QNetworkRequest::AlwaysCache: 212 return WebCore::ReturnCacheDataDontLoad; 213 default: 214 break; 215 } 216 return WebCore::UseProtocolCachePolicy; 217 } 218 219 QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame, 220 WebCore::HTMLFrameOwnerElement* ownerFrameElement, 221 const WTF::String& frameName) 222 : name(frameName) 223 , ownerElement(ownerFrameElement) 224 , page(parentPage) 225 , allowsScrolling(true) 226 , marginWidth(0) 227 , marginHeight(0) 228 { 229 frameLoaderClient = new FrameLoaderClientQt(); 230 frame = Frame::create(page, ownerElement, frameLoaderClient); 231 232 // FIXME: All of the below should probably be moved over into WebCore 233 frame->tree()->setName(name); 234 if (parentFrame) 235 parentFrame->tree()->appendChild(frame); 236 } 237 238 void QWebFramePrivate::init(QWebFrame *qframe, QWebFrameData *frameData) 239 { 240 q = qframe; 241 242 allowsScrolling = frameData->allowsScrolling; 243 marginWidth = frameData->marginWidth; 244 marginHeight = frameData->marginHeight; 245 frame = frameData->frame.get(); 246 frameLoaderClient = frameData->frameLoaderClient; 247 frameLoaderClient->setFrame(qframe, frame); 248 249 frame->init(); 250 } 251 252 void QWebFramePrivate::setPage(QWebPage* newPage) 253 { 254 if (page == newPage) 255 return; 256 257 // The QWebFrame is created as a child of QWebPage or a parent QWebFrame. 258 // That adds it to QObject's internal children list and ensures it will be 259 // deleted when parent QWebPage is deleted. Reparent if needed. 260 if (q->parent() == qobject_cast<QObject*>(page)) 261 q->setParent(newPage); 262 263 page = newPage; 264 emit q->pageChanged(); 265 } 266 267 WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const 268 { 269 if (!frame->view()) 270 return 0; 271 return frame->view()->horizontalScrollbar(); 272 } 273 274 WebCore::Scrollbar* QWebFramePrivate::verticalScrollBar() const 275 { 276 if (!frame->view()) 277 return 0; 278 return frame->view()->verticalScrollbar(); 279 } 280 281 #if ENABLE(TILED_BACKING_STORE) 282 void QWebFramePrivate::renderFromTiledBackingStore(GraphicsContext* context, const QRegion& clip) 283 { 284 ASSERT(frame->tiledBackingStore()); 285 286 if (!frame->view() || !frame->contentRenderer()) 287 return; 288 289 QVector<QRect> vector = clip.rects(); 290 if (vector.isEmpty()) 291 return; 292 293 QPainter* painter = context->platformContext(); 294 295 WebCore::FrameView* view = frame->view(); 296 297 int scrollX = view->scrollX(); 298 int scrollY = view->scrollY(); 299 context->translate(-scrollX, -scrollY); 300 301 for (int i = 0; i < vector.size(); ++i) { 302 const QRect& clipRect = vector.at(i); 303 304 painter->save(); 305 306 QRect rect = clipRect.translated(scrollX, scrollY); 307 painter->setClipRect(rect, Qt::IntersectClip); 308 309 frame->tiledBackingStore()->paint(context, rect); 310 311 painter->restore(); 312 } 313 314 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) 315 renderCompositedLayers(context, IntRect(clip.boundingRect())); 316 renderFrameExtras(context, QFlags<QWebFrame::RenderLayer>(QWebFrame::ScrollBarLayer) | QWebFrame::PanIconLayer, clip); 317 #endif 318 } 319 #endif 320 321 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) 322 void QWebFramePrivate::renderCompositedLayers(GraphicsContext* context, const IntRect& clip) 323 { 324 if (!rootGraphicsLayer) 325 return; 326 327 textureMapper->setGraphicsContext(context); 328 textureMapper->setImageInterpolationQuality(context->imageInterpolationQuality()); 329 textureMapper->setTextDrawingMode(context->textDrawingMode()); 330 QPainter* painter = context->platformContext(); 331 FrameView* view = frame->view(); 332 painter->save(); 333 painter->beginNativePainting(); 334 TextureMapperContentLayer::PaintOptions options; 335 options.visibleRect = clip; 336 options.targetRect = view->frameRect(); 337 options.viewportSize = view->size(); 338 options.opacity = painter->opacity(); 339 rootGraphicsLayer->paint(textureMapper.get(), options); 340 painter->endNativePainting(); 341 painter->restore(); 342 } 343 #endif 344 345 void QWebFramePrivate::renderRelativeCoords(GraphicsContext* context, QFlags<QWebFrame::RenderLayer> layers, const QRegion& clip) 346 { 347 if (!frame->view() || !frame->contentRenderer()) 348 return; 349 350 QVector<QRect> vector = clip.rects(); 351 if (vector.isEmpty()) 352 return; 353 354 QPainter* painter = context->platformContext(); 355 356 WebCore::FrameView* view = frame->view(); 357 view->updateLayoutAndStyleIfNeededRecursive(); 358 359 if (layers & QWebFrame::ContentsLayer) { 360 for (int i = 0; i < vector.size(); ++i) { 361 const QRect& clipRect = vector.at(i); 362 363 QRect rect = clipRect.intersected(view->frameRect()); 364 365 context->save(); 366 painter->setClipRect(clipRect, Qt::IntersectClip); 367 368 int x = view->x(); 369 int y = view->y(); 370 371 int scrollX = view->scrollX(); 372 int scrollY = view->scrollY(); 373 374 context->translate(x, y); 375 rect.translate(-x, -y); 376 context->translate(-scrollX, -scrollY); 377 rect.translate(scrollX, scrollY); 378 context->clip(view->visibleContentRect()); 379 380 view->paintContents(context, rect); 381 382 context->restore(); 383 } 384 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) 385 renderCompositedLayers(context, IntRect(clip.boundingRect())); 386 #endif 387 } 388 renderFrameExtras(context, layers, clip); 389 #if ENABLE(INSPECTOR) 390 if (frame->page()->inspectorController()->highlightedNode()) { 391 context->save(); 392 frame->page()->inspectorController()->drawNodeHighlight(*context); 393 context->restore(); 394 } 395 #endif 396 } 397 398 void QWebFramePrivate::renderFrameExtras(GraphicsContext* context, QFlags<QWebFrame::RenderLayer> layers, const QRegion& clip) 399 { 400 if (!(layers & (QWebFrame::PanIconLayer | QWebFrame::ScrollBarLayer))) 401 return; 402 QPainter* painter = context->platformContext(); 403 WebCore::FrameView* view = frame->view(); 404 QVector<QRect> vector = clip.rects(); 405 for (int i = 0; i < vector.size(); ++i) { 406 const QRect& clipRect = vector.at(i); 407 408 QRect intersectedRect = clipRect.intersected(view->frameRect()); 409 410 painter->save(); 411 painter->setClipRect(clipRect, Qt::IntersectClip); 412 413 int x = view->x(); 414 int y = view->y(); 415 416 if (layers & QWebFrame::ScrollBarLayer 417 && !view->scrollbarsSuppressed() 418 && (view->horizontalScrollbar() || view->verticalScrollbar())) { 419 420 QRect rect = intersectedRect; 421 context->translate(x, y); 422 rect.translate(-x, -y); 423 view->paintScrollbars(context, rect); 424 context->translate(-x, -y); 425 } 426 427 #if ENABLE(PAN_SCROLLING) 428 if (layers & QWebFrame::PanIconLayer) 429 view->paintPanScrollIcon(context); 430 #endif 431 432 painter->restore(); 433 } 434 } 435 436 void QWebFramePrivate::emitUrlChanged() 437 { 438 url = frame->document()->url(); 439 emit q->urlChanged(url); 440 } 441 442 void QWebFramePrivate::_q_orientationChanged() 443 { 444 #if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) 445 int orientation; 446 WebCore::Frame* frame = core(q); 447 448 switch (m_orientation.reading()->orientation()) { 449 case QtMobility::QOrientationReading::TopUp: 450 orientation = 0; 451 break; 452 case QtMobility::QOrientationReading::TopDown: 453 orientation = 180; 454 break; 455 case QtMobility::QOrientationReading::LeftUp: 456 orientation = -90; 457 break; 458 case QtMobility::QOrientationReading::RightUp: 459 orientation = 90; 460 break; 461 case QtMobility::QOrientationReading::FaceUp: 462 case QtMobility::QOrientationReading::FaceDown: 463 // WebCore unable to handle it 464 default: 465 return; 466 } 467 frame->sendOrientationChangeEvent(orientation); 468 #endif 469 } 470 /*! 471 \class QWebFrame 472 \since 4.4 473 \brief The QWebFrame class represents a frame in a web page. 474 475 \inmodule QtWebKit 476 477 QWebFrame represents a frame inside a web page. Each QWebPage 478 object contains at least one frame, the main frame, obtained using 479 QWebPage::mainFrame(). Additional frames will be created for HTML 480 \c{<frame>} or \c{<iframe>} elements. 481 482 A frame can be loaded using load() or setUrl(). Alternatively, if you have 483 the HTML content readily available, you can use setHtml() instead. 484 485 The page() function returns a pointer to the web page object. See 486 \l{QWebView}{Elements of QWebView} for an explanation of how web 487 frames are related to a web page and web view. 488 489 The QWebFrame class also offers methods to retrieve both the URL currently 490 loaded by the frame (see url()) as well as the URL originally requested 491 to be loaded (see requestedUrl()). These methods make possible the retrieval 492 of the URL before and after a DNS resolution or a redirection occurs during 493 the load process. The requestedUrl() also matches to the URL added to the 494 frame history (\l{QWebHistory}) if load is successful. 495 496 The title of an HTML frame can be accessed with the title() property. 497 Additionally, a frame may also specify an icon, which can be accessed 498 using the icon() property. If the title or the icon changes, the 499 corresponding titleChanged() and iconChanged() signals will be emitted. 500 The zoomFactor() property can be used to change the overall size 501 of the content displayed in the frame. 502 503 QWebFrame objects are created and controlled by the web page. You 504 can connect to the web page's \l{QWebPage::}{frameCreated()} signal 505 to be notified when a new frame is created. 506 507 There are multiple ways to programmatically examine the contents of a frame. 508 The hitTestContent() function can be used to find elements by coordinate. 509 For access to the underlying DOM tree, there is documentElement(), 510 findAllElements() and findFirstElement(). 511 512 A QWebFrame can be printed onto a QPrinter using the print() function. 513 This function is marked as a slot and can be conveniently connected to 514 \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()} 515 signal. 516 517 \sa QWebPage 518 */ 519 520 /*! 521 \enum QWebFrame::RenderLayer 522 523 This enum describes the layers available for rendering using \l{QWebFrame::}{render()}. 524 The layers can be OR-ed together from the following list: 525 526 \value ContentsLayer The web content of the frame 527 \value ScrollBarLayer The scrollbars of the frame 528 \value PanIconLayer The icon used when panning the frame 529 530 \value AllLayers Includes all the above layers 531 */ 532 533 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) 534 : QObject(parent) 535 , d(new QWebFramePrivate) 536 { 537 d->page = parent; 538 d->init(this, frameData); 539 540 if (!frameData->url.isEmpty()) { 541 WebCore::ResourceRequest request(frameData->url, frameData->referrer); 542 d->frame->loader()->load(request, frameData->name, false); 543 } 544 #if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) 545 connect(&d->m_orientation, SIGNAL(readingChanged()), this, SLOT(_q_orientationChanged())); 546 d->m_orientation.start(); 547 #endif 548 } 549 550 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) 551 : QObject(parent) 552 , d(new QWebFramePrivate) 553 { 554 d->page = parent->d->page; 555 d->init(this, frameData); 556 #if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION) 557 connect(&d->m_orientation, SIGNAL(readingChanged()), this, SLOT(_q_orientationChanged())); 558 d->m_orientation.start(); 559 #endif 560 } 561 562 QWebFrame::~QWebFrame() 563 { 564 if (d->frame && d->frame->loader() && d->frame->loader()->client()) 565 static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0; 566 567 delete d; 568 } 569 570 /*! 571 Make \a object available under \a name from within the frame's JavaScript 572 context. The \a object will be inserted as a child of the frame's window 573 object. 574 575 Qt properties will be exposed as JavaScript properties and slots as 576 JavaScript methods. 577 The interaction between C++ and JavaScript is explained in the documentation of the \l{The QtWebKit Bridge}{QtWebKit bridge}. 578 579 If you want to ensure that your QObjects remain accessible after loading a 580 new URL, you should add them in a slot connected to the 581 javaScriptWindowObjectCleared() signal. 582 583 If Javascript is not enabled for this page, then this method does nothing. 584 585 The \a object will never be explicitly deleted by QtWebKit. 586 */ 587 void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object) 588 { 589 addToJavaScriptWindowObject(name, object, QScriptEngine::QtOwnership); 590 } 591 592 /*! 593 \fn void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership own) 594 \overload 595 596 Make \a object available under \a name from within the frame's JavaScript 597 context. The \a object will be inserted as a child of the frame's window 598 object. 599 600 Qt properties will be exposed as JavaScript properties and slots as 601 JavaScript methods. 602 The interaction between C++ and JavaScript is explained in the documentation of the \l{The QtWebKit Bridge}{QtWebKit bridge}. 603 604 If you want to ensure that your QObjects remain accessible after loading a 605 new URL, you should add them in a slot connected to the 606 javaScriptWindowObjectCleared() signal. 607 608 If Javascript is not enabled for this page, then this method does nothing. 609 610 The ownership of \a object is specified using \a own. 611 */ 612 void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership) 613 { 614 if (!page()->settings()->testAttribute(QWebSettings::JavascriptEnabled)) 615 return; 616 #if USE(JSC) 617 JSC::JSLock lock(JSC::SilenceAssertionsOnly); 618 JSDOMWindow* window = toJSDOMWindow(d->frame, mainThreadNormalWorld()); 619 JSC::Bindings::RootObject* root; 620 if (ownership == QScriptEngine::QtOwnership) 621 root = d->frame->script()->cacheableBindingRootObject(); 622 else 623 root = d->frame->script()->bindingRootObject(); 624 625 if (!window) { 626 qDebug() << "Warning: couldn't get window object"; 627 return; 628 } 629 if (!root) { 630 qDebug() << "Warning: couldn't get root object"; 631 return; 632 } 633 634 JSC::ExecState* exec = window->globalExec(); 635 636 JSC::JSObject* runtimeObject = 637 JSC::Bindings::QtInstance::getQtInstance(object, root, ownership)->createRuntimeObject(exec); 638 639 JSC::PutPropertySlot slot; 640 window->put(exec, JSC::Identifier(exec, reinterpret_cast_ptr<const UChar*>(name.constData()), name.length()), runtimeObject, slot); 641 #elif USE(V8) 642 QScriptEngine* engine = d->frame->script()->qtScriptEngine(); 643 if (!engine) 644 return; 645 QScriptValue v = engine->newQObject(object, ownership); 646 engine->globalObject().property("window").setProperty(name, v); 647 #endif 648 } 649 650 /*! 651 Returns the frame's content as HTML, enclosed in HTML and BODY tags. 652 653 \sa setHtml(), toPlainText() 654 */ 655 QString QWebFrame::toHtml() const 656 { 657 if (!d->frame->document()) 658 return QString(); 659 return createMarkup(d->frame->document()); 660 } 661 662 /*! 663 Returns the content of this frame converted to plain text, completely 664 stripped of all HTML formatting. 665 666 \sa toHtml() 667 */ 668 QString QWebFrame::toPlainText() const 669 { 670 if (d->frame->view() && d->frame->view()->layoutPending()) 671 d->frame->view()->layout(); 672 673 Element *documentElement = d->frame->document()->documentElement(); 674 if (documentElement) 675 return documentElement->innerText(); 676 return QString(); 677 } 678 679 /*! 680 Returns a dump of the rendering tree. This is mainly useful for debugging 681 html. 682 */ 683 QString QWebFrame::renderTreeDump() const 684 { 685 if (d->frame->view() && d->frame->view()->layoutPending()) 686 d->frame->view()->layout(); 687 688 return externalRepresentation(d->frame); 689 } 690 691 /*! 692 \property QWebFrame::title 693 \brief the title of the frame as defined by the HTML <title> element 694 695 \sa titleChanged() 696 */ 697 698 QString QWebFrame::title() const 699 { 700 if (d->frame->document()) 701 return d->frame->loader()->documentLoader()->title().string(); 702 return QString(); 703 } 704 705 /*! 706 \since 4.5 707 \brief Returns the meta data in this frame as a QMultiMap 708 709 The meta data consists of the name and content attributes of the 710 of the \c{<meta>} tags in the HTML document. 711 712 For example: 713 714 \code 715 <html> 716 <head> 717 <meta name="description" content="This document is a tutorial about Qt development"> 718 <meta name="keywords" content="Qt, WebKit, Programming"> 719 </head> 720 ... 721 </html> 722 \endcode 723 724 Given the above HTML code the metaData() function will return a map with two entries: 725 \table 726 \header \o Key 727 \o Value 728 \row \o "description" 729 \o "This document is a tutorial about Qt development" 730 \row \o "keywords" 731 \o "Qt, WebKit, Programming" 732 \endtable 733 734 This function returns a multi map to support multiple meta tags with the same attribute name. 735 */ 736 QMultiMap<QString, QString> QWebFrame::metaData() const 737 { 738 if (!d->frame->document()) 739 return QMap<QString, QString>(); 740 741 QMultiMap<QString, QString> map; 742 Document* doc = d->frame->document(); 743 RefPtr<NodeList> list = doc->getElementsByTagName("meta"); 744 unsigned len = list->length(); 745 for (unsigned i = 0; i < len; i++) { 746 HTMLMetaElement* meta = static_cast<HTMLMetaElement*>(list->item(i)); 747 map.insert(meta->name(), meta->content()); 748 } 749 return map; 750 } 751 752 static inline void clearCoreFrame(WebCore::Frame* frame) 753 { 754 frame->loader()->activeDocumentLoader()->writer()->begin(); 755 frame->loader()->activeDocumentLoader()->writer()->end(); 756 } 757 758 static inline bool isCoreFrameClear(WebCore::Frame* frame) 759 { 760 return frame->document()->url().isEmpty(); 761 } 762 763 static inline QUrl ensureAbsoluteUrl(const QUrl &url) 764 { 765 if (!url.isValid() || !url.isRelative()) 766 return url; 767 768 // This contains the URL with absolute path but without 769 // the query and the fragment part. 770 QUrl baseUrl = QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath()); 771 772 // The path is removed so the query and the fragment parts are there. 773 QString pathRemoved = url.toString(QUrl::RemovePath); 774 QUrl toResolve(pathRemoved); 775 776 return baseUrl.resolved(toResolve); 777 } 778 779 /*! 780 \property QWebFrame::url 781 \brief the url of the frame currently viewed 782 783 Setting this property clears the view and loads the URL. 784 785 By default, this property contains an empty, invalid URL. 786 787 \sa urlChanged() 788 */ 789 790 void QWebFrame::setUrl(const QUrl &url) 791 { 792 clearCoreFrame(d->frame); 793 const QUrl absolute = ensureAbsoluteUrl(url); 794 d->url = absolute; 795 load(absolute); 796 } 797 798 QUrl QWebFrame::url() const 799 { 800 return d->url; 801 } 802 803 /*! 804 \since 4.6 805 \property QWebFrame::requestedUrl 806 807 The URL requested to loaded by the frame currently viewed. The URL may differ from 808 the one returned by url() if a DNS resolution or a redirection occurs. 809 810 \sa url(), setUrl() 811 */ 812 QUrl QWebFrame::requestedUrl() const 813 { 814 return d->frameLoaderClient->lastRequestedUrl(); 815 } 816 /*! 817 \since 4.6 818 \property QWebFrame::baseUrl 819 \brief the base URL of the frame, can be used to resolve relative URLs 820 \since 4.6 821 */ 822 823 QUrl QWebFrame::baseUrl() const 824 { 825 if (isCoreFrameClear(d->frame)) 826 return QUrl(d->url).resolved(QUrl()); 827 return d->frame->document()->baseURL(); 828 } 829 830 /*! 831 \property QWebFrame::icon 832 \brief the icon associated with this frame 833 834 \sa iconChanged(), QWebSettings::iconForUrl() 835 */ 836 837 QIcon QWebFrame::icon() const 838 { 839 return QWebSettings::iconForUrl(d->frame->document()->url()); 840 } 841 842 /*! 843 The name of this frame as defined by the parent frame. 844 */ 845 QString QWebFrame::frameName() const 846 { 847 return d->frame->tree()->uniqueName(); 848 } 849 850 /*! 851 The web page that contains this frame. 852 853 \sa pageChanged() 854 */ 855 QWebPage *QWebFrame::page() const 856 { 857 return d->page; 858 } 859 860 /*! 861 Loads \a url into this frame. 862 863 \note The view remains the same until enough data has arrived to display the new \a url. 864 865 \sa setUrl(), setHtml(), setContent() 866 */ 867 void QWebFrame::load(const QUrl &url) 868 { 869 // The load() overload ensures that the url is absolute. 870 load(QNetworkRequest(url)); 871 } 872 873 /*! 874 Loads a network request, \a req, into this frame, using the method specified in \a 875 operation. 876 877 \a body is optional and is only used for POST operations. 878 879 \note The view remains the same until enough data has arrived to display the new content. 880 881 \sa setUrl() 882 */ 883 void QWebFrame::load(const QNetworkRequest &req, 884 QNetworkAccessManager::Operation operation, 885 const QByteArray &body) 886 { 887 if (d->parentFrame()) 888 d->page->d->insideOpenCall = true; 889 890 QUrl url = ensureAbsoluteUrl(req.url()); 891 892 WebCore::ResourceRequest request(url); 893 894 switch (operation) { 895 case QNetworkAccessManager::HeadOperation: 896 request.setHTTPMethod("HEAD"); 897 break; 898 case QNetworkAccessManager::GetOperation: 899 request.setHTTPMethod("GET"); 900 break; 901 case QNetworkAccessManager::PutOperation: 902 request.setHTTPMethod("PUT"); 903 break; 904 case QNetworkAccessManager::PostOperation: 905 request.setHTTPMethod("POST"); 906 break; 907 case QNetworkAccessManager::DeleteOperation: 908 request.setHTTPMethod("DELETE"); 909 break; 910 case QNetworkAccessManager::CustomOperation: 911 request.setHTTPMethod(req.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray().constData()); 912 break; 913 case QNetworkAccessManager::UnknownOperation: 914 // eh? 915 break; 916 } 917 918 QVariant cacheLoad = req.attribute(QNetworkRequest::CacheLoadControlAttribute); 919 if (cacheLoad.isValid()) { 920 bool ok; 921 uint cacheLoadValue = cacheLoad.toUInt(&ok); 922 if (ok) 923 request.setCachePolicy(cacheLoadControlToCachePolicy(cacheLoadValue)); 924 } 925 926 QList<QByteArray> httpHeaders = req.rawHeaderList(); 927 for (int i = 0; i < httpHeaders.size(); ++i) { 928 const QByteArray &headerName = httpHeaders.at(i); 929 request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName))); 930 } 931 932 if (!body.isEmpty()) 933 request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size())); 934 935 d->frame->loader()->load(request, false); 936 937 if (d->parentFrame()) 938 d->page->d->insideOpenCall = false; 939 } 940 941 /*! 942 Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative 943 URLs in the document, such as referenced images or stylesheets. 944 945 The \a html is loaded immediately; external objects are loaded asynchronously. 946 947 If a script in the \a html runs longer than the default script timeout (currently 10 seconds), 948 for example due to being blocked by a modal JavaScript alert dialog, this method will return 949 as soon as possible after the timeout and any subsequent \a html will be loaded asynchronously. 950 951 When using this method WebKit assumes that external resources such as JavaScript programs or style 952 sheets are encoded in UTF-8 unless otherwise specified. For example, the encoding of an external 953 script can be specified through the charset attribute of the HTML script tag. It is also possible 954 for the encoding to be specified by web server. 955 956 This is a convenience function equivalent to setContent(html, "text/html", baseUrl). 957 958 \note This method will not affect session or global history for the frame. 959 960 \warning This function works only for HTML, for other mime types (i.e. XHTML, SVG) 961 setContent() should be used instead. 962 963 \sa toHtml(), setContent(), load() 964 */ 965 void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl) 966 { 967 KURL kurl(baseUrl); 968 WebCore::ResourceRequest request(kurl); 969 const QByteArray utf8 = html.toUtf8(); 970 WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); 971 WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), KURL()); 972 d->frame->loader()->load(request, substituteData, false); 973 } 974 975 /*! 976 Sets the content of this frame to the specified content \a data. If the \a mimeType argument 977 is empty it is currently assumed that the content is HTML but in future versions we may introduce 978 auto-detection. 979 980 External objects referenced in the content are located relative to \a baseUrl. 981 982 The \a data is loaded immediately; external objects are loaded asynchronously. 983 984 \note This method will not affect session or global history for the frame. 985 986 \sa toHtml(), setHtml() 987 */ 988 void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) 989 { 990 KURL kurl(baseUrl); 991 WebCore::ResourceRequest request(kurl); 992 WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length()); 993 QString actualMimeType; 994 WTF::String encoding; 995 if (mimeType.isEmpty()) 996 actualMimeType = QLatin1String("text/html"); 997 else { 998 actualMimeType = extractMIMETypeFromMediaType(mimeType); 999 encoding = extractCharsetFromMediaType(mimeType); 1000 } 1001 WebCore::SubstituteData substituteData(buffer, WTF::String(actualMimeType), encoding, KURL()); 1002 d->frame->loader()->load(request, substituteData, false); 1003 } 1004 1005 /*! 1006 Returns the parent frame of this frame, or 0 if the frame is the web pages 1007 main frame. 1008 1009 This is equivalent to qobject_cast<QWebFrame*>(frame->parent()). 1010 1011 \sa childFrames() 1012 */ 1013 QWebFrame *QWebFrame::parentFrame() const 1014 { 1015 return d->parentFrame(); 1016 } 1017 1018 /*! 1019 Returns a list of all frames that are direct children of this frame. 1020 1021 \sa parentFrame() 1022 */ 1023 QList<QWebFrame*> QWebFrame::childFrames() const 1024 { 1025 QList<QWebFrame*> rc; 1026 if (d->frame) { 1027 FrameTree *tree = d->frame->tree(); 1028 for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) { 1029 FrameLoader *loader = child->loader(); 1030 QWebFrame* webFrame = qobject_cast<QWebFrame*>(loader->networkingContext()->originatingObject()); 1031 if (webFrame) 1032 rc.append(webFrame); 1033 } 1034 1035 } 1036 return rc; 1037 } 1038 1039 /*! 1040 Returns the scrollbar policy for the scrollbar defined by \a orientation. 1041 */ 1042 Qt::ScrollBarPolicy QWebFrame::scrollBarPolicy(Qt::Orientation orientation) const 1043 { 1044 if (orientation == Qt::Horizontal) 1045 return d->horizontalScrollBarPolicy; 1046 return d->verticalScrollBarPolicy; 1047 } 1048 1049 /*! 1050 Sets the scrollbar policy for the scrollbar defined by \a orientation to \a policy. 1051 */ 1052 void QWebFrame::setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy) 1053 { 1054 Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded); 1055 Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff); 1056 Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn); 1057 1058 if (orientation == Qt::Horizontal) { 1059 d->horizontalScrollBarPolicy = policy; 1060 if (d->frame->view()) { 1061 d->frame->view()->setHorizontalScrollbarMode((ScrollbarMode)policy, policy != Qt::ScrollBarAsNeeded /* lock */); 1062 d->frame->view()->updateCanHaveScrollbars(); 1063 } 1064 } else { 1065 d->verticalScrollBarPolicy = policy; 1066 if (d->frame->view()) { 1067 d->frame->view()->setVerticalScrollbarMode((ScrollbarMode)policy, policy != Qt::ScrollBarAsNeeded /* lock */); 1068 d->frame->view()->updateCanHaveScrollbars(); 1069 } 1070 } 1071 } 1072 1073 /*! 1074 Sets the current \a value for the scrollbar with orientation \a orientation. 1075 1076 The scrollbar forces the \a value to be within the legal range: minimum <= value <= maximum. 1077 1078 Changing the value also updates the thumb position. 1079 1080 \sa scrollBarMinimum(), scrollBarMaximum() 1081 */ 1082 void QWebFrame::setScrollBarValue(Qt::Orientation orientation, int value) 1083 { 1084 Scrollbar *sb; 1085 sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); 1086 if (sb) { 1087 if (value < 0) 1088 value = 0; 1089 else if (value > scrollBarMaximum(orientation)) 1090 value = scrollBarMaximum(orientation); 1091 sb->scrollableArea()->scrollToOffsetWithoutAnimation(orientation == Qt::Horizontal ? HorizontalScrollbar : VerticalScrollbar, value); 1092 } 1093 } 1094 1095 /*! 1096 Returns the current value for the scrollbar with orientation \a orientation, or 0 1097 if no scrollbar is found for \a orientation. 1098 1099 \sa scrollBarMinimum(), scrollBarMaximum() 1100 */ 1101 int QWebFrame::scrollBarValue(Qt::Orientation orientation) const 1102 { 1103 Scrollbar *sb; 1104 sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); 1105 if (sb) 1106 return sb->value(); 1107 return 0; 1108 } 1109 1110 /*! 1111 Returns the maximum value for the scrollbar with orientation \a orientation, or 0 1112 if no scrollbar is found for \a orientation. 1113 1114 \sa scrollBarMinimum() 1115 */ 1116 int QWebFrame::scrollBarMaximum(Qt::Orientation orientation) const 1117 { 1118 Scrollbar *sb; 1119 sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); 1120 if (sb) 1121 return sb->maximum(); 1122 return 0; 1123 } 1124 1125 /*! 1126 Returns the minimum value for the scrollbar with orientation \a orientation. 1127 1128 The minimum value is always 0. 1129 1130 \sa scrollBarMaximum() 1131 */ 1132 int QWebFrame::scrollBarMinimum(Qt::Orientation orientation) const 1133 { 1134 Q_UNUSED(orientation) 1135 return 0; 1136 } 1137 1138 /*! 1139 \since 4.6 1140 Returns the geometry for the scrollbar with orientation \a orientation. 1141 1142 If the scrollbar does not exist an empty rect is returned. 1143 */ 1144 QRect QWebFrame::scrollBarGeometry(Qt::Orientation orientation) const 1145 { 1146 Scrollbar *sb; 1147 sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar(); 1148 if (sb) 1149 return sb->frameRect(); 1150 return QRect(); 1151 } 1152 1153 /*! 1154 \since 4.5 1155 Scrolls the frame \a dx pixels to the right and \a dy pixels downward. Both 1156 \a dx and \a dy may be negative. 1157 1158 \sa QWebFrame::scrollPosition 1159 */ 1160 1161 void QWebFrame::scroll(int dx, int dy) 1162 { 1163 if (!d->frame->view()) 1164 return; 1165 1166 d->frame->view()->scrollBy(IntSize(dx, dy)); 1167 } 1168 1169 /*! 1170 \property QWebFrame::scrollPosition 1171 \since 4.5 1172 \brief the position the frame is currently scrolled to. 1173 */ 1174 1175 QPoint QWebFrame::scrollPosition() const 1176 { 1177 if (!d->frame->view()) 1178 return QPoint(0, 0); 1179 1180 IntSize ofs = d->frame->view()->scrollOffset(); 1181 return QPoint(ofs.width(), ofs.height()); 1182 } 1183 1184 void QWebFrame::setScrollPosition(const QPoint &pos) 1185 { 1186 QPoint current = scrollPosition(); 1187 int dx = pos.x() - current.x(); 1188 int dy = pos.y() - current.y(); 1189 scroll(dx, dy); 1190 } 1191 1192 /*! 1193 \since 4.7 1194 Scrolls the frame to the given \a anchor name. 1195 */ 1196 void QWebFrame::scrollToAnchor(const QString& anchor) 1197 { 1198 FrameView *view = d->frame->view(); 1199 if (view) 1200 view->scrollToAnchor(anchor); 1201 } 1202 1203 /*! 1204 \since 4.6 1205 Render the \a layer of the frame using \a painter clipping to \a clip. 1206 1207 \sa print() 1208 */ 1209 1210 void QWebFrame::render(QPainter* painter, RenderLayer layer, const QRegion& clip) 1211 { 1212 GraphicsContext context(painter); 1213 if (context.paintingDisabled() && !context.updatingControlTints()) 1214 return; 1215 1216 if (!clip.isEmpty()) 1217 d->renderRelativeCoords(&context, layer, clip); 1218 else if (d->frame->view()) 1219 d->renderRelativeCoords(&context, layer, QRegion(d->frame->view()->frameRect())); 1220 } 1221 1222 /*! 1223 Render the frame into \a painter clipping to \a clip. 1224 */ 1225 void QWebFrame::render(QPainter* painter, const QRegion& clip) 1226 { 1227 GraphicsContext context(painter); 1228 if (context.paintingDisabled() && !context.updatingControlTints()) 1229 return; 1230 1231 d->renderRelativeCoords(&context, AllLayers, clip); 1232 } 1233 1234 /*! 1235 Render the frame into \a painter. 1236 */ 1237 void QWebFrame::render(QPainter* painter) 1238 { 1239 if (!d->frame->view()) 1240 return; 1241 1242 GraphicsContext context(painter); 1243 if (context.paintingDisabled() && !context.updatingControlTints()) 1244 return; 1245 1246 d->renderRelativeCoords(&context, AllLayers, QRegion(d->frame->view()->frameRect())); 1247 } 1248 1249 /*! 1250 \property QWebFrame::textSizeMultiplier 1251 \brief the scaling factor for all text in the frame 1252 \obsolete 1253 1254 Use setZoomFactor instead, in combination with the ZoomTextOnly attribute in 1255 QWebSettings. 1256 1257 \note Setting this property also enables the ZoomTextOnly attribute in 1258 QWebSettings. 1259 */ 1260 1261 /*! 1262 Sets the value of the multiplier used to scale the text in a Web frame to 1263 the \a factor specified. 1264 */ 1265 void QWebFrame::setTextSizeMultiplier(qreal factor) 1266 { 1267 page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, true); 1268 1269 d->frame->setPageAndTextZoomFactors(1, factor); 1270 } 1271 1272 /*! 1273 Returns the value of the multiplier used to scale the text in a Web frame. 1274 */ 1275 qreal QWebFrame::textSizeMultiplier() const 1276 { 1277 return page()->settings()->testAttribute(QWebSettings::ZoomTextOnly) ? d->frame->textZoomFactor() : d->frame->pageZoomFactor(); 1278 } 1279 1280 /*! 1281 \property QWebFrame::zoomFactor 1282 \since 4.5 1283 \brief the zoom factor for the frame 1284 */ 1285 1286 void QWebFrame::setZoomFactor(qreal factor) 1287 { 1288 if (page()->settings()->testAttribute(QWebSettings::ZoomTextOnly)) 1289 d->frame->setTextZoomFactor(factor); 1290 else 1291 d->frame->setPageZoomFactor(factor); 1292 } 1293 1294 qreal QWebFrame::zoomFactor() const 1295 { 1296 return page()->settings()->testAttribute(QWebSettings::ZoomTextOnly) ? d->frame->textZoomFactor() : d->frame->pageZoomFactor(); 1297 } 1298 1299 /*! 1300 \property QWebFrame::focus 1301 \since 4.6 1302 1303 Returns true if this frame has keyboard input focus; otherwise, returns false. 1304 */ 1305 bool QWebFrame::hasFocus() const 1306 { 1307 WebCore::Frame* ff = d->frame->page()->focusController()->focusedFrame(); 1308 return ff && QWebFramePrivate::kit(ff) == this; 1309 } 1310 1311 /*! 1312 \since 4.6 1313 1314 Gives keyboard input focus to this frame. 1315 */ 1316 void QWebFrame::setFocus() 1317 { 1318 QWebFramePrivate::core(this)->page()->focusController()->setFocusedFrame(QWebFramePrivate::core(this)); 1319 } 1320 1321 /*! 1322 Returns the position of the frame relative to it's parent frame. 1323 */ 1324 QPoint QWebFrame::pos() const 1325 { 1326 if (!d->frame->view()) 1327 return QPoint(); 1328 1329 return d->frame->view()->frameRect().location(); 1330 } 1331 1332 /*! 1333 Return the geometry of the frame relative to it's parent frame. 1334 */ 1335 QRect QWebFrame::geometry() const 1336 { 1337 if (!d->frame->view()) 1338 return QRect(); 1339 return d->frame->view()->frameRect(); 1340 } 1341 1342 /*! 1343 \property QWebFrame::contentsSize 1344 \brief the size of the contents in this frame 1345 1346 \sa contentsSizeChanged() 1347 */ 1348 QSize QWebFrame::contentsSize() const 1349 { 1350 FrameView *view = d->frame->view(); 1351 if (!view) 1352 return QSize(); 1353 return QSize(view->contentsWidth(), view->contentsHeight()); 1354 } 1355 1356 /*! 1357 \since 4.6 1358 1359 Returns the document element of this frame. 1360 1361 The document element provides access to the entire structured 1362 content of the frame. 1363 */ 1364 QWebElement QWebFrame::documentElement() const 1365 { 1366 WebCore::Document *doc = d->frame->document(); 1367 if (!doc) 1368 return QWebElement(); 1369 return QWebElement(doc->documentElement()); 1370 } 1371 1372 /*! 1373 \since 4.6 1374 Returns a new list of elements matching the given CSS selector \a selectorQuery. 1375 If there are no matching elements, an empty list is returned. 1376 1377 \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is 1378 used for the query. 1379 1380 \sa QWebElement::findAll() 1381 */ 1382 QWebElementCollection QWebFrame::findAllElements(const QString &selectorQuery) const 1383 { 1384 return documentElement().findAll(selectorQuery); 1385 } 1386 1387 /*! 1388 \since 4.6 1389 Returns the first element in the frame's document that matches the 1390 given CSS selector \a selectorQuery. If there is no matching element, a 1391 null element is returned. 1392 1393 \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is 1394 used for the query. 1395 1396 \sa QWebElement::findFirst() 1397 */ 1398 QWebElement QWebFrame::findFirstElement(const QString &selectorQuery) const 1399 { 1400 return documentElement().findFirst(selectorQuery); 1401 } 1402 1403 /*! 1404 Performs a hit test on the frame contents at the given position \a pos and returns the hit test result. 1405 */ 1406 QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const 1407 { 1408 if (!d->frame->view() || !d->frame->contentRenderer()) 1409 return QWebHitTestResult(); 1410 1411 HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false, /*ignoreClipping*/ true); 1412 1413 if (result.scrollbar()) 1414 return QWebHitTestResult(); 1415 1416 return QWebHitTestResult(new QWebHitTestResultPrivate(result)); 1417 } 1418 1419 /*! \reimp 1420 */ 1421 bool QWebFrame::event(QEvent *e) 1422 { 1423 return QObject::event(e); 1424 } 1425 1426 #ifndef QT_NO_PRINTER 1427 /*! 1428 Prints the frame to the given \a printer. 1429 1430 \sa render() 1431 */ 1432 void QWebFrame::print(QPrinter *printer) const 1433 { 1434 QPainter painter; 1435 if (!painter.begin(printer)) 1436 return; 1437 1438 const qreal zoomFactorX = (qreal)printer->logicalDpiX() / qt_defaultDpi(); 1439 const qreal zoomFactorY = (qreal)printer->logicalDpiY() / qt_defaultDpi(); 1440 1441 PrintContext printContext(d->frame); 1442 float pageHeight = 0; 1443 1444 QRect qprinterRect = printer->pageRect(); 1445 1446 IntRect pageRect(0, 0, 1447 int(qprinterRect.width() / zoomFactorX), 1448 int(qprinterRect.height() / zoomFactorY)); 1449 1450 printContext.begin(pageRect.width()); 1451 1452 printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight); 1453 1454 int docCopies; 1455 int pageCopies; 1456 if (printer->collateCopies()) { 1457 docCopies = 1; 1458 pageCopies = printer->numCopies(); 1459 } else { 1460 docCopies = printer->numCopies(); 1461 pageCopies = 1; 1462 } 1463 1464 int fromPage = printer->fromPage(); 1465 int toPage = printer->toPage(); 1466 bool ascending = true; 1467 1468 if (fromPage == 0 && toPage == 0) { 1469 fromPage = 1; 1470 toPage = printContext.pageCount(); 1471 } 1472 // paranoia check 1473 fromPage = qMax(1, fromPage); 1474 toPage = qMin(static_cast<int>(printContext.pageCount()), toPage); 1475 if (toPage < fromPage) { 1476 // if the user entered a page range outside the actual number 1477 // of printable pages, just return 1478 return; 1479 } 1480 1481 if (printer->pageOrder() == QPrinter::LastPageFirst) { 1482 int tmp = fromPage; 1483 fromPage = toPage; 1484 toPage = tmp; 1485 ascending = false; 1486 } 1487 1488 painter.scale(zoomFactorX, zoomFactorY); 1489 GraphicsContext ctx(&painter); 1490 1491 for (int i = 0; i < docCopies; ++i) { 1492 int page = fromPage; 1493 while (true) { 1494 for (int j = 0; j < pageCopies; ++j) { 1495 if (printer->printerState() == QPrinter::Aborted 1496 || printer->printerState() == QPrinter::Error) { 1497 printContext.end(); 1498 return; 1499 } 1500 printContext.spoolPage(ctx, page - 1, pageRect.width()); 1501 if (j < pageCopies - 1) 1502 printer->newPage(); 1503 } 1504 1505 if (page == toPage) 1506 break; 1507 1508 if (ascending) 1509 ++page; 1510 else 1511 --page; 1512 1513 printer->newPage(); 1514 } 1515 1516 if ( i < docCopies - 1) 1517 printer->newPage(); 1518 } 1519 1520 printContext.end(); 1521 } 1522 #endif // QT_NO_PRINTER 1523 1524 /*! 1525 Evaluates the JavaScript defined by \a scriptSource using this frame as context 1526 and returns the result of the last executed statement. 1527 1528 \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared() 1529 */ 1530 QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource) 1531 { 1532 ScriptController *proxy = d->frame->script(); 1533 QVariant rc; 1534 if (proxy) { 1535 #if USE(JSC) 1536 int distance = 0; 1537 JSC::JSValue v = d->frame->script()->executeScript(ScriptSourceCode(scriptSource)).jsValue(); 1538 1539 rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject(mainThreadNormalWorld())->globalExec(), v, QMetaType::Void, &distance); 1540 #elif USE(V8) 1541 QScriptEngine* engine = d->frame->script()->qtScriptEngine(); 1542 if (!engine) 1543 return rc; 1544 rc = engine->evaluate(scriptSource).toVariant(); 1545 #endif 1546 } 1547 return rc; 1548 } 1549 1550 /*! 1551 \since 4.5 1552 1553 Returns the frame's security origin. 1554 */ 1555 QWebSecurityOrigin QWebFrame::securityOrigin() const 1556 { 1557 QWebFrame* that = const_cast<QWebFrame*>(this); 1558 QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(QWebFramePrivate::core(that)->document()->securityOrigin()); 1559 return QWebSecurityOrigin(priv); 1560 } 1561 1562 WebCore::Frame* QWebFramePrivate::core(const QWebFrame* webFrame) 1563 { 1564 return webFrame->d->frame; 1565 } 1566 1567 QWebFrame* QWebFramePrivate::kit(const WebCore::Frame* coreFrame) 1568 { 1569 return qobject_cast<QWebFrame*>(coreFrame->loader()->networkingContext()->originatingObject()); 1570 } 1571 1572 1573 /*! 1574 \fn void QWebFrame::javaScriptWindowObjectCleared() 1575 1576 This signal is emitted whenever the global window object of the JavaScript 1577 environment is cleared, e.g., before starting a new load. 1578 1579 If you intend to add QObjects to a QWebFrame using 1580 addToJavaScriptWindowObject(), you should add them in a slot connected 1581 to this signal. This ensures that your objects remain accessible when 1582 loading new URLs. 1583 */ 1584 1585 /*! 1586 \fn void QWebFrame::provisionalLoad() 1587 \internal 1588 */ 1589 1590 /*! 1591 \fn void QWebFrame::titleChanged(const QString &title) 1592 1593 This signal is emitted whenever the title of the frame changes. 1594 The \a title string specifies the new title. 1595 1596 \sa title() 1597 */ 1598 1599 /*! 1600 \fn void QWebFrame::urlChanged(const QUrl &url) 1601 1602 This signal is emitted with the URL of the frame when the frame's title is 1603 received. The new URL is specified by \a url. 1604 1605 \sa url() 1606 */ 1607 1608 /*! 1609 \fn void QWebFrame::initialLayoutCompleted() 1610 1611 This signal is emitted when the frame is laid out the first time. 1612 This is the first time you will see contents displayed on the frame. 1613 1614 \note A frame can be laid out multiple times. 1615 */ 1616 1617 /*! 1618 \fn void QWebFrame::iconChanged() 1619 1620 This signal is emitted when the icon ("favicon") associated with the frame 1621 has been loaded. 1622 1623 \sa icon() 1624 */ 1625 1626 /*! 1627 \fn void QWebFrame::contentsSizeChanged(const QSize &size) 1628 \since 4.6 1629 1630 This signal is emitted when the frame's contents size changes 1631 to \a size. 1632 1633 \sa contentsSize() 1634 */ 1635 1636 /*! 1637 \fn void QWebFrame::loadStarted() 1638 \since 4.6 1639 1640 This signal is emitted when a new load of this frame is started. 1641 1642 \sa loadFinished() 1643 */ 1644 1645 /*! 1646 \fn void QWebFrame::loadFinished(bool ok) 1647 \since 4.6 1648 1649 This signal is emitted when a load of this frame is finished. 1650 \a ok will indicate whether the load was successful or any error occurred. 1651 1652 \sa loadStarted() 1653 */ 1654 1655 /*! 1656 \fn void QWebFrame::pageChanged() 1657 \since 4.7 1658 1659 This signal is emitted when this frame has been moved to a different QWebPage. 1660 1661 \sa page() 1662 */ 1663 1664 /*! 1665 \class QWebHitTestResult 1666 \since 4.4 1667 \brief The QWebHitTestResult class provides information about the web 1668 page content after a hit test. 1669 1670 \inmodule QtWebKit 1671 1672 QWebHitTestResult is returned by QWebFrame::hitTestContent() to provide 1673 information about the content of the web page at the specified position. 1674 */ 1675 1676 /*! 1677 \internal 1678 */ 1679 QWebHitTestResult::QWebHitTestResult(QWebHitTestResultPrivate *priv) 1680 : d(priv) 1681 { 1682 } 1683 1684 QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest) 1685 : isContentEditable(false) 1686 , isContentSelected(false) 1687 , isScrollBar(false) 1688 { 1689 if (!hitTest.innerNode()) 1690 return; 1691 pos = hitTest.point(); 1692 WebCore::TextDirection dir; 1693 title = hitTest.title(dir); 1694 linkText = hitTest.textContent(); 1695 linkUrl = hitTest.absoluteLinkURL(); 1696 linkTitle = hitTest.titleDisplayString(); 1697 alternateText = hitTest.altDisplayString(); 1698 imageUrl = hitTest.absoluteImageURL(); 1699 innerNode = hitTest.innerNode(); 1700 innerNonSharedNode = hitTest.innerNonSharedNode(); 1701 boundingRect = innerNonSharedNode ? innerNonSharedNode->renderer()->absoluteBoundingBoxRect(true) : IntRect(); 1702 WebCore::Image *img = hitTest.image(); 1703 if (img) { 1704 QPixmap *pix = img->nativeImageForCurrentFrame(); 1705 if (pix) 1706 pixmap = *pix; 1707 } 1708 WebCore::Frame *wframe = hitTest.targetFrame(); 1709 if (wframe) 1710 linkTargetFrame = QWebFramePrivate::kit(wframe); 1711 linkElement = QWebElement(hitTest.URLElement()); 1712 1713 isContentEditable = hitTest.isContentEditable(); 1714 isContentSelected = hitTest.isSelected(); 1715 isScrollBar = hitTest.scrollbar(); 1716 1717 if (innerNonSharedNode && innerNonSharedNode->document() 1718 && innerNonSharedNode->document()->frame()) 1719 frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame()); 1720 1721 enclosingBlock = QWebElement(WebCore::enclosingBlock(innerNode.get())); 1722 } 1723 1724 /*! 1725 Constructs a null hit test result. 1726 */ 1727 QWebHitTestResult::QWebHitTestResult() 1728 : d(0) 1729 { 1730 } 1731 1732 /*! 1733 Constructs a hit test result from \a other. 1734 */ 1735 QWebHitTestResult::QWebHitTestResult(const QWebHitTestResult &other) 1736 : d(0) 1737 { 1738 if (other.d) 1739 d = new QWebHitTestResultPrivate(*other.d); 1740 } 1741 1742 /*! 1743 Assigns the \a other hit test result to this. 1744 */ 1745 QWebHitTestResult &QWebHitTestResult::operator=(const QWebHitTestResult &other) 1746 { 1747 if (this != &other) { 1748 if (other.d) { 1749 if (!d) 1750 d = new QWebHitTestResultPrivate; 1751 *d = *other.d; 1752 } else { 1753 delete d; 1754 d = 0; 1755 } 1756 } 1757 return *this; 1758 } 1759 1760 /*! 1761 Destructor. 1762 */ 1763 QWebHitTestResult::~QWebHitTestResult() 1764 { 1765 delete d; 1766 } 1767 1768 /*! 1769 Returns true if the hit test result is null; otherwise returns false. 1770 */ 1771 bool QWebHitTestResult::isNull() const 1772 { 1773 return !d; 1774 } 1775 1776 /*! 1777 Returns the position where the hit test occured. 1778 */ 1779 QPoint QWebHitTestResult::pos() const 1780 { 1781 if (!d) 1782 return QPoint(); 1783 return d->pos; 1784 } 1785 1786 /*! 1787 \since 4.5 1788 Returns the bounding rect of the element. 1789 */ 1790 QRect QWebHitTestResult::boundingRect() const 1791 { 1792 if (!d) 1793 return QRect(); 1794 return d->boundingRect; 1795 } 1796 1797 /*! 1798 \since 4.6 1799 Returns the block element that encloses the element hit. 1800 1801 A block element is an element that is rendered using the 1802 CSS "block" style. This includes for example text 1803 paragraphs. 1804 */ 1805 QWebElement QWebHitTestResult::enclosingBlockElement() const 1806 { 1807 if (!d) 1808 return QWebElement(); 1809 return d->enclosingBlock; 1810 } 1811 1812 /*! 1813 Returns the title of the nearest enclosing HTML element. 1814 */ 1815 QString QWebHitTestResult::title() const 1816 { 1817 if (!d) 1818 return QString(); 1819 return d->title; 1820 } 1821 1822 /*! 1823 Returns the text of the link. 1824 */ 1825 QString QWebHitTestResult::linkText() const 1826 { 1827 if (!d) 1828 return QString(); 1829 return d->linkText; 1830 } 1831 1832 /*! 1833 Returns the url to which the link points to. 1834 */ 1835 QUrl QWebHitTestResult::linkUrl() const 1836 { 1837 if (!d) 1838 return QUrl(); 1839 return d->linkUrl; 1840 } 1841 1842 /*! 1843 Returns the title of the link. 1844 */ 1845 QUrl QWebHitTestResult::linkTitle() const 1846 { 1847 if (!d) 1848 return QUrl(); 1849 return d->linkTitle; 1850 } 1851 1852 /*! 1853 \since 4.6 1854 Returns the element that represents the link. 1855 1856 \sa linkTargetFrame() 1857 */ 1858 QWebElement QWebHitTestResult::linkElement() const 1859 { 1860 if (!d) 1861 return QWebElement(); 1862 return d->linkElement; 1863 } 1864 1865 /*! 1866 Returns the frame that will load the link if it is activated. 1867 1868 \sa linkElement() 1869 */ 1870 QWebFrame *QWebHitTestResult::linkTargetFrame() const 1871 { 1872 if (!d) 1873 return 0; 1874 return d->linkTargetFrame; 1875 } 1876 1877 /*! 1878 Returns the alternate text of the element. This corresponds to the HTML alt attribute. 1879 */ 1880 QString QWebHitTestResult::alternateText() const 1881 { 1882 if (!d) 1883 return QString(); 1884 return d->alternateText; 1885 } 1886 1887 /*! 1888 Returns the url of the image. 1889 */ 1890 QUrl QWebHitTestResult::imageUrl() const 1891 { 1892 if (!d) 1893 return QUrl(); 1894 return d->imageUrl; 1895 } 1896 1897 /*! 1898 Returns a QPixmap containing the image. A null pixmap is returned if the 1899 element being tested is not an image. 1900 */ 1901 QPixmap QWebHitTestResult::pixmap() const 1902 { 1903 if (!d) 1904 return QPixmap(); 1905 return d->pixmap; 1906 } 1907 1908 /*! 1909 Returns true if the content is editable by the user; otherwise returns false. 1910 */ 1911 bool QWebHitTestResult::isContentEditable() const 1912 { 1913 if (!d) 1914 return false; 1915 return d->isContentEditable; 1916 } 1917 1918 /*! 1919 Returns true if the content tested is part of the selection; otherwise returns false. 1920 */ 1921 bool QWebHitTestResult::isContentSelected() const 1922 { 1923 if (!d) 1924 return false; 1925 return d->isContentSelected; 1926 } 1927 1928 /*! 1929 \since 4.6 1930 Returns the underlying DOM element as QWebElement. 1931 */ 1932 QWebElement QWebHitTestResult::element() const 1933 { 1934 if (!d || !d->innerNonSharedNode || !d->innerNonSharedNode->isElementNode()) 1935 return QWebElement(); 1936 1937 return QWebElement(static_cast<WebCore::Element*>(d->innerNonSharedNode.get())); 1938 } 1939 1940 /*! 1941 Returns the frame the hit test was executed in. 1942 */ 1943 QWebFrame *QWebHitTestResult::frame() const 1944 { 1945 if (!d) 1946 return 0; 1947 return d->frame; 1948 } 1949 1950 #include "moc_qwebframe.cpp" 1951