blob: f54780d2fe5263c51ca971438f9bc3c9e7acd006 [file] [log] [blame]
/*
* 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 "config.h"
#include "web/WebLocalFrameImpl.h"
#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/dom/Document.h"
#include "core/dom/Node.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/InputMethodController.h"
#include "core/editing/PlainTextRange.h"
#include "core/editing/SpellChecker.h"
#include "core/editing/TextAffinity.h"
#include "core/editing/TextIterator.h"
#include "core/editing/htmlediting.h"
#include "core/editing/markup.h"
#include "core/frame/Console.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/ScriptCallStack.h"
#include "core/loader/MojoLoader.h"
#include "core/page/Chrome.h"
#include "core/page/EventHandler.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/RenderBox.h"
#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/RenderTreeAsText.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/style/StyleInheritedData.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "platform/TraceEvent.h"
#include "platform/UserGestureIndicator.h"
#include "platform/clipboard/ClipboardUtilities.h"
#include "platform/fonts/FontCache.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsLayerClient.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/heap/Handle.h"
#include "platform/network/ResourceRequest.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/scroll/Scrollbar.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "public/platform/Platform.h"
#include "public/platform/WebFloatPoint.h"
#include "public/platform/WebFloatRect.h"
#include "public/platform/WebLayer.h"
#include "public/platform/WebPoint.h"
#include "public/platform/WebRect.h"
#include "public/platform/WebSize.h"
#include "public/platform/WebURLError.h"
#include "public/platform/WebVector.h"
#include "public/web/WebConsoleMessage.h"
#include "public/web/WebDocument.h"
#include "public/web/WebElement.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebNode.h"
#include "public/web/WebRange.h"
#include "public/web/WebScriptSource.h"
#include "web/CompositionUnderlineVectorBuilder.h"
#include "web/WebViewImpl.h"
#include "wtf/CurrentTime.h"
#include "wtf/HashMap.h"
#include <algorithm>
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->documentElement(), exceptionState);
if (!exceptionState.hadException()) {
// 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;
}
WebLocalFrame* WebLocalFrame::frameForCurrentContext()
{
v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
if (context.IsEmpty())
return 0;
return frameForContext(context);
}
WebLocalFrame* WebLocalFrame::frameForContext(v8::Handle<v8::Context> context)
{
return WebLocalFrameImpl::fromFrame(toFrameIfNotDetached(context));
}
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();
}
bool WebLocalFrameImpl::hasHorizontalScrollbar() const
{
// FIXME(sky): Remove
return false;
}
bool WebLocalFrameImpl::hasVerticalScrollbar() const
{
// FIXME(sky): Remove
return false;
}
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());
TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first());
v8::HandleScope handleScope(toIsolate(frame()));
frame()->script().executeScriptInMainWorld(ScriptSourceCode(source.code, source.url, position));
}
void WebLocalFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup)
{
ASSERT(frame());
RELEASE_ASSERT(worldID > 0);
RELEASE_ASSERT(worldID < EmbedderWorldIdLimit);
Vector<ScriptSourceCode> sources;
for (unsigned i = 0; i < numSources; ++i) {
TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first());
sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position));
}
v8::HandleScope handleScope(toIsolate(frame()));
frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0);
}
void WebLocalFrameImpl::setIsolatedWorldHumanReadableName(int worldID, const WebString& humanReadableName)
{
ASSERT(frame());
DOMWrapperWorld::setIsolatedWorldHumanReadableName(worldID, humanReadableName);
}
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()
{
if (!frame())
return;
V8GCController::collectGarbage(v8::Isolate::GetCurrent());
}
v8::Handle<v8::Value> WebLocalFrameImpl::executeScriptAndReturnValue(const WebScriptSource& source)
{
ASSERT(frame());
// TODO: Remove this after blink has rolled and chromium change landed. (crrev.com/516753002)
UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine), OrdinalNumber::first());
return frame()->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(source.code, source.url, position));
}
void WebLocalFrameImpl::executeScriptInIsolatedWorld(int worldID, const WebScriptSource* sourcesIn, unsigned numSources, int extensionGroup, WebVector<v8::Local<v8::Value> >* results)
{
ASSERT(frame());
RELEASE_ASSERT(worldID > 0);
RELEASE_ASSERT(worldID < EmbedderWorldIdLimit);
Vector<ScriptSourceCode> sources;
for (unsigned i = 0; i < numSources; ++i) {
TextPosition position(OrdinalNumber::fromOneBasedInt(sourcesIn[i].startLine), OrdinalNumber::first());
sources.append(ScriptSourceCode(sourcesIn[i].code, sourcesIn[i].url, position));
}
if (results) {
Vector<v8::Local<v8::Value> > scriptResults;
frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, &scriptResults);
WebVector<v8::Local<v8::Value> > v8Results(scriptResults.size());
for (unsigned i = 0; i < scriptResults.size(); i++)
v8Results[i] = v8::Local<v8::Value>::New(toIsolate(frame()), scriptResults[i]);
results->swap(v8Results);
} else {
v8::HandleScope handleScope(toIsolate(frame()));
frame()->script().executeScriptInIsolatedWorld(worldID, sources, extensionGroup, 0);
}
}
v8::Handle<v8::Value> WebLocalFrameImpl::callFunctionEvenIfScriptDisabled(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> argv[])
{
ASSERT(frame());
return frame()->script().callFunction(function, receiver, argc, argv);
}
v8::Local<v8::Context> WebLocalFrameImpl::mainWorldScriptContext() const
{
return toV8Context(frame(), DOMWrapperWorld::mainWorld());
}
void WebLocalFrameImpl::load(const WebURL& url, mojo::ScopedDataPipeConsumerHandle responseStream)
{
frame()->mojoLoader().load(url, responseStream.Pass());
}
void WebLocalFrameImpl::setReferrerForRequest(WebURLRequest& request, const WebURL& referrerURL)
{
String referrer = referrerURL.isEmpty() ? frame()->document()->outgoingReferrer() : String(referrerURL.spec().utf16());
referrer = SecurityPolicy::generateReferrerHeader(frame()->document()->referrerPolicy(), request.url(), referrer);
if (referrer.isEmpty())
return;
request.setHTTPReferrer(referrer, static_cast<WebReferrerPolicy>(frame()->document()->referrerPolicy()));
}
unsigned WebLocalFrameImpl::unloadListenerCount() const
{
return frame()->domWindow()->pendingUnloadEventListeners();
}
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();
}
WebRange WebLocalFrameImpl::markedRange() const
{
return frame()->inputMethodController().compositionRange();
}
bool WebLocalFrameImpl::firstRectForCharacterRange(unsigned location, unsigned length, WebRect& rect) const
{
if ((location + length < location) && (location + length))
length = 0;
Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
ASSERT(editable);
RefPtr<Range> range = PlainTextRange(location, location + length).createRange(*editable);
if (!range)
return false;
IntRect intRect = frame()->editor().firstRectForRange(range.get());
rect = WebRect(intRect);
rect = frame()->view()->contentsToWindow(rect);
return true;
}
size_t WebLocalFrameImpl::characterIndexForPoint(const WebPoint& webPoint) const
{
if (!frame())
return kNotFound;
IntPoint point = frame()->view()->windowToContents(webPoint);
HitTestResult result = frame()->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active);
RefPtr<Range> range = frame()->rangeForPoint(result.roundedPointInInnerNodeFrame());
if (!range)
return kNotFound;
Element* editable = frame()->selection().rootEditableElementOrDocumentElement();
ASSERT(editable);
return PlainTextRange::create(*editable, *range.get()).start();
}
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;
}
WebString WebLocalFrameImpl::selectionAsMarkup() const
{
RefPtr<Range> range = frame()->selection().toNormalizedRange();
if (!range)
return WebString();
return createMarkup(range.get(), 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
}
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);
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::contentAsMarkup() const
{
if (!frame())
return WebString();
return createMarkup(frame()->document());
}
WebString WebLocalFrameImpl::renderTreeAsText(RenderAsTextControls toShow) const
{
RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal;
if (toShow & RenderAsTextDebug)
behavior |= RenderAsTextShowCompositedLayers | RenderAsTextShowAddresses | RenderAsTextShowIDAndClass | RenderAsTextShowLayerNesting;
return externalRepresentation(frame(), behavior);
}
WebString WebLocalFrameImpl::markerTextForListItem(const WebElement& webElement) const
{
return WebString();
}
WebRect WebLocalFrameImpl::selectionBoundsRect() const
{
return hasSelection() ? WebRect(IntRect(frame()->selection().bounds(false))) : WebRect();
}
bool WebLocalFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) const
{
if (!frame())
return false;
return frame()->spellChecker().selectionStartHasSpellingMarkerFor(from, length);
}
WebString WebLocalFrameImpl::layerTreeAsText(bool showDebugInfo) const
{
if (!frame())
return WebString();
return WebString(frame()->layerTreeAsText(showDebugInfo ? LayerTreeIncludesDebugInfo : LayerTreeNormal));
}
// 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();
webView->suppressInvalidations(true);
frame()->createView(webView->size(), webView->baseBackgroundColor(), webView->isTransparent());
frame()->view()->setInputEventsTransformForEmulation(m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
webView->suppressInvalidations(false);
}
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);
}
void WebLocalFrameImpl::invalidateAll() const
{
ASSERT(frame() && frame()->view());
FrameView* view = frame()->view();
view->invalidateRect(view->frameRect());
}
} // namespace blink