|  | /* | 
|  | * Copyright (C) 2009 Google Inc. All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions are | 
|  | * met: | 
|  | * | 
|  | *     * Redistributions of source code must retain the above copyright | 
|  | * notice, this list of conditions and the following disclaimer. | 
|  | *     * Redistributions in binary form must reproduce the above | 
|  | * copyright notice, this list of conditions and the following disclaimer | 
|  | * in the documentation and/or other materials provided with the | 
|  | * distribution. | 
|  | *     * Neither the name of Google Inc. nor the names of its | 
|  | * contributors may be used to endorse or promote products derived from | 
|  | * this software without specific prior written permission. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | // How ownership works | 
|  | // ------------------- | 
|  | // | 
|  | // Big oh represents a refcounted relationship: owner O--- ownee | 
|  | // | 
|  | // WebView (for the toplevel frame only) | 
|  | //    O | 
|  | //    |           WebFrame | 
|  | //    |              O | 
|  | //    |              | | 
|  | //   Page O------- LocalFrame (m_mainFrame) O-------O FrameView | 
|  | //                   || | 
|  | //                   || | 
|  | //               FrameLoader | 
|  | // | 
|  | // FrameLoader and LocalFrame are formerly one object that was split apart because | 
|  | // it got too big. They basically have the same lifetime, hence the double line. | 
|  | // | 
|  | // From the perspective of the embedder, WebFrame is simply an object that it | 
|  | // allocates by calling WebFrame::create() and must be freed by calling close(). | 
|  | // Internally, WebFrame is actually refcounted and it holds a reference to its | 
|  | // corresponding LocalFrame in WebCore. | 
|  | // | 
|  | // How frames are destroyed | 
|  | // ------------------------ | 
|  | // | 
|  | // The main frame is never destroyed and is re-used. The FrameLoader is re-used | 
|  | // and a reference to the main frame is kept by the Page. | 
|  | // | 
|  | // When frame content is replaced, all subframes are destroyed. This happens | 
|  | // in FrameLoader::detachFromParent for each subframe in a pre-order depth-first | 
|  | // traversal. Note that child node order may not match DOM node order! | 
|  | // detachFromParent() calls FrameLoaderClient::detachedFromParent(), which calls | 
|  | // WebFrame::frameDetached(). This triggers WebFrame to clear its reference to | 
|  | // LocalFrame, and also notifies the embedder via WebFrameClient that the frame is | 
|  | // detached. Most embedders will invoke close() on the WebFrame at this point, | 
|  | // triggering its deletion unless something else is still retaining a reference. | 
|  | // | 
|  | // Thie client is expected to be set whenever the WebLocalFrameImpl is attached to | 
|  | // the DOM. | 
|  |  | 
|  | #include "sky/engine/config.h" | 
|  | #include "sky/engine/web/WebLocalFrameImpl.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include "mojo/public/cpp/system/data_pipe.h" | 
|  | #include "sky/engine/bindings/exception_state.h" | 
|  | #include "sky/engine/bindings/exception_state_placeholder.h" | 
|  | #include "sky/engine/core/dom/Document.h" | 
|  | #include "sky/engine/core/dom/Node.h" | 
|  | #include "sky/engine/core/dom/NodeTraversal.h" | 
|  | #include "sky/engine/core/dom/shadow/ShadowRoot.h" | 
|  | #include "sky/engine/core/editing/Editor.h" | 
|  | #include "sky/engine/core/editing/FrameSelection.h" | 
|  | #include "sky/engine/core/editing/InputMethodController.h" | 
|  | #include "sky/engine/core/editing/PlainTextRange.h" | 
|  | #include "sky/engine/core/editing/SpellChecker.h" | 
|  | #include "sky/engine/core/editing/TextAffinity.h" | 
|  | #include "sky/engine/core/editing/TextIterator.h" | 
|  | #include "sky/engine/core/editing/htmlediting.h" | 
|  | #include "sky/engine/core/frame/FrameHost.h" | 
|  | #include "sky/engine/core/frame/FrameView.h" | 
|  | #include "sky/engine/core/frame/LocalDOMWindow.h" | 
|  | #include "sky/engine/core/frame/Settings.h" | 
|  | #include "sky/engine/core/html/HTMLAnchorElement.h" | 
|  | #include "sky/engine/core/inspector/ConsoleMessage.h" | 
|  | #include "sky/engine/core/loader/MojoLoader.h" | 
|  | #include "sky/engine/core/page/EventHandler.h" | 
|  | #include "sky/engine/core/page/FocusController.h" | 
|  | #include "sky/engine/core/page/Page.h" | 
|  | #include "sky/engine/core/rendering/HitTestResult.h" | 
|  | #include "sky/engine/core/rendering/RenderBox.h" | 
|  | #include "sky/engine/core/rendering/RenderLayer.h" | 
|  | #include "sky/engine/core/rendering/RenderObject.h" | 
|  | #include "sky/engine/core/rendering/RenderTreeAsText.h" | 
|  | #include "sky/engine/core/rendering/RenderView.h" | 
|  | #include "sky/engine/core/rendering/style/StyleInheritedData.h" | 
|  | #include "sky/engine/platform/TraceEvent.h" | 
|  | #include "sky/engine/platform/clipboard/ClipboardUtilities.h" | 
|  | #include "sky/engine/platform/fonts/FontCache.h" | 
|  | #include "sky/engine/platform/graphics/GraphicsContext.h" | 
|  | #include "sky/engine/platform/graphics/skia/SkiaUtils.h" | 
|  | #include "sky/engine/platform/heap/Handle.h" | 
|  | #include "sky/engine/platform/network/ResourceRequest.h" | 
|  | #include "sky/engine/platform/weborigin/KURL.h" | 
|  | #include "sky/engine/platform/weborigin/SecurityPolicy.h" | 
|  | #include "sky/engine/public/platform/Platform.h" | 
|  | #include "sky/engine/public/platform/WebFloatPoint.h" | 
|  | #include "sky/engine/public/platform/WebFloatRect.h" | 
|  | #include "sky/engine/public/platform/WebLayer.h" | 
|  | #include "sky/engine/public/platform/WebPoint.h" | 
|  | #include "sky/engine/public/platform/WebRect.h" | 
|  | #include "sky/engine/public/platform/WebSize.h" | 
|  | #include "sky/engine/public/platform/WebURLError.h" | 
|  | #include "sky/engine/public/platform/WebVector.h" | 
|  | #include "sky/engine/public/web/WebConsoleMessage.h" | 
|  | #include "sky/engine/public/web/WebDocument.h" | 
|  | #include "sky/engine/public/web/WebElement.h" | 
|  | #include "sky/engine/public/web/WebFrameClient.h" | 
|  | #include "sky/engine/public/web/WebNode.h" | 
|  | #include "sky/engine/public/web/WebRange.h" | 
|  | #include "sky/engine/public/web/WebScriptSource.h" | 
|  | #include "sky/engine/web/CompositionUnderlineVectorBuilder.h" | 
|  | #include "sky/engine/web/WebViewImpl.h" | 
|  | #include "sky/engine/wtf/CurrentTime.h" | 
|  | #include "sky/engine/wtf/HashMap.h" | 
|  |  | 
|  | namespace blink { | 
|  |  | 
|  | static int frameCount = 0; | 
|  |  | 
|  | // Key for a StatsCounter tracking how many WebFrames are active. | 
|  | static const char webFrameActiveCount[] = "WebFrameActiveCount"; | 
|  |  | 
|  | static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) | 
|  | { | 
|  | Document* document = frame->document(); | 
|  | if (!document) | 
|  | return; | 
|  |  | 
|  | if (!frame->view()) | 
|  | return; | 
|  |  | 
|  | // Select the document body. | 
|  | RefPtr<Range> range(document->createRange()); | 
|  | TrackExceptionState exceptionState; | 
|  | range->selectNodeContents(document, exceptionState); | 
|  |  | 
|  | if (!exceptionState.had_exception()) { | 
|  | // The text iterator will walk nodes giving us text. This is similar to | 
|  | // the plainText() function in core/editing/TextIterator.h, but we implement the maximum | 
|  | // size and also copy the results directly into a wstring, avoiding the | 
|  | // string conversion. | 
|  | for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { | 
|  | it.appendTextToStringBuilder(output, 0, maxChars - output.length()); | 
|  | if (output.length() >= maxChars) | 
|  | return; // Filled up the buffer. | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // WebFrame ------------------------------------------------------------------- | 
|  |  | 
|  | int WebFrame::instanceCount() | 
|  | { | 
|  | return frameCount; | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::isWebLocalFrame() const | 
|  | { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame() | 
|  | { | 
|  | return this; | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::close() | 
|  | { | 
|  | m_client = 0; | 
|  |  | 
|  | deref(); // Balances ref() acquired in WebFrame::create | 
|  | } | 
|  |  | 
|  | WebSize WebLocalFrameImpl::contentsSize() const | 
|  | { | 
|  | return frame()->view()->size(); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::hasVisibleContent() const | 
|  | { | 
|  | return frame()->view()->width() > 0 && frame()->view()->height() > 0; | 
|  | } | 
|  |  | 
|  | WebRect WebLocalFrameImpl::visibleContentRect() const | 
|  | { | 
|  | return frame()->view()->frameRect(); | 
|  | } | 
|  |  | 
|  | WebView* WebLocalFrameImpl::view() const | 
|  | { | 
|  | return viewImpl(); | 
|  | } | 
|  |  | 
|  | WebDocument WebLocalFrameImpl::document() const | 
|  | { | 
|  | if (!frame() || !frame()->document()) | 
|  | return WebDocument(); | 
|  | return WebDocument(frame()->document()); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::executeScript(const WebScriptSource& source) | 
|  | { | 
|  | ASSERT(frame()); | 
|  | // TODO(dart) | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::addMessageToConsole(const WebConsoleMessage& message) | 
|  | { | 
|  | ASSERT(frame()); | 
|  |  | 
|  | MessageLevel webCoreMessageLevel; | 
|  | switch (message.level) { | 
|  | case WebConsoleMessage::LevelDebug: | 
|  | webCoreMessageLevel = DebugMessageLevel; | 
|  | break; | 
|  | case WebConsoleMessage::LevelLog: | 
|  | webCoreMessageLevel = LogMessageLevel; | 
|  | break; | 
|  | case WebConsoleMessage::LevelWarning: | 
|  | webCoreMessageLevel = WarningMessageLevel; | 
|  | break; | 
|  | case WebConsoleMessage::LevelError: | 
|  | webCoreMessageLevel = ErrorMessageLevel; | 
|  | break; | 
|  | default: | 
|  | ASSERT_NOT_REACHED(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | frame()->document()->addConsoleMessage(ConsoleMessage::create(OtherMessageSource, webCoreMessageLevel, message.text)); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::collectGarbage() | 
|  | { | 
|  | // TODO(dart): Implement. | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::loadFromDataPipeWithURL(mojo::ScopedDataPipeConsumerHandle responseStream, const WebURL& url) | 
|  | { | 
|  | frame()->mojoLoader().init(url); | 
|  | frame()->mojoLoader().parse(responseStream.Pass()); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::load(const WebURL& url) | 
|  | { | 
|  | frame()->mojoLoader().init(url); | 
|  | m_fetcher = adoptPtr(new MojoFetcher(this, url)); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::OnReceivedResponse(mojo::URLResponsePtr response) | 
|  | { | 
|  | m_fetcher.clear(); | 
|  | if (!response->body.is_valid()) | 
|  | LOG(FATAL) << "Response has no body."; | 
|  | frame()->mojoLoader().parse(response->body.Pass()); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::replaceSelection(const WebString& text) | 
|  | { | 
|  | bool selectReplacement = false; | 
|  | bool smartReplace = true; | 
|  | frame()->editor().replaceSelectionWithText(text, selectReplacement, smartReplace); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::insertText(const WebString& text) | 
|  | { | 
|  | if (frame()->inputMethodController().hasComposition()) | 
|  | frame()->inputMethodController().confirmComposition(text); | 
|  | else | 
|  | frame()->editor().insertText(text, 0); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::setMarkedText(const WebString& text, unsigned location, unsigned length) | 
|  | { | 
|  | Vector<CompositionUnderline> decorations; | 
|  | frame()->inputMethodController().setComposition(text, decorations, location, length); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::unmarkText() | 
|  | { | 
|  | frame()->inputMethodController().cancelComposition(); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::hasMarkedText() const | 
|  | { | 
|  | return frame()->inputMethodController().hasComposition(); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebNode& node) | 
|  | { | 
|  | ASSERT(frame()); | 
|  |  | 
|  | if (name.length() <= 2) | 
|  | return false; | 
|  |  | 
|  | // Since we don't have NSControl, we will convert the format of command | 
|  | // string and call the function on Editor directly. | 
|  | String command = name; | 
|  |  | 
|  | // Make sure the first letter is upper case. | 
|  | command.replace(0, 1, command.substring(0, 1).upper()); | 
|  |  | 
|  | // Remove the trailing ':' if existing. | 
|  | if (command[command.length() - 1] == UChar(':')) | 
|  | command = command.substring(0, command.length() - 1); | 
|  |  | 
|  | return frame()->editor().executeCommand(command); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::executeCommand(const WebString& name, const WebString& value, const WebNode& node) | 
|  | { | 
|  | ASSERT(frame()); | 
|  |  | 
|  | return frame()->editor().executeCommand(name, value); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const | 
|  | { | 
|  | ASSERT(frame()); | 
|  | return frame()->editor().command(name).isEnabled(); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::enableContinuousSpellChecking(bool enable) | 
|  | { | 
|  | if (enable == isContinuousSpellCheckingEnabled()) | 
|  | return; | 
|  | frame()->spellChecker().toggleContinuousSpellChecking(); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::isContinuousSpellCheckingEnabled() const | 
|  | { | 
|  | return frame()->spellChecker().isContinuousSpellCheckingEnabled(); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::requestTextChecking(const WebElement& webElement) | 
|  | { | 
|  | if (webElement.isNull()) | 
|  | return; | 
|  | frame()->spellChecker().requestTextChecking(*webElement.constUnwrap<Element>()); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::replaceMisspelledRange(const WebString& text) | 
|  | { | 
|  | frame()->spellChecker().replaceMisspelledRange(text); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::removeSpellingMarkers() | 
|  | { | 
|  | frame()->spellChecker().removeSpellingMarkers(); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::hasSelection() const | 
|  | { | 
|  | // frame()->selection()->isNone() never returns true. | 
|  | return frame()->selection().start() != frame()->selection().end(); | 
|  | } | 
|  |  | 
|  | WebRange WebLocalFrameImpl::selectionRange() const | 
|  | { | 
|  | return frame()->selection().toNormalizedRange(); | 
|  | } | 
|  |  | 
|  | WebString WebLocalFrameImpl::selectionAsText() const | 
|  | { | 
|  | RefPtr<Range> range = frame()->selection().toNormalizedRange(); | 
|  | if (!range) | 
|  | return WebString(); | 
|  |  | 
|  | String text = range->text(); | 
|  | replaceNBSPWithSpace(text); | 
|  | return text; | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::selectWordAroundPosition(LocalFrame* frame, VisiblePosition position) | 
|  | { | 
|  | VisibleSelection selection(position); | 
|  | selection.expandUsingGranularity(WordGranularity); | 
|  |  | 
|  | TextGranularity granularity = selection.isRange() ? WordGranularity : CharacterGranularity; | 
|  | frame->selection().setSelection(selection, granularity); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::selectWordAroundCaret() | 
|  | { | 
|  | FrameSelection& selection = frame()->selection(); | 
|  | if (selection.isNone() || selection.isRange()) | 
|  | return false; | 
|  | selectWordAroundPosition(frame(), selection.selection().visibleStart()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::selectRange(const WebPoint& base, const WebPoint& extent) | 
|  | { | 
|  | moveRangeSelection(base, extent); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::selectRange(const WebRange& webRange) | 
|  | { | 
|  | if (RefPtr<Range> range = static_cast<PassRefPtr<Range> >(webRange)) | 
|  | frame()->selection().setSelectedRange(range.get(), VP_DEFAULT_AFFINITY, FrameSelection::NonDirectional, NotUserTriggered); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::moveRangeSelection(const WebPoint& base, const WebPoint& extent) | 
|  | { | 
|  | VisiblePosition basePosition = visiblePositionForWindowPoint(base); | 
|  | VisiblePosition extentPosition = visiblePositionForWindowPoint(extent); | 
|  | VisibleSelection newSelection = VisibleSelection(basePosition, extentPosition); | 
|  | frame()->selection().setSelection(newSelection, CharacterGranularity); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::moveCaretSelection(const WebPoint& point) | 
|  | { | 
|  | Element* editable = frame()->selection().rootEditableElement(); | 
|  | if (!editable) | 
|  | return; | 
|  |  | 
|  | VisiblePosition position = visiblePositionForWindowPoint(point); | 
|  | frame()->selection().moveTo(position, UserTriggered); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end) | 
|  | { | 
|  | return frame()->inputMethodController().setEditableSelectionOffsets(PlainTextRange(start, end)); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::setCompositionFromExistingText(int compositionStart, int compositionEnd, const WebVector<WebCompositionUnderline>& underlines) | 
|  | { | 
|  | if (!frame()->editor().canEdit()) | 
|  | return false; | 
|  |  | 
|  | InputMethodController& inputMethodController = frame()->inputMethodController(); | 
|  | inputMethodController.cancelComposition(); | 
|  |  | 
|  | if (compositionStart == compositionEnd) | 
|  | return true; | 
|  |  | 
|  | inputMethodController.setCompositionFromExistingText(CompositionUnderlineVectorBuilder(underlines), compositionStart, compositionEnd); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::extendSelectionAndDelete(int before, int after) | 
|  | { | 
|  | frame()->inputMethodController().extendSelectionAndDelete(before, after); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::setCaretVisible(bool visible) | 
|  | { | 
|  | frame()->selection().setCaretVisible(visible); | 
|  | } | 
|  |  | 
|  | VisiblePosition WebLocalFrameImpl::visiblePositionForWindowPoint(const WebPoint& point) | 
|  | { | 
|  | HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping; | 
|  | HitTestResult result(frame()->view()->windowToContents(roundedIntPoint(FloatPoint(point)))); | 
|  | frame()->document()->renderView()->layer()->hitTest(request, result.hitTestLocation(), result); | 
|  |  | 
|  | if (Node* node = result.targetNode()) | 
|  | return frame()->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node); | 
|  | return VisiblePosition(); | 
|  | } | 
|  |  | 
|  | WebString WebLocalFrameImpl::contentAsText(size_t maxChars) const | 
|  | { | 
|  | if (!frame()) | 
|  | return WebString(); | 
|  | StringBuilder text; | 
|  | frameContentAsPlainText(maxChars, frame(), text); | 
|  | return text.toString(); | 
|  | } | 
|  |  | 
|  | WebString WebLocalFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const | 
|  | { | 
|  | RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal; | 
|  |  | 
|  | if (toShow & RenderAsTextDebug) | 
|  | behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting; | 
|  |  | 
|  | return externalRepresentation(frame(), behavior); | 
|  | } | 
|  |  | 
|  | bool WebLocalFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const | 
|  | { | 
|  | if (!frame()) | 
|  | return false; | 
|  | return frame()->spellChecker().selectionStartHasSpellingMarkerFor(from, length); | 
|  | } | 
|  |  | 
|  | // WebLocalFrameImpl public --------------------------------------------------------- | 
|  |  | 
|  | WebLocalFrame* WebLocalFrame::create(WebFrameClient* client) | 
|  | { | 
|  | return WebLocalFrameImpl::create(client); | 
|  | } | 
|  |  | 
|  | WebLocalFrameImpl* WebLocalFrameImpl::create(WebFrameClient* client) | 
|  | { | 
|  | return adoptRef(new WebLocalFrameImpl(client)).leakRef(); | 
|  | } | 
|  |  | 
|  | WebLocalFrameImpl::WebLocalFrameImpl(WebFrameClient* client) | 
|  | : m_frameLoaderClientImpl(this) | 
|  | , m_client(client) | 
|  | , m_inputEventsScaleFactorForEmulation(1) | 
|  | { | 
|  | Platform::current()->incrementStatsCounter(webFrameActiveCount); | 
|  | frameCount++; | 
|  | } | 
|  |  | 
|  | WebLocalFrameImpl::~WebLocalFrameImpl() | 
|  | { | 
|  | Platform::current()->decrementStatsCounter(webFrameActiveCount); | 
|  | frameCount--; | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::setCoreFrame(PassRefPtr<LocalFrame> frame) | 
|  | { | 
|  | m_frame = frame; | 
|  | } | 
|  |  | 
|  | PassRefPtr<LocalFrame> WebLocalFrameImpl::initializeCoreFrame(FrameHost* host) | 
|  | { | 
|  | RefPtr<LocalFrame> frame = LocalFrame::create(&m_frameLoaderClientImpl, host); | 
|  | setCoreFrame(frame); | 
|  | return frame; | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::createFrameView() | 
|  | { | 
|  | TRACE_EVENT0("blink", "WebLocalFrameImpl::createFrameView"); | 
|  |  | 
|  | ASSERT(frame()); // If frame() doesn't exist, we probably didn't init properly. | 
|  |  | 
|  | WebViewImpl* webView = viewImpl(); | 
|  | frame()->createView(webView->size(), webView->baseBackgroundColor(), webView->isTransparent()); | 
|  | frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation); | 
|  | } | 
|  |  | 
|  | WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame) | 
|  | { | 
|  | if (!frame) | 
|  | return 0; | 
|  | return fromFrame(*frame); | 
|  | } | 
|  |  | 
|  | WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame& frame) | 
|  | { | 
|  | FrameLoaderClient* client = frame.loaderClient(); | 
|  | if (!client || !client->isFrameLoaderClientImpl()) | 
|  | return 0; | 
|  | return toFrameLoaderClientImpl(client)->webFrame(); | 
|  | } | 
|  |  | 
|  | WebViewImpl* WebLocalFrameImpl::viewImpl() const | 
|  | { | 
|  | if (!frame()) | 
|  | return 0; | 
|  | return WebViewImpl::fromPage(frame()->page()); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::didFail(const ResourceError& error) | 
|  | { | 
|  | if (!client()) | 
|  | return; | 
|  | client()->didFailLoad(this, error); | 
|  | } | 
|  |  | 
|  | void WebLocalFrameImpl::setInputEventsTransformForEmulation(const IntSize& offset, float contentScaleFactor) | 
|  | { | 
|  | m_inputEventsOffsetForEmulation = offset; | 
|  | m_inputEventsScaleFactorForEmulation = contentScaleFactor; | 
|  | if (frame()->view()) | 
|  | frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation); | 
|  | } | 
|  |  | 
|  | } // namespace blink |