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