44e0aca32614c3a82354631ace2c86c033d77ba6
[WebKit-https.git] / Source / WebCore / page / Frame.cpp
1 /*
2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  *                     1999 Lars Knoll <knoll@kde.org>
4  *                     1999 Antti Koivisto <koivisto@kde.org>
5  *                     2000 Simon Hausmann <hausmann@kde.org>
6  *                     2000 Stefan Schimanski <1Stein@gmx.de>
7  *                     2001 George Staikos <staikos@kde.org>
8  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
9  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
10  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
11  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
12  * Copyright (C) 2008 Google Inc.
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public License
25  * along with this library; see the file COPYING.LIB.  If not, write to
26  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 #include "config.h"
31 #include "Frame.h"
32
33 #include "AnimationController.h"
34 #include "ApplyStyleCommand.h"
35 #include "BackForwardController.h"
36 #include "CSSComputedStyleDeclaration.h"
37 #include "CSSPropertyNames.h"
38 #include "CachedCSSStyleSheet.h"
39 #include "CachedResourceLoader.h"
40 #include "Chrome.h"
41 #include "ChromeClient.h"
42 #include "DOMWindow.h"
43 #include "DocumentType.h"
44 #include "Editor.h"
45 #include "EditorClient.h"
46 #include "Event.h"
47 #include "EventHandler.h"
48 #include "EventNames.h"
49 #include "FloatQuad.h"
50 #include "FocusController.h"
51 #include "FrameDestructionObserver.h"
52 #include "FrameLoader.h"
53 #include "FrameLoaderClient.h"
54 #include "FrameSelection.h"
55 #include "FrameView.h"
56 #include "GraphicsContext.h"
57 #include "GraphicsLayer.h"
58 #include "HTMLDocument.h"
59 #include "HTMLFormControlElement.h"
60 #include "HTMLFormElement.h"
61 #include "HTMLFrameElementBase.h"
62 #include "HTMLNames.h"
63 #include "HTMLTableCellElement.h"
64 #include "HitTestResult.h"
65 #include "ImageBuffer.h"
66 #include "InspectorInstrumentation.h"
67 #include "JSDOMWindowShell.h"
68 #include "Logging.h"
69 #include "MathMLNames.h"
70 #include "MediaFeatureNames.h"
71 #include "Navigator.h"
72 #include "NodeList.h"
73 #include "NodeTraversal.h"
74 #include "Page.h"
75 #include "PageCache.h"
76 #include "PageGroup.h"
77 #include "RegularExpression.h"
78 #include "RenderPart.h"
79 #include "RenderTableCell.h"
80 #include "RenderTextControl.h"
81 #include "RenderTheme.h"
82 #include "RenderView.h"
83 #include "RuntimeEnabledFeatures.h"
84 #include "SVGNames.h"
85 #include "ScriptController.h"
86 #include "ScriptSourceCode.h"
87 #include "ScriptValue.h"
88 #include "ScrollingCoordinator.h"
89 #include "Settings.h"
90 #include "StylePropertySet.h"
91 #include "TextIterator.h"
92 #include "TextNodeTraversal.h"
93 #include "TextResourceDecoder.h"
94 #include "UserContentURLPattern.h"
95 #include "UserTypingGestureIndicator.h"
96 #include "VisibleUnits.h"
97 #include "WebKitFontFamilyNames.h"
98 #include "XLinkNames.h"
99 #include "XMLNSNames.h"
100 #include "XMLNames.h"
101 #include "htmlediting.h"
102 #include "markup.h"
103 #include "npruntime_impl.h"
104 #include "runtime_root.h"
105 #include <wtf/PassOwnPtr.h>
106 #include <wtf/RefCountedLeakCounter.h>
107 #include <wtf/StdLibExtras.h>
108
109 #if USE(ACCELERATED_COMPOSITING)
110 #include "RenderLayerCompositor.h"
111 #endif
112
113 #if ENABLE(SVG)
114 #include "SVGDocument.h"
115 #include "SVGDocumentExtensions.h"
116 #endif
117
118 #if USE(TILED_BACKING_STORE)
119 #include "TiledBackingStore.h"
120 #endif
121
122 using namespace std;
123
124 namespace WebCore {
125
126 using namespace HTMLNames;
127
128 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
129
130 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
131 {
132     if (!ownerElement)
133         return 0;
134     return ownerElement->document().frame();
135 }
136
137 static inline float parentPageZoomFactor(Frame* frame)
138 {
139     Frame* parent = frame->tree().parent();
140     if (!parent)
141         return 1;
142     return parent->pageZoomFactor();
143 }
144
145 static inline float parentTextZoomFactor(Frame* frame)
146 {
147     Frame* parent = frame->tree().parent();
148     if (!parent)
149         return 1;
150     return parent->textZoomFactor();
151 }
152
153 inline Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
154     : m_page(page)
155     , m_settings(&page->settings())
156     , m_treeNode(this, parentFromOwnerElement(ownerElement))
157     , m_loader(*this, *frameLoaderClient)
158     , m_navigationScheduler(this)
159     , m_ownerElement(ownerElement)
160     , m_script(createOwned<ScriptController>(*this))
161     , m_editor(Editor::create(*this))
162     , m_selection(adoptPtr(new FrameSelection(this)))
163     , m_eventHandler(adoptPtr(new EventHandler(*this)))
164     , m_animationController(adoptPtr(new AnimationController(this)))
165     , m_pageZoomFactor(parentPageZoomFactor(this))
166     , m_textZoomFactor(parentTextZoomFactor(this))
167 #if ENABLE(ORIENTATION_EVENTS)
168     , m_orientation(0)
169 #endif
170     , m_inViewSourceMode(false)
171     , m_activeDOMObjectsAndAnimationsSuspendedCount(0)
172 {
173     ASSERT(page);
174     AtomicString::init();
175     HTMLNames::init();
176     QualifiedName::init();
177     MediaFeatureNames::init();
178     SVGNames::init();
179     XLinkNames::init();
180     MathMLNames::init();
181     XMLNSNames::init();
182     XMLNames::init();
183     WebKitFontFamilyNames::init();
184
185     if (!ownerElement) {
186 #if USE(TILED_BACKING_STORE)
187         // Top level frame only for now.
188         setTiledBackingStoreEnabled(settings().tiledBackingStoreEnabled());
189 #endif
190     } else {
191         page->incrementSubframeCount();
192         ownerElement->setContentFrame(this);
193     }
194
195 #ifndef NDEBUG
196     frameCounter.increment();
197 #endif
198
199     // Pause future ActiveDOMObjects if this frame is being created while the page is in a paused state.
200     Frame* parent = parentFromOwnerElement(ownerElement);
201     if (parent && parent->activeDOMObjectsAndAnimationsSuspended())
202         suspendActiveDOMObjectsAndAnimations();
203 }
204
205 PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
206 {
207     return adoptRef(new Frame(page, ownerElement, client));
208 }
209
210 Frame::~Frame()
211 {
212     setView(0);
213     loader().cancelAndClear();
214
215     // FIXME: We should not be doing all this work inside the destructor
216
217 #ifndef NDEBUG
218     frameCounter.decrement();
219 #endif
220
221     disconnectOwnerElement();
222
223     HashSet<FrameDestructionObserver*>::iterator stop = m_destructionObservers.end();
224     for (HashSet<FrameDestructionObserver*>::iterator it = m_destructionObservers.begin(); it != stop; ++it)
225         (*it)->frameDestroyed();
226 }
227
228 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
229 {
230     m_destructionObservers.add(observer);
231 }
232
233 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
234 {
235     m_destructionObservers.remove(observer);
236 }
237
238 void Frame::setView(PassRefPtr<FrameView> view)
239 {
240     // We the custom scroll bars as early as possible to prevent m_doc->detach()
241     // from messing with the view such that its scroll bars won't be torn down.
242     // FIXME: We should revisit this.
243     if (m_view)
244         m_view->prepareForDetach();
245
246     // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
247     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
248     // these calls to work.
249     if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache()) {
250         // FIXME: We don't call willRemove here. Why is that OK?
251         m_doc->prepareForDestruction();
252     }
253     
254     if (m_view)
255         m_view->unscheduleRelayout();
256     
257     eventHandler().clear();
258
259     m_view = view;
260
261     // Only one form submission is allowed per view of a part.
262     // Since this part may be getting reused as a result of being
263     // pulled from the back/forward cache, reset this flag.
264     loader().resetMultipleFormSubmissionProtection();
265     
266 #if USE(TILED_BACKING_STORE)
267     if (m_view && tiledBackingStore())
268         m_view->setPaintsEntireContents(true);
269 #endif
270 }
271
272 void Frame::setDocument(PassRefPtr<Document> newDocument)
273 {
274     ASSERT(!newDocument || newDocument->frame() == this);
275
276     if (m_doc && m_doc->attached() && !m_doc->inPageCache()) {
277         // FIXME: We don't call willRemove here. Why is that OK?
278         m_doc->detach();
279     }
280
281     m_doc = newDocument.get();
282     ASSERT(!m_doc || m_doc->domWindow());
283     ASSERT(!m_doc || m_doc->domWindow()->frame() == this);
284
285     // Don't use m_doc because it can be overwritten and we want to guarantee
286     // that the document is not destroyed during this function call.
287     if (newDocument)
288         newDocument->didBecomeCurrentDocumentInFrame();
289 }
290
291 #if ENABLE(ORIENTATION_EVENTS)
292 void Frame::sendOrientationChangeEvent(int orientation)
293 {
294     m_orientation = orientation;
295     if (Document* doc = document())
296         doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
297 }
298 #endif // ENABLE(ORIENTATION_EVENTS)
299
300 static PassOwnPtr<RegularExpression> createRegExpForLabels(const Vector<String>& labels)
301 {
302     // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
303     // the same across calls.  We can't do that.
304
305     DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive));
306     String pattern("(");
307     unsigned int numLabels = labels.size();
308     unsigned int i;
309     for (i = 0; i < numLabels; i++) {
310         String label = labels[i];
311
312         bool startsWithWordChar = false;
313         bool endsWithWordChar = false;
314         if (label.length()) {
315             startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0;
316             endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0;
317         }
318
319         if (i)
320             pattern.append("|");
321         // Search for word boundaries only if label starts/ends with "word characters".
322         // If we always searched for word boundaries, this wouldn't work for languages
323         // such as Japanese.
324         if (startsWithWordChar)
325             pattern.append("\\b");
326         pattern.append(label);
327         if (endsWithWordChar)
328             pattern.append("\\b");
329     }
330     pattern.append(")");
331     return adoptPtr(new RegularExpression(pattern, TextCaseInsensitive));
332 }
333
334 String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell)
335 {
336     HTMLTableCellElement* aboveCell = cell->cellAbove();
337     if (aboveCell) {
338         // search within the above cell we found for a match
339         size_t lengthSearched = 0;    
340         for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) {
341             if (!textNode->renderer() || textNode->renderer()->style()->visibility() != VISIBLE)
342                 continue;
343             // For each text chunk, run the regexp
344             String nodeString = textNode->data();
345             int pos = regExp->searchRev(nodeString);
346             if (pos >= 0) {
347                 if (resultDistanceFromStartOfCell)
348                     *resultDistanceFromStartOfCell = lengthSearched;
349                 return nodeString.substring(pos, regExp->matchedLength());
350             }
351             lengthSearched += nodeString.length();
352         }
353     }
354
355     // Any reason in practice to search all cells in that are above cell?
356     if (resultDistanceFromStartOfCell)
357         *resultDistanceFromStartOfCell = notFound;
358     return String();
359 }
360
361 String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove)
362 {
363     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
364     // We stop searching after we've seen this many chars
365     const unsigned int charsSearchedThreshold = 500;
366     // This is the absolute max we search.  We allow a little more slop than
367     // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
368     const unsigned int maxCharsSearched = 600;
369     // If the starting element is within a table, the cell that contains it
370     HTMLTableCellElement* startingTableCell = 0;
371     bool searchedCellAbove = false;
372
373     if (resultDistance)
374         *resultDistance = notFound;
375     if (resultIsInCellAbove)
376         *resultIsInCellAbove = false;
377     
378     // walk backwards in the node tree, until another element, or form, or end of tree
379     int unsigned lengthSearched = 0;
380     Node* n;
381     for (n = NodeTraversal::previous(element); n && lengthSearched < charsSearchedThreshold; n = NodeTraversal::previous(n)) {
382         // We hit another form element or the start of the form - bail out
383         if (isHTMLFormElement(n) || (n->isHTMLElement() && toElement(n)->isFormControlElement()))
384             break;
385
386         if (n->hasTagName(tdTag) && !startingTableCell) {
387             startingTableCell = static_cast<HTMLTableCellElement*>(n);
388         } else if (n->hasTagName(trTag) && startingTableCell) {
389             String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
390             if (!result.isEmpty()) {
391                 if (resultIsInCellAbove)
392                     *resultIsInCellAbove = true;
393                 return result;
394             }
395             searchedCellAbove = true;
396         } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
397             // For each text chunk, run the regexp
398             String nodeString = n->nodeValue();
399             // add 100 for slop, to make it more likely that we'll search whole nodes
400             if (lengthSearched + nodeString.length() > maxCharsSearched)
401                 nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
402             int pos = regExp->searchRev(nodeString);
403             if (pos >= 0) {
404                 if (resultDistance)
405                     *resultDistance = lengthSearched;
406                 return nodeString.substring(pos, regExp->matchedLength());
407             }
408             lengthSearched += nodeString.length();
409         }
410     }
411
412     // If we started in a cell, but bailed because we found the start of the form or the
413     // previous element, we still might need to search the row above us for a label.
414     if (startingTableCell && !searchedCellAbove) {
415          String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance);
416         if (!result.isEmpty()) {
417             if (resultIsInCellAbove)
418                 *resultIsInCellAbove = true;
419             return result;
420         }
421     }
422     return String();
423 }
424
425 static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch)
426 {
427     if (stringToMatch.isEmpty())
428         return String();
429
430     String mutableStringToMatch = stringToMatch;
431
432     // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
433     replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " ");
434     mutableStringToMatch.replace('_', ' ');
435     
436     OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
437     // Use the largest match we can find in the whole string
438     int pos;
439     int length;
440     int bestPos = -1;
441     int bestLength = -1;
442     int start = 0;
443     do {
444         pos = regExp->match(mutableStringToMatch, start);
445         if (pos != -1) {
446             length = regExp->matchedLength();
447             if (length >= bestLength) {
448                 bestPos = pos;
449                 bestLength = length;
450             }
451             start = pos + 1;
452         }
453     } while (pos != -1);
454     
455     if (bestPos != -1)
456         return mutableStringToMatch.substring(bestPos, bestLength);
457     return String();
458 }
459     
460 String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
461 {
462     // Match against the name element, then against the id element if no match is found for the name element.
463     // See 7538330 for one popular site that benefits from the id element check.
464     // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic
465     // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way.
466     String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getNameAttribute());
467     if (!resultFromNameAttribute.isEmpty())
468         return resultFromNameAttribute;
469     
470     return matchLabelsAgainstString(labels, element->getAttribute(idAttr));
471 }
472
473 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
474 {
475     // In setting printing, we should not validate resources already cached for the document.
476     // See https://bugs.webkit.org/show_bug.cgi?id=43704
477     ResourceCacheValidationSuppressor validationSuppressor(m_doc->cachedResourceLoader());
478
479     m_doc->setPrinting(printing);
480     view()->adjustMediaTypeForPrinting(printing);
481
482     m_doc->styleResolverChanged(RecalcStyleImmediately);
483     if (shouldUsePrintingLayout()) {
484         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
485     } else {
486         view()->forceLayout();
487         if (shouldAdjustViewSize == AdjustViewSize)
488             view()->adjustViewSize();
489     }
490
491     // Subframes of the one we're printing don't lay out to the page size.
492     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
493         child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
494 }
495
496 bool Frame::shouldUsePrintingLayout() const
497 {
498     // Only top frame being printed should be fit to page size.
499     // Subframes should be constrained by parents only.
500     return m_doc->printing() && (!tree().parent() || !tree().parent()->m_doc->printing());
501 }
502
503 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
504 {
505     FloatSize resultSize;
506     if (!contentRenderer())
507         return FloatSize();
508
509     if (contentRenderer()->style()->isHorizontalWritingMode()) {
510         ASSERT(fabs(originalSize.width()) > numeric_limits<float>::epsilon());
511         float ratio = originalSize.height() / originalSize.width();
512         resultSize.setWidth(floorf(expectedSize.width()));
513         resultSize.setHeight(floorf(resultSize.width() * ratio));
514     } else {
515         ASSERT(fabs(originalSize.height()) > numeric_limits<float>::epsilon());
516         float ratio = originalSize.width() / originalSize.height();
517         resultSize.setHeight(floorf(expectedSize.height()));
518         resultSize.setWidth(floorf(resultSize.height() * ratio));
519     }
520     return resultSize;
521 }
522
523 void Frame::injectUserScripts(UserScriptInjectionTime injectionTime)
524 {
525     if (!m_page)
526         return;
527
528     if (loader().stateMachine()->creatingInitialEmptyDocument() && !settings().shouldInjectUserScriptsInInitialEmptyDocument())
529         return;
530
531     // Walk the hashtable. Inject by world.
532     const UserScriptMap* userScripts = m_page->group().userScripts();
533     if (!userScripts)
534         return;
535     UserScriptMap::const_iterator end = userScripts->end();
536     for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it)
537         injectUserScriptsForWorld(it->key.get(), *it->value, injectionTime);
538 }
539
540 void Frame::injectUserScriptsForWorld(DOMWrapperWorld* world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime)
541 {
542     if (userScripts.isEmpty())
543         return;
544
545     Document* doc = document();
546     if (!doc)
547         return;
548
549     Vector<ScriptSourceCode> sourceCode;
550     unsigned count = userScripts.size();
551     for (unsigned i = 0; i < count; ++i) {
552         UserScript* script = userScripts[i].get();
553         if (script->injectedFrames() == InjectInTopFrameOnly && ownerElement())
554             continue;
555
556         if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist()))
557             m_script->evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world);
558     }
559 }
560
561 RenderView* Frame::contentRenderer() const
562 {
563     return document() ? document()->renderView() : 0;
564 }
565
566 RenderPart* Frame::ownerRenderer() const
567 {
568     HTMLFrameOwnerElement* ownerElement = m_ownerElement;
569     if (!ownerElement)
570         return 0;
571     RenderObject* object = ownerElement->renderer();
572     if (!object)
573         return 0;
574     // FIXME: If <object> is ever fixed to disassociate itself from frames
575     // that it has started but canceled, then this can turn into an ASSERT
576     // since m_ownerElement would be 0 when the load is canceled.
577     // https://bugs.webkit.org/show_bug.cgi?id=18585
578     if (!object->isRenderPart())
579         return 0;
580     return toRenderPart(object);
581 }
582
583 Frame* Frame::frameForWidget(const Widget* widget)
584 {
585     ASSERT_ARG(widget, widget);
586
587     if (RenderWidget* renderer = RenderWidget::find(widget))
588         if (Element* element = renderer->element())
589             return element->document().frame();
590
591     // Assume all widgets are either a FrameView or owned by a RenderWidget.
592     // FIXME: That assumption is not right for scroll bars!
593     ASSERT_WITH_SECURITY_IMPLICATION(widget->isFrameView());
594     return &toFrameView(widget)->frame();
595 }
596
597 void Frame::clearTimers(FrameView *view, Document *document)
598 {
599     if (view) {
600         view->unscheduleRelayout();
601         view->frame().animation().suspendAnimationsForDocument(document);
602         view->frame().eventHandler().stopAutoscrollTimer();
603     }
604 }
605
606 void Frame::clearTimers()
607 {
608     clearTimers(m_view.get(), document());
609 }
610
611 void Frame::willDetachPage()
612 {
613     if (Frame* parent = tree().parent())
614         parent->loader().checkLoadComplete();
615
616     HashSet<FrameDestructionObserver*>::iterator stop = m_destructionObservers.end();
617     for (HashSet<FrameDestructionObserver*>::iterator it = m_destructionObservers.begin(); it != stop; ++it)
618         (*it)->willDetachPage();
619
620     // FIXME: It's unclear as to why this is called more than once, but it is,
621     // so page() could be NULL.
622     if (page() && page()->focusController().focusedFrame() == this)
623         page()->focusController().setFocusedFrame(0);
624
625     if (page() && page()->scrollingCoordinator() && m_view)
626         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
627
628     script().clearScriptObjects();
629     script().updatePlatformScriptObjects();
630 }
631
632 void Frame::disconnectOwnerElement()
633 {
634     if (m_ownerElement) {
635         // We use the ownerElement's document to retrieve the cache, because the contentDocument for this
636         // frame is already detached (and can't access the top level AX cache).
637         // However, we pass in the current document to clearTextMarkerNodesInUse so we can identify the
638         // nodes inside this document that need to be removed from the cache.
639         
640         // We don't clear the AXObjectCache here because we don't want to clear the top level cache
641         // when a sub-frame is removed.
642 #if HAVE(ACCESSIBILITY)
643         if (AXObjectCache* cache = m_ownerElement->document().existingAXObjectCache())
644             cache->clearTextMarkerNodesInUse(document());
645 #endif
646         
647         m_ownerElement->clearContentFrame();
648         if (m_page)
649             m_page->decrementSubframeCount();
650     }
651     m_ownerElement = 0;
652 }
653
654 String Frame::displayStringModifiedByEncoding(const String& str) const
655 {
656     return document() ? document()->displayStringModifiedByEncoding(str) : str;
657 }
658
659 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
660 {
661     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
662     Node* node = result.innerNonSharedNode();
663     if (!node)
664         return VisiblePosition();
665     RenderObject* renderer = node->renderer();
666     if (!renderer)
667         return VisiblePosition();
668     VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
669     if (visiblePos.isNull())
670         visiblePos = firstPositionInOrBeforeNode(node);
671     return visiblePos;
672 }
673
674 Document* Frame::documentAtPoint(const IntPoint& point)
675 {
676     if (!view())
677         return 0;
678
679     IntPoint pt = view()->windowToContents(point);
680     HitTestResult result = HitTestResult(pt);
681
682     if (contentRenderer())
683         result = eventHandler().hitTestResultAtPoint(pt);
684     return result.innerNode() ? &result.innerNode()->document() : 0;
685 }
686
687 PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
688 {
689     VisiblePosition position = visiblePositionForPoint(framePoint);
690     if (position.isNull())
691         return 0;
692
693     VisiblePosition previous = position.previous();
694     if (previous.isNotNull()) {
695         RefPtr<Range> previousCharacterRange = makeRange(previous, position);
696         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
697         if (rect.contains(framePoint))
698             return previousCharacterRange.release();
699     }
700
701     VisiblePosition next = position.next();
702     if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
703         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
704         if (rect.contains(framePoint))
705             return nextCharacterRange.release();
706     }
707
708     return 0;
709 }
710
711 void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
712     const IntSize& fixedLayoutSize, const IntRect& fixedVisibleContentRect ,
713     bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
714     ScrollbarMode verticalScrollbarMode, bool verticalLock)
715 {
716     ASSERT(this);
717     ASSERT(m_page);
718
719     bool isMainFrame = m_page->frameIsMainFrame(this);
720
721     if (isMainFrame && view())
722         view()->setParentVisible(false);
723
724     setView(0);
725
726     RefPtr<FrameView> frameView;
727     if (isMainFrame) {
728         frameView = FrameView::create(*this, viewportSize);
729         frameView->setFixedLayoutSize(fixedLayoutSize);
730         frameView->setFixedVisibleContentRect(fixedVisibleContentRect);
731         frameView->setUseFixedLayout(useFixedLayout);
732     } else
733         frameView = FrameView::create(*this);
734
735     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
736
737     setView(frameView);
738
739     if (backgroundColor.isValid())
740         frameView->updateBackgroundRecursively(backgroundColor, transparent);
741
742     if (isMainFrame)
743         frameView->setParentVisible(true);
744
745     if (ownerRenderer())
746         ownerRenderer()->setWidget(frameView);
747
748     if (HTMLFrameOwnerElement* owner = ownerElement())
749         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
750 }
751
752 #if USE(TILED_BACKING_STORE)
753 void Frame::setTiledBackingStoreEnabled(bool enabled)
754 {
755     if (!enabled) {
756         m_tiledBackingStore.clear();
757         return;
758     }
759     if (m_tiledBackingStore)
760         return;
761     m_tiledBackingStore = adoptPtr(new TiledBackingStore(this));
762     m_tiledBackingStore->setCommitTileUpdatesOnIdleEventLoop(true);
763     if (m_view)
764         m_view->setPaintsEntireContents(true);
765 }
766
767 void Frame::tiledBackingStorePaintBegin()
768 {
769     if (!m_view)
770         return;
771     m_view->updateLayoutAndStyleIfNeededRecursive();
772     m_view->flushDeferredRepaints();
773 }
774
775 void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
776 {
777     if (!m_view)
778         return;
779     m_view->paintContents(context, rect);
780 }
781
782 void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
783 {
784     if (!m_page || !m_view)
785         return;
786     unsigned size = paintedArea.size();
787     // Request repaint from the system
788     for (unsigned n = 0; n < size; ++n)
789         m_page->chrome().invalidateContentsAndRootView(m_view->contentsToRootView(paintedArea[n]), false);
790 }
791
792 IntRect Frame::tiledBackingStoreContentsRect()
793 {
794     if (!m_view)
795         return IntRect();
796     return IntRect(IntPoint(), m_view->contentsSize());
797 }
798
799 IntRect Frame::tiledBackingStoreVisibleRect()
800 {
801     if (!m_page)
802         return IntRect();
803     return m_page->chrome().client().visibleRectForTiledBackingStore();
804 }
805
806 Color Frame::tiledBackingStoreBackgroundColor() const
807 {
808     if (!m_view)
809         return Color();
810     return m_view->baseBackgroundColor();
811 }
812 #endif
813
814 String Frame::layerTreeAsText(LayerTreeFlags flags) const
815 {
816 #if USE(ACCELERATED_COMPOSITING)
817     document()->updateLayout();
818
819     if (!contentRenderer())
820         return String();
821
822     return contentRenderer()->compositor().layerTreeAsText(flags);
823 #else
824     UNUSED_PARAM(flags);
825     return String();
826 #endif
827 }
828
829 String Frame::trackedRepaintRectsAsText() const
830 {
831     if (!m_view)
832         return String();
833     return m_view->trackedRepaintRectsAsText();
834 }
835
836 void Frame::setPageZoomFactor(float factor)
837 {
838     setPageAndTextZoomFactors(factor, m_textZoomFactor);
839 }
840
841 void Frame::setTextZoomFactor(float factor)
842 {
843     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
844 }
845
846 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
847 {
848     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
849         return;
850
851     Page* page = this->page();
852     if (!page)
853         return;
854
855     Document* document = this->document();
856     if (!document)
857         return;
858
859     m_editor->dismissCorrectionPanelAsIgnored();
860
861 #if ENABLE(SVG)
862     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
863     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
864     if (document->isSVGDocument()) {
865         if (!toSVGDocument(document)->zoomAndPanEnabled())
866             return;
867     }
868 #endif
869
870     if (m_pageZoomFactor != pageZoomFactor) {
871         if (FrameView* view = this->view()) {
872             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
873             LayoutPoint scrollPosition = view->scrollPosition();
874             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
875             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
876         }
877     }
878
879     m_pageZoomFactor = pageZoomFactor;
880     m_textZoomFactor = textZoomFactor;
881
882     document->recalcStyle(Style::Force);
883
884     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
885         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
886
887     if (FrameView* view = this->view()) {
888         if (document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
889             view->layout();
890     }
891
892     if (page->frameIsMainFrame(this))
893         pageCache()->markPagesForFullStyleRecalc(page);
894 }
895
896 float Frame::frameScaleFactor() const
897 {
898     Page* page = this->page();
899
900     // Main frame is scaled with respect to he container but inner frames are not scaled with respect to the main frame.
901     if (!page || &page->mainFrame() != this || settings().applyPageScaleFactorInCompositor())
902         return 1;
903
904     return page->pageScaleFactor();
905 }
906
907 void Frame::suspendActiveDOMObjectsAndAnimations()
908 {
909     bool wasSuspended = activeDOMObjectsAndAnimationsSuspended();
910
911     m_activeDOMObjectsAndAnimationsSuspendedCount++;
912
913     if (wasSuspended)
914         return;
915
916     // FIXME: Suspend/resume calls will not match if the frame is navigated, and gets a new document.
917     if (document()) {
918         document()->suspendScriptedAnimationControllerCallbacks();
919         animation().suspendAnimationsForDocument(document());
920         document()->suspendActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
921     }
922 }
923
924 void Frame::resumeActiveDOMObjectsAndAnimations()
925 {
926     ASSERT(activeDOMObjectsAndAnimationsSuspended());
927
928     m_activeDOMObjectsAndAnimationsSuspendedCount--;
929
930     if (activeDOMObjectsAndAnimationsSuspended())
931         return;
932
933     if (document()) {
934         document()->resumeActiveDOMObjects(ActiveDOMObject::PageWillBeSuspended);
935         animation().resumeAnimationsForDocument(document());
936         document()->resumeScriptedAnimationControllerCallbacks();
937     }
938
939     if (m_view)
940         m_view->resumeAnimatingImages();
941 }
942
943 #if USE(ACCELERATED_COMPOSITING)
944 void Frame::deviceOrPageScaleFactorChanged()
945 {
946     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
947         child->deviceOrPageScaleFactorChanged();
948
949     if (RenderView* root = contentRenderer())
950         root->compositor().deviceOrPageScaleFactorChanged();
951 }
952 #endif
953
954 bool Frame::isURLAllowed(const KURL& url) const
955 {
956     // We allow one level of self-reference because some sites depend on that,
957     // but we don't allow more than one.
958     if (m_page->subframeCount() >= Page::maxNumberOfFrames)
959         return false;
960     bool foundSelfReference = false;
961     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
962         if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) {
963             if (foundSelfReference)
964                 return false;
965             foundSelfReference = true;
966         }
967     }
968     return true;
969 }
970
971 #if !PLATFORM(MAC) && !PLATFORM(WIN)
972 struct ScopedFramePaintingState {
973     ScopedFramePaintingState(Frame* frame, Node* node)
974         : frame(frame)
975         , node(node)
976         , paintBehavior(frame->view()->paintBehavior())
977         , backgroundColor(frame->view()->baseBackgroundColor())
978     {
979         ASSERT(!node || node->renderer());
980         if (node)
981             node->renderer()->updateDragState(true);
982     }
983
984     ~ScopedFramePaintingState()
985     {
986         if (node && node->renderer())
987             node->renderer()->updateDragState(false);
988         frame->view()->setPaintBehavior(paintBehavior);
989         frame->view()->setBaseBackgroundColor(backgroundColor);
990         frame->view()->setNodeToDraw(0);
991     }
992
993     Frame* frame;
994     Node* node;
995     PaintBehavior paintBehavior;
996     Color backgroundColor;
997 };
998
999 DragImageRef Frame::nodeImage(Node* node)
1000 {
1001     if (!node->renderer())
1002         return 0;
1003
1004     const ScopedFramePaintingState state(this, node);
1005
1006     m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers);
1007
1008     // When generating the drag image for an element, ignore the document background.
1009     m_view->setBaseBackgroundColor(Color::transparent);
1010     m_doc->updateLayout();
1011     m_view->setNodeToDraw(node); // Enable special sub-tree drawing mode.
1012
1013     // Document::updateLayout may have blown away the original RenderObject.
1014     RenderObject* renderer = node->renderer();
1015     if (!renderer)
1016       return 0;
1017
1018     LayoutRect topLevelRect;
1019     IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect));
1020
1021     float deviceScaleFactor = 1;
1022     if (m_page)
1023         deviceScaleFactor = m_page->deviceScaleFactor();
1024     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
1025     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
1026
1027     OwnPtr<ImageBuffer> buffer(ImageBuffer::create(paintingRect.size(), deviceScaleFactor, ColorSpaceDeviceRGB));
1028     if (!buffer)
1029         return 0;
1030     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
1031     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
1032
1033     m_view->paintContents(buffer->context(), paintingRect);
1034
1035     RefPtr<Image> image = buffer->copyImage();
1036     return createDragImageFromImage(image.get(), ImageOrientationDescription(renderer->shouldRespectImageOrientation()));
1037 }
1038
1039 DragImageRef Frame::dragImageForSelection()
1040 {
1041     if (!selection().isRange())
1042         return 0;
1043
1044     const ScopedFramePaintingState state(this, 0);
1045     m_view->setPaintBehavior(PaintBehaviorSelectionOnly);
1046     m_doc->updateLayout();
1047
1048     IntRect paintingRect = enclosingIntRect(selection().bounds());
1049
1050     float deviceScaleFactor = 1;
1051     if (m_page)
1052         deviceScaleFactor = m_page->deviceScaleFactor();
1053     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
1054     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
1055
1056     OwnPtr<ImageBuffer> buffer(ImageBuffer::create(paintingRect.size(), deviceScaleFactor, ColorSpaceDeviceRGB));
1057     if (!buffer)
1058         return 0;
1059     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
1060     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
1061
1062     m_view->paintContents(buffer->context(), paintingRect);
1063
1064     RefPtr<Image> image = buffer->copyImage();
1065     return createDragImageFromImage(image.get(), ImageOrientationDescription());
1066 }
1067
1068 #endif
1069
1070 } // namespace WebCore