1 /* 2 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 // How ownership works 32 // ------------------- 33 // 34 // Big oh represents a refcounted relationship: owner O--- ownee 35 // 36 // WebView (for the toplevel frame only) 37 // O 38 // | WebFrame 39 // | O 40 // | | 41 // Page O------- LocalFrame (m_mainFrame) O-------O FrameView 42 // || 43 // || 44 // FrameLoader 45 // 46 // FrameLoader and LocalFrame are formerly one object that was split apart because 47 // it got too big. They basically have the same lifetime, hence the double line. 48 // 49 // From the perspective of the embedder, WebFrame is simply an object that it 50 // allocates by calling WebFrame::create() and must be freed by calling close(). 51 // Internally, WebFrame is actually refcounted and it holds a reference to its 52 // corresponding LocalFrame in WebCore. 53 // 54 // How frames are destroyed 55 // ------------------------ 56 // 57 // The main frame is never destroyed and is re-used. The FrameLoader is re-used 58 // and a reference to the main frame is kept by the Page. 59 // 60 // When frame content is replaced, all subframes are destroyed. This happens 61 // in FrameLoader::detachFromParent for each subframe in a pre-order depth-first 62 // traversal. Note that child node order may not match DOM node order! 63 // detachFromParent() calls FrameLoaderClient::detachedFromParent(), which calls 64 // WebFrame::frameDetached(). This triggers WebFrame to clear its reference to 65 // LocalFrame, and also notifies the embedder via WebFrameClient that the frame is 66 // detached. Most embedders will invoke close() on the WebFrame at this point, 67 // triggering its deletion unless something else is still retaining a reference. 68 // 69 // Thie client is expected to be set whenever the WebLocalFrameImpl is attached to 70 // the DOM. 71 72 #include "config.h" 73 #include "web/WebLocalFrameImpl.h" 74 75 #include "bindings/v8/DOMWrapperWorld.h" 76 #include "bindings/v8/ExceptionState.h" 77 #include "bindings/v8/ExceptionStatePlaceholder.h" 78 #include "bindings/v8/ScriptController.h" 79 #include "bindings/v8/ScriptSourceCode.h" 80 #include "bindings/v8/ScriptValue.h" 81 #include "bindings/v8/V8GCController.h" 82 #include "bindings/v8/V8PerIsolateData.h" 83 #include "core/HTMLNames.h" 84 #include "core/dom/Document.h" 85 #include "core/dom/DocumentMarker.h" 86 #include "core/dom/DocumentMarkerController.h" 87 #include "core/dom/IconURL.h" 88 #include "core/dom/MessagePort.h" 89 #include "core/dom/Node.h" 90 #include "core/dom/NodeTraversal.h" 91 #include "core/dom/shadow/ShadowRoot.h" 92 #include "core/editing/Editor.h" 93 #include "core/editing/FrameSelection.h" 94 #include "core/editing/InputMethodController.h" 95 #include "core/editing/PlainTextRange.h" 96 #include "core/editing/SpellChecker.h" 97 #include "core/editing/TextAffinity.h" 98 #include "core/editing/TextIterator.h" 99 #include "core/editing/htmlediting.h" 100 #include "core/editing/markup.h" 101 #include "core/frame/Console.h" 102 #include "core/frame/LocalDOMWindow.h" 103 #include "core/frame/FrameHost.h" 104 #include "core/frame/FrameView.h" 105 #include "core/frame/Settings.h" 106 #include "core/html/HTMLCollection.h" 107 #include "core/html/HTMLFormElement.h" 108 #include "core/html/HTMLFrameElementBase.h" 109 #include "core/html/HTMLFrameOwnerElement.h" 110 #include "core/html/HTMLHeadElement.h" 111 #include "core/html/HTMLInputElement.h" 112 #include "core/html/HTMLLinkElement.h" 113 #include "core/html/PluginDocument.h" 114 #include "core/inspector/InspectorController.h" 115 #include "core/inspector/ScriptCallStack.h" 116 #include "core/loader/DocumentLoader.h" 117 #include "core/loader/FrameLoadRequest.h" 118 #include "core/loader/FrameLoader.h" 119 #include "core/loader/HistoryItem.h" 120 #include "core/loader/SubstituteData.h" 121 #include "core/page/Chrome.h" 122 #include "core/page/EventHandler.h" 123 #include "core/page/FocusController.h" 124 #include "core/page/FrameTree.h" 125 #include "core/page/Page.h" 126 #include "core/page/PrintContext.h" 127 #include "core/rendering/HitTestResult.h" 128 #include "core/rendering/RenderBox.h" 129 #include "core/rendering/RenderFrame.h" 130 #include "core/rendering/RenderLayer.h" 131 #include "core/rendering/RenderObject.h" 132 #include "core/rendering/RenderTreeAsText.h" 133 #include "core/rendering/RenderView.h" 134 #include "core/rendering/style/StyleInheritedData.h" 135 #include "core/timing/Performance.h" 136 #include "modules/geolocation/GeolocationController.h" 137 #include "modules/notifications/NotificationController.h" 138 #include "modules/screen_orientation/ScreenOrientationController.h" 139 #include "platform/TraceEvent.h" 140 #include "platform/UserGestureIndicator.h" 141 #include "platform/clipboard/ClipboardUtilities.h" 142 #include "platform/fonts/FontCache.h" 143 #include "platform/graphics/GraphicsContext.h" 144 #include "platform/graphics/GraphicsLayerClient.h" 145 #include "platform/graphics/skia/SkiaUtils.h" 146 #include "platform/heap/Handle.h" 147 #include "platform/network/ResourceRequest.h" 148 #include "platform/scroll/ScrollTypes.h" 149 #include "platform/scroll/ScrollbarTheme.h" 150 #include "platform/weborigin/KURL.h" 151 #include "platform/weborigin/SchemeRegistry.h" 152 #include "platform/weborigin/SecurityPolicy.h" 153 #include "public/platform/Platform.h" 154 #include "public/platform/WebFloatPoint.h" 155 #include "public/platform/WebFloatRect.h" 156 #include "public/platform/WebLayer.h" 157 #include "public/platform/WebPoint.h" 158 #include "public/platform/WebRect.h" 159 #include "public/platform/WebSize.h" 160 #include "public/platform/WebURLError.h" 161 #include "public/platform/WebVector.h" 162 #include "public/web/WebConsoleMessage.h" 163 #include "public/web/WebDOMEvent.h" 164 #include "public/web/WebDOMEventListener.h" 165 #include "public/web/WebDocument.h" 166 #include "public/web/WebFindOptions.h" 167 #include "public/web/WebFormElement.h" 168 #include "public/web/WebFrameClient.h" 169 #include "public/web/WebHistoryItem.h" 170 #include "public/web/WebIconURL.h" 171 #include "public/web/WebInputElement.h" 172 #include "public/web/WebNode.h" 173 #include "public/web/WebPerformance.h" 174 #include "public/web/WebPlugin.h" 175 #include "public/web/WebPrintParams.h" 176 #include "public/web/WebRange.h" 177 #include "public/web/WebScriptSource.h" 178 #include "public/web/WebSecurityOrigin.h" 179 #include "public/web/WebSerializedScriptValue.h" 180 #include "web/AssociatedURLLoader.h" 181 #include "web/CompositionUnderlineVectorBuilder.h" 182 #include "web/EventListenerWrapper.h" 183 #include "web/FindInPageCoordinates.h" 184 #include "web/GeolocationClientProxy.h" 185 #include "web/LocalFileSystemClient.h" 186 #include "web/MIDIClientProxy.h" 187 #include "web/PageOverlay.h" 188 #include "web/SharedWorkerRepositoryClientImpl.h" 189 #include "web/TextFinder.h" 190 #include "web/WebDataSourceImpl.h" 191 #include "web/WebDevToolsAgentPrivate.h" 192 #include "web/WebPluginContainerImpl.h" 193 #include "web/WebViewImpl.h" 194 #include "wtf/CurrentTime.h" 195 #include "wtf/HashMap.h" 196 #include <algorithm> 197 198 using namespace WebCore; 199 200 namespace blink { 201 202 static int frameCount = 0; 203 204 // Key for a StatsCounter tracking how many WebFrames are active. 205 static const char webFrameActiveCount[] = "WebFrameActiveCount"; 206 207 static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) 208 { 209 Document* document = frame->document(); 210 if (!document) 211 return; 212 213 if (!frame->view()) 214 return; 215 216 // TextIterator iterates over the visual representation of the DOM. As such, 217 // it requires you to do a layout before using it (otherwise it'll crash). 218 document->updateLayout(); 219 220 // Select the document body. 221 RefPtrWillBeRawPtr<Range> range(document->createRange()); 222 TrackExceptionState exceptionState; 223 range->selectNodeContents(document->body(), exceptionState); 224 225 if (!exceptionState.hadException()) { 226 // The text iterator will walk nodes giving us text. This is similar to 227 // the plainText() function in core/editing/TextIterator.h, but we implement the maximum 228 // size and also copy the results directly into a wstring, avoiding the 229 // string conversion. 230 for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { 231 it.appendTextToStringBuilder(output, 0, maxChars - output.length()); 232 if (output.length() >= maxChars) 233 return; // Filled up the buffer. 234 } 235 } 236 237 // The separator between frames when the frames are converted to plain text. 238 const LChar frameSeparator[] = { '\n', '\n' }; 239 const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator); 240 241 // Recursively walk the children. 242 const FrameTree& frameTree = frame->tree(); 243 for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) { 244 if (!curChild->isLocalFrame()) 245 continue; 246 LocalFrame* curLocalChild = toLocalFrame(curChild); 247 // Ignore the text of non-visible frames. 248 RenderView* contentRenderer = curLocalChild->contentRenderer(); 249 RenderPart* ownerRenderer = curLocalChild->ownerRenderer(); 250 if (!contentRenderer || !contentRenderer->width() || !contentRenderer->height() 251 || (contentRenderer->x() + contentRenderer->width() <= 0) || (contentRenderer->y() + contentRenderer->height() <= 0) 252 || (ownerRenderer && ownerRenderer->style() && ownerRenderer->style()->visibility() != VISIBLE)) { 253 continue; 254 } 255 256 // Make sure the frame separator won't fill up the buffer, and give up if 257 // it will. The danger is if the separator will make the buffer longer than 258 // maxChars. This will cause the computation above: 259 // maxChars - output->size() 260 // to be a negative number which will crash when the subframe is added. 261 if (output.length() >= maxChars - frameSeparatorLength) 262 return; 263 264 output.append(frameSeparator, frameSeparatorLength); 265 frameContentAsPlainText(maxChars, curLocalChild, output); 266 if (output.length() >= maxChars) 267 return; // Filled up the buffer. 268 } 269 } 270 271 WebPluginContainerImpl* WebLocalFrameImpl::pluginContainerFromFrame(LocalFrame* frame) 272 { 273 if (!frame) 274 return 0; 275 if (!frame->document() || !frame->document()->isPluginDocument()) 276 return 0; 277 PluginDocument* pluginDocument = toPluginDocument(frame->document()); 278 return toWebPluginContainerImpl(pluginDocument->pluginWidget()); 279 } 280 281 WebPluginContainerImpl* WebLocalFrameImpl::pluginContainerFromNode(WebCore::LocalFrame* frame, const WebNode& node) 282 { 283 WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame); 284 if (pluginContainer) 285 return pluginContainer; 286 return toWebPluginContainerImpl(node.pluginContainer()); 287 } 288 289 // Simple class to override some of PrintContext behavior. Some of the methods 290 // made virtual so that they can be overridden by ChromePluginPrintContext. 291 class ChromePrintContext : public PrintContext { 292 WTF_MAKE_NONCOPYABLE(ChromePrintContext); 293 public: 294 ChromePrintContext(LocalFrame* frame) 295 : PrintContext(frame) 296 , m_printedPageWidth(0) 297 { 298 } 299 300 virtual ~ChromePrintContext() { } 301 302 virtual void begin(float width, float height) 303 { 304 ASSERT(!m_printedPageWidth); 305 m_printedPageWidth = width; 306 PrintContext::begin(m_printedPageWidth, height); 307 } 308 309 virtual void end() 310 { 311 PrintContext::end(); 312 } 313 314 virtual float getPageShrink(int pageNumber) const 315 { 316 IntRect pageRect = m_pageRects[pageNumber]; 317 return m_printedPageWidth / pageRect.width(); 318 } 319 320 // Spools the printed page, a subrect of frame(). Skip the scale step. 321 // NativeTheme doesn't play well with scaling. Scaling is done browser side 322 // instead. Returns the scale to be applied. 323 // On Linux, we don't have the problem with NativeTheme, hence we let WebKit 324 // do the scaling and ignore the return value. 325 virtual float spoolPage(GraphicsContext& context, int pageNumber) 326 { 327 IntRect pageRect = m_pageRects[pageNumber]; 328 float scale = m_printedPageWidth / pageRect.width(); 329 330 context.save(); 331 #if OS(POSIX) && !OS(MACOSX) 332 context.scale(scale, scale); 333 #endif 334 context.translate(static_cast<float>(-pageRect.x()), static_cast<float>(-pageRect.y())); 335 context.clip(pageRect); 336 frame()->view()->paintContents(&context, pageRect); 337 if (context.supportsURLFragments()) 338 outputLinkedDestinations(context, frame()->document(), pageRect); 339 context.restore(); 340 return scale; 341 } 342 343 void spoolAllPagesWithBoundaries(GraphicsContext& graphicsContext, const FloatSize& pageSizeInPixels) 344 { 345 if (!frame()->document() || !frame()->view() || !frame()->document()->renderView()) 346 return; 347 348 frame()->document()->updateLayout(); 349 350 float pageHeight; 351 computePageRects(FloatRect(FloatPoint(0, 0), pageSizeInPixels), 0, 0, 1, pageHeight); 352 353 const float pageWidth = pageSizeInPixels.width(); 354 size_t numPages = pageRects().size(); 355 int totalHeight = numPages * (pageSizeInPixels.height() + 1) - 1; 356 357 // Fill the whole background by white. 358 graphicsContext.setFillColor(Color::white); 359 graphicsContext.fillRect(FloatRect(0, 0, pageWidth, totalHeight)); 360 361 int currentHeight = 0; 362 for (size_t pageIndex = 0; pageIndex < numPages; pageIndex++) { 363 // Draw a line for a page boundary if this isn't the first page. 364 if (pageIndex > 0) { 365 graphicsContext.save(); 366 graphicsContext.setStrokeColor(Color(0, 0, 255)); 367 graphicsContext.setFillColor(Color(0, 0, 255)); 368 graphicsContext.drawLine(IntPoint(0, currentHeight), IntPoint(pageWidth, currentHeight)); 369 graphicsContext.restore(); 370 } 371 372 graphicsContext.save(); 373 374 graphicsContext.translate(0, currentHeight); 375 #if OS(WIN) || OS(MACOSX) 376 // Account for the disabling of scaling in spoolPage. In the context 377 // of spoolAllPagesWithBoundaries the scale HAS NOT been pre-applied. 378 float scale = getPageShrink(pageIndex); 379 graphicsContext.scale(scale, scale); 380 #endif 381 spoolPage(graphicsContext, pageIndex); 382 graphicsContext.restore(); 383 384 currentHeight += pageSizeInPixels.height() + 1; 385 } 386 } 387 388 virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight) 389 { 390 PrintContext::computePageRects(printRect, headerHeight, footerHeight, userScaleFactor, outPageHeight); 391 } 392 393 virtual int pageCount() const 394 { 395 return PrintContext::pageCount(); 396 } 397 398 private: 399 // Set when printing. 400 float m_printedPageWidth; 401 }; 402 403 // Simple class to override some of PrintContext behavior. This is used when 404 // the frame hosts a plugin that supports custom printing. In this case, we 405 // want to delegate all printing related calls to the plugin. 406 class ChromePluginPrintContext : public ChromePrintContext { 407 public: 408 ChromePluginPrintContext(LocalFrame* frame, WebPluginContainerImpl* plugin, const WebPrintParams& printParams) 409 : ChromePrintContext(frame), m_plugin(plugin), m_pageCount(0), m_printParams(printParams) 410 { 411 } 412 413 virtual ~ChromePluginPrintContext() { } 414 415 virtual void begin(float width, float height) 416 { 417 } 418 419 virtual void end() 420 { 421 m_plugin->printEnd(); 422 } 423 424 virtual float getPageShrink(int pageNumber) const 425 { 426 // We don't shrink the page (maybe we should ask the widget ??) 427 return 1.0; 428 } 429 430 virtual void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight) 431 { 432 m_printParams.printContentArea = IntRect(printRect); 433 m_pageCount = m_plugin->printBegin(m_printParams); 434 } 435 436 virtual int pageCount() const 437 { 438 return m_pageCount; 439 } 440 441 // Spools the printed page, a subrect of frame(). Skip the scale step. 442 // NativeTheme doesn't play well with scaling. Scaling is done browser side 443 // instead. Returns the scale to be applied. 444 virtual float spoolPage(GraphicsContext& context, int pageNumber) 445 { 446 m_plugin->printPage(pageNumber, &context); 447 return 1.0; 448 } 449 450 private: 451 // Set when printing. 452 WebPluginContainerImpl* m_plugin; 453 int m_pageCount; 454 WebPrintParams m_printParams; 455 456 }; 457 458 static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) 459 { 460 return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0; 461 } 462 463 // WebFrame ------------------------------------------------------------------- 464 465 int WebFrame::instanceCount() 466 { 467 return frameCount; 468 } 469 470 WebLocalFrame* WebLocalFrame::frameForCurrentContext() 471 { 472 v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext(); 473 if (context.IsEmpty()) 474 return 0; 475 return frameForContext(context); 476 } 477 478 WebLocalFrame* WebLocalFrame::frameForContext(v8::Handle<v8::Context> context) 479 { 480 return WebLocalFrameImpl::fromFrame(toFrameIfNotDetached(context)); 481 } 482 483 WebLocalFrame* WebLocalFrame::fromFrameOwnerElement(const WebElement& element) 484 { 485 return WebLocalFrameImpl::fromFrameOwnerElement(PassRefPtrWillBeRawPtr<Element>(element).get()); 486 } 487 488 bool WebLocalFrameImpl::isWebLocalFrame() const 489 { 490 return true; 491 } 492 493 WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame() 494 { 495 return this; 496 } 497 498 bool WebLocalFrameImpl::isWebRemoteFrame() const 499 { 500 return false; 501 } 502 503 WebRemoteFrame* WebLocalFrameImpl::toWebRemoteFrame() 504 { 505 ASSERT_NOT_REACHED(); 506 return 0; 507 } 508 509 void WebLocalFrameImpl::close() 510 { 511 m_client = 0; 512 513 // FIXME: Oilpan: Signal to LocalFrame and its supplements that the frame is 514 // being torn down so it can do prompt clean-up. For example, this will 515 // clear the raw back pointer to m_geolocationClientProxy. Once 516 // GeolocationClientProxy is on-heap it looks like we can completely remove 517 // |willBeDestroyed| from supplements since tracing will ensure safety. 518 if (m_frame) 519 m_frame->willBeDestroyed(); 520 521 deref(); // Balances ref() acquired in WebFrame::create 522 } 523 524 WebString WebLocalFrameImpl::uniqueName() const 525 { 526 return frame()->tree().uniqueName(); 527 } 528 529 WebString WebLocalFrameImpl::assignedName() const 530 { 531 return frame()->tree().name(); 532 } 533 534 void WebLocalFrameImpl::setName(const WebString& name) 535 { 536 frame()->tree().setName(name); 537 } 538 539 WebVector<WebIconURL> WebLocalFrameImpl::iconURLs(int iconTypesMask) const 540 { 541 // The URL to the icon may be in the header. As such, only 542 // ask the loader for the icon if it's finished loading. 543 if (frame()->loader().state() == FrameStateComplete) 544 return frame()->document()->iconURLs(iconTypesMask); 545 return WebVector<WebIconURL>(); 546 } 547 548 void WebLocalFrameImpl::setIsRemote(bool isRemote) 549 { 550 m_isRemote = isRemote; 551 if (isRemote) 552 client()->initializeChildFrame(frame()->view()->frameRect(), frame()->view()->visibleContentScaleFactor()); 553 } 554 555 void WebLocalFrameImpl::setRemoteWebLayer(WebLayer* webLayer) 556 { 557 if (!frame()) 558 return; 559 560 if (frame()->remotePlatformLayer()) 561 GraphicsLayer::unregisterContentsLayer(frame()->remotePlatformLayer()); 562 if (webLayer) 563 GraphicsLayer::registerContentsLayer(webLayer); 564 frame()->setRemotePlatformLayer(webLayer); 565 // FIXME: This should be moved to WebRemoteFrame. 566 ASSERT(frame()->deprecatedLocalOwner()); 567 frame()->deprecatedLocalOwner()->setNeedsCompositingUpdate(); 568 if (RenderPart* renderer = frame()->ownerRenderer()) 569 renderer->layer()->updateSelfPaintingLayer(); 570 } 571 572 void WebLocalFrameImpl::setPermissionClient(WebPermissionClient* permissionClient) 573 { 574 m_permissionClient = permissionClient; 575 } 576 577 void WebLocalFrameImpl::setSharedWorkerRepositoryClient(WebSharedWorkerRepositoryClient* client) 578 { 579 m_sharedWorkerRepositoryClient = SharedWorkerRepositoryClientImpl::create(client); 580 } 581 582 WebSize WebLocalFrameImpl::scrollOffset() const 583 { 584 FrameView* view = frameView(); 585 if (!view) 586 return WebSize(); 587 return view->scrollOffset(); 588 } 589 590 WebSize WebLocalFrameImpl::minimumScrollOffset() const 591 { 592 FrameView* view = frameView(); 593 if (!view) 594 return WebSize(); 595 return toIntSize(view->minimumScrollPosition()); 596 } 597 598 WebSize WebLocalFrameImpl::maximumScrollOffset() const 599 { 600 FrameView* view = frameView(); 601 if (!view) 602 return WebSize(); 603 return toIntSize(view->maximumScrollPosition()); 604 } 605 606 void WebLocalFrameImpl::setScrollOffset(const WebSize& offset) 607 { 608 if (FrameView* view = frameView()) 609 view->setScrollOffset(IntPoint(offset.width, offset.height)); 610 } 611 612 WebSize WebLocalFrameImpl::contentsSize() const 613 { 614 return frame()->view()->contentsSize(); 615 } 616 617 bool WebLocalFrameImpl::hasVisibleContent() const 618 { 619 if (RenderPart* renderer = frame()->ownerRenderer()) { 620 if (renderer->style()->visibility() != VISIBLE) 621 return false; 622 } 623 return frame()->view()->visibleWidth() > 0 && frame()->view()->visibleHeight() > 0; 624 } 625 626 WebRect WebLocalFrameImpl::visibleContentRect() const 627 { 628 return frame()->view()->visibleContentRect(); 629 } 630 631 bool WebLocalFrameImpl::hasHorizontalScrollbar() const 632 { 633 return frame() && frame()->view() && frame()->view()->horizontalScrollbar(); 634 } 635 636 bool WebLocalFrameImpl::hasVerticalScrollbar() const 637 { 638 return frame() && frame()->view() && frame()->view()->verticalScrollbar(); 639 } 640 641 WebView* WebLocalFrameImpl::view() const 642 { 643 return viewImpl(); 644 } 645 646 void WebLocalFrameImpl::setOpener(WebFrame* opener) 647 { 648 // FIXME: Does this need to move up into WebFrame too? 649 if (WebFrame::opener() && !opener && m_client) 650 m_client->didDisownOpener(this); 651 652 WebFrame::setOpener(opener); 653 654 ASSERT(m_frame); 655 if (m_frame && m_frame->document()) 656 m_frame->document()->initSecurityContext(); 657 } 658 659 WebDocument WebLocalFrameImpl::document() const 660 { 661 if (!frame() || !frame()->document()) 662 return WebDocument(); 663 return WebDocument(frame()->document()); 664 } 665 666 WebPerformance WebLocalFrameImpl::performance() const 667 { 668 if (!frame()) 669 return WebPerformance(); 670 return WebPerformance(&frame()->domWindow()->performance()); 671 } 672 673 bool WebLocalFrameImpl::dispatchBeforeUnloadEvent() 674 { 675 if (!frame()) 676 return true; 677 return frame()->loader().shouldClose(); 678 } 679 680 void WebLocalFrameImpl::dispatchUnloadEvent() 681 { 682 if (!frame()) 683 return; 684 frame()->loader().closeURL(); 685 } 686 687 NPObject* WebLocalFrameImpl::windowObject() const 688 { 689 if (!frame()) 690 return 0; 691 return frame()->script().windowScriptNPObject(); 692 } 693 694 void WebLocalFrameImpl::bindToWindowObject(const WebString& name, NPObject* object) 695 { 696 bindToWindowObject(name, object, 0); 697 } 698 699 void WebLocalFrameImpl::bindToWindowObject(const WebString& name, NPObject* object, void*) 700 { 701 if (!frame() || !frame()->script().canExecuteScripts(NotAboutToExecuteScript)) 702 return; 703 frame()->script().bindToWindowObject(frame(), String(name), object); 704 } 705 706 void WebLocalFrameImpl::executeScript(const WebScriptSource& source) 707 { 708 ASSERT(frame()); 709 TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first()); 710 v8::HandleScope handleScope(toIsolate(frame())); 711 frame()->script().executeScriptInMainWorld(ScriptSourceCode(source.code, source.url, position)); 712 } 713 714 void WebLocalFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup) 715 { 716 ASSERT(frame()); 717 RELEASE_ASSERT(worldID > 0); 718 RELEASE_ASSERT(worldID < EmbedderWorldIdLimit); 719 720 Vector<ScriptSourceCode> sources; 721 for (unsigned i = 0; i < numSources; ++i) { 722 TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first()); 723 sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position)); 724 } 725 726 v8::HandleScope handleScope(toIsolate(frame())); 727 frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0); 728 } 729 730 void WebLocalFrameImpl::setIsolatedWorldSecurityOrigin(int worldID, const WebSecurityOrigin& securityOrigin) 731 { 732 ASSERT(frame()); 733 DOMWrapperWorld::setIsolatedWorldSecurityOrigin(worldID, securityOrigin.get()); 734 } 735 736 void WebLocalFrameImpl::setIsolatedWorldContentSecurityPolicy(int worldID, const WebString& policy) 737 { 738 ASSERT(frame()); 739 DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(worldID, policy); 740 } 741 742 void WebLocalFrameImpl::addMessageToConsole(const WebConsoleMessage& message) 743 { 744 ASSERT(frame()); 745 746 MessageLevel webCoreMessageLevel; 747 switch (message.level) { 748 case WebConsoleMessage::LevelDebug: 749 webCoreMessageLevel = DebugMessageLevel; 750 break; 751 case WebConsoleMessage::LevelLog: 752 webCoreMessageLevel = LogMessageLevel; 753 break; 754 case WebConsoleMessage::LevelWarning: 755 webCoreMessageLevel = WarningMessageLevel; 756 break; 757 case WebConsoleMessage::LevelError: 758 webCoreMessageLevel = ErrorMessageLevel; 759 break; 760 default: 761 ASSERT_NOT_REACHED(); 762 return; 763 } 764 765 frame()->document()->addConsoleMessage(OtherMessageSource, webCoreMessageLevel, message.text); 766 } 767 768 void WebLocalFrameImpl::collectGarbage() 769 { 770 if (!frame()) 771 return; 772 if (!frame()->settings()->scriptEnabled()) 773 return; 774 V8GCController::collectGarbage(v8::Isolate::GetCurrent()); 775 } 776 777 bool WebLocalFrameImpl::checkIfRunInsecureContent(const WebURL& url) const 778 { 779 ASSERT(frame()); 780 return frame()->loader().mixedContentChecker()->canRunInsecureContent(frame()->document()->securityOrigin(), url); 781 } 782 783 v8::Handle<v8::Value> WebLocalFrameImpl::executeScriptAndReturnValue(const WebScriptSource& source) 784 { 785 ASSERT(frame()); 786 787 // FIXME: This fake user gesture is required to make a bunch of pyauto 788 // tests pass. If this isn't needed in non-test situations, we should 789 // consider removing this code and changing the tests. 790 // http://code.google.com/p/chromium/issues/detail?id=86397 791 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); 792 793 TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first()); 794 return frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(source.code, source.url, position)); 795 } 796 797 void WebLocalFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup, WebVector<v8::Local<v8::Value> >* results) 798 { 799 ASSERT(frame()); 800 RELEASE_ASSERT(worldID > 0); 801 RELEASE_ASSERT(worldID < EmbedderWorldIdLimit); 802 803 Vector<ScriptSourceCode> sources; 804 805 for (unsigned i = 0; i < numSources; ++i) { 806 TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first()); 807 sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position)); 808 } 809 810 if (results) { 811 Vector<v8::Local<v8::Value> > scriptResults; 812 frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, &scriptResults); 813 WebVector<v8::Local<v8::Value> > v8Results(scriptResults.size()); 814 for (unsigned i = 0; i < scriptResults.size(); i++) 815 v8Results[i] = v8::Local<v8::Value>::New(toIsolate(frame()), scriptResults[i]); 816 results->swap(v8Results); 817 } else { 818 v8::HandleScope handleScope(toIsolate(frame())); 819 frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0); 820 } 821 } 822 823 v8::Handle<v8::Value> WebLocalFrameImpl::callFunctionEvenIfScriptDisabled(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> argv[]) 824 { 825 ASSERT(frame()); 826 return frame()->script().callFunction(function, receiver, argc, argv); 827 } 828 829 v8::Local<v8::Context> WebLocalFrameImpl::mainWorldScriptContext() const 830 { 831 return toV8Context(frame(), DOMWrapperWorld::mainWorld()); 832 } 833 834 void WebLocalFrameImpl::reload(bool ignoreCache) 835 { 836 ASSERT(frame()); 837 frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload); 838 } 839 840 void WebLocalFrameImpl::reloadWithOverrideURL(const WebURL& overrideUrl, bool ignoreCache) 841 { 842 ASSERT(frame()); 843 frame()->loader().reload(ignoreCache ? EndToEndReload : NormalReload, overrideUrl); 844 } 845 846 void WebLocalFrameImpl::loadRequest(const WebURLRequest& request) 847 { 848 ASSERT(frame()); 849 ASSERT(!request.isNull()); 850 const ResourceRequest& resourceRequest = request.toResourceRequest(); 851 852 if (resourceRequest.url().protocolIs("javascript")) { 853 loadJavaScriptURL(resourceRequest.url()); 854 return; 855 } 856 857 frame()->loader().load(FrameLoadRequest(0, resourceRequest)); 858 } 859 860 void WebLocalFrameImpl::loadHistoryItem(const WebHistoryItem& item, WebHistoryLoadType loadType, WebURLRequest::CachePolicy cachePolicy) 861 { 862 ASSERT(frame()); 863 RefPtr<HistoryItem> historyItem = PassRefPtr<HistoryItem>(item); 864 ASSERT(historyItem); 865 frame()->loader().loadHistoryItem(historyItem.get(), static_cast<HistoryLoadType>(loadType), static_cast<ResourceRequestCachePolicy>(cachePolicy)); 866 } 867 868 void WebLocalFrameImpl::loadData(const WebData& data, const WebString& mimeType, const WebString& textEncoding, const WebURL& baseURL, const WebURL& unreachableURL, bool replace) 869 { 870 ASSERT(frame()); 871 872 // If we are loading substitute data to replace an existing load, then 873 // inherit all of the properties of that original request. This way, 874 // reload will re-attempt the original request. It is essential that 875 // we only do this when there is an unreachableURL since a non-empty 876 // unreachableURL informs FrameLoader::reload to load unreachableURL 877 // instead of the currently loaded URL. 878 ResourceRequest request; 879 if (replace && !unreachableURL.isEmpty() && frame()->loader().provisionalDocumentLoader()) 880 request = frame()->loader().provisionalDocumentLoader()->originalRequest(); 881 request.setURL(baseURL); 882 883 FrameLoadRequest frameRequest(0, request, SubstituteData(data, mimeType, textEncoding, unreachableURL)); 884 ASSERT(frameRequest.substituteData().isValid()); 885 frameRequest.setLockBackForwardList(replace); 886 frame()->loader().load(frameRequest); 887 } 888 889 void WebLocalFrameImpl::loadHTMLString(const WebData& data, const WebURL& baseURL, const WebURL& unreachableURL, bool replace) 890 { 891 ASSERT(frame()); 892 loadData(data, WebString::fromUTF8("text/html"), WebString::fromUTF8("UTF-8"), baseURL, unreachableURL, replace); 893 } 894 895 bool WebLocalFrameImpl::isLoading() const 896 { 897 if (!frame()) 898 return false; 899 return frame()->loader().isLoading(); 900 } 901 902 void WebLocalFrameImpl::stopLoading() 903 { 904 if (!frame()) 905 return; 906 // FIXME: Figure out what we should really do here. It seems like a bug 907 // that FrameLoader::stopLoading doesn't call stopAllLoaders. 908 frame()->loader().stopAllLoaders(); 909 } 910 911 WebDataSource* WebLocalFrameImpl::provisionalDataSource() const 912 { 913 ASSERT(frame()); 914 915 // We regard the policy document loader as still provisional. 916 DocumentLoader* documentLoader = frame()->loader().provisionalDocumentLoader(); 917 if (!documentLoader) 918 documentLoader = frame()->loader().policyDocumentLoader(); 919 920 return DataSourceForDocLoader(documentLoader); 921 } 922 923 WebDataSource* WebLocalFrameImpl::dataSource() const 924 { 925 ASSERT(frame()); 926 return DataSourceForDocLoader(frame()->loader().documentLoader()); 927 } 928 929 void WebLocalFrameImpl::enableViewSourceMode(bool enable) 930 { 931 if (frame()) 932 frame()->setInViewSourceMode(enable); 933 } 934 935 bool WebLocalFrameImpl::isViewSourceModeEnabled() const 936 { 937 if (!frame()) 938 return false; 939 return frame()->inViewSourceMode(); 940 } 941 942 void WebLocalFrameImpl::setReferrerForRequest(WebURLRequest& request, const WebURL& referrerURL) 943 { 944 String referrer = referrerURL.isEmpty() ? frame()->document()->outgoingReferrer() : String(referrerURL.spec().utf16()); 945 referrer = SecurityPolicy::generateReferrerHeader(frame()->document()->referrerPolicy(), request.url(), referrer); 946 if (referrer.isEmpty()) 947 return; 948 request.setHTTPReferrer(referrer, static_cast<WebReferrerPolicy>(frame()->document()->referrerPolicy())); 949 } 950 951 void WebLocalFrameImpl::dispatchWillSendRequest(WebURLRequest& request) 952 { 953 ResourceResponse response; 954 frame()->loader().client()->dispatchWillSendRequest(0, 0, request.toMutableResourceRequest(), response); 955 } 956 957 WebURLLoader* WebLocalFrameImpl::createAssociatedURLLoader(const WebURLLoaderOptions& options) 958 { 959 return new AssociatedURLLoader(this, options); 960 } 961 962 unsigned WebLocalFrameImpl::unloadListenerCount() const 963 { 964 return frame()->domWindow()->pendingUnloadEventListeners(); 965 } 966 967 void WebLocalFrameImpl::replaceSelection(const WebString& text) 968 { 969 bool selectReplacement = false; 970 bool smartReplace = true; 971 frame()->editor().replaceSelectionWithText(text, selectReplacement, smartReplace); 972 } 973 974 void WebLocalFrameImpl::insertText(const WebString& text) 975 { 976 if (frame()->inputMethodController().hasComposition()) 977 frame()->inputMethodController().confirmComposition(text); 978 else 979 frame()->editor().insertText(text, 0); 980 } 981 982 void WebLocalFrameImpl::setMarkedText(const WebString& text, unsigned location, unsigned length) 983 { 984 Vector<CompositionUnderline> decorations; 985 frame()->inputMethodController().setComposition(text, decorations, location, length); 986 } 987 988 void WebLocalFrameImpl::unmarkText() 989 { 990 frame()->inputMethodController().cancelComposition(); 991 } 992 993 bool WebLocalFrameImpl::hasMarkedText() const 994 { 995 return frame()->inputMethodController().hasComposition(); 996 } 997 998 WebRange WebLocalFrameImpl::markedRange() const 999 { 1000 return frame()->inputMethodController().compositionRange(); 1001 } 1002 1003 bool WebLocalFrameImpl::firstRectForCharacterRange(unsigned location, unsigned length, WebRect& rect) const 1004 { 1005 if ((location + length < location) && (location + length)) 1006 length = 0; 1007 1008 Element* editable = frame()->selection().rootEditableElementOrDocumentElement(); 1009 ASSERT(editable); 1010 RefPtrWillBeRawPtr<Range> range = PlainTextRange(location, location + length).createRange(*editable); 1011 if (!range) 1012 return false; 1013 IntRect intRect = frame()->editor().firstRectForRange(range.get()); 1014 rect = WebRect(intRect); 1015 rect = frame()->view()->contentsToWindow(rect); 1016 return true; 1017 } 1018 1019 size_t WebLocalFrameImpl::characterIndexForPoint(const WebPoint& webPoint) const 1020 { 1021 if (!frame()) 1022 return kNotFound; 1023 1024 IntPoint point = frame()->view()->windowToContents(webPoint); 1025 HitTestResult result = frame()->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); 1026 RefPtrWillBeRawPtr<Range> range = frame()->rangeForPoint(result.roundedPointInInnerNodeFrame()); 1027 if (!range) 1028 return kNotFound; 1029 Element* editable = frame()->selection().rootEditableElementOrDocumentElement(); 1030 ASSERT(editable); 1031 return PlainTextRange::create(*editable, *range.get()).start(); 1032 } 1033 1034 bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebNode& node) 1035 { 1036 ASSERT(frame()); 1037 1038 if (name.length() <= 2) 1039 return false; 1040 1041 // Since we don't have NSControl, we will convert the format of command 1042 // string and call the function on Editor directly. 1043 String command = name; 1044 1045 // Make sure the first letter is upper case. 1046 command.replace(0, 1, command.substring(0, 1).upper()); 1047 1048 // Remove the trailing ':' if existing. 1049 if (command[command.length() - 1] == UChar(':')) 1050 command = command.substring(0, command.length() - 1); 1051 1052 WebPluginContainerImpl* pluginContainer = pluginContainerFromNode(frame(), node); 1053 if (pluginContainer && pluginContainer->executeEditCommand(name)) 1054 return true; 1055 1056 bool result = true; 1057 1058 // Specially handling commands that Editor::execCommand does not directly 1059 // support. 1060 if (command == "DeleteToEndOfParagraph") { 1061 if (!frame()->editor().deleteWithDirection(DirectionForward, ParagraphBoundary, true, false)) 1062 frame()->editor().deleteWithDirection(DirectionForward, CharacterGranularity, true, false); 1063 } else if (command == "Indent") { 1064 frame()->editor().indent(); 1065 } else if (command == "Outdent") { 1066 frame()->editor().outdent(); 1067 } else if (command == "DeleteBackward") { 1068 result = frame()->editor().command(AtomicString("BackwardDelete")).execute(); 1069 } else if (command == "DeleteForward") { 1070 result = frame()->editor().command(AtomicString("ForwardDelete")).execute(); 1071 } else if (command == "AdvanceToNextMisspelling") { 1072 // Wee need to pass false here or else the currently selected word will never be skipped. 1073 frame()->spellChecker().advanceToNextMisspelling(false); 1074 } else if (command == "ToggleSpellPanel") { 1075 frame()->spellChecker().showSpellingGuessPanel(); 1076 } else { 1077 result = frame()->editor().command(command).execute(); 1078 } 1079 return result; 1080 } 1081 1082 bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebString& value, const WebNode& node) 1083 { 1084 ASSERT(frame()); 1085 String webName = name; 1086 1087 WebPluginContainerImpl* pluginContainer = pluginContainerFromNode(frame(), node); 1088 if (pluginContainer && pluginContainer->executeEditCommand(name, value)) 1089 return true; 1090 1091 // moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit for editable nodes. 1092 if (!frame()->editor().canEdit() && webName == "moveToBeginningOfDocument") 1093 return viewImpl()->bubblingScroll(ScrollUp, ScrollByDocument); 1094 1095 if (!frame()->editor().canEdit() && webName == "moveToEndOfDocument") 1096 return viewImpl()->bubblingScroll(ScrollDown, ScrollByDocument); 1097 1098 if (webName == "showGuessPanel") { 1099 frame()->spellChecker().showSpellingGuessPanel(); 1100 return true; 1101 } 1102 1103 return frame()->editor().command(webName).execute(value); 1104 } 1105 1106 bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const 1107 { 1108 ASSERT(frame()); 1109 return frame()->editor().command(name).isEnabled(); 1110 } 1111 1112 void WebLocalFrameImpl::enableContinuousSpellChecking(bool enable) 1113 { 1114 if (enable == isContinuousSpellCheckingEnabled()) 1115 return; 1116 frame()->spellChecker().toggleContinuousSpellChecking(); 1117 } 1118 1119 bool WebLocalFrameImpl::isContinuousSpellCheckingEnabled() const 1120 { 1121 return frame()->spellChecker().isContinuousSpellCheckingEnabled(); 1122 } 1123 1124 void WebLocalFrameImpl::requestTextChecking(const WebElement& webElement) 1125 { 1126 if (webElement.isNull()) 1127 return; 1128 frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>()); 1129 } 1130 1131 void WebLocalFrameImpl::replaceMisspelledRange(const WebString& text) 1132 { 1133 // If this caret selection has two or more markers, this function replace the range covered by the first marker with the specified word as Microsoft Word does. 1134 if (pluginContainerFromFrame(frame())) 1135 return; 1136 RefPtrWillBeRawPtr<Range> caretRange = frame()->selection().toNormalizedRange(); 1137 if (!caretRange) 1138 return; 1139 WillBeHeapVector<DocumentMarker*> markers = frame()->document()->markers().markersInRange(caretRange.get(), DocumentMarker::MisspellingMarkers()); 1140 if (markers.size() < 1 || markers[0]->startOffset() >= markers[0]->endOffset()) 1141 return; 1142 RefPtrWillBeRawPtr<Range> markerRange = Range::create(caretRange->ownerDocument(), caretRange->startContainer(), markers[0]->startOffset(), caretRange->endContainer(), markers[0]->endOffset()); 1143 if (!markerRange) 1144 return; 1145 frame()->selection().setSelection(VisibleSelection(markerRange.get()), CharacterGranularity); 1146 frame()->editor().replaceSelectionWithText(text, false, false); 1147 } 1148 1149 void WebLocalFrameImpl::removeSpellingMarkers() 1150 { 1151 frame()->document()->markers().removeMarkers(DocumentMarker::MisspellingMarkers()); 1152 } 1153 1154 bool WebLocalFrameImpl::hasSelection() const 1155 { 1156 WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame()); 1157 if (pluginContainer) 1158 return pluginContainer->plugin()->hasSelection(); 1159 1160 // frame()->selection()->isNone() never returns true. 1161 return frame()->selection().start() != frame()->selection().end(); 1162 } 1163 1164 WebRange WebLocalFrameImpl::selectionRange() const 1165 { 1166 return frame()->selection().toNormalizedRange(); 1167 } 1168 1169 WebString WebLocalFrameImpl::selectionAsText() const 1170 { 1171 WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame()); 1172 if (pluginContainer) 1173 return pluginContainer->plugin()->selectionAsText(); 1174 1175 RefPtrWillBeRawPtr<Range> range = frame()->selection().toNormalizedRange(); 1176 if (!range) 1177 return WebString(); 1178 1179 String text = range->text(); 1180 #if OS(WIN) 1181 replaceNewlinesWithWindowsStyleNewlines(text); 1182 #endif 1183 replaceNBSPWithSpace(text); 1184 return text; 1185 } 1186 1187 WebString WebLocalFrameImpl::selectionAsMarkup() const 1188 { 1189 WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame()); 1190 if (pluginContainer) 1191 return pluginContainer->plugin()->selectionAsMarkup(); 1192 1193 RefPtrWillBeRawPtr<Range> range = frame()->selection().toNormalizedRange(); 1194 if (!range) 1195 return WebString(); 1196 1197 return createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs); 1198 } 1199 1200 void WebLocalFrameImpl::selectWordAroundPosition(LocalFrame* frame, VisiblePosition position) 1201 { 1202 VisibleSelection selection(position); 1203 selection.expandUsingGranularity(WordGranularity); 1204 1205 TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity; 1206 frame->selection().setSelection(selection, granularity); 1207 } 1208 1209 bool WebLocalFrameImpl::selectWordAroundCaret() 1210 { 1211 FrameSelection& selection = frame()->selection(); 1212 if (selection.isNone() || selection.isRange()) 1213 return false; 1214 selectWordAroundPosition(frame(), selection.selection().visibleStart()); 1215 return true; 1216 } 1217 1218 void WebLocalFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent) 1219 { 1220 moveRangeSelection(base, extent); 1221 } 1222 1223 void WebLocalFrameImpl::selectRange(const WebRange& webRange) 1224 { 1225 if (RefPtrWillBeRawPtr<Range> range = static_cast<PassRefPtrWillBeRawPtr<Range> >(webRange)) 1226 frame()->selection().setSelectedRange(range.get(), WebCore::VP_DEFAULT_AFFINITY, FrameSelection::NonDirectional, NotUserTriggered); 1227 } 1228 1229 void WebLocalFrameImpl::moveRangeSelection(const WebPoint& base, const WebPoint& extent) 1230 { 1231 VisiblePosition basePosition = visiblePositionForWindowPoint(base); 1232 VisiblePosition extentPosition = visiblePositionForWindowPoint(extent); 1233 VisibleSelection newSelection = VisibleSelection(basePosition, extentPosition); 1234 frame()->selection().setSelection(newSelection, CharacterGranularity); 1235 } 1236 1237 void WebLocalFrameImpl::moveCaretSelection(const WebPoint& point) 1238 { 1239 Element* editable = frame()->selection().rootEditableElement(); 1240 if (!editable) 1241 return; 1242 1243 VisiblePosition position = visiblePositionForWindowPoint(point); 1244 frame()->selection().moveTo(position, UserTriggered); 1245 } 1246 1247 bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end) 1248 { 1249 return frame()->inputMethodController().setEditableSelectionOffsets(PlainTextRange(start, end)); 1250 } 1251 1252 bool WebLocalFrameImpl::setCompositionFromExistingText(int compositionStart, int compositionEnd, const WebVector<WebCompositionUnderline>& underlines) 1253 { 1254 if (!frame()->editor().canEdit()) 1255 return false; 1256 1257 InputMethodController& inputMethodController = frame()->inputMethodController(); 1258 inputMethodController.cancelComposition(); 1259 1260 if (compositionStart == compositionEnd) 1261 return true; 1262 1263 inputMethodController.setCompositionFromExistingText(CompositionUnderlineVectorBuilder(underlines), compositionStart, compositionEnd); 1264 1265 return true; 1266 } 1267 1268 void WebLocalFrameImpl::extendSelectionAndDelete(int before, int after) 1269 { 1270 if (WebPlugin* plugin = focusedPluginIfInputMethodSupported()) { 1271 plugin->extendSelectionAndDelete(before, after); 1272 return; 1273 } 1274 frame()->inputMethodController().extendSelectionAndDelete(before, after); 1275 } 1276 1277 void WebLocalFrameImpl::setCaretVisible(bool visible) 1278 { 1279 frame()->selection().setCaretVisible(visible); 1280 } 1281 1282 VisiblePosition WebLocalFrameImpl::visiblePositionForWindowPoint(const WebPoint& point) 1283 { 1284 // FIXME(bokan): crbug.com/371902 - These scale/pinch transforms shouldn't 1285 // be ad hoc and explicit. 1286 PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport(); 1287 FloatPoint unscaledPoint(point); 1288 unscaledPoint.scale(1 / view()->pageScaleFactor(), 1 / view()->pageScaleFactor()); 1289 unscaledPoint.moveBy(pinchViewport.visibleRect().location()); 1290 1291 HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent; 1292 HitTestResult result(frame()->view()->windowToContents(roundedIntPoint(unscaledPoint))); 1293 frame()->document()->renderView()->layer()->hitTest(request, result); 1294 1295 if (Node* node = result.targetNode()) 1296 return frame()->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node); 1297 return VisiblePosition(); 1298 } 1299 1300 WebPlugin* WebLocalFrameImpl::focusedPluginIfInputMethodSupported() 1301 { 1302 WebPluginContainerImpl* container = WebLocalFrameImpl::pluginContainerFromNode(frame(), WebNode(frame()->document()->focusedElement())); 1303 if (container && container->supportsInputMethod()) 1304 return container->plugin(); 1305 return 0; 1306 } 1307 1308 int WebLocalFrameImpl::printBegin(const WebPrintParams& printParams, const WebNode& constrainToNode) 1309 { 1310 ASSERT(!frame()->document()->isFrameSet()); 1311 WebPluginContainerImpl* pluginContainer = 0; 1312 if (constrainToNode.isNull()) { 1313 // If this is a plugin document, check if the plugin supports its own 1314 // printing. If it does, we will delegate all printing to that. 1315 pluginContainer = pluginContainerFromFrame(frame()); 1316 } else { 1317 // We only support printing plugin nodes for now. 1318 pluginContainer = toWebPluginContainerImpl(constrainToNode.pluginContainer()); 1319 } 1320 1321 if (pluginContainer && pluginContainer->supportsPaginatedPrint()) 1322 m_printContext = adoptPtr(new ChromePluginPrintContext(frame(), pluginContainer, printParams)); 1323 else 1324 m_printContext = adoptPtr(new ChromePrintContext(frame())); 1325 1326 FloatRect rect(0, 0, static_cast<float>(printParams.printContentArea.width), static_cast<float>(printParams.printContentArea.height)); 1327 m_printContext->begin(rect.width(), rect.height()); 1328 float pageHeight; 1329 // We ignore the overlays calculation for now since they are generated in the 1330 // browser. pageHeight is actually an output parameter. 1331 m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight); 1332 1333 return m_printContext->pageCount(); 1334 } 1335 1336 float WebLocalFrameImpl::getPrintPageShrink(int page) 1337 { 1338 ASSERT(m_printContext && page >= 0); 1339 return m_printContext->getPageShrink(page); 1340 } 1341 1342 float WebLocalFrameImpl::printPage(int page, WebCanvas* canvas) 1343 { 1344 #if ENABLE(PRINTING) 1345 ASSERT(m_printContext && page >= 0 && frame() && frame()->document()); 1346 1347 GraphicsContext graphicsContext(canvas); 1348 graphicsContext.setPrinting(true); 1349 return m_printContext->spoolPage(graphicsContext, page); 1350 #else 1351 return 0; 1352 #endif 1353 } 1354 1355 void WebLocalFrameImpl::printEnd() 1356 { 1357 ASSERT(m_printContext); 1358 m_printContext->end(); 1359 m_printContext.clear(); 1360 } 1361 1362 bool WebLocalFrameImpl::isPrintScalingDisabledForPlugin(const WebNode& node) 1363 { 1364 WebPluginContainerImpl* pluginContainer = node.isNull() ? pluginContainerFromFrame(frame()) : toWebPluginContainerImpl(node.pluginContainer()); 1365 1366 if (!pluginContainer || !pluginContainer->supportsPaginatedPrint()) 1367 return false; 1368 1369 return pluginContainer->isPrintScalingDisabled(); 1370 } 1371 1372 bool WebLocalFrameImpl::hasCustomPageSizeStyle(int pageIndex) 1373 { 1374 return frame()->document()->styleForPage(pageIndex)->pageSizeType() != PAGE_SIZE_AUTO; 1375 } 1376 1377 bool WebLocalFrameImpl::isPageBoxVisible(int pageIndex) 1378 { 1379 return frame()->document()->isPageBoxVisible(pageIndex); 1380 } 1381 1382 void WebLocalFrameImpl::pageSizeAndMarginsInPixels(int pageIndex, WebSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft) 1383 { 1384 IntSize size = pageSize; 1385 frame()->document()->pageSizeAndMarginsInPixels(pageIndex, size, marginTop, marginRight, marginBottom, marginLeft); 1386 pageSize = size; 1387 } 1388 1389 WebString WebLocalFrameImpl::pageProperty(const WebString& propertyName, int pageIndex) 1390 { 1391 ASSERT(m_printContext); 1392 return m_printContext->pageProperty(frame(), propertyName.utf8().data(), pageIndex); 1393 } 1394 1395 bool WebLocalFrameImpl::find(int identifier, const WebString& searchText, const WebFindOptions& options, bool wrapWithinFrame, WebRect* selectionRect) 1396 { 1397 return ensureTextFinder().find(identifier, searchText, options, wrapWithinFrame, selectionRect); 1398 } 1399 1400 void WebLocalFrameImpl::stopFinding(bool clearSelection) 1401 { 1402 if (m_textFinder) { 1403 if (!clearSelection) 1404 setFindEndstateFocusAndSelection(); 1405 m_textFinder->stopFindingAndClearSelection(); 1406 } 1407 } 1408 1409 void WebLocalFrameImpl::scopeStringMatches(int identifier, const WebString& searchText, const WebFindOptions& options, bool reset) 1410 { 1411 ensureTextFinder().scopeStringMatches(identifier, searchText, options, reset); 1412 } 1413 1414 void WebLocalFrameImpl::cancelPendingScopingEffort() 1415 { 1416 if (m_textFinder) 1417 m_textFinder->cancelPendingScopingEffort(); 1418 } 1419 1420 void WebLocalFrameImpl::increaseMatchCount(int count, int identifier) 1421 { 1422 // This function should only be called on the mainframe. 1423 ASSERT(!parent()); 1424 ensureTextFinder().increaseMatchCount(identifier, count); 1425 } 1426 1427 void WebLocalFrameImpl::resetMatchCount() 1428 { 1429 ensureTextFinder().resetMatchCount(); 1430 } 1431 1432 void WebLocalFrameImpl::sendOrientationChangeEvent() 1433 { 1434 if (frame()) 1435 frame()->sendOrientationChangeEvent(); 1436 } 1437 1438 void WebLocalFrameImpl::dispatchMessageEventWithOriginCheck(const WebSecurityOrigin& intendedTargetOrigin, const WebDOMEvent& event) 1439 { 1440 ASSERT(!event.isNull()); 1441 frame()->domWindow()->dispatchMessageEventWithOriginCheck(intendedTargetOrigin.get(), event, nullptr); 1442 } 1443 1444 int WebLocalFrameImpl::findMatchMarkersVersion() const 1445 { 1446 ASSERT(!parent()); 1447 1448 if (m_textFinder) 1449 return m_textFinder->findMatchMarkersVersion(); 1450 return 0; 1451 } 1452 1453 int WebLocalFrameImpl::selectNearestFindMatch(const WebFloatPoint& point, WebRect* selectionRect) 1454 { 1455 ASSERT(!parent()); 1456 return ensureTextFinder().selectNearestFindMatch(point, selectionRect); 1457 } 1458 1459 WebFloatRect WebLocalFrameImpl::activeFindMatchRect() 1460 { 1461 ASSERT(!parent()); 1462 1463 if (m_textFinder) 1464 return m_textFinder->activeFindMatchRect(); 1465 return WebFloatRect(); 1466 } 1467 1468 void WebLocalFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects) 1469 { 1470 ASSERT(!parent()); 1471 ensureTextFinder().findMatchRects(outputRects); 1472 } 1473 1474 void WebLocalFrameImpl::setTickmarks(const WebVector<WebRect>& tickmarks) 1475 { 1476 if (frameView()) { 1477 Vector<IntRect> tickmarksConverted(tickmarks.size()); 1478 for (size_t i = 0; i < tickmarks.size(); ++i) 1479 tickmarksConverted[i] = tickmarks[i]; 1480 frameView()->setTickmarks(tickmarksConverted); 1481 invalidateScrollbar(); 1482 } 1483 } 1484 1485 WebString WebLocalFrameImpl::contentAsText(size_t maxChars) const 1486 { 1487 if (!frame()) 1488 return WebString(); 1489 StringBuilder text; 1490 frameContentAsPlainText(maxChars, frame(), text); 1491 return text.toString(); 1492 } 1493 1494 WebString WebLocalFrameImpl::contentAsMarkup() const 1495 { 1496 if (!frame()) 1497 return WebString(); 1498 return createFullMarkup(frame()->document()); 1499 } 1500 1501 WebString WebLocalFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const 1502 { 1503 RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal; 1504 1505 if (toShow & RenderAsTextDebug) 1506 behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting; 1507 1508 if (toShow & RenderAsTextPrinting) 1509 behavior |= RenderAsTextPrintingMode; 1510 1511 return externalRepresentation(frame(), behavior); 1512 } 1513 1514 WebString WebLocalFrameImpl::markerTextForListItem(const WebElement& webElement) const 1515 { 1516 return WebCore::markerTextForListItem(const_cast<Element*>(webElement.constUnwrap<Element>())); 1517 } 1518 1519 void WebLocalFrameImpl::printPagesWithBoundaries(WebCanvas* canvas, const WebSize& pageSizeInPixels) 1520 { 1521 ASSERT(m_printContext); 1522 1523 GraphicsContext graphicsContext(canvas); 1524 graphicsContext.setPrinting(true); 1525 1526 m_printContext->spoolAllPagesWithBoundaries(graphicsContext, FloatSize(pageSizeInPixels.width, pageSizeInPixels.height)); 1527 } 1528 1529 WebRect WebLocalFrameImpl::selectionBoundsRect() const 1530 { 1531 return hasSelection() ? WebRect(IntRect(frame()->selection().bounds(false))) : WebRect(); 1532 } 1533 1534 bool WebLocalFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const 1535 { 1536 if (!frame()) 1537 return false; 1538 return frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length); 1539 } 1540 1541 WebString WebLocalFrameImpl::layerTreeAsText(bool showDebugInfo) const 1542 { 1543 if (!frame()) 1544 return WebString(); 1545 1546 return WebString(frame()->layerTreeAsText(showDebugInfo ? LayerTreeIncludesDebugInfo : LayerTreeNormal)); 1547 } 1548 1549 // WebLocalFrameImpl public --------------------------------------------------------- 1550 1551 WebLocalFrame* WebLocalFrame::create(WebFrameClient* client) 1552 { 1553 return WebLocalFrameImpl::create(client); 1554 } 1555 1556 WebLocalFrameImpl* WebLocalFrameImpl::create(WebFrameClient* client) 1557 { 1558 return adoptRef(new WebLocalFrameImpl(client)).leakRef(); 1559 } 1560 1561 WebLocalFrameImpl::WebLocalFrameImpl(WebFrameClient* client) 1562 : m_frameLoaderClientImpl(this) 1563 , m_client(client) 1564 , m_permissionClient(0) 1565 , m_inputEventsScaleFactorForEmulation(1) 1566 , m_userMediaClientImpl(this) 1567 , m_geolocationClientProxy(adoptPtr(new GeolocationClientProxy(client ? client->geolocationClient() : 0))) 1568 { 1569 blink::Platform::current()->incrementStatsCounter(webFrameActiveCount); 1570 frameCount++; 1571 } 1572 1573 WebLocalFrameImpl::~WebLocalFrameImpl() 1574 { 1575 blink::Platform::current()->decrementStatsCounter(webFrameActiveCount); 1576 frameCount--; 1577 1578 cancelPendingScopingEffort(); 1579 } 1580 1581 void WebLocalFrameImpl::setWebCoreFrame(PassRefPtr<WebCore::LocalFrame> frame) 1582 { 1583 m_frame = frame; 1584 1585 // FIXME: we shouldn't add overhead to every frame by registering these objects when they're not used. 1586 if (m_frame) { 1587 OwnPtr<NotificationPresenterImpl> notificationPresenter = adoptPtr(new NotificationPresenterImpl()); 1588 if (m_client) 1589 notificationPresenter->initialize(m_client->notificationPresenter()); 1590 1591 provideNotification(*m_frame, notificationPresenter.release()); 1592 provideUserMediaTo(*m_frame, &m_userMediaClientImpl); 1593 provideGeolocationTo(*m_frame, m_geolocationClientProxy.get()); 1594 m_geolocationClientProxy->setController(GeolocationController::from(m_frame.get())); 1595 provideMIDITo(*m_frame, MIDIClientProxy::create(m_client ? m_client->webMIDIClient() : 0)); 1596 if (RuntimeEnabledFeatures::screenOrientationEnabled()) 1597 ScreenOrientationController::provideTo(*m_frame, m_client ? m_client->webScreenOrientationClient() : 0); 1598 provideLocalFileSystemTo(*m_frame, LocalFileSystemClient::create()); 1599 } 1600 } 1601 1602 void WebLocalFrameImpl::initializeAsMainFrame(WebCore::Page* page) 1603 { 1604 setWebCoreFrame(LocalFrame::create(&m_frameLoaderClientImpl, &page->frameHost(), 0)); 1605 1606 // We must call init() after m_frame is assigned because it is referenced 1607 // during init(). 1608 m_frame->init(); 1609 } 1610 1611 PassRefPtr<LocalFrame> WebLocalFrameImpl::createChildFrame(const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement) 1612 { 1613 ASSERT(m_client); 1614 WebLocalFrameImpl* webframeChild = toWebLocalFrameImpl(m_client->createChildFrame(this, request.frameName())); 1615 if (!webframeChild) 1616 return nullptr; 1617 1618 // FIXME: Using subResourceAttributeName as fallback is not a perfect 1619 // solution. subResourceAttributeName returns just one attribute name. The 1620 // element might not have the attribute, and there might be other attributes 1621 // which can identify the element. 1622 RefPtr<LocalFrame> child = webframeChild->initializeAsChildFrame(frame()->host(), ownerElement, request.frameName(), ownerElement->getAttribute(ownerElement->subResourceAttributeName())); 1623 // Initializing the WebCore frame may cause the new child to be detached, since it may dispatch a load event in the parent. 1624 if (!child->tree().parent()) 1625 return nullptr; 1626 1627 // If we're moving in the back/forward list, we might want to replace the content 1628 // of this child frame with whatever was there at that point. 1629 RefPtr<HistoryItem> childItem; 1630 if (isBackForwardLoadType(frame()->loader().loadType()) && !frame()->document()->loadEventFinished()) 1631 childItem = PassRefPtr<HistoryItem>(webframeChild->client()->historyItemForNewChildFrame(webframeChild)); 1632 1633 if (childItem) 1634 child->loader().loadHistoryItem(childItem.get()); 1635 else 1636 child->loader().load(FrameLoadRequest(0, request.resourceRequest(), "_self")); 1637 1638 // Note a synchronous navigation (about:blank) would have already processed 1639 // onload, so it is possible for the child frame to have already been 1640 // detached by script in the page. 1641 if (!child->tree().parent()) 1642 return nullptr; 1643 return child; 1644 } 1645 1646 void WebLocalFrameImpl::didChangeContentsSize(const IntSize& size) 1647 { 1648 // This is only possible on the main frame. 1649 if (m_textFinder && m_textFinder->totalMatchCount() > 0) { 1650 ASSERT(!parent()); 1651 m_textFinder->increaseMarkerVersion(); 1652 } 1653 } 1654 1655 void WebLocalFrameImpl::createFrameView() 1656 { 1657 TRACE_EVENT0("webkit", "WebLocalFrameImpl::createFrameView"); 1658 1659 ASSERT(frame()); // If frame() doesn't exist, we probably didn't init properly. 1660 1661 WebViewImpl* webView = viewImpl(); 1662 bool isMainFrame = webView->mainFrameImpl()->frame() == frame(); 1663 if (isMainFrame) 1664 webView->suppressInvalidations(true); 1665 1666 frame()->createView(webView->size(), webView->baseBackgroundColor(), webView->isTransparent()); 1667 if (webView->shouldAutoResize() && isMainFrame) 1668 frame()->view()->enableAutoSizeMode(true, webView->minAutoSize(), webView->maxAutoSize()); 1669 1670 frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation); 1671 1672 if (isMainFrame) 1673 webView->suppressInvalidations(false); 1674 } 1675 1676 WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame) 1677 { 1678 if (!frame) 1679 return 0; 1680 return fromFrame(*frame); 1681 } 1682 1683 WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame& frame) 1684 { 1685 FrameLoaderClient* client = frame.loader().client(); 1686 if (!client || !client->isFrameLoaderClientImpl()) 1687 return 0; 1688 return toFrameLoaderClientImpl(client)->webFrame(); 1689 } 1690 1691 WebLocalFrameImpl* WebLocalFrameImpl::fromFrameOwnerElement(Element* element) 1692 { 1693 // FIXME: Why do we check specifically for <iframe> and <frame> here? Why can't we get the WebLocalFrameImpl from an <object> element, for example. 1694 if (!isHTMLFrameElementBase(element)) 1695 return 0; 1696 return fromFrame(toLocalFrame(toHTMLFrameElementBase(element)->contentFrame())); 1697 } 1698 1699 WebViewImpl* WebLocalFrameImpl::viewImpl() const 1700 { 1701 if (!frame()) 1702 return 0; 1703 return WebViewImpl::fromPage(frame()->page()); 1704 } 1705 1706 WebDataSourceImpl* WebLocalFrameImpl::dataSourceImpl() const 1707 { 1708 return static_cast<WebDataSourceImpl*>(dataSource()); 1709 } 1710 1711 WebDataSourceImpl* WebLocalFrameImpl::provisionalDataSourceImpl() const 1712 { 1713 return static_cast<WebDataSourceImpl*>(provisionalDataSource()); 1714 } 1715 1716 void WebLocalFrameImpl::setFindEndstateFocusAndSelection() 1717 { 1718 WebLocalFrameImpl* mainFrameImpl = viewImpl()->mainFrameImpl(); 1719 1720 if (this != mainFrameImpl->activeMatchFrame()) 1721 return; 1722 1723 if (Range* activeMatch = m_textFinder->activeMatch()) { 1724 // If the user has set the selection since the match was found, we 1725 // don't focus anything. 1726 VisibleSelection selection(frame()->selection().selection()); 1727 if (!selection.isNone()) 1728 return; 1729 1730 // Try to find the first focusable node up the chain, which will, for 1731 // example, focus links if we have found text within the link. 1732 Node* node = activeMatch->firstNode(); 1733 if (node && node->isInShadowTree()) { 1734 if (Node* host = node->shadowHost()) { 1735 if (isHTMLInputElement(*host) || isHTMLTextAreaElement(*host)) 1736 node = host; 1737 } 1738 } 1739 for (; node; node = node->parentNode()) { 1740 if (!node->isElementNode()) 1741 continue; 1742 Element* element = toElement(node); 1743 if (element->isFocusable()) { 1744 // Found a focusable parent node. Set the active match as the 1745 // selection and focus to the focusable node. 1746 frame()->selection().setSelection(VisibleSelection(activeMatch)); 1747 frame()->document()->setFocusedElement(element); 1748 return; 1749 } 1750 } 1751 1752 // Iterate over all the nodes in the range until we find a focusable node. 1753 // This, for example, sets focus to the first link if you search for 1754 // text and text that is within one or more links. 1755 node = activeMatch->firstNode(); 1756 for (; node && node != activeMatch->pastLastNode(); node = NodeTraversal::next(*node)) { 1757 if (!node->isElementNode()) 1758 continue; 1759 Element* element = toElement(node); 1760 if (element->isFocusable()) { 1761 frame()->document()->setFocusedElement(element); 1762 return; 1763 } 1764 } 1765 1766 // No node related to the active match was focusable, so set the 1767 // active match as the selection (so that when you end the Find session, 1768 // you'll have the last thing you found highlighted) and make sure that 1769 // we have nothing focused (otherwise you might have text selected but 1770 // a link focused, which is weird). 1771 frame()->selection().setSelection(VisibleSelection(activeMatch)); 1772 frame()->document()->setFocusedElement(nullptr); 1773 1774 // Finally clear the active match, for two reasons: 1775 // We just finished the find 'session' and we don't want future (potentially 1776 // unrelated) find 'sessions' operations to start at the same place. 1777 // The WebLocalFrameImpl could get reused and the activeMatch could end up pointing 1778 // to a document that is no longer valid. Keeping an invalid reference around 1779 // is just asking for trouble. 1780 m_textFinder->resetActiveMatch(); 1781 } 1782 } 1783 1784 void WebLocalFrameImpl::didFail(const ResourceError& error, bool wasProvisional) 1785 { 1786 if (!client()) 1787 return; 1788 WebURLError webError = error; 1789 if (wasProvisional) 1790 client()->didFailProvisionalLoad(this, webError); 1791 else 1792 client()->didFailLoad(this, webError); 1793 } 1794 1795 void WebLocalFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars) 1796 { 1797 frame()->view()->setCanHaveScrollbars(canHaveScrollbars); 1798 } 1799 1800 void WebLocalFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor) 1801 { 1802 m_inputEventsOffsetForEmulation = offset; 1803 m_inputEventsScaleFactorForEmulation = contentScaleFactor; 1804 if (frame()->view()) 1805 frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation); 1806 } 1807 1808 void WebLocalFrameImpl::loadJavaScriptURL(const KURL& url) 1809 { 1810 // This is copied from ScriptController::executeScriptIfJavaScriptURL. 1811 // Unfortunately, we cannot just use that method since it is private, and 1812 // it also doesn't quite behave as we require it to for bookmarklets. The 1813 // key difference is that we need to suppress loading the string result 1814 // from evaluating the JS URL if executing the JS URL resulted in a 1815 // location change. We also allow a JS URL to be loaded even if scripts on 1816 // the page are otherwise disabled. 1817 1818 if (!frame()->document() || !frame()->page()) 1819 return; 1820 1821 RefPtrWillBeRawPtr<Document> ownerDocument(frame()->document()); 1822 1823 // Protect privileged pages against bookmarklets and other javascript manipulations. 1824 if (SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(frame()->document()->url().protocol())) 1825 return; 1826 1827 String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:"))); 1828 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); 1829 v8::HandleScope handleScope(toIsolate(frame())); 1830 v8::Local<v8::Value> result = frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(script)); 1831 if (result.IsEmpty() || !result->IsString()) 1832 return; 1833 String scriptResult = toCoreString(v8::Handle<v8::String>::Cast(result)); 1834 if (!frame()->navigationScheduler().locationChangePending()) 1835 frame()->document()->loader()->replaceDocument(scriptResult, ownerDocument.get()); 1836 } 1837 1838 void WebLocalFrameImpl::addStyleSheetByURL(const WebString& url) 1839 { 1840 RefPtrWillBeRawPtr<Element> styleElement = frame()->document()->createElement(HTMLNames::linkTag, false); 1841 1842 styleElement->setAttribute(HTMLNames::typeAttr, "text/css"); 1843 styleElement->setAttribute(HTMLNames::relAttr, "stylesheet"); 1844 styleElement->setAttribute(HTMLNames::hrefAttr, url); 1845 1846 frame()->document()->head()->appendChild(styleElement.release(), IGNORE_EXCEPTION); 1847 } 1848 1849 void WebLocalFrameImpl::willDetachParent() 1850 { 1851 // Do not expect string scoping results from any frames that got detached 1852 // in the middle of the operation. 1853 if (m_textFinder && m_textFinder->scopingInProgress()) { 1854 1855 // There is a possibility that the frame being detached was the only 1856 // pending one. We need to make sure final replies can be sent. 1857 m_textFinder->flushCurrentScoping(); 1858 1859 m_textFinder->cancelPendingScopingEffort(); 1860 } 1861 } 1862 1863 WebLocalFrameImpl* WebLocalFrameImpl::activeMatchFrame() const 1864 { 1865 ASSERT(!parent()); 1866 1867 if (m_textFinder) 1868 return m_textFinder->activeMatchFrame(); 1869 return 0; 1870 } 1871 1872 WebCore::Range* WebLocalFrameImpl::activeMatch() const 1873 { 1874 if (m_textFinder) 1875 return m_textFinder->activeMatch(); 1876 return 0; 1877 } 1878 1879 TextFinder& WebLocalFrameImpl::ensureTextFinder() 1880 { 1881 if (!m_textFinder) 1882 m_textFinder = TextFinder::create(*this); 1883 1884 return *m_textFinder; 1885 } 1886 1887 void WebLocalFrameImpl::invalidateScrollbar() const 1888 { 1889 ASSERT(frame() && frame()->view()); 1890 FrameView* view = frame()->view(); 1891 // Invalidate the vertical scroll bar region for the view. 1892 Scrollbar* scrollbar = view->verticalScrollbar(); 1893 if (scrollbar) 1894 scrollbar->invalidate(); 1895 } 1896 1897 void WebLocalFrameImpl::invalidateAll() const 1898 { 1899 ASSERT(frame() && frame()->view()); 1900 FrameView* view = frame()->view(); 1901 view->invalidateRect(view->frameRect()); 1902 invalidateScrollbar(); 1903 } 1904 1905 PassRefPtr<LocalFrame> WebLocalFrameImpl::initializeAsChildFrame(FrameHost* host, FrameOwner* owner, const AtomicString& name, const AtomicString& fallbackName) 1906 { 1907 RefPtr<LocalFrame> frame = LocalFrame::create(&m_frameLoaderClientImpl, host, owner); 1908 setWebCoreFrame(frame); 1909 frame->tree().setName(name, fallbackName); 1910 // May dispatch JS events; frame may be detached after this. 1911 frame->init(); 1912 return frame; 1913 } 1914 1915 } // namespace blink 1916