PageRenderTime 93ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/webview/native/Source/WebCore/dom/Document.cpp

https://bitbucket.org/rbair/rbair-controls-8
C++ | 6127 lines | 4589 code | 989 blank | 549 comment | 1212 complexity | bd9f26ee639f73684538d18164e3df14 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
  1. /*
  2. * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  3. * (C) 1999 Antti Koivisto (koivisto@kde.org)
  4. * (C) 2001 Dirk Mueller (mueller@kde.org)
  5. * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
  6. * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
  7. * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  8. * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
  9. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
  10. * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Library General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2 of the License, or (at your option) any later version.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Library General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Library General Public License
  23. * along with this library; see the file COPYING.LIB. If not, write to
  24. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  25. * Boston, MA 02110-1301, USA.
  26. */
  27. #include "config.h"
  28. #include "Document.h"
  29. #include "AXObjectCache.h"
  30. #include "AnimationController.h"
  31. #include "Attr.h"
  32. #include "Attribute.h"
  33. #include "CDATASection.h"
  34. #include "CSSParser.h"
  35. #include "CSSStyleDeclaration.h"
  36. #include "CSSStyleSheet.h"
  37. #include "CSSValueKeywords.h"
  38. #include "CachedCSSStyleSheet.h"
  39. #include "CachedResourceLoader.h"
  40. #include "Chrome.h"
  41. #include "ChromeClient.h"
  42. #include "Comment.h"
  43. #include "Console.h"
  44. #include "ContentSecurityPolicy.h"
  45. #include "ContextFeatures.h"
  46. #include "CookieJar.h"
  47. #include "DOMImplementation.h"
  48. #include "DOMSelection.h"
  49. #include "DOMWindow.h"
  50. #include "DateComponents.h"
  51. #include "DeviceMotionController.h"
  52. #include "DeviceMotionEvent.h"
  53. #include "DeviceOrientationController.h"
  54. #include "DeviceOrientationEvent.h"
  55. #include "DocumentEventQueue.h"
  56. #include "DocumentFragment.h"
  57. #include "DocumentLoader.h"
  58. #include "DocumentMarkerController.h"
  59. #include "DocumentType.h"
  60. #include "EditingText.h"
  61. #include "Editor.h"
  62. #include "Element.h"
  63. #include "ElementShadow.h"
  64. #include "EntityReference.h"
  65. #include "Event.h"
  66. #include "EventFactory.h"
  67. #include "EventHandler.h"
  68. #include "EventListener.h"
  69. #include "EventNames.h"
  70. #include "ExceptionCode.h"
  71. #include "FlowThreadController.h"
  72. #include "FocusController.h"
  73. #include "FormController.h"
  74. #include "Frame.h"
  75. #include "FrameLoader.h"
  76. #include "FrameLoaderClient.h"
  77. #include "FrameSelection.h"
  78. #include "FrameTree.h"
  79. #include "FrameView.h"
  80. #include "GeolocationController.h"
  81. #include "HashChangeEvent.h"
  82. #include "HistogramSupport.h"
  83. #include "History.h"
  84. #include "HTMLAllCollection.h"
  85. #include "HTMLAnchorElement.h"
  86. #include "HTMLBodyElement.h"
  87. #include "HTMLCanvasElement.h"
  88. #include "HTMLCollection.h"
  89. #include "HTMLDocument.h"
  90. #include "HTMLElementFactory.h"
  91. #include "HTMLFrameOwnerElement.h"
  92. #include "HTMLHeadElement.h"
  93. #include "HTMLIFrameElement.h"
  94. #include "HTMLLinkElement.h"
  95. #include "HTMLMapElement.h"
  96. #include "HTMLNameCollection.h"
  97. #include "HTMLNames.h"
  98. #include "HTMLParserIdioms.h"
  99. #include "HTMLStyleElement.h"
  100. #include "HTMLTitleElement.h"
  101. #include "HTTPParsers.h"
  102. #include "HitTestRequest.h"
  103. #include "HitTestResult.h"
  104. #include "ImageLoader.h"
  105. #include "InspectorCounters.h"
  106. #include "InspectorInstrumentation.h"
  107. #include "Logging.h"
  108. #include "MediaQueryList.h"
  109. #include "MediaQueryMatcher.h"
  110. #include "MemoryInstrumentation.h"
  111. #include "MouseEventWithHitTestResults.h"
  112. #include "NameNodeList.h"
  113. #include "NestingLevelIncrementer.h"
  114. #include "NewXMLDocumentParser.h"
  115. #include "NodeFilter.h"
  116. #include "NodeIterator.h"
  117. #include "NodeRareData.h"
  118. #include "NodeWithIndex.h"
  119. #include "Page.h"
  120. #include "PageGroup.h"
  121. #include "PageTransitionEvent.h"
  122. #include "PlatformKeyboardEvent.h"
  123. #include "PluginDocument.h"
  124. #include "PointerLockController.h"
  125. #include "PopStateEvent.h"
  126. #include "ProcessingInstruction.h"
  127. #include "RegisteredEventListener.h"
  128. #include "RenderArena.h"
  129. #include "RenderNamedFlowThread.h"
  130. #include "RenderTextControl.h"
  131. #include "RenderView.h"
  132. #include "RenderWidget.h"
  133. #include "SchemeRegistry.h"
  134. #include "ScopedEventQueue.h"
  135. #include "ScriptCallStack.h"
  136. #include "ScriptController.h"
  137. #include "ScriptElement.h"
  138. #include "ScriptEventListener.h"
  139. #include "ScriptRunner.h"
  140. #include "ScrollingCoordinator.h"
  141. #include "SecurityOrigin.h"
  142. #include "SecurityPolicy.h"
  143. #include "SegmentedString.h"
  144. #include "SelectorQuery.h"
  145. #include "Settings.h"
  146. #include "ShadowRoot.h"
  147. #include "StaticHashSetNodeList.h"
  148. #include "StyleResolver.h"
  149. #include "StyleSheetContents.h"
  150. #include "StyleSheetList.h"
  151. #include "TextResourceDecoder.h"
  152. #include "Timer.h"
  153. #include "TransformSource.h"
  154. #include "TreeWalker.h"
  155. #include "UndoManager.h"
  156. #include "UserContentURLPattern.h"
  157. #include "WebKitNamedFlow.h"
  158. #include "WebKitNamedFlowCollection.h"
  159. #include "XMLDocumentParser.h"
  160. #include "XMLHttpRequest.h"
  161. #include "XMLNSNames.h"
  162. #include "XMLNames.h"
  163. #include "XPathEvaluator.h"
  164. #include "XPathExpression.h"
  165. #include "XPathNSResolver.h"
  166. #include "XPathResult.h"
  167. #include "htmlediting.h"
  168. #include <wtf/CurrentTime.h>
  169. #include <wtf/HashFunctions.h>
  170. #include <wtf/MainThread.h>
  171. #include <wtf/PassRefPtr.h>
  172. #include <wtf/StdLibExtras.h>
  173. #include <wtf/text/StringBuffer.h>
  174. #if ENABLE(SHARED_WORKERS)
  175. #include "SharedWorkerRepository.h"
  176. #endif
  177. #if ENABLE(XSLT)
  178. #include "XSLTProcessor.h"
  179. #endif
  180. #if ENABLE(SVG)
  181. #include "SVGDocumentExtensions.h"
  182. #include "SVGElementFactory.h"
  183. #include "SVGNames.h"
  184. #include "SVGSVGElement.h"
  185. #include "SVGStyleElement.h"
  186. #endif
  187. #if ENABLE(TOUCH_EVENTS)
  188. #include "TouchList.h"
  189. #endif
  190. #if ENABLE(MATHML)
  191. #include "MathMLElement.h"
  192. #include "MathMLElementFactory.h"
  193. #include "MathMLNames.h"
  194. #endif
  195. #if ENABLE(FULLSCREEN_API)
  196. #include "RenderFullScreen.h"
  197. #endif
  198. #if ENABLE(REQUEST_ANIMATION_FRAME)
  199. #include "RequestAnimationFrameCallback.h"
  200. #include "ScriptedAnimationController.h"
  201. #endif
  202. #if ENABLE(MICRODATA)
  203. #include "MicroDataItemList.h"
  204. #include "NodeRareData.h"
  205. #endif
  206. #if ENABLE(LINK_PRERENDER)
  207. #include "Prerenderer.h"
  208. #endif
  209. #if ENABLE(TEXT_AUTOSIZING)
  210. #include "TextAutosizer.h"
  211. #endif
  212. using namespace std;
  213. using namespace WTF;
  214. using namespace Unicode;
  215. namespace WebCore {
  216. using namespace HTMLNames;
  217. // #define INSTRUMENT_LAYOUT_SCHEDULING 1
  218. static const unsigned cMaxWriteRecursionDepth = 21;
  219. // This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
  220. // FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high
  221. // for dual G5s. :)
  222. static const int cLayoutScheduleThreshold = 250;
  223. // DOM Level 2 says (letters added):
  224. //
  225. // a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
  226. // b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
  227. // c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
  228. // d) Characters which have a font or compatibility decomposition (i.e. those with a "compatibility formatting tag" in field 5 of the database -- marked by field 5 beginning with a "<") are not allowed.
  229. // e) The following characters are treated as name-start characters rather than name characters, because the property file classifies them as Alphabetic: [#x02BB-#x02C1], #x0559, #x06E5, #x06E6.
  230. // f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
  231. // g) Character #x00B7 is classified as an extender, because the property list so identifies it.
  232. // h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
  233. // i) Characters ':' and '_' are allowed as name-start characters.
  234. // j) Characters '-' and '.' are allowed as name characters.
  235. //
  236. // It also contains complete tables. If we decide it's better, we could include those instead of the following code.
  237. static inline bool isValidNameStart(UChar32 c)
  238. {
  239. // rule (e) above
  240. if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
  241. return true;
  242. // rule (i) above
  243. if (c == ':' || c == '_')
  244. return true;
  245. // rules (a) and (f) above
  246. const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
  247. if (!(Unicode::category(c) & nameStartMask))
  248. return false;
  249. // rule (c) above
  250. if (c >= 0xF900 && c < 0xFFFE)
  251. return false;
  252. // rule (d) above
  253. DecompositionType decompType = decompositionType(c);
  254. if (decompType == DecompositionFont || decompType == DecompositionCompat)
  255. return false;
  256. return true;
  257. }
  258. static inline bool isValidNamePart(UChar32 c)
  259. {
  260. // rules (a), (e), and (i) above
  261. if (isValidNameStart(c))
  262. return true;
  263. // rules (g) and (h) above
  264. if (c == 0x00B7 || c == 0x0387)
  265. return true;
  266. // rule (j) above
  267. if (c == '-' || c == '.')
  268. return true;
  269. // rules (b) and (f) above
  270. const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
  271. if (!(Unicode::category(c) & otherNamePartMask))
  272. return false;
  273. // rule (c) above
  274. if (c >= 0xF900 && c < 0xFFFE)
  275. return false;
  276. // rule (d) above
  277. DecompositionType decompType = decompositionType(c);
  278. if (decompType == DecompositionFont || decompType == DecompositionCompat)
  279. return false;
  280. return true;
  281. }
  282. static bool shouldInheritSecurityOriginFromOwner(const KURL& url)
  283. {
  284. // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
  285. //
  286. // If a Document has the address "about:blank"
  287. // The origin of the Document is the origin it was assigned when its browsing context was created.
  288. //
  289. // Note: We generalize this to all "blank" URLs and invalid URLs because we
  290. // treat all of these URLs as about:blank.
  291. //
  292. return !url.isValid() || url.isBlankURL();
  293. }
  294. static Widget* widgetForNode(Node* focusedNode)
  295. {
  296. if (!focusedNode)
  297. return 0;
  298. RenderObject* renderer = focusedNode->renderer();
  299. if (!renderer || !renderer->isWidget())
  300. return 0;
  301. return toRenderWidget(renderer)->widget();
  302. }
  303. static bool acceptsEditingFocus(Node* node)
  304. {
  305. ASSERT(node);
  306. ASSERT(node->rendererIsEditable());
  307. Node* root = node->rootEditableElement();
  308. Frame* frame = node->document()->frame();
  309. if (!frame || !root)
  310. return false;
  311. return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
  312. }
  313. static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
  314. {
  315. // targetFrame can be 0 when we're trying to navigate a top-level frame
  316. // that has a 0 opener.
  317. if (!targetFrame)
  318. return false;
  319. const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
  320. for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
  321. Document* ancestorDocument = ancestorFrame->document();
  322. // FIXME: Should be an ASSERT? Frames should alway have documents.
  323. if (!ancestorDocument)
  324. return true;
  325. const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
  326. if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
  327. return true;
  328. // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
  329. // FIXME: It's a bit strange to special-case local origins here. Should we be doing
  330. // something more general instead?
  331. if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
  332. return true;
  333. }
  334. return false;
  335. }
  336. static void printNavigationErrorMessage(Frame* frame, const KURL& activeURL)
  337. {
  338. // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
  339. String message = "Unsafe JavaScript attempt to initiate a navigation change for frame with URL " +
  340. frame->document()->url().string() + " from frame with URL " + activeURL.string() + ".\n";
  341. // FIXME: should we print to the console of the document performing the navigation instead?
  342. frame->domWindow()->printErrorMessage(message);
  343. }
  344. static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
  345. class DocumentWeakReference : public ThreadSafeRefCounted<DocumentWeakReference> {
  346. public:
  347. static PassRefPtr<DocumentWeakReference> create(Document* document)
  348. {
  349. return adoptRef(new DocumentWeakReference(document));
  350. }
  351. Document* document()
  352. {
  353. ASSERT(isMainThread());
  354. return m_document;
  355. }
  356. void clear()
  357. {
  358. ASSERT(isMainThread());
  359. m_document = 0;
  360. }
  361. private:
  362. DocumentWeakReference(Document* document)
  363. : m_document(document)
  364. {
  365. ASSERT(isMainThread());
  366. }
  367. Document* m_document;
  368. };
  369. uint64_t Document::s_globalTreeVersion = 0;
  370. Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
  371. : ContainerNode(0, CreateDocument)
  372. , TreeScope(this)
  373. , m_guardRefCount(0)
  374. , m_contextFeatures(ContextFeatures::defaultSwitch())
  375. , m_compatibilityMode(NoQuirksMode)
  376. , m_compatibilityModeLocked(false)
  377. , m_domTreeVersion(++s_globalTreeVersion)
  378. #if ENABLE(MUTATION_OBSERVERS)
  379. , m_mutationObserverTypes(0)
  380. #endif
  381. , m_styleSheets(StyleSheetList::create(this))
  382. , m_hadActiveLoadingStylesheet(false)
  383. , m_readyState(Complete)
  384. , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
  385. , m_pendingStyleRecalcShouldForce(false)
  386. , m_frameElementsShouldIgnoreScrolling(false)
  387. , m_containsValidityStyleRules(false)
  388. , m_updateFocusAppearanceRestoresSelection(false)
  389. , m_ignoreDestructiveWriteCount(0)
  390. , m_titleSetExplicitly(false)
  391. , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
  392. , m_loadEventFinished(false)
  393. , m_startTime(currentTime())
  394. , m_overMinimumLayoutThreshold(false)
  395. , m_scriptRunner(ScriptRunner::create(this))
  396. , m_xmlVersion("1.0")
  397. , m_xmlStandalone(StandaloneUnspecified)
  398. , m_hasXMLDeclaration(0)
  399. , m_savedRenderer(0)
  400. , m_designMode(inherit)
  401. #if ENABLE(DASHBOARD_SUPPORT)
  402. , m_hasDashboardRegions(false)
  403. , m_dashboardRegionsDirty(false)
  404. #endif
  405. , m_createRenderers(true)
  406. , m_inPageCache(false)
  407. , m_accessKeyMapValid(false)
  408. , m_useSecureKeyboardEntryWhenActive(false)
  409. , m_isXHTML(isXHTML)
  410. , m_isHTML(isHTML)
  411. , m_isViewSource(false)
  412. , m_sawElementsInKnownNamespaces(false)
  413. , m_isSrcdocDocument(false)
  414. , m_documentRareData(0)
  415. , m_eventQueue(DocumentEventQueue::create(this))
  416. , m_weakReference(DocumentWeakReference::create(this))
  417. , m_idAttributeName(idAttr)
  418. #if ENABLE(FULLSCREEN_API)
  419. , m_areKeysEnabledInFullScreen(0)
  420. , m_fullScreenRenderer(0)
  421. , m_fullScreenChangeDelayTimer(this, &Document::fullScreenChangeDelayTimerFired)
  422. , m_isAnimatingFullScreen(false)
  423. #endif
  424. , m_loadEventDelayCount(0)
  425. , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
  426. , m_referrerPolicy(ReferrerPolicyDefault)
  427. , m_directionSetOnDocumentElement(false)
  428. , m_writingModeSetOnDocumentElement(false)
  429. , m_writeRecursionIsTooDeep(false)
  430. , m_writeRecursionDepth(0)
  431. , m_wheelEventHandlerCount(0)
  432. , m_touchEventHandlerCount(0)
  433. #if ENABLE(UNDO_MANAGER)
  434. , m_undoManager(0)
  435. #endif
  436. , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
  437. , m_scheduledTasksAreSuspended(false)
  438. , m_visualUpdatesAllowed(true)
  439. , m_visualUpdatesSuppressionTimer(this, &Document::visualUpdatesSuppressionTimerFired)
  440. #ifndef NDEBUG
  441. , m_didDispatchViewportPropertiesChanged(false)
  442. #endif
  443. {
  444. m_document = this;
  445. m_pageGroupUserSheetCacheValid = false;
  446. m_printing = false;
  447. m_paginatedForScreen = false;
  448. m_ignoreAutofocus = false;
  449. m_frame = frame;
  450. if (m_frame)
  451. provideContextFeaturesToDocumentFrom(this, m_frame->page());
  452. // We depend on the url getting immediately set in subframes, but we
  453. // also depend on the url NOT getting immediately set in opened windows.
  454. // See fast/dom/early-frame-url.html
  455. // and fast/dom/location-new-window-no-crash.html, respectively.
  456. // FIXME: Can/should we unify this behavior?
  457. if ((frame && frame->ownerElement()) || !url.isEmpty())
  458. setURL(url);
  459. m_axObjectCache = 0;
  460. m_markers = adoptPtr(new DocumentMarkerController);
  461. m_cachedResourceLoader = adoptPtr(new CachedResourceLoader(this));
  462. #if ENABLE(LINK_PRERENDER)
  463. m_prerenderer = Prerenderer::create(this);
  464. #endif
  465. #if ENABLE(TEXT_AUTOSIZING)
  466. m_textAutosizer = TextAutosizer::create(this);
  467. #endif
  468. m_visuallyOrdered = false;
  469. m_bParsing = false;
  470. m_wellFormed = false;
  471. m_textColor = Color::black;
  472. m_listenerTypes = 0;
  473. m_inStyleRecalc = false;
  474. m_closeAfterStyleRecalc = false;
  475. m_usesSiblingRules = false;
  476. m_usesSiblingRulesOverride = false;
  477. m_usesFirstLineRules = false;
  478. m_usesFirstLetterRules = false;
  479. m_usesBeforeAfterRules = false;
  480. m_usesBeforeAfterRulesOverride = false;
  481. m_usesRemUnits = false;
  482. m_usesLinkRules = false;
  483. m_gotoAnchorNeededAfterStylesheetsLoad = false;
  484. m_didCalculateStyleResolver = false;
  485. m_hasDirtyStyleResolver = false;
  486. m_pendingStylesheets = 0;
  487. m_ignorePendingStylesheets = false;
  488. m_hasNodesWithPlaceholderStyle = false;
  489. m_pendingSheetLayout = NoLayoutWithPendingSheets;
  490. m_cssTarget = 0;
  491. resetLinkColor();
  492. resetVisitedLinkColor();
  493. resetActiveLinkColor();
  494. m_processingLoadEvent = false;
  495. initSecurityContext();
  496. initDNSPrefetch();
  497. static int docID = 0;
  498. m_docID = docID++;
  499. for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
  500. m_nodeListCounts[i] = 0;
  501. for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_collections); i++)
  502. m_collections[i] = 0;
  503. InspectorCounters::incrementCounter(InspectorCounters::DocumentCounter);
  504. }
  505. static void histogramMutationEventUsage(const unsigned short& listenerTypes)
  506. {
  507. HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMSubtreeModified", static_cast<bool>(listenerTypes & Document::DOMSUBTREEMODIFIED_LISTENER), 2);
  508. HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInserted", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTED_LISTENER), 2);
  509. HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemoved", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVED_LISTENER), 2);
  510. HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemovedFromDocument", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER), 2);
  511. HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInsertedIntoDocument", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER), 2);
  512. HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMCharacterDataModified", static_cast<bool>(listenerTypes & Document::DOMCHARACTERDATAMODIFIED_LISTENER), 2);
  513. }
  514. #if ENABLE(FULLSCREEN_API)
  515. static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, const HTMLFrameOwnerElement* owner)
  516. {
  517. if (!owner)
  518. return true;
  519. do {
  520. if (!owner->hasAttribute(attribute))
  521. return false;
  522. } while ((owner = owner->document()->ownerElement()));
  523. return true;
  524. }
  525. #endif
  526. Document::~Document()
  527. {
  528. ASSERT(!renderer());
  529. ASSERT(!m_inPageCache);
  530. ASSERT(!m_savedRenderer);
  531. ASSERT(m_ranges.isEmpty());
  532. ASSERT(!m_styleRecalcTimer.isActive());
  533. ASSERT(!m_parentTreeScope);
  534. ASSERT(!m_guardRefCount);
  535. m_scriptRunner.clear();
  536. histogramMutationEventUsage(m_listenerTypes);
  537. removeAllEventListeners();
  538. // Currently we believe that Document can never outlive the parser.
  539. // Although the Document may be replaced synchronously, DocumentParsers
  540. // generally keep at least one reference to an Element which would in turn
  541. // has a reference to the Document. If you hit this ASSERT, then that
  542. // assumption is wrong. DocumentParser::detach() should ensure that even
  543. // if the DocumentParser outlives the Document it won't cause badness.
  544. ASSERT(!m_parser || m_parser->refCount() == 1);
  545. detachParser();
  546. m_renderArena.clear();
  547. clearAXObjectCache();
  548. m_decoder = 0;
  549. if (m_styleSheets)
  550. m_styleSheets->documentDestroyed();
  551. if (m_namedFlows)
  552. m_namedFlows->documentDestroyed();
  553. if (m_elemSheet)
  554. m_elemSheet->clearOwnerNode();
  555. if (m_pageUserSheet)
  556. m_pageUserSheet->clearOwnerNode();
  557. if (m_pageGroupUserSheets) {
  558. for (size_t i = 0; i < m_pageGroupUserSheets->size(); ++i)
  559. (*m_pageGroupUserSheets)[i]->clearOwnerNode();
  560. }
  561. if (m_userSheets) {
  562. for (size_t i = 0; i < m_userSheets->size(); ++i)
  563. (*m_userSheets)[i]->clearOwnerNode();
  564. }
  565. deleteCustomFonts();
  566. m_weakReference->clear();
  567. if (m_mediaQueryMatcher)
  568. m_mediaQueryMatcher->documentDestroyed();
  569. clearStyleResolver(); // We need to destory CSSFontSelector before destroying m_cachedResourceLoader.
  570. m_cachedResourceLoader.clear();
  571. #if ENABLE(UNDO_MANAGER)
  572. if (m_undoManager)
  573. m_undoManager->undoScopeHostDestroyed();
  574. #endif
  575. // We must call clearRareData() here since a Document class inherits TreeScope
  576. // as well as Node. See a comment on TreeScope.h for the reason.
  577. if (hasRareData())
  578. clearRareData();
  579. ASSERT(!m_listsInvalidatedAtDocument.size());
  580. for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
  581. ASSERT(!m_nodeListCounts[i]);
  582. for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_collections); i++)
  583. ASSERT(!m_collections[i]);
  584. m_document = 0;
  585. InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
  586. }
  587. void Document::removedLastRef()
  588. {
  589. ASSERT(!m_deletionHasBegun);
  590. if (m_guardRefCount) {
  591. // If removing a child removes the last self-only ref, we don't
  592. // want the scope to be destructed until after
  593. // removeAllChildren returns, so we guard ourselves with an
  594. // extra self-only ref.
  595. guardRef();
  596. // We must make sure not to be retaining any of our children through
  597. // these extra pointers or we will create a reference cycle.
  598. m_docType = 0;
  599. m_focusedNode = 0;
  600. m_hoverNode = 0;
  601. m_activeNode = 0;
  602. m_titleElement = 0;
  603. m_documentElement = 0;
  604. m_contextFeatures = ContextFeatures::defaultSwitch();
  605. #if ENABLE(FULLSCREEN_API)
  606. m_fullScreenElement = 0;
  607. m_fullScreenElementStack.clear();
  608. #endif
  609. detachParser();
  610. // removeAllChildren() doesn't always unregister IDs,
  611. // so tear down scope information upfront to avoid having stale references in the map.
  612. destroyTreeScopeData();
  613. removeAllChildren();
  614. m_markers->detach();
  615. m_cssCanvasElements.clear();
  616. #if ENABLE(REQUEST_ANIMATION_FRAME)
  617. // FIXME: consider using ActiveDOMObject.
  618. if (m_scriptedAnimationController)
  619. m_scriptedAnimationController->clearDocumentPointer();
  620. m_scriptedAnimationController.clear();
  621. #endif
  622. #ifndef NDEBUG
  623. m_inRemovedLastRefFunction = false;
  624. #endif
  625. guardDeref();
  626. } else {
  627. #ifndef NDEBUG
  628. m_deletionHasBegun = true;
  629. #endif
  630. delete this;
  631. }
  632. }
  633. Element* Document::getElementById(const AtomicString& id) const
  634. {
  635. return TreeScope::getElementById(id);
  636. }
  637. Element* Document::getElementByAccessKey(const String& key)
  638. {
  639. if (key.isEmpty())
  640. return 0;
  641. if (!m_accessKeyMapValid) {
  642. buildAccessKeyMap(this);
  643. m_accessKeyMapValid = true;
  644. }
  645. return m_elementsByAccessKey.get(key.impl());
  646. }
  647. void Document::buildAccessKeyMap(TreeScope* scope)
  648. {
  649. ASSERT(scope);
  650. Node* rootNode = scope->rootNode();
  651. for (Node* node = rootNode; node; node = node->traverseNextNode(rootNode)) {
  652. if (!node->isElementNode())
  653. continue;
  654. Element* element = static_cast<Element*>(node);
  655. const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
  656. if (!accessKey.isEmpty())
  657. m_elementsByAccessKey.set(accessKey.impl(), element);
  658. for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
  659. buildAccessKeyMap(root);
  660. }
  661. }
  662. void Document::invalidateAccessKeyMap()
  663. {
  664. m_accessKeyMapValid = false;
  665. m_elementsByAccessKey.clear();
  666. }
  667. SelectorQueryCache* Document::selectorQueryCache()
  668. {
  669. if (!m_selectorQueryCache)
  670. m_selectorQueryCache = adoptPtr(new SelectorQueryCache());
  671. return m_selectorQueryCache.get();
  672. }
  673. MediaQueryMatcher* Document::mediaQueryMatcher()
  674. {
  675. if (!m_mediaQueryMatcher)
  676. m_mediaQueryMatcher = MediaQueryMatcher::create(this);
  677. return m_mediaQueryMatcher.get();
  678. }
  679. void Document::setCompatibilityMode(CompatibilityMode mode)
  680. {
  681. if (m_compatibilityModeLocked || mode == m_compatibilityMode)
  682. return;
  683. ASSERT(!m_styleSheets->length());
  684. bool wasInQuirksMode = inQuirksMode();
  685. m_compatibilityMode = mode;
  686. selectorQueryCache()->invalidate();
  687. if (inQuirksMode() != wasInQuirksMode) {
  688. // All user stylesheets have to reparse using the different mode.
  689. clearPageUserSheet();
  690. clearPageGroupUserSheets();
  691. }
  692. }
  693. String Document::compatMode() const
  694. {
  695. return inQuirksMode() ? "BackCompat" : "CSS1Compat";
  696. }
  697. void Document::resetLinkColor()
  698. {
  699. m_linkColor = Color(0, 0, 238);
  700. }
  701. void Document::resetVisitedLinkColor()
  702. {
  703. m_visitedLinkColor = Color(85, 26, 139);
  704. }
  705. void Document::resetActiveLinkColor()
  706. {
  707. m_activeLinkColor.setNamedColor("red");
  708. }
  709. void Document::setDocType(PassRefPtr<DocumentType> docType)
  710. {
  711. // This should never be called more than once.
  712. ASSERT(!m_docType || !docType);
  713. m_docType = docType;
  714. if (m_docType) {
  715. this->adoptIfNeeded(m_docType.get());
  716. #if ENABLE(LEGACY_VIEWPORT_ADAPTION)
  717. if (m_docType->publicId().startsWith("-//wapforum//dtd xhtml mobile 1.", /* caseSensitive */ false))
  718. processViewport("width=device-width, height=device-height", ViewportArguments::XHTMLMobileProfile);
  719. #endif
  720. }
  721. // Doctype affects the interpretation of the stylesheets.
  722. clearStyleResolver();
  723. }
  724. DOMImplementation* Document::implementation()
  725. {
  726. if (!m_implementation)
  727. m_implementation = DOMImplementation::create(this);
  728. return m_implementation.get();
  729. }
  730. void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
  731. {
  732. ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
  733. Element* newDocumentElement = firstElementChild(this);
  734. if (newDocumentElement == m_documentElement)
  735. return;
  736. m_documentElement = newDocumentElement;
  737. // The root style used for media query matching depends on the document element.
  738. clearStyleResolver();
  739. }
  740. PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
  741. {
  742. if (!isValidName(name)) {
  743. ec = INVALID_CHARACTER_ERR;
  744. return 0;
  745. }
  746. if (m_isXHTML)
  747. return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), this, 0, false);
  748. return createElement(QualifiedName(nullAtom, name, nullAtom), false);
  749. }
  750. PassRefPtr<DocumentFragment> Document::createDocumentFragment()
  751. {
  752. return DocumentFragment::create(document());
  753. }
  754. PassRefPtr<Text> Document::createTextNode(const String& data)
  755. {
  756. return Text::create(this, data);
  757. }
  758. PassRefPtr<Comment> Document::createComment(const String& data)
  759. {
  760. return Comment::create(this, data);
  761. }
  762. PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
  763. {
  764. if (isHTMLDocument()) {
  765. ec = NOT_SUPPORTED_ERR;
  766. return 0;
  767. }
  768. return CDATASection::create(this, data);
  769. }
  770. PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
  771. {
  772. if (!isValidName(target)) {
  773. ec = INVALID_CHARACTER_ERR;
  774. return 0;
  775. }
  776. if (isHTMLDocument()) {
  777. ec = NOT_SUPPORTED_ERR;
  778. return 0;
  779. }
  780. return ProcessingInstruction::create(this, target, data);
  781. }
  782. PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec)
  783. {
  784. if (!isValidName(name)) {
  785. ec = INVALID_CHARACTER_ERR;
  786. return 0;
  787. }
  788. if (isHTMLDocument()) {
  789. ec = NOT_SUPPORTED_ERR;
  790. return 0;
  791. }
  792. return EntityReference::create(this, name);
  793. }
  794. PassRefPtr<EditingText> Document::createEditingTextNode(const String& text)
  795. {
  796. return EditingText::create(this, text);
  797. }
  798. PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
  799. {
  800. return StylePropertySet::create()->ensureCSSStyleDeclaration();
  801. }
  802. PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
  803. {
  804. ec = 0;
  805. if (!importedNode) {
  806. ec = NOT_SUPPORTED_ERR;
  807. return 0;
  808. }
  809. switch (importedNode->nodeType()) {
  810. case TEXT_NODE:
  811. return createTextNode(importedNode->nodeValue());
  812. case CDATA_SECTION_NODE:
  813. return createCDATASection(importedNode->nodeValue(), ec);
  814. case ENTITY_REFERENCE_NODE:
  815. return createEntityReference(importedNode->nodeName(), ec);
  816. case PROCESSING_INSTRUCTION_NODE:
  817. return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec);
  818. case COMMENT_NODE:
  819. return createComment(importedNode->nodeValue());
  820. case ELEMENT_NODE: {
  821. Element* oldElement = static_cast<Element*>(importedNode);
  822. // FIXME: The following check might be unnecessary. Is it possible that
  823. // oldElement has mismatched prefix/namespace?
  824. if (!hasValidNamespaceForElements(oldElement->tagQName())) {
  825. ec = NAMESPACE_ERR;
  826. return 0;
  827. }
  828. RefPtr<Element> newElement = createElement(oldElement->tagQName(), ec);
  829. if (ec)
  830. return 0;
  831. newElement->cloneDataFromElement(*oldElement);
  832. if (deep) {
  833. for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
  834. RefPtr<Node> newChild = importNode(oldChild, true, ec);
  835. if (ec)
  836. return 0;
  837. newElement->appendChild(newChild.release(), ec);
  838. if (ec)
  839. return 0;
  840. }
  841. }
  842. return newElement.release();
  843. }
  844. case ATTRIBUTE_NODE:
  845. return Attr::create(this, QualifiedName(nullAtom, static_cast<Attr*>(importedNode)->name(), nullAtom), static_cast<Attr*>(importedNode)->value());
  846. case DOCUMENT_FRAGMENT_NODE: {
  847. if (importedNode->isShadowRoot()) {
  848. // ShadowRoot nodes should not be explicitly importable.
  849. // Either they are imported along with their host node, or created implicitly.
  850. break;
  851. }
  852. DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode);
  853. RefPtr<DocumentFragment> newFragment = createDocumentFragment();
  854. if (deep) {
  855. for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
  856. RefPtr<Node> newChild = importNode(oldChild, true, ec);
  857. if (ec)
  858. return 0;
  859. newFragment->appendChild(newChild.release(), ec);
  860. if (ec)
  861. return 0;
  862. }
  863. }
  864. return newFragment.release();
  865. }
  866. case ENTITY_NODE:
  867. case NOTATION_NODE:
  868. // FIXME: It should be possible to import these node types, however in DOM3 the DocumentType is readonly, so there isn't much sense in doing that.
  869. // Ability to add these imported nodes to a DocumentType will be considered for addition to a future release of the DOM.
  870. case DOCUMENT_NODE:
  871. case DOCUMENT_TYPE_NODE:
  872. case XPATH_NAMESPACE_NODE:
  873. break;
  874. }
  875. ec = NOT_SUPPORTED_ERR;
  876. return 0;
  877. }
  878. PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
  879. {
  880. if (!source) {
  881. ec = NOT_SUPPORTED_ERR;
  882. return 0;
  883. }
  884. if (source->isReadOnlyNode()) {
  885. ec = NO_MODIFICATION_ALLOWED_ERR;
  886. return 0;
  887. }
  888. EventQueueScope scope;
  889. switch (source->nodeType()) {
  890. case ENTITY_NODE:
  891. case NOTATION_NODE:
  892. case DOCUMENT_NODE:
  893. case DOCUMENT_TYPE_NODE:
  894. case XPATH_NAMESPACE_NODE:
  895. ec = NOT_SUPPORTED_ERR;
  896. return 0;
  897. case ATTRIBUTE_NODE: {
  898. Attr* attr = static_cast<Attr*>(source.get());
  899. if (attr->ownerElement())
  900. attr->ownerElement()->removeAttributeNode(attr, ec);
  901. attr->setSpecified(true);
  902. break;
  903. }
  904. default:
  905. if (source->isShadowRoot()) {
  906. // ShadowRoot cannot disconnect itself from the host node.
  907. ec = HIERARCHY_REQUEST_ERR;
  908. return 0;
  909. }
  910. // FIXME: What about <frame> and <object>?
  911. if (source->hasTagName(iframeTag)) {
  912. HTMLIFrameElement* iframe = static_cast<HTMLIFrameElement*>(source.get());
  913. if (frame() && frame()->tree()->isDescendantOf(iframe->contentFrame())) {
  914. ec = HIERARCHY_REQUEST_ERR;
  915. return 0;
  916. }
  917. }
  918. if (source->parentNode())
  919. source->parentNode()->removeChild(source.get(), ec);
  920. }
  921. this->adoptIfNeeded(source.get());
  922. return source;
  923. }
  924. bool Document::hasValidNamespaceForElements(const QualifiedName& qName)
  925. {
  926. // These checks are from DOM Core Level 2, createElementNS
  927. // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
  928. if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div")
  929. return false;
  930. if (qName.prefix() == xmlAtom && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang")
  931. return false;
  932. // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
  933. // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
  934. // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar")
  935. if ((qName.prefix() == xmlnsAtom && qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI) || (qName.prefix() != xmlnsAtom && qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI))
  936. return false;
  937. return true;
  938. }
  939. bool Document::hasValidNamespaceForAttributes(const QualifiedName& qName)
  940. {
  941. // Spec: DOM Level 2 Core: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-ElSetAttrNS
  942. if (qName.prefix().isEmpty() && qName.localName() == xmlnsAtom) {
  943. // Note: The case of an "xmlns" qualified name with a namespace of
  944. // xmlnsNamespaceURI is specifically allowed (See <http://www.w3.org/2000/xmlns/>).
  945. return qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI;
  946. }
  947. return hasValidNamespaceForElements(qName);
  948. }
  949. // FIXME: This should really be in a possible ElementFactory class
  950. PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser)
  951. {
  952. RefPtr<Element> e;
  953. // FIXME: Use registered namespaces and look up in a hash to find the right factory.
  954. if (qName.namespaceURI() == xhtmlNamespaceURI)
  955. e = HTMLElementFactory::createHTMLElement(qName, this, 0, createdByParser);
  956. #if ENABLE(SVG)
  957. else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
  958. e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
  959. #endif
  960. #if ENABLE(MATHML)
  961. else if (qName.namespaceURI() == MathMLNames::mathmlNamespaceURI)
  962. e = MathMLElementFactory::createMathMLElement(qName, this, createdByParser);
  963. #endif
  964. if (e)
  965. m_sawElementsInKnownNamespaces = true;
  966. else
  967. e = Element::create(qName, document());
  968. // <image> uses imgTag so we need a special rule.
  969. ASSERT((qName.matches(imageTag) && e->tagQName().matches(imgTag) && e->tagQName().prefix() == qName.prefix()) || qName == e->tagQName());
  970. return e.release();
  971. }
  972. bool Document::regionBasedColumnsEnabled() const
  973. {
  974. return settings() && settings()->regionBasedColumnsEnabled();
  975. }
  976. bool Document::cssRegionsEnabled() const
  977. {
  978. return settings() && settings()->cssRegionsEnabled();
  979. }
  980. bool Document::cssGridLayoutEnabled() const
  981. {
  982. return settings() && settings()->cssGridLayoutEnabled();
  983. }
  984. #if ENABLE(CSS_REGIONS)
  985. PassRefPtr<WebKitNamedFlow> Document::webkitGetFlowByName(const String& flowName)
  986. {
  987. if (!cssRegionsEnabled() || !renderer())
  988. return 0;
  989. // It's possible to have pending styles not applied that affect the existing flows.
  990. updateStyleIfNeeded();
  991. return namedFlows()->flowByName(flowName);
  992. }
  993. #endif
  994. WebKitNamedFlowCollection* Document::namedFlows()
  995. {
  996. if (!m_namedFlows)
  997. m_namedFlows = WebKitNamedFlowCollection::create(this);
  998. return m_namedFlows.get();
  999. }
  1000. PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
  1001. {
  1002. String prefix, localName;
  1003. if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
  1004. return 0;
  1005. QualifiedName qName(prefix, localName, namespaceURI);
  1006. if (!hasValidNamespaceForElements(qName)) {
  1007. ec = NAMESPACE_ERR;
  1008. return 0;
  1009. }
  1010. return createElement(qName, false);
  1011. }
  1012. String Document::readyState() const
  1013. {
  1014. DEFINE_STATIC_LOCAL(const String, loading, ("loading"));
  1015. DEFINE_STATIC_LOCAL(const String, interactive, ("interactive"));
  1016. DEFINE_STATIC_LOCAL(const String, complete, ("complete"));
  1017. switch (m_readyState) {
  1018. case Loading:
  1019. return loading;
  1020. case Interactive:
  1021. return interactive;
  1022. case Complete:
  1023. return complete;
  1024. }
  1025. ASSERT_NOT_REACHED();
  1026. return String();
  1027. }
  1028. void Document::setReadyState(ReadyState readyState)
  1029. {
  1030. if (readyState == m_readyState)
  1031. return;
  1032. switch (readyState) {
  1033. case Loading:
  1034. if (!m_documentTiming.domLoading)
  1035. m_documentTiming.domLoading = monotonicallyIncreasingTime();
  1036. break;
  1037. case Interactive:
  1038. if (!m_documentTiming.domInteractive)
  1039. m_documentTiming.domInteractive = monotonicallyIncreasingTime();
  1040. break;
  1041. case Complete:
  1042. if (!m_documentTiming.domComplete)
  1043. m_documentTiming.domComplete = monotonicallyIncreasingTime();
  1044. break;
  1045. }
  1046. m_readyState = readyState;
  1047. dispatchEvent(Event::create(eventNames().readystatechangeEvent, false, false));
  1048. if (settings() && settings()->suppressesIncrementalRendering())
  1049. setVisualUpdatesAllowed(readyState);
  1050. }
  1051. void Document::setVisualUpdatesAllowed(ReadyState readyState)
  1052. {
  1053. ASSERT(settings() && settings()->suppressesIncrementalRendering());
  1054. switch (readyState) {
  1055. case Loading:
  1056. ASSERT(!m_visualUpdatesSuppressionTimer.isActive());
  1057. ASSERT(m_visualUpdatesAllowed);
  1058. m_visualUpdatesSuppressionTimer.startOneShot(settings()->incrementalRenderingSuppressionTimeoutInSeconds());
  1059. setVisualUpdatesAllowed(false);
  1060. break;
  1061. case Interactive:
  1062. ASSERT(m_visualUpdatesSuppressionTimer.isActive() || m_visualUpdatesAllowed);
  1063. break;
  1064. case Complete:
  1065. if (m_visualUpdatesSuppressionTimer.isActive()) {
  1066. ASSERT(!m_visualUpdatesAllowed);
  1067. m_visualUpdatesSuppressionTimer.stop();
  1068. setVisualUpdatesAllowed(true);
  1069. } else
  1070. ASSERT(m_visualUpdatesAllowed);
  1071. break;
  1072. }
  1073. }
  1074. void Document::setVisualUpdatesAllowed(bool visualUpdatesAllowed)
  1075. {
  1076. if (m_visualUpdatesAllowed == visualUpdatesAllowed)
  1077. return;
  1078. m_visualUpdatesAllowed = visualUpdatesAllowed;
  1079. if (!visualUpdatesAllowed)
  1080. return;
  1081. #if USE(ACCELERATED_COMPOSITING)
  1082. if (view())
  1083. view()->updateCompositingLayersAfterLayout();
  1084. #endif
  1085. if (renderer())
  1086. renderer()->repaint();
  1087. }
  1088. void Document::visualUpdatesSuppressionTimerFired(Timer<Document>*)
  1089. {
  1090. ASSERT(!m_visualUpdatesAllowed);
  1091. setVisualUpdatesAllowed(true);
  1092. }
  1093. String Document::encoding() const
  1094. {
  1095. if (TextResourceDecoder* d = decoder())
  1096. return d->encoding().domName();
  1097. return String();
  1098. }
  1099. String Document::defaultCharset() const
  1100. {
  1101. if (Settings* settings = this->settings())
  1102. return settings->defaultTextEncodingName();
  1103. return String();
  1104. }
  1105. void Document::setCharset(const String& charset)
  1106. {
  1107. if (!decoder())
  1108. return;
  1109. decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
  1110. }
  1111. void Document::setContentLanguage(const String& language)
  1112. {
  1113. if (m_contentLanguage == language)
  1114. return;
  1115. m_contentLanguage = language;
  1116. // Recalculate style so language is used when selecting the initial font.
  1117. styleResolverChanged(DeferRecalcStyle);
  1118. }
  1119. void Document::setXMLVersion(const String& version, ExceptionCode& ec)
  1120. {
  1121. if (!implementation()->hasFeature("XML", String())) {
  1122. ec = NOT_SUPPORTED_ERR;
  1123. return;
  1124. }
  1125. if (!XMLDocumentParser::supportsXMLVersion(version)) {
  1126. ec = NOT_SUPPORTED_ERR;
  1127. return;
  1128. }
  1129. m_xmlVersion = version;
  1130. }
  1131. void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
  1132. {
  1133. if (!implementation()->hasFeature("XML", String())) {
  1134. ec = NOT_SUPPORTED_ERR;
  1135. return;
  1136. }
  1137. m_xmlStandalone = standalone ? Standalone : NotStandalone;
  1138. }
  1139. void Document::setDocumentURI(const String& uri)
  1140. {
  1141. // This property is read-only from JavaScript, but writable from Objective-C.
  1142. m_documentURI = uri;
  1143. updateBaseURL();
  1144. }
  1145. KURL Document::baseURI() const
  1146. {
  1147. return m_baseURL;
  1148. }
  1149. void Document::setContent(const String& content)
  1150. {
  1151. open();
  1152. m_parser->append(content);
  1153. close();
  1154. }
  1155. String Document::suggestedMIMEType() const
  1156. {
  1157. if (m_document->isXHTMLDocument())
  1158. return "application/xhtml+xml";
  1159. if (m_document->isSVGDocument())
  1160. return "image/svg+xml";
  1161. if (m_document->xmlStandalone())
  1162. return "text/xml";
  1163. if (m_document->isHTMLDocument())
  1164. return "text/html";
  1165. if (DocumentLoader* documentLoader = loader())
  1166. return documentLoader->responseMIMEType();
  1167. return String();
  1168. }
  1169. // FIXME: We need to discuss the DOM API here at some point. Ideas:
  1170. // * making it receive a rect as parameter, i.e. nodesFromRect(x, y, w, h);
  1171. // * making it receive the expading size of each direction separately,
  1172. // i.e. nodesFromRect(x, y, topSize, rightSize, bottomSize, leftSize);
  1173. PassRefPtr<NodeList> Document::nodesFromRect(int centerX, int centerY, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent) const
  1174. {
  1175. // FIXME: Share code between this, elementFromPoint and caretRangeFromPoint.
  1176. if (!renderer())
  1177. return 0;
  1178. Frame* frame = this->frame();
  1179. if (!frame)
  1180. return 0;
  1181. FrameView* frameView = frame->view();
  1182. if (!frameView)
  1183. return 0;
  1184. float zoomFactor = frame->pageZoomFactor();
  1185. LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + view()->scrollX(), centerY * zoomFactor + view()->scrollY()));
  1186. int type = HitTestRequest::ReadOnly | HitTestRequest::Active;
  1187. // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
  1188. if (ignoreClipping)
  1189. type |= HitTestRequest::IgnoreClipping;
  1190. else if (!frameView->visibleContentRect().intersects(HitTestResult::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
  1191. return 0;
  1192. HitTestRequest request(type);
  1193. // Passing a zero padding will trigger a rect hit test, however for the purposes of nodesFromRect,
  1194. // we special handle this case in order to return a valid NodeList.
  1195. if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
  1196. HitTestResult result(point);
  1197. return handleZeroPadding(request, result);
  1198. }
  1199. enum ShadowContentFilterPolicy shadowContentFilterPolicy = allowShadowContent ? AllowShadowContent : DoNotAllowShadowContent;
  1200. HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding, shadowContentFilterPolicy);
  1201. renderView()->hitTest(request, result);
  1202. return StaticHashSetNodeList::adopt(result.rectBasedTestResult());
  1203. }
  1204. PassRefPtr<NodeList> Document::handleZeroPadding(const HitTestRequest& request, HitTestResult& result) const
  1205. {
  1206. renderView()->hitTest(request, result);
  1207. Node* node = result.innerNode();
  1208. if (!node)
  1209. return 0;
  1210. node = node->shadowAncestorNode();
  1211. ListHashSet<RefPtr<Node> > list;
  1212. list.add(node);
  1213. return StaticHashSetNodeList::adopt(list);
  1214. }
  1215. static Node* nodeFromPoint(Frame* frame, RenderView* renderView, int x, int y, LayoutPoint* localPoint = 0)
  1216. {
  1217. if (!frame)
  1218. return 0;
  1219. FrameView* frameView = frame->view();
  1220. if (!frameView)
  1221. return 0;
  1222. float zoomFactor = frame->pageZoomFactor();
  1223. IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + frameView->scrollX(), y * zoomFactor + frameView->scrollY()));
  1224. if (!frameView->visibleContentRect().contains(point))
  1225. return 0;
  1226. HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
  1227. HitTestResult result(point);
  1228. renderView->hitTest(request, result);
  1229. if (localPoint)
  1230. *localPoint = result.localPoint();
  1231. return result.innerNode();
  1232. }
  1233. Element* Document::elementFromPoint(int x, int y) const
  1234. {
  1235. if (!renderer())
  1236. return 0;
  1237. Node* node = nodeFromPoint(frame(), renderView(), x, y);
  1238. while (node && !node->isElementNode())
  1239. node = node->parentNode();
  1240. if (node)
  1241. node = ancestorInThisScope(node);
  1242. return static_cast<Element*>(node);
  1243. }
  1244. PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y)
  1245. {
  1246. if (!renderer())
  1247. return 0;
  1248. LayoutPoint localPoint;
  1249. Node* node = nodeFromPoint(frame(), renderView(), x, y, &localPoint);
  1250. if (!node)
  1251. return 0;
  1252. Node* shadowAncestorNode = ancestorInThisScope(node);
  1253. if (shadowAncestorNode != node) {
  1254. unsigned offset = shadowAncestorNode->nodeIndex();
  1255. ContainerNode* container = shadowAncestorNode->parentNode();
  1256. return Range::create(this, container, offset, container, offset);
  1257. }
  1258. RenderObject* renderer = node->renderer();
  1259. if (!renderer)
  1260. return 0;
  1261. VisiblePosition visiblePosition = renderer->positionForPoint(localPoint);
  1262. if (visiblePosition.isNull())
  1263. return 0;
  1264. Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
  1265. return Range::create(this, rangeCompliantPosition, rangeCompliantPosition);
  1266. }
  1267. /*
  1268. * Performs three operations:
  1269. * 1. Convert control characters to spaces
  1270. * 2. Trim leading and trailing spaces
  1271. * 3. Collapse internal whitespace.
  1272. */
  1273. static inline StringWithDirection canonicalizedTitle(Document* document, const StringWithDirection& titleWithDirection)
  1274. {
  1275. const String& title = titleWithDirection.string();
  1276. const UChar* characters = title.characters();
  1277. unsigned length = title.length();
  1278. unsigned i;
  1279. StringBuffer<UChar> buffer(length);
  1280. unsigned builderIndex = 0;
  1281. // Skip leading spaces and leading characters that would convert to spaces
  1282. for (i = 0; i < length; ++i) {
  1283. UChar c = characters[i];
  1284. if (!(c <= 0x20 || c == 0x7F))
  1285. break;
  1286. }
  1287. if (i == length)
  1288. return StringWithDirection();
  1289. // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace.
  1290. bool previousCharWasWS = false;
  1291. for (; i < length; ++i) {
  1292. UChar c = characters[i];
  1293. if (c <= 0x20 || c == 0x7F || (WTF::Unicode::category(c) & (WTF::Unicode::Separator_Line | WTF::Unicode::Separator_Paragraph))) {
  1294. if (previousCharWasWS)
  1295. continue;
  1296. buffer[builderIndex++] = ' ';
  1297. previousCharWasWS = true;
  1298. } else {
  1299. buffer[builderIndex++] = c;
  1300. previousCharWasWS = false;
  1301. }
  1302. }
  1303. // Strip trailing spaces
  1304. while (builderIndex > 0) {
  1305. --builderIndex;
  1306. if (buffer[builderIndex] != ' ')
  1307. break;
  1308. }
  1309. if (!builderIndex && buffer[builderIndex] == ' ')
  1310. return StringWithDirection();
  1311. buffer.shrink(builderIndex + 1);
  1312. // Replace the backslashes with currency symbols if the encoding requires it.
  1313. document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length());
  1314. return StringWithDirection(String::adopt(buffer), titleWithDirection.direction());
  1315. }
  1316. void Document::updateTitle(const StringWithDirection& title)
  1317. {
  1318. if (m_rawTitle == title)
  1319. return;
  1320. m_rawTitle = title;
  1321. m_title = canonicalizedTitle(this, m_rawTitle);
  1322. if (Frame* f = frame())
  1323. f->loader()->setTitle(m_title);
  1324. }
  1325. void Document::setTitle(const String& title)
  1326. {
  1327. // Title set by JavaScript -- overrides any title elements.
  1328. m_titleSetExplicitly = true;
  1329. if (!isHTMLDocument() && !isXHTMLDocument())
  1330. m_titleElement = 0;
  1331. else if (!m_titleElement) {
  1332. if (HTMLElement* headElement = head()) {
  1333. m_titleElement = createElement(titleTag, false);
  1334. ExceptionCode ec = 0;
  1335. headElement->appendChild(m_titleElement, ec);
  1336. ASSERT(!ec);
  1337. }
  1338. }
  1339. // The DOM API has no method of specifying direction, so assume LTR.
  1340. updateTitle(StringWithDirection(title, LTR));
  1341. if (m_titleElement) {
  1342. ASSERT(m_titleElement->hasTagName(titleTag));
  1343. if (m_titleElement->hasTagName(titleTag))
  1344. static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(title);
  1345. }
  1346. }
  1347. void Document::setTitleElement(const StringWithDirection& title, Element* titleElement)
  1348. {
  1349. if (titleElement != m_titleElement) {
  1350. if (m_titleElement || m_titleSetExplicitly)
  1351. // Only allow the first title element to change the title -- others have no effect.
  1352. return;
  1353. m_titleElement = titleElement;
  1354. }
  1355. updateTitle(title);
  1356. }
  1357. void Document::removeTitle(Element* titleElement)
  1358. {
  1359. if (m_titleElement != titleElement)
  1360. return;
  1361. m_titleElement = 0;
  1362. m_titleSetExplicitly = false;
  1363. // Update title based on first title element in the head, if one exists.
  1364. if (HTMLElement* headElement = head()) {
  1365. for (Node* e = headElement->firstChild(); e; e = e->nextSibling())
  1366. if (e->hasTagName(titleTag)) {
  1367. HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e);
  1368. setTitleElement(titleElement->textWithDirection(), titleElement);
  1369. break;
  1370. }
  1371. }
  1372. if (!m_titleElement)
  1373. updateTitle(StringWithDirection());
  1374. }
  1375. #if ENABLE(PAGE_VISIBILITY_API)
  1376. PageVisibilityState Document::visibilityState() const
  1377. {
  1378. // The visibility of the document is inherited from the visibility of the
  1379. // page. If there is no page associated with the document, we will assume
  1380. // that the page is visible i.e. invisibility has to be explicitly
  1381. // specified by the embedder.
  1382. if (!m_frame || !m_frame->page())
  1383. return PageVisibilityStateVisible;
  1384. return m_frame->page()->visibilityState();
  1385. }
  1386. String Document::webkitVisibilityState() const
  1387. {
  1388. return pageVisibilityStateString(visibilityState());
  1389. }
  1390. bool Document::webkitHidden() const
  1391. {
  1392. return visibilityState() != PageVisibilityStateVisible;
  1393. }
  1394. void Document::dispatchVisibilityStateChangeEvent()
  1395. {
  1396. dispatchEvent(Event::create(eventNames().webkitvisibilitychangeEvent, false, false));
  1397. }
  1398. #endif
  1399. String Document::nodeName() const
  1400. {
  1401. return "#document";
  1402. }
  1403. Node::NodeType Document::nodeType() const
  1404. {
  1405. return DOCUMENT_NODE;
  1406. }
  1407. FormController* Document::formController()
  1408. {
  1409. if (!m_formController)
  1410. m_formController = FormController::create();
  1411. return m_formController.get();
  1412. }
  1413. Vector<String> Document::formElementsState() const
  1414. {
  1415. if (!m_formController)
  1416. return Vector<String>();
  1417. return m_formController->formElementsState();
  1418. }
  1419. void Document::setStateForNewFormElements(const Vector<String>& stateVector)
  1420. {
  1421. if (!stateVector.size() && !m_formController)
  1422. return;
  1423. formController()->setStateForNewFormElements(stateVector);
  1424. }
  1425. FrameView* Document::view() const
  1426. {
  1427. return m_frame ? m_frame->view() : 0;
  1428. }
  1429. Page* Document::page() const
  1430. {
  1431. return m_frame ? m_frame->page() : 0;
  1432. }
  1433. Settings* Document::settings() const
  1434. {
  1435. return m_frame ? m_frame->settings() : 0;
  1436. }
  1437. PassRefPtr<Range> Document::createRange()
  1438. {
  1439. return Range::create(this);
  1440. }
  1441. PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow,
  1442. PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
  1443. {
  1444. if (!root) {
  1445. ec = NOT_SUPPORTED_ERR;
  1446. return 0;
  1447. }
  1448. return NodeIterator::create(root, whatToShow, filter, expandEntityReferences);
  1449. }
  1450. PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned whatToShow,
  1451. PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
  1452. {
  1453. if (!root) {
  1454. ec = NOT_SUPPORTED_ERR;
  1455. return 0;
  1456. }
  1457. return TreeWalker::create(root, whatToShow, filter, expandEntityReferences);
  1458. }
  1459. void Document::scheduleForcedStyleRecalc()
  1460. {
  1461. m_pendingStyleRecalcShouldForce = true;
  1462. scheduleStyleRecalc();
  1463. }
  1464. void Document::scheduleStyleRecalc()
  1465. {
  1466. if (shouldDisplaySeamlesslyWithParent()) {
  1467. // When we're seamless, our parent document manages our style recalcs.
  1468. ownerElement()->setNeedsStyleRecalc();
  1469. ownerElement()->document()->scheduleStyleRecalc();
  1470. return;
  1471. }
  1472. if (m_styleRecalcTimer.isActive() || inPageCache())
  1473. return;
  1474. ASSERT(childNeedsStyleRecalc() || m_pendingStyleRecalcShouldForce);
  1475. if (!documentsThatNeedStyleRecalc)
  1476. documentsThatNeedStyleRecalc = new HashSet<Document*>;
  1477. documentsThatNeedStyleRecalc->add(this);
  1478. // FIXME: Why on earth is this here? This is clearly misplaced.
  1479. invalidateAccessKeyMap();
  1480. m_styleRecalcTimer.startOneShot(0);
  1481. InspectorInstrumentation::didScheduleStyleRecalculation(this);
  1482. }
  1483. void Document::unscheduleStyleRecalc()
  1484. {
  1485. ASSERT(!childNeedsStyleRecalc());
  1486. if (documentsThatNeedStyleRecalc)
  1487. documentsThatNeedStyleRecalc->remove(this);
  1488. m_styleRecalcTimer.stop();
  1489. m_pendingStyleRecalcShouldForce = false;
  1490. }
  1491. bool Document::isPendingStyleRecalc() const
  1492. {
  1493. return m_styleRecalcTimer.isActive() && !m_inStyleRecalc;
  1494. }
  1495. void Document::styleRecalcTimerFired(Timer<Document>*)
  1496. {
  1497. updateStyleIfNeeded();
  1498. }
  1499. bool Document::childNeedsAndNotInStyleRecalc()
  1500. {
  1501. return childNeedsStyleRecalc() && !m_inStyleRecalc;
  1502. }
  1503. void Document::recalcStyle(StyleChange change)
  1504. {
  1505. // we should not enter style recalc while painting
  1506. if (view() && view()->isPainting()) {
  1507. ASSERT(!view()->isPainting());
  1508. return;
  1509. }
  1510. if (m_inStyleRecalc)
  1511. return; // Guard against re-entrancy. -dwh
  1512. // FIXME: We should update style on our ancestor chain before proceeding (especially for seamless),
  1513. // however doing so currently causes several tests to crash, as Frame::setDocument calls Document::attach
  1514. // before setting the DOMWindow on the Frame, or the SecurityOrigin on the document. The attach, in turn
  1515. // resolves style (here) and then when we resolve style on the parent chain, we may end up
  1516. // re-attaching our containing iframe, which when asked HTMLFrameElementBase::isURLAllowed
  1517. // hits a null-dereference due to security code always assuming the document has a SecurityOrigin.
  1518. if (m_hasDirtyStyleResolver)
  1519. updateActiveStylesheets(RecalcStyleImmediately);
  1520. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(this);
  1521. if (m_elemSheet && m_elemSheet->contents()->usesRemUnits())
  1522. m_usesRemUnits = true;
  1523. m_inStyleRecalc = true;
  1524. suspendPostAttachCallbacks();
  1525. RenderWidget::suspendWidgetHierarchyUpdates();
  1526. RefPtr<FrameView> frameView = view();
  1527. if (frameView) {
  1528. frameView->pauseScheduledEvents();
  1529. frameView->beginDeferredRepaints();
  1530. }
  1531. ASSERT(!renderer() || renderArena());
  1532. if (!renderer() || !renderArena())
  1533. goto bail_out;
  1534. if (m_pendingStyleRecalcShouldForce)
  1535. change = Force;
  1536. // Recalculating the root style (on the document) is not needed in the common case.
  1537. if ((change == Force) || (shouldDisplaySeamlesslyWithParent() && (change >= Inherit))) {
  1538. // style selector may set this again during recalc
  1539. m_hasNodesWithPlaceholderStyle = false;
  1540. RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(this, m_styleResolver ? m_styleResolver->fontSelector() : 0);
  1541. StyleChange ch = Node::diff(documentStyle.get(), renderer()->style(), this);
  1542. if (ch != NoChange)
  1543. renderer()->setStyle(documentStyle.release());
  1544. }
  1545. for (Node* n = firstChild(); n; n = n->nextSibling()) {
  1546. if (!n->isElementNode())
  1547. continue;
  1548. Element* element = static_cast<Element*>(n);
  1549. if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc())
  1550. element->recalcStyle(change);
  1551. }
  1552. #if USE(ACCELERATED_COMPOSITING)
  1553. if (view()) {
  1554. bool layoutPending = view()->layoutPending() || renderer()->needsLayout();
  1555. // If we didn't update compositing layers because of layout(), we need to do so here.
  1556. if (!layoutPending)
  1557. view()->updateCompositingLayersAfterStyleChange();
  1558. }
  1559. #endif
  1560. bail_out:
  1561. clearNeedsStyleRecalc();
  1562. clearChildNeedsStyleRecalc();
  1563. unscheduleStyleRecalc();
  1564. m_inStyleRecalc = false;
  1565. // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
  1566. if (m_styleResolver)
  1567. resetCSSFeatureFlags();
  1568. if (frameView) {
  1569. frameView->resumeScheduledEvents();
  1570. frameView->endDeferredRepaints();
  1571. }
  1572. RenderWidget::resumeWidgetHierarchyUpdates();
  1573. resumePostAttachCallbacks();
  1574. // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished.
  1575. if (m_closeAfterStyleRecalc) {
  1576. m_closeAfterStyleRecalc = false;
  1577. implicitClose();
  1578. }
  1579. InspectorInstrumentation::didRecalculateStyle(cookie);
  1580. }
  1581. void Document::updateStyleIfNeeded()
  1582. {
  1583. ASSERT(isMainThread());
  1584. ASSERT(!view() || (!view()->isInLayout() && !view()->isPainting()));
  1585. if ((!m_pendingStyleRecalcShouldForce && !childNeedsStyleRecalc()) || inPageCache())
  1586. return;
  1587. AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
  1588. recalcStyle(NoChange);
  1589. }
  1590. void Document::updateStyleForAllDocuments()
  1591. {
  1592. ASSERT(isMainThread());
  1593. if (!documentsThatNeedStyleRecalc)
  1594. return;
  1595. while (documentsThatNeedStyleRecalc->size()) {
  1596. HashSet<Document*>::iterator it = documentsThatNeedStyleRecalc->begin();
  1597. Document* doc = *it;
  1598. documentsThatNeedStyleRecalc->remove(doc);
  1599. doc->updateStyleIfNeeded();
  1600. }
  1601. }
  1602. void Document::updateLayout()
  1603. {
  1604. ASSERT(isMainThread());
  1605. if (Element* oe = ownerElement())
  1606. oe->document()->updateLayout();
  1607. updateStyleIfNeeded();
  1608. // Only do a layout if changes have occurred that make it necessary.
  1609. FrameView* v = view();
  1610. if (v && renderer() && (v->layoutPending() || renderer()->needsLayout()))
  1611. v->layout();
  1612. }
  1613. // FIXME: This is a bad idea and needs to be removed eventually.
  1614. // Other browsers load stylesheets before they continue parsing the web page.
  1615. // Since we don't, we can run JavaScript code that needs answers before the
  1616. // stylesheets are loaded. Doing a layout ignoring the pending stylesheets
  1617. // lets us get reasonable answers. The long term solution to this problem is
  1618. // to instead suspend JavaScript execution.
  1619. void Document::updateLayoutIgnorePendingStylesheets()
  1620. {
  1621. bool oldIgnore = m_ignorePendingStylesheets;
  1622. if (!haveStylesheetsLoaded()) {
  1623. m_ignorePendingStylesheets = true;
  1624. // FIXME: We are willing to attempt to suppress painting with outdated style info only once. Our assumption is that it would be
  1625. // dangerous to try to stop it a second time, after page content has already been loaded and displayed
  1626. // with accurate style information. (Our suppression involves blanking the whole page at the
  1627. // moment. If it were more refined, we might be able to do something better.)
  1628. // It's worth noting though that this entire method is a hack, since what we really want to do is
  1629. // suspend JS instead of doing a layout with inaccurate information.
  1630. HTMLElement* bodyElement = body();
  1631. if (bodyElement && !bodyElement->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {
  1632. m_pendingSheetLayout = DidLayoutWithPendingSheets;
  1633. styleResolverChanged(RecalcStyleImmediately);
  1634. } else if (m_hasNodesWithPlaceholderStyle)
  1635. // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes
  1636. // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive
  1637. // but here we need up-to-date style immediately.
  1638. recalcStyle(Force);
  1639. }
  1640. updateLayout();
  1641. m_ignorePendingStylesheets = oldIgnore;
  1642. }
  1643. PassRefPtr<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element* element)
  1644. {
  1645. ASSERT_ARG(element, element->document() == this);
  1646. bool oldIgnore = m_ignorePendingStylesheets;
  1647. m_ignorePendingStylesheets = true;
  1648. RefPtr<RenderStyle> style = styleResolver()->styleForElement(element, element->parentNode() ? element->parentNode()->computedStyle() : 0);
  1649. m_ignorePendingStylesheets = oldIgnore;
  1650. return style.release();
  1651. }
  1652. PassRefPtr<RenderStyle> Document::styleForPage(int pageIndex)
  1653. {
  1654. RefPtr<RenderStyle> style = styleResolver()->styleForPage(pageIndex);
  1655. return style.release();
  1656. }
  1657. void Document::registerCustomFont(PassOwnPtr<FontData> fontData)
  1658. {
  1659. m_customFonts.append(fontData);
  1660. }
  1661. void Document::deleteCustomFonts()
  1662. {
  1663. size_t size = m_customFonts.size();
  1664. for (size_t i = 0; i < size; ++i)
  1665. GlyphPageTreeNode::pruneTreeCustomFontData(m_customFonts[i].get());
  1666. m_customFonts.clear();
  1667. }
  1668. bool Document::isPageBoxVisible(int pageIndex)
  1669. {
  1670. RefPtr<RenderStyle> style = styleForPage(pageIndex);
  1671. return style->visibility() != HIDDEN; // display property doesn't apply to @page.
  1672. }
  1673. void Document::pageSizeAndMarginsInPixels(int pageIndex, IntSize& pageSize, int& marginTop, int& marginRight, int& marginBottom, int& marginLeft)
  1674. {
  1675. RefPtr<RenderStyle> style = styleForPage(pageIndex);
  1676. RenderView* view = renderView();
  1677. int width = pageSize.width();
  1678. int height = pageSize.height();
  1679. switch (style->pageSizeType()) {
  1680. case PAGE_SIZE_AUTO:
  1681. break;
  1682. case PAGE_SIZE_AUTO_LANDSCAPE:
  1683. if (width < height)
  1684. std::swap(width, height);
  1685. break;
  1686. case PAGE_SIZE_AUTO_PORTRAIT:
  1687. if (width > height)
  1688. std::swap(width, height);
  1689. break;
  1690. case PAGE_SIZE_RESOLVED: {
  1691. LengthSize size = style->pageSize();
  1692. ASSERT(size.width().isFixed());
  1693. ASSERT(size.height().isFixed());
  1694. width = valueForLength(size.width(), 0, view);
  1695. height = valueForLength(size.height(), 0, view);
  1696. break;
  1697. }
  1698. default:
  1699. ASSERT_NOT_REACHED();
  1700. }
  1701. pageSize = IntSize(width, height);
  1702. // The percentage is calculated with respect to the width even for margin top and bottom.
  1703. // http://www.w3.org/TR/CSS2/box.html#margin-properties
  1704. marginTop = style->marginTop().isAuto() ? marginTop : intValueForLength(style->marginTop(), width, view);
  1705. marginRight = style->marginRight().isAuto() ? marginRight : intValueForLength(style->marginRight(), width, view);
  1706. marginBottom = style->marginBottom().isAuto() ? marginBottom : intValueForLength(style->marginBottom(), width, view);
  1707. marginLeft = style->marginLeft().isAuto() ? marginLeft : intValueForLength(style->marginLeft(), width, view);
  1708. }
  1709. void Document::setDocumentRareData(NodeRareData* rareData)
  1710. {
  1711. m_documentRareData = rareData;
  1712. }
  1713. void Document::setIsViewSource(bool isViewSource)
  1714. {
  1715. m_isViewSource = isViewSource;
  1716. if (!m_isViewSource)
  1717. return;
  1718. setSecurityOrigin(SecurityOrigin::createUnique());
  1719. }
  1720. void Document::combineCSSFeatureFlags()
  1721. {
  1722. // Delay resetting the flags until after next style recalc since unapplying the style may not work without these set (this is true at least with before/after).
  1723. m_usesSiblingRules = m_usesSiblingRules || m_styleResolver->usesSiblingRules();
  1724. m_usesFirstLineRules = m_usesFirstLineRules || m_styleResolver->usesFirstLineRules();
  1725. m_usesBeforeAfterRules = m_usesBeforeAfterRules || m_styleResolver->usesBeforeAfterRules();
  1726. m_usesLinkRules = m_usesLinkRules || m_styleResolver->usesLinkRules();
  1727. }
  1728. void Document::resetCSSFeatureFlags()
  1729. {
  1730. m_usesSiblingRules = m_styleResolver->usesSiblingRules();
  1731. m_usesFirstLineRules = m_styleResolver->usesFirstLineRules();
  1732. m_usesBeforeAfterRules = m_styleResolver->usesBeforeAfterRules();
  1733. m_usesLinkRules = m_styleResolver->usesLinkRules();
  1734. }
  1735. void Document::createStyleResolver()
  1736. {
  1737. bool matchAuthorAndUserStyles = true;
  1738. if (Settings* docSettings = settings())
  1739. matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled();
  1740. m_styleResolver = adoptPtr(new StyleResolver(this, matchAuthorAndUserStyles));
  1741. combineCSSFeatureFlags();
  1742. }
  1743. inline void Document::clearStyleResolver()
  1744. {
  1745. m_styleResolver.clear();
  1746. }
  1747. void Document::attach()
  1748. {
  1749. ASSERT(!attached());
  1750. ASSERT(!m_inPageCache);
  1751. ASSERT(!m_axObjectCache || this != topDocument());
  1752. if (!m_renderArena)
  1753. m_renderArena = adoptPtr(new RenderArena);
  1754. // Create the rendering tree
  1755. setRenderer(new (m_renderArena.get()) RenderView(this, view()));
  1756. #if USE(ACCELERATED_COMPOSITING)
  1757. renderView()->didMoveOnscreen();
  1758. #endif
  1759. recalcStyle(Force);
  1760. RenderObject* render = renderer();
  1761. setRenderer(0);
  1762. ContainerNode::attach();
  1763. setRenderer(render);
  1764. }
  1765. void Document::detach()
  1766. {
  1767. ASSERT(attached());
  1768. ASSERT(!m_inPageCache);
  1769. #if ENABLE(POINTER_LOCK)
  1770. if (page())
  1771. page()->pointerLockController()->documentDetached(this);
  1772. #endif
  1773. if (this == topDocument())
  1774. clearAXObjectCache();
  1775. stopActiveDOMObjects();
  1776. m_eventQueue->close();
  1777. #if ENABLE(FULLSCREEN_API)
  1778. m_fullScreenChangeEventTargetQueue.clear();
  1779. m_fullScreenErrorEventTargetQueue.clear();
  1780. #endif
  1781. #if ENABLE(REQUEST_ANIMATION_FRAME)
  1782. // FIXME: consider using ActiveDOMObject.
  1783. if (m_scriptedAnimationController)
  1784. m_scriptedAnimationController->clearDocumentPointer();
  1785. m_scriptedAnimationController.clear();
  1786. #endif
  1787. RenderObject* render = renderer();
  1788. documentWillBecomeInactive();
  1789. #if ENABLE(SHARED_WORKERS)
  1790. SharedWorkerRepository::documentDetached(this);
  1791. #endif
  1792. if (m_frame) {
  1793. FrameView* view = m_frame->view();
  1794. if (view)
  1795. view->detachCustomScrollbars();
  1796. }
  1797. // indicate destruction mode, i.e. attached() but renderer == 0
  1798. setRenderer(0);
  1799. #if ENABLE(FULLSCREEN_API)
  1800. if (m_fullScreenRenderer)
  1801. setFullScreenRenderer(0);
  1802. #endif
  1803. m_hoverNode = 0;
  1804. m_focusedNode = 0;
  1805. m_activeNode = 0;
  1806. ContainerNode::detach();
  1807. unscheduleStyleRecalc();
  1808. if (render)
  1809. render->destroy();
  1810. // This is required, as our Frame might delete itself as soon as it detaches
  1811. // us. However, this violates Node::detach() semantics, as it's never
  1812. // possible to re-attach. Eventually Document::detach() should be renamed,
  1813. // or this setting of the frame to 0 could be made explicit in each of the
  1814. // callers of Document::detach().
  1815. m_frame = 0;
  1816. m_renderArena.clear();
  1817. }
  1818. void Document::prepareForDestruction()
  1819. {
  1820. disconnectDescendantFrames();
  1821. if (DOMWindow* window = this->domWindow())
  1822. window->willDetachDocumentFromFrame();
  1823. detach();
  1824. }
  1825. void Document::removeAllEventListeners()
  1826. {
  1827. EventTarget::removeAllEventListeners();
  1828. if (DOMWindow* domWindow = this->domWindow())
  1829. domWindow->removeAllEventListeners();
  1830. for (Node* node = firstChild(); node; node = node->traverseNextNode())
  1831. node->removeAllEventListeners();
  1832. }
  1833. void Document::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why)
  1834. {
  1835. ScriptExecutionContext::suspendActiveDOMObjects(why);
  1836. #if ENABLE(DEVICE_ORIENTATION)
  1837. if (!page())
  1838. return;
  1839. if (DeviceMotionController* controller = DeviceMotionController::from(page()))
  1840. controller->suspendEventsForAllListeners(domWindow());
  1841. if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
  1842. controller->suspendEventsForAllListeners(domWindow());
  1843. #endif
  1844. }
  1845. void Document::resumeActiveDOMObjects()
  1846. {
  1847. ScriptExecutionContext::resumeActiveDOMObjects();
  1848. #if ENABLE(DEVICE_ORIENTATION)
  1849. if (!page())
  1850. return;
  1851. if (DeviceMotionController* controller = DeviceMotionController::from(page()))
  1852. controller->resumeEventsForAllListeners(domWindow());
  1853. if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
  1854. controller->resumeEventsForAllListeners(domWindow());
  1855. #endif
  1856. }
  1857. RenderView* Document::renderView() const
  1858. {
  1859. return toRenderView(renderer());
  1860. }
  1861. void Document::clearAXObjectCache()
  1862. {
  1863. // clear cache in top document
  1864. if (m_axObjectCache) {
  1865. // Clear the cache member variable before calling delete because attempts
  1866. // are made to access it during destruction.
  1867. AXObjectCache* axObjectCache = m_axObjectCache;
  1868. m_axObjectCache = 0;
  1869. delete axObjectCache;
  1870. return;
  1871. }
  1872. // ask the top-level document to clear its cache
  1873. Document* doc = topDocument();
  1874. if (doc != this)
  1875. doc->clearAXObjectCache();
  1876. }
  1877. bool Document::axObjectCacheExists() const
  1878. {
  1879. if (m_axObjectCache)
  1880. return true;
  1881. Document* doc = topDocument();
  1882. if (doc != this)
  1883. return doc->axObjectCacheExists();
  1884. return false;
  1885. }
  1886. AXObjectCache* Document::axObjectCache() const
  1887. {
  1888. // The only document that actually has a AXObjectCache is the top-level
  1889. // document. This is because we need to be able to get from any WebCoreAXObject
  1890. // to any other WebCoreAXObject on the same page. Using a single cache allows
  1891. // lookups across nested webareas (i.e. multiple documents).
  1892. if (m_axObjectCache) {
  1893. // return already known top-level cache
  1894. if (!ownerElement())
  1895. return m_axObjectCache;
  1896. // In some pages with frames, the cache is created before the sub-webarea is
  1897. // inserted into the tree. Here, we catch that case and just toss the old
  1898. // cache and start over.
  1899. // NOTE: This recovery may no longer be needed. I have been unable to trigger
  1900. // it again. See rdar://5794454
  1901. // FIXME: Can this be fixed when inserting the subframe instead of now?
  1902. // FIXME: If this function was called to get the cache in order to remove
  1903. // an AXObject, we are now deleting the cache as a whole and returning a
  1904. // new empty cache that does not contain the AXObject! That should actually
  1905. // be OK. I am concerned about other cases like this where accessing the
  1906. // cache blows away the AXObject being operated on.
  1907. delete m_axObjectCache;
  1908. m_axObjectCache = 0;
  1909. }
  1910. // ask the top-level document for its cache
  1911. Document* doc = topDocument();
  1912. if (doc != this)
  1913. return doc->axObjectCache();
  1914. // this is the top-level document, so install a new cache
  1915. m_axObjectCache = new AXObjectCache(this);
  1916. return m_axObjectCache;
  1917. }
  1918. void Document::setVisuallyOrdered()
  1919. {
  1920. m_visuallyOrdered = true;
  1921. if (renderer())
  1922. renderer()->style()->setRTLOrdering(VisualOrder);
  1923. }
  1924. PassRefPtr<DocumentParser> Document::createParser()
  1925. {
  1926. // FIXME: this should probably pass the frame instead
  1927. #if ENABLE(NEW_XML)
  1928. return NewXMLDocumentParser::create(this);
  1929. #else
  1930. return XMLDocumentParser::create(this, view());
  1931. #endif
  1932. }
  1933. ScriptableDocumentParser* Document::scriptableDocumentParser() const
  1934. {
  1935. return parser() ? parser()->asScriptableDocumentParser() : 0;
  1936. }
  1937. void Document::open(Document* ownerDocument)
  1938. {
  1939. if (ownerDocument) {
  1940. setURL(ownerDocument->url());
  1941. m_cookieURL = ownerDocument->cookieURL();
  1942. setSecurityOrigin(ownerDocument->securityOrigin());
  1943. }
  1944. if (m_frame) {
  1945. if (ScriptableDocumentParser* parser = scriptableDocumentParser()) {
  1946. if (parser->isParsing()) {
  1947. // FIXME: HTML5 doesn't tell us to check this, it might not be correct.
  1948. if (parser->isExecutingScript())
  1949. return;
  1950. if (!parser->wasCreatedByScript() && parser->hasInsertionPoint())
  1951. return;
  1952. }
  1953. }
  1954. if (m_frame->loader()->state() == FrameStateProvisional)
  1955. m_frame->loader()->stopAllLoaders();
  1956. }
  1957. removeAllEventListeners();
  1958. implicitOpen();
  1959. if (ScriptableDocumentParser* parser = scriptableDocumentParser())
  1960. parser->setWasCreatedByScript(true);
  1961. if (DOMWindow* domWindow = this->domWindow())
  1962. domWindow->removeAllEventListeners();
  1963. if (m_frame)
  1964. m_frame->loader()->didExplicitOpen();
  1965. }
  1966. void Document::detachParser()
  1967. {
  1968. if (!m_parser)
  1969. return;
  1970. m_parser->detach();
  1971. m_parser.clear();
  1972. }
  1973. void Document::cancelParsing()
  1974. {
  1975. if (!m_parser)
  1976. return;
  1977. // We have to clear the parser to avoid possibly triggering
  1978. // the onload handler when closing as a side effect of a cancel-style
  1979. // change, such as opening a new document or closing the window while
  1980. // still parsing
  1981. detachParser();
  1982. explicitClose();
  1983. }
  1984. void Document::implicitOpen()
  1985. {
  1986. cancelParsing();
  1987. removeChildren();
  1988. setCompatibilityMode(NoQuirksMode);
  1989. m_parser = createParser();
  1990. setParsing(true);
  1991. setReadyState(Loading);
  1992. }
  1993. HTMLElement* Document::body() const
  1994. {
  1995. Node* de = documentElement();
  1996. if (!de)
  1997. return 0;
  1998. // try to prefer a FRAMESET element over BODY
  1999. Node* body = 0;
  2000. for (Node* i = de->firstChild(); i; i = i->nextSibling()) {
  2001. if (i->hasTagName(framesetTag))
  2002. return toHTMLElement(i);
  2003. if (i->hasTagName(bodyTag) && !body)
  2004. body = i;
  2005. }
  2006. return toHTMLElement(body);
  2007. }
  2008. void Document::setBody(PassRefPtr<HTMLElement> prpNewBody, ExceptionCode& ec)
  2009. {
  2010. RefPtr<HTMLElement> newBody = prpNewBody;
  2011. if (!newBody || !documentElement() || !newBody->hasTagName(bodyTag)) {
  2012. ec = HIERARCHY_REQUEST_ERR;
  2013. return;
  2014. }
  2015. if (newBody->document() && newBody->document() != this) {
  2016. ec = 0;
  2017. RefPtr<Node> node = importNode(newBody.get(), true, ec);
  2018. if (ec)
  2019. return;
  2020. newBody = toHTMLElement(node.get());
  2021. }
  2022. HTMLElement* b = body();
  2023. if (!b)
  2024. documentElement()->appendChild(newBody.release(), ec);
  2025. else
  2026. documentElement()->replaceChild(newBody.release(), b, ec);
  2027. }
  2028. HTMLHeadElement* Document::head()
  2029. {
  2030. Node* de = documentElement();
  2031. if (!de)
  2032. return 0;
  2033. for (Node* e = de->firstChild(); e; e = e->nextSibling())
  2034. if (e->hasTagName(headTag))
  2035. return static_cast<HTMLHeadElement*>(e);
  2036. return 0;
  2037. }
  2038. void Document::close()
  2039. {
  2040. // FIXME: We should follow the specification more closely:
  2041. // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close
  2042. if (!scriptableDocumentParser() || !scriptableDocumentParser()->wasCreatedByScript() || !scriptableDocumentParser()->isParsing())
  2043. return;
  2044. explicitClose();
  2045. }
  2046. void Document::explicitClose()
  2047. {
  2048. if (m_parser)
  2049. m_parser->finish();
  2050. if (!m_frame) {
  2051. // Because we have no frame, we don't know if all loading has completed,
  2052. // so we just call implicitClose() immediately. FIXME: This might fire
  2053. // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>.
  2054. implicitClose();
  2055. return;
  2056. }
  2057. m_frame->loader()->checkCompleted();
  2058. }
  2059. void Document::implicitClose()
  2060. {
  2061. // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached.
  2062. if (m_inStyleRecalc) {
  2063. m_closeAfterStyleRecalc = true;
  2064. return;
  2065. }
  2066. bool wasLocationChangePending = frame() && frame()->navigationScheduler()->locationChangePending();
  2067. bool doload = !parsing() && m_parser && !m_processingLoadEvent && !wasLocationChangePending;
  2068. if (!doload)
  2069. return;
  2070. m_processingLoadEvent = true;
  2071. ScriptableDocumentParser* parser = scriptableDocumentParser();
  2072. m_wellFormed = parser && parser->wellFormed();
  2073. // We have to clear the parser, in case someone document.write()s from the
  2074. // onLoad event handler, as in Radar 3206524.
  2075. detachParser();
  2076. // Parser should have picked up all preloads by now
  2077. m_cachedResourceLoader->clearPreloads();
  2078. // FIXME: We kick off the icon loader when the Document is done parsing.
  2079. // There are earlier opportunities we could start it:
  2080. // -When the <head> finishes parsing
  2081. // -When any new HTMLLinkElement is inserted into the document
  2082. // But those add a dynamic component to the favicon that has UI
  2083. // ramifications, and we need to decide what is the Right Thing To Do(tm)
  2084. Frame* f = frame();
  2085. if (f) {
  2086. f->loader()->icon()->startLoader();
  2087. f->animation()->resumeAnimationsForDocument(this);
  2088. }
  2089. ImageLoader::dispatchPendingBeforeLoadEvents();
  2090. ImageLoader::dispatchPendingLoadEvents();
  2091. ImageLoader::dispatchPendingErrorEvents();
  2092. HTMLLinkElement::dispatchPendingLoadEvents();
  2093. HTMLStyleElement::dispatchPendingLoadEvents();
  2094. #if ENABLE(SVG)
  2095. // To align the HTML load event and the SVGLoad event for the outermost <svg> element, fire it from
  2096. // here, instead of doing it from SVGElement::finishedParsingChildren (if externalResourcesRequired="false",
  2097. // which is the default, for ='true' its fired at a later time, once all external resources finished loading).
  2098. if (svgExtensions())
  2099. accessSVGExtensions()->dispatchSVGLoadEventToOutermostSVGElements();
  2100. #endif
  2101. dispatchWindowLoadEvent();
  2102. enqueuePageshowEvent(PageshowEventNotPersisted);
  2103. enqueuePopstateEvent(m_pendingStateObject ? m_pendingStateObject.release() : SerializedScriptValue::nullValue());
  2104. if (f)
  2105. f->loader()->handledOnloadEvents();
  2106. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2107. if (!ownerElement())
  2108. printf("onload fired at %d\n", elapsedTime());
  2109. #endif
  2110. // An event handler may have removed the frame
  2111. if (!frame()) {
  2112. m_processingLoadEvent = false;
  2113. return;
  2114. }
  2115. // Make sure both the initial layout and reflow happen after the onload
  2116. // fires. This will improve onload scores, and other browsers do it.
  2117. // If they wanna cheat, we can too. -dwh
  2118. if (frame()->navigationScheduler()->locationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
  2119. // Just bail out. Before or during the onload we were shifted to another page.
  2120. // The old i-Bench suite does this. When this happens don't bother painting or laying out.
  2121. m_processingLoadEvent = false;
  2122. view()->unscheduleRelayout();
  2123. return;
  2124. }
  2125. frame()->loader()->checkCallImplicitClose();
  2126. RenderObject* renderObject = renderer();
  2127. // We used to force a synchronous display and flush here. This really isn't
  2128. // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
  2129. // (if your platform is syncing flushes and limiting them to 60fps).
  2130. m_overMinimumLayoutThreshold = true;
  2131. if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
  2132. updateStyleIfNeeded();
  2133. // Always do a layout after loading if needed.
  2134. if (view() && renderObject && (!renderObject->firstChild() || renderObject->needsLayout()))
  2135. view()->layout();
  2136. }
  2137. m_processingLoadEvent = false;
  2138. #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
  2139. if (f && renderObject && AXObjectCache::accessibilityEnabled()) {
  2140. // The AX cache may have been cleared at this point, but we need to make sure it contains an
  2141. // AX object to send the notification to. getOrCreate will make sure that an valid AX object
  2142. // exists in the cache (we ignore the return value because we don't need it here). This is
  2143. // only safe to call when a layout is not in progress, so it can not be used in postNotification.
  2144. axObjectCache()->getOrCreate(renderObject);
  2145. if (this == topDocument())
  2146. axObjectCache()->postNotification(renderObject, AXObjectCache::AXLoadComplete, true);
  2147. else {
  2148. // AXLoadComplete can only be posted on the top document, so if it's a document
  2149. // in an iframe that just finished loading, post AXLayoutComplete instead.
  2150. axObjectCache()->postNotification(renderObject, AXObjectCache::AXLayoutComplete, true);
  2151. }
  2152. }
  2153. #endif
  2154. #if ENABLE(SVG)
  2155. if (svgExtensions())
  2156. accessSVGExtensions()->startAnimations();
  2157. #endif
  2158. }
  2159. void Document::setParsing(bool b)
  2160. {
  2161. m_bParsing = b;
  2162. if (!m_bParsing && view())
  2163. view()->scheduleRelayout();
  2164. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2165. if (!ownerElement() && !m_bParsing)
  2166. printf("Parsing finished at %d\n", elapsedTime());
  2167. #endif
  2168. }
  2169. bool Document::shouldScheduleLayout()
  2170. {
  2171. // This function will only be called when FrameView thinks a layout is needed.
  2172. // This enforces a couple extra rules.
  2173. //
  2174. // (a) Only schedule a layout once the stylesheets are loaded.
  2175. // (b) Only schedule layout once we have a body element.
  2176. return (haveStylesheetsLoaded() && body())
  2177. || (documentElement() && !documentElement()->hasTagName(htmlTag));
  2178. }
  2179. bool Document::isLayoutTimerActive()
  2180. {
  2181. return view() && view()->layoutPending() && !minimumLayoutDelay();
  2182. }
  2183. int Document::minimumLayoutDelay()
  2184. {
  2185. if (m_overMinimumLayoutThreshold)
  2186. return 0;
  2187. int elapsed = elapsedTime();
  2188. m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold;
  2189. // We'll want to schedule the timer to fire at the minimum layout threshold.
  2190. return max(0, cLayoutScheduleThreshold - elapsed);
  2191. }
  2192. int Document::elapsedTime() const
  2193. {
  2194. return static_cast<int>((currentTime() - m_startTime) * 1000);
  2195. }
  2196. void Document::write(const SegmentedString& text, Document* ownerDocument)
  2197. {
  2198. NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);
  2199. m_writeRecursionIsTooDeep = (m_writeRecursionDepth > 1) && m_writeRecursionIsTooDeep;
  2200. m_writeRecursionIsTooDeep = (m_writeRecursionDepth > cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep;
  2201. if (m_writeRecursionIsTooDeep)
  2202. return;
  2203. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2204. if (!ownerElement())
  2205. printf("Beginning a document.write at %d\n", elapsedTime());
  2206. #endif
  2207. bool hasInsertionPoint = m_parser && m_parser->hasInsertionPoint();
  2208. if (!hasInsertionPoint && m_ignoreDestructiveWriteCount)
  2209. return;
  2210. if (!hasInsertionPoint)
  2211. open(ownerDocument);
  2212. ASSERT(m_parser);
  2213. m_parser->insert(text);
  2214. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2215. if (!ownerElement())
  2216. printf("Ending a document.write at %d\n", elapsedTime());
  2217. #endif
  2218. }
  2219. void Document::write(const String& text, Document* ownerDocument)
  2220. {
  2221. write(SegmentedString(text), ownerDocument);
  2222. }
  2223. void Document::writeln(const String& text, Document* ownerDocument)
  2224. {
  2225. write(text, ownerDocument);
  2226. write("\n", ownerDocument);
  2227. }
  2228. const KURL& Document::virtualURL() const
  2229. {
  2230. return m_url;
  2231. }
  2232. KURL Document::virtualCompleteURL(const String& url) const
  2233. {
  2234. return completeURL(url);
  2235. }
  2236. double Document::minimumTimerInterval() const
  2237. {
  2238. Page* p = page();
  2239. if (!p)
  2240. return ScriptExecutionContext::minimumTimerInterval();
  2241. return p->settings()->minDOMTimerInterval();
  2242. }
  2243. EventTarget* Document::errorEventTarget()
  2244. {
  2245. return domWindow();
  2246. }
  2247. void Document::logExceptionToConsole(const String& errorMessage, const String& sourceURL, int lineNumber, PassRefPtr<ScriptCallStack> callStack)
  2248. {
  2249. addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, sourceURL, lineNumber, callStack);
  2250. }
  2251. void Document::setURL(const KURL& url)
  2252. {
  2253. const KURL& newURL = url.isEmpty() ? blankURL() : url;
  2254. if (newURL == m_url)
  2255. return;
  2256. m_url = newURL;
  2257. m_documentURI = m_url.string();
  2258. updateBaseURL();
  2259. contextFeatures()->urlDidChange(this);
  2260. }
  2261. void Document::updateBaseURL()
  2262. {
  2263. KURL oldBaseURL = m_baseURL;
  2264. // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 HTML], the base URI is computed using
  2265. // first the value of the href attribute of the HTML BASE element if any, and the value of the documentURI attribute
  2266. // from the Document interface otherwise.
  2267. if (!m_baseElementURL.isEmpty())
  2268. m_baseURL = m_baseElementURL;
  2269. else if (!m_baseURLOverride.isEmpty())
  2270. m_baseURL = m_baseURLOverride;
  2271. else {
  2272. // The documentURI attribute is read-only from JavaScript, but writable from Objective C, so we need to retain
  2273. // this fallback behavior. We use a null base URL, since the documentURI attribute is an arbitrary string
  2274. // and DOM 3 Core does not specify how it should be resolved.
  2275. m_baseURL = KURL(KURL(), documentURI());
  2276. }
  2277. selectorQueryCache()->invalidate();
  2278. if (!m_baseURL.isValid())
  2279. m_baseURL = KURL();
  2280. if (m_elemSheet) {
  2281. // Element sheet is silly. It never contains anything.
  2282. ASSERT(!m_elemSheet->contents()->ruleCount());
  2283. bool usesRemUnits = m_elemSheet->contents()->usesRemUnits();
  2284. m_elemSheet = CSSStyleSheet::createInline(this, m_baseURL);
  2285. // FIXME: So we are not really the parser. The right fix is to eliminate the element sheet completely.
  2286. m_elemSheet->contents()->parserSetUsesRemUnits(usesRemUnits);
  2287. }
  2288. if (!equalIgnoringFragmentIdentifier(oldBaseURL, m_baseURL)) {
  2289. // Base URL change changes any relative visited links.
  2290. // FIXME: There are other URLs in the tree that would need to be re-evaluated on dynamic base URL change. Style should be invalidated too.
  2291. for (Node* node = firstChild(); node; node = node->traverseNextNode()) {
  2292. if (node->hasTagName(aTag))
  2293. static_cast<HTMLAnchorElement*>(node)->invalidateCachedVisitedLinkHash();
  2294. }
  2295. }
  2296. }
  2297. void Document::setBaseURLOverride(const KURL& url)
  2298. {
  2299. m_baseURLOverride = url;
  2300. updateBaseURL();
  2301. }
  2302. void Document::processBaseElement()
  2303. {
  2304. // Find the first href attribute in a base element and the first target attribute in a base element.
  2305. const AtomicString* href = 0;
  2306. const AtomicString* target = 0;
  2307. for (Node* node = document()->firstChild(); node && (!href || !target); node = node->traverseNextNode()) {
  2308. if (node->hasTagName(baseTag)) {
  2309. if (!href) {
  2310. const AtomicString& value = static_cast<Element*>(node)->fastGetAttribute(hrefAttr);
  2311. if (!value.isNull())
  2312. href = &value;
  2313. }
  2314. if (!target) {
  2315. const AtomicString& value = static_cast<Element*>(node)->fastGetAttribute(targetAttr);
  2316. if (!value.isNull())
  2317. target = &value;
  2318. }
  2319. }
  2320. }
  2321. // FIXME: Since this doesn't share code with completeURL it may not handle encodings correctly.
  2322. KURL baseElementURL;
  2323. if (href) {
  2324. String strippedHref = stripLeadingAndTrailingHTMLSpaces(*href);
  2325. if (!strippedHref.isEmpty())
  2326. baseElementURL = KURL(url(), strippedHref);
  2327. }
  2328. if (m_baseElementURL != baseElementURL) {
  2329. m_baseElementURL = baseElementURL;
  2330. updateBaseURL();
  2331. }
  2332. m_baseTarget = target ? *target : nullAtom;
  2333. }
  2334. String Document::userAgent(const KURL& url) const
  2335. {
  2336. return frame() ? frame()->loader()->userAgent(url) : String();
  2337. }
  2338. void Document::disableEval()
  2339. {
  2340. if (!frame())
  2341. return;
  2342. frame()->script()->disableEval();
  2343. }
  2344. bool Document::canNavigate(Frame* targetFrame)
  2345. {
  2346. if (!m_frame)
  2347. return false;
  2348. // FIXME: We shouldn't call this function without a target frame, but
  2349. // fast/forms/submit-to-blank-multiple-times.html depends on this function
  2350. // returning true when supplied with a 0 targetFrame.
  2351. if (!targetFrame)
  2352. return true;
  2353. // Frame-busting is generally allowed (unless we're sandboxed and prevent from frame-busting).
  2354. if (!isSandboxed(SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
  2355. return true;
  2356. if (isSandboxed(SandboxNavigation)) {
  2357. if (targetFrame->tree()->isDescendantOf(m_frame))
  2358. return true;
  2359. printNavigationErrorMessage(targetFrame, url());
  2360. return false;
  2361. }
  2362. // This is the normal case. A document can navigate its decendant frames,
  2363. // or, more generally, a document can navigate a frame if the document is
  2364. // in the same origin as any of that frame's ancestors (in the frame
  2365. // hierarchy).
  2366. //
  2367. // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
  2368. // historical information about this security check.
  2369. if (canAccessAncestor(securityOrigin(), targetFrame))
  2370. return true;
  2371. // Top-level frames are easier to navigate than other frames because they
  2372. // display their URLs in the address bar (in most browsers). However, there
  2373. // are still some restrictions on navigation to avoid nuisance attacks.
  2374. // Specifically, a document can navigate a top-level frame if that frame
  2375. // opened the document or if the document is the same-origin with any of
  2376. // the top-level frame's opener's ancestors (in the frame hierarchy).
  2377. //
  2378. // In both of these cases, the document performing the navigation is in
  2379. // some way related to the frame being navigate (e.g., by the "opener"
  2380. // and/or "parent" relation). Requiring some sort of relation prevents a
  2381. // document from navigating arbitrary, unrelated top-level frames.
  2382. if (!targetFrame->tree()->parent()) {
  2383. if (targetFrame == m_frame->loader()->opener())
  2384. return true;
  2385. if (canAccessAncestor(securityOrigin(), targetFrame->loader()->opener()))
  2386. return true;
  2387. }
  2388. printNavigationErrorMessage(targetFrame, url());
  2389. return false;
  2390. }
  2391. Frame* Document::findUnsafeParentScrollPropagationBoundary()
  2392. {
  2393. Frame* currentFrame = m_frame;
  2394. Frame* ancestorFrame = currentFrame->tree()->parent();
  2395. while (ancestorFrame) {
  2396. if (!ancestorFrame->document()->securityOrigin()->canAccess(securityOrigin()))
  2397. return currentFrame;
  2398. currentFrame = ancestorFrame;
  2399. ancestorFrame = ancestorFrame->tree()->parent();
  2400. }
  2401. return 0;
  2402. }
  2403. CSSStyleSheet* Document::pageUserSheet()
  2404. {
  2405. if (m_pageUserSheet)
  2406. return m_pageUserSheet.get();
  2407. Page* owningPage = page();
  2408. if (!owningPage)
  2409. return 0;
  2410. String userSheetText = owningPage->userStyleSheet();
  2411. if (userSheetText.isEmpty())
  2412. return 0;
  2413. // Parse the sheet and cache it.
  2414. m_pageUserSheet = CSSStyleSheet::createInline(this, settings()->userStyleSheetLocation());
  2415. m_pageUserSheet->contents()->setIsUserStyleSheet(true);
  2416. m_pageUserSheet->contents()->parseString(userSheetText);
  2417. return m_pageUserSheet.get();
  2418. }
  2419. void Document::clearPageUserSheet()
  2420. {
  2421. if (m_pageUserSheet) {
  2422. m_pageUserSheet = 0;
  2423. styleResolverChanged(DeferRecalcStyle);
  2424. }
  2425. }
  2426. void Document::updatePageUserSheet()
  2427. {
  2428. clearPageUserSheet();
  2429. if (pageUserSheet())
  2430. styleResolverChanged(RecalcStyleImmediately);
  2431. }
  2432. const Vector<RefPtr<CSSStyleSheet> >* Document::pageGroupUserSheets() const
  2433. {
  2434. if (m_pageGroupUserSheetCacheValid)
  2435. return m_pageGroupUserSheets.get();
  2436. m_pageGroupUserSheetCacheValid = true;
  2437. Page* owningPage = page();
  2438. if (!owningPage)
  2439. return 0;
  2440. const PageGroup& pageGroup = owningPage->group();
  2441. const UserStyleSheetMap* sheetsMap = pageGroup.userStyleSheets();
  2442. if (!sheetsMap)
  2443. return 0;
  2444. UserStyleSheetMap::const_iterator end = sheetsMap->end();
  2445. for (UserStyleSheetMap::const_iterator it = sheetsMap->begin(); it != end; ++it) {
  2446. const UserStyleSheetVector* sheets = it->second.get();
  2447. for (unsigned i = 0; i < sheets->size(); ++i) {
  2448. const UserStyleSheet* sheet = sheets->at(i).get();
  2449. if (sheet->injectedFrames() == InjectInTopFrameOnly && ownerElement())
  2450. continue;
  2451. if (!UserContentURLPattern::matchesPatterns(url(), sheet->whitelist(), sheet->blacklist()))
  2452. continue;
  2453. RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(this), sheet->url());
  2454. if (!m_pageGroupUserSheets)
  2455. m_pageGroupUserSheets = adoptPtr(new Vector<RefPtr<CSSStyleSheet> >);
  2456. m_pageGroupUserSheets->append(groupSheet);
  2457. groupSheet->contents()->setIsUserStyleSheet(sheet->level() == UserStyleUserLevel);
  2458. groupSheet->contents()->parseString(sheet->source());
  2459. }
  2460. }
  2461. return m_pageGroupUserSheets.get();
  2462. }
  2463. void Document::clearPageGroupUserSheets()
  2464. {
  2465. m_pageGroupUserSheetCacheValid = false;
  2466. if (m_pageGroupUserSheets && m_pageGroupUserSheets->size()) {
  2467. m_pageGroupUserSheets->clear();
  2468. styleResolverChanged(DeferRecalcStyle);
  2469. }
  2470. }
  2471. void Document::updatePageGroupUserSheets()
  2472. {
  2473. clearPageGroupUserSheets();
  2474. if (pageGroupUserSheets() && pageGroupUserSheets()->size())
  2475. styleResolverChanged(RecalcStyleImmediately);
  2476. }
  2477. void Document::addUserSheet(PassRefPtr<StyleSheetContents> userSheet)
  2478. {
  2479. if (!m_userSheets)
  2480. m_userSheets = adoptPtr(new Vector<RefPtr<CSSStyleSheet> >);
  2481. m_userSheets->append(CSSStyleSheet::create(userSheet, this));
  2482. styleResolverChanged(RecalcStyleImmediately);
  2483. }
  2484. void Document::seamlessParentUpdatedStylesheets()
  2485. {
  2486. styleResolverChanged(RecalcStyleImmediately);
  2487. }
  2488. CSSStyleSheet* Document::elementSheet()
  2489. {
  2490. if (!m_elemSheet)
  2491. m_elemSheet = CSSStyleSheet::createInline(this, m_baseURL);
  2492. return m_elemSheet.get();
  2493. }
  2494. int Document::nodeAbsIndex(Node *node)
  2495. {
  2496. ASSERT(node->document() == this);
  2497. int absIndex = 0;
  2498. for (Node* n = node; n && n != this; n = n->traversePreviousNode())
  2499. absIndex++;
  2500. return absIndex;
  2501. }
  2502. Node* Document::nodeWithAbsIndex(int absIndex)
  2503. {
  2504. Node* n = this;
  2505. for (int i = 0; n && (i < absIndex); i++)
  2506. n = n->traverseNextNode();
  2507. return n;
  2508. }
  2509. void Document::processHttpEquiv(const String& equiv, const String& content)
  2510. {
  2511. ASSERT(!equiv.isNull() && !content.isNull());
  2512. Frame* frame = this->frame();
  2513. if (equalIgnoringCase(equiv, "default-style")) {
  2514. // The preferred style set has been overridden as per section
  2515. // 14.3.2 of the HTML4.0 specification. We need to update the
  2516. // sheet used variable and then update our style selector.
  2517. // For more info, see the test at:
  2518. // http://www.hixie.ch/tests/evil/css/import/main/preferred.html
  2519. // -dwh
  2520. m_selectedStylesheetSet = content;
  2521. m_preferredStylesheetSet = content;
  2522. styleResolverChanged(DeferRecalcStyle);
  2523. } else if (equalIgnoringCase(equiv, "refresh")) {
  2524. double delay;
  2525. String url;
  2526. if (frame && parseHTTPRefresh(content, true, delay, url)) {
  2527. if (url.isEmpty())
  2528. url = m_url.string();
  2529. else
  2530. url = completeURL(url).string();
  2531. frame->navigationScheduler()->scheduleRedirect(delay, url);
  2532. }
  2533. } else if (equalIgnoringCase(equiv, "set-cookie")) {
  2534. // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
  2535. if (isHTMLDocument()) {
  2536. ExceptionCode ec; // Exception (for sandboxed documents) ignored.
  2537. static_cast<HTMLDocument*>(this)->setCookie(content, ec);
  2538. }
  2539. } else if (equalIgnoringCase(equiv, "content-language"))
  2540. setContentLanguage(content);
  2541. else if (equalIgnoringCase(equiv, "x-dns-prefetch-control"))
  2542. parseDNSPrefetchControlHeader(content);
  2543. else if (equalIgnoringCase(equiv, "x-frame-options")) {
  2544. if (frame) {
  2545. FrameLoader* frameLoader = frame->loader();
  2546. if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) {
  2547. frameLoader->stopAllLoaders();
  2548. frame->navigationScheduler()->scheduleLocationChange(securityOrigin(), blankURL(), String());
  2549. DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to display document because display forbidden by X-Frame-Options.\n"));
  2550. addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage);
  2551. }
  2552. }
  2553. } else if (equalIgnoringCase(equiv, "x-webkit-csp"))
  2554. contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::EnforcePolicy);
  2555. else if (equalIgnoringCase(equiv, "x-webkit-csp-report-only"))
  2556. contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::ReportOnly);
  2557. }
  2558. // Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
  2559. static bool isSeparator(UChar c)
  2560. {
  2561. return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ',' || c == '\0';
  2562. }
  2563. void Document::processArguments(const String& features, void* data, ArgumentsCallback callback)
  2564. {
  2565. // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
  2566. int keyBegin, keyEnd;
  2567. int valueBegin, valueEnd;
  2568. int i = 0;
  2569. int length = features.length();
  2570. String buffer = features.lower();
  2571. while (i < length) {
  2572. // skip to first non-separator, but don't skip past the end of the string
  2573. while (isSeparator(buffer[i])) {
  2574. if (i >= length)
  2575. break;
  2576. i++;
  2577. }
  2578. keyBegin = i;
  2579. // skip to first separator
  2580. while (!isSeparator(buffer[i]))
  2581. i++;
  2582. keyEnd = i;
  2583. // skip to first '=', but don't skip past a ',' or the end of the string
  2584. while (buffer[i] != '=') {
  2585. if (buffer[i] == ',' || i >= length)
  2586. break;
  2587. i++;
  2588. }
  2589. // skip to first non-separator, but don't skip past a ',' or the end of the string
  2590. while (isSeparator(buffer[i])) {
  2591. if (buffer[i] == ',' || i >= length)
  2592. break;
  2593. i++;
  2594. }
  2595. valueBegin = i;
  2596. // skip to first separator
  2597. while (!isSeparator(buffer[i]))
  2598. i++;
  2599. valueEnd = i;
  2600. ASSERT(i <= length);
  2601. String keyString = buffer.substring(keyBegin, keyEnd - keyBegin);
  2602. String valueString = buffer.substring(valueBegin, valueEnd - valueBegin);
  2603. callback(keyString, valueString, this, data);
  2604. }
  2605. }
  2606. void Document::processViewport(const String& features, ViewportArguments::Type origin)
  2607. {
  2608. ASSERT(!features.isNull());
  2609. if (origin < m_viewportArguments.type)
  2610. return;
  2611. m_viewportArguments = ViewportArguments(origin);
  2612. processArguments(features, (void*)&m_viewportArguments, &setViewportFeature);
  2613. updateViewportArguments();
  2614. }
  2615. void Document::updateViewportArguments()
  2616. {
  2617. if (page() && page()->mainFrame() == frame()) {
  2618. #ifndef NDEBUG
  2619. m_didDispatchViewportPropertiesChanged = true;
  2620. #endif
  2621. page()->chrome()->dispatchViewportPropertiesDidChange(m_viewportArguments);
  2622. }
  2623. }
  2624. void Document::processReferrerPolicy(const String& policy)
  2625. {
  2626. ASSERT(!policy.isNull());
  2627. m_referrerPolicy = ReferrerPolicyDefault;
  2628. if (equalIgnoringCase(policy, "never"))
  2629. m_referrerPolicy = ReferrerPolicyNever;
  2630. else if (equalIgnoringCase(policy, "always"))
  2631. m_referrerPolicy = ReferrerPolicyAlways;
  2632. else if (equalIgnoringCase(policy, "origin"))
  2633. m_referrerPolicy = ReferrerPolicyOrigin;
  2634. }
  2635. MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const LayoutPoint& documentPoint, const PlatformMouseEvent& event)
  2636. {
  2637. ASSERT(!renderer() || renderer()->isRenderView());
  2638. if (!renderer())
  2639. return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint()));
  2640. HitTestResult result(documentPoint);
  2641. renderView()->hitTest(request, result);
  2642. if (!request.readOnly())
  2643. updateStyleIfNeeded();
  2644. return MouseEventWithHitTestResults(event, result);
  2645. }
  2646. // DOM Section 1.1.1
  2647. bool Document::childTypeAllowed(NodeType type) const
  2648. {
  2649. switch (type) {
  2650. case ATTRIBUTE_NODE:
  2651. case CDATA_SECTION_NODE:
  2652. case DOCUMENT_FRAGMENT_NODE:
  2653. case DOCUMENT_NODE:
  2654. case ENTITY_NODE:
  2655. case ENTITY_REFERENCE_NODE:
  2656. case NOTATION_NODE:
  2657. case TEXT_NODE:
  2658. case XPATH_NAMESPACE_NODE:
  2659. return false;
  2660. case COMMENT_NODE:
  2661. case PROCESSING_INSTRUCTION_NODE:
  2662. return true;
  2663. case DOCUMENT_TYPE_NODE:
  2664. case ELEMENT_NODE:
  2665. // Documents may contain no more than one of each of these.
  2666. // (One Element and one DocumentType.)
  2667. for (Node* c = firstChild(); c; c = c->nextSibling())
  2668. if (c->nodeType() == type)
  2669. return false;
  2670. return true;
  2671. }
  2672. return false;
  2673. }
  2674. bool Document::canReplaceChild(Node* newChild, Node* oldChild)
  2675. {
  2676. if (!oldChild)
  2677. // ContainerNode::replaceChild will raise a NOT_FOUND_ERR.
  2678. return true;
  2679. if (oldChild->nodeType() == newChild->nodeType())
  2680. return true;
  2681. int numDoctypes = 0;
  2682. int numElements = 0;
  2683. // First, check how many doctypes and elements we have, not counting
  2684. // the child we're about to remove.
  2685. for (Node* c = firstChild(); c; c = c->nextSibling()) {
  2686. if (c == oldChild)
  2687. continue;
  2688. switch (c->nodeType()) {
  2689. case DOCUMENT_TYPE_NODE:
  2690. numDoctypes++;
  2691. break;
  2692. case ELEMENT_NODE:
  2693. numElements++;
  2694. break;
  2695. default:
  2696. break;
  2697. }
  2698. }
  2699. // Then, see how many doctypes and elements might be added by the new child.
  2700. if (newChild->nodeType() == DOCUMENT_FRAGMENT_NODE) {
  2701. for (Node* c = newChild->firstChild(); c; c = c->nextSibling()) {
  2702. switch (c->nodeType()) {
  2703. case ATTRIBUTE_NODE:
  2704. case CDATA_SECTION_NODE:
  2705. case DOCUMENT_FRAGMENT_NODE:
  2706. case DOCUMENT_NODE:
  2707. case ENTITY_NODE:
  2708. case ENTITY_REFERENCE_NODE:
  2709. case NOTATION_NODE:
  2710. case TEXT_NODE:
  2711. case XPATH_NAMESPACE_NODE:
  2712. return false;
  2713. case COMMENT_NODE:
  2714. case PROCESSING_INSTRUCTION_NODE:
  2715. break;
  2716. case DOCUMENT_TYPE_NODE:
  2717. numDoctypes++;
  2718. break;
  2719. case ELEMENT_NODE:
  2720. numElements++;
  2721. break;
  2722. }
  2723. }
  2724. } else {
  2725. switch (newChild->nodeType()) {
  2726. case ATTRIBUTE_NODE:
  2727. case CDATA_SECTION_NODE:
  2728. case DOCUMENT_FRAGMENT_NODE:
  2729. case DOCUMENT_NODE:
  2730. case ENTITY_NODE:
  2731. case ENTITY_REFERENCE_NODE:
  2732. case NOTATION_NODE:
  2733. case TEXT_NODE:
  2734. case XPATH_NAMESPACE_NODE:
  2735. return false;
  2736. case COMMENT_NODE:
  2737. case PROCESSING_INSTRUCTION_NODE:
  2738. return true;
  2739. case DOCUMENT_TYPE_NODE:
  2740. numDoctypes++;
  2741. break;
  2742. case ELEMENT_NODE:
  2743. numElements++;
  2744. break;
  2745. }
  2746. }
  2747. if (numElements > 1 || numDoctypes > 1)
  2748. return false;
  2749. return true;
  2750. }
  2751. PassRefPtr<Node> Document::cloneNode(bool /*deep*/)
  2752. {
  2753. // Spec says cloning Document nodes is "implementation dependent"
  2754. // so we do not support it...
  2755. return 0;
  2756. }
  2757. StyleSheetList* Document::styleSheets()
  2758. {
  2759. return m_styleSheets.get();
  2760. }
  2761. String Document::preferredStylesheetSet() const
  2762. {
  2763. return m_preferredStylesheetSet;
  2764. }
  2765. String Document::selectedStylesheetSet() const
  2766. {
  2767. return m_selectedStylesheetSet;
  2768. }
  2769. void Document::setSelectedStylesheetSet(const String& aString)
  2770. {
  2771. m_selectedStylesheetSet = aString;
  2772. styleResolverChanged(DeferRecalcStyle);
  2773. }
  2774. // This method is called whenever a top-level stylesheet has finished loading.
  2775. void Document::removePendingSheet()
  2776. {
  2777. // Make sure we knew this sheet was pending, and that our count isn't out of sync.
  2778. ASSERT(m_pendingStylesheets > 0);
  2779. m_pendingStylesheets--;
  2780. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2781. if (!ownerElement())
  2782. printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
  2783. #endif
  2784. if (m_pendingStylesheets)
  2785. return;
  2786. styleResolverChanged(RecalcStyleIfNeeded);
  2787. if (ScriptableDocumentParser* parser = scriptableDocumentParser())
  2788. parser->executeScriptsWaitingForStylesheets();
  2789. if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
  2790. view()->scrollToFragment(m_url);
  2791. }
  2792. void Document::evaluateMediaQueryList()
  2793. {
  2794. if (m_mediaQueryMatcher)
  2795. m_mediaQueryMatcher->styleResolverChanged();
  2796. }
  2797. void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
  2798. {
  2799. // Don't bother updating, since we haven't loaded all our style info yet
  2800. // and haven't calculated the style selector for the first time.
  2801. if (!attached() || (!m_didCalculateStyleResolver && !haveStylesheetsLoaded())) {
  2802. m_styleResolver.clear();
  2803. return;
  2804. }
  2805. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2806. if (!ownerElement())
  2807. printf("Beginning update of style selector at time %d.\n", elapsedTime());
  2808. #endif
  2809. bool stylesheetChangeRequiresStyleRecalc = updateActiveStylesheets(updateFlag);
  2810. if (updateFlag == DeferRecalcStyle) {
  2811. scheduleForcedStyleRecalc();
  2812. return;
  2813. }
  2814. if (didLayoutWithPendingStylesheets() && m_pendingStylesheets <= 0) {
  2815. m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
  2816. if (renderer())
  2817. renderer()->repaint();
  2818. }
  2819. if (!stylesheetChangeRequiresStyleRecalc)
  2820. return;
  2821. // This recalcStyle initiates a new recalc cycle. We need to bracket it to
  2822. // make sure animations get the correct update time
  2823. {
  2824. AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
  2825. recalcStyle(Force);
  2826. }
  2827. #ifdef INSTRUMENT_LAYOUT_SCHEDULING
  2828. if (!ownerElement())
  2829. printf("Finished update of style selector at time %d\n", elapsedTime());
  2830. #endif
  2831. if (renderer()) {
  2832. renderer()->setNeedsLayoutAndPrefWidthsRecalc();
  2833. if (view())
  2834. view()->scheduleRelayout();
  2835. }
  2836. evaluateMediaQueryList();
  2837. }
  2838. void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser)
  2839. {
  2840. if (!node->inDocument())
  2841. return;
  2842. // Until the <body> exists, we have no choice but to compare document positions,
  2843. // since styles outside of the body and head continue to be shunted into the head
  2844. // (and thus can shift to end up before dynamically added DOM content that is also
  2845. // outside the body).
  2846. if ((createdByParser && body()) || m_styleSheetCandidateNodes.isEmpty()) {
  2847. m_styleSheetCandidateNodes.add(node);
  2848. return;
  2849. }
  2850. // Determine an appropriate insertion point.
  2851. StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin();
  2852. StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end();
  2853. StyleSheetCandidateListHashSet::iterator it = end;
  2854. Node* followingNode = 0;
  2855. do {
  2856. --it;
  2857. Node* n = *it;
  2858. unsigned short position = n->compareDocumentPosition(node);
  2859. if (position == DOCUMENT_POSITION_FOLLOWING) {
  2860. m_styleSheetCandidateNodes.insertBefore(followingNode, node);
  2861. return;
  2862. }
  2863. followingNode = n;
  2864. } while (it != begin);
  2865. m_styleSheetCandidateNodes.insertBefore(followingNode, node);
  2866. }
  2867. void Document::removeStyleSheetCandidateNode(Node* node)
  2868. {
  2869. m_styleSheetCandidateNodes.remove(node);
  2870. }
  2871. void Document::collectActiveStylesheets(Vector<RefPtr<StyleSheet> >& sheets)
  2872. {
  2873. if (settings() && !settings()->authorAndUserStylesEnabled())
  2874. return;
  2875. StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin();
  2876. StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end();
  2877. for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) {
  2878. Node* n = *it;
  2879. StyleSheet* sheet = 0;
  2880. if (n->nodeType() == PROCESSING_INSTRUCTION_NODE) {
  2881. // Processing instruction (XML documents only).
  2882. // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
  2883. ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
  2884. sheet = pi->sheet();
  2885. #if ENABLE(XSLT)
  2886. // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
  2887. if (pi->isXSL() && !transformSourceDocument()) {
  2888. // Don't apply XSL transforms until loading is finished.
  2889. if (!parsing())
  2890. applyXSLTransform(pi);
  2891. return;
  2892. }
  2893. #endif
  2894. } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag)))
  2895. #if ENABLE(SVG)
  2896. || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
  2897. #endif
  2898. ) {
  2899. Element* e = static_cast<Element*>(n);
  2900. AtomicString title = e->getAttribute(titleAttr);
  2901. bool enabledViaScript = false;
  2902. if (e->hasLocalName(linkTag)) {
  2903. // <LINK> element
  2904. HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n);
  2905. if (linkElement->isDisabled())
  2906. continue;
  2907. enabledViaScript = linkElement->isEnabledViaScript();
  2908. if (linkElement->styleSheetIsLoading()) {
  2909. // it is loading but we should still decide which style sheet set to use
  2910. if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSet.isEmpty()) {
  2911. const AtomicString& rel = e->getAttribute(relAttr);
  2912. if (!rel.contains("alternate")) {
  2913. m_preferredStylesheetSet = title;
  2914. m_selectedStylesheetSet = title;
  2915. }
  2916. }
  2917. continue;
  2918. }
  2919. if (!linkElement->sheet())
  2920. title = nullAtom;
  2921. }
  2922. // Get the current preferred styleset. This is the
  2923. // set of sheets that will be enabled.
  2924. #if ENABLE(SVG)
  2925. if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
  2926. sheet = static_cast<SVGStyleElement*>(n)->sheet();
  2927. else
  2928. #endif
  2929. if (e->hasLocalName(linkTag))
  2930. sheet = static_cast<HTMLLinkElement*>(n)->sheet();
  2931. else
  2932. // <STYLE> element
  2933. sheet = static_cast<HTMLStyleElement*>(n)->sheet();
  2934. // Check to see if this sheet belongs to a styleset
  2935. // (thus making it PREFERRED or ALTERNATE rather than
  2936. // PERSISTENT).
  2937. AtomicString rel = e->getAttribute(relAttr);
  2938. if (!enabledViaScript && !title.isEmpty()) {
  2939. // Yes, we have a title.
  2940. if (m_preferredStylesheetSet.isEmpty()) {
  2941. // No preferred set has been established. If
  2942. // we are NOT an alternate sheet, then establish
  2943. // us as the preferred set. Otherwise, just ignore
  2944. // this sheet.
  2945. if (e->hasLocalName(styleTag) || !rel.contains("alternate"))
  2946. m_preferredStylesheetSet = m_selectedStylesheetSet = title;
  2947. }
  2948. if (title != m_preferredStylesheetSet)
  2949. sheet = 0;
  2950. }
  2951. if (rel.contains("alternate") && title.isEmpty())
  2952. sheet = 0;
  2953. }
  2954. if (sheet)
  2955. sheets.append(sheet);
  2956. }
  2957. }
  2958. bool Document::testAddedStylesheetRequiresStyleRecalc(StyleSheetContents* stylesheet)
  2959. {
  2960. // See if all rules on the sheet are scoped to some specific ids or classes.
  2961. // Then test if we actually have any of those in the tree at the moment.
  2962. HashSet<AtomicStringImpl*> idScopes;
  2963. HashSet<AtomicStringImpl*> classScopes;
  2964. if (!StyleResolver::determineStylesheetSelectorScopes(stylesheet, idScopes, classScopes))
  2965. return true;
  2966. // Invalidate the subtrees that match the scopes.
  2967. Node* node = firstChild();
  2968. while (node) {
  2969. if (!node->isStyledElement()) {
  2970. node = node->traverseNextNode();
  2971. continue;
  2972. }
  2973. StyledElement* element = static_cast<StyledElement*>(node);
  2974. if (SelectorChecker::elementMatchesSelectorScopes(element, idScopes, classScopes)) {
  2975. element->setNeedsStyleRecalc();
  2976. // The whole subtree is now invalidated, we can skip to the next sibling.
  2977. node = node->traverseNextSibling();
  2978. continue;
  2979. }
  2980. node = node->traverseNextNode();
  2981. }
  2982. return false;
  2983. }
  2984. void Document::analyzeStylesheetChange(StyleResolverUpdateFlag updateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleResolverReset, bool& requiresFullStyleRecalc)
  2985. {
  2986. requiresStyleResolverReset = true;
  2987. requiresFullStyleRecalc = true;
  2988. // Stylesheets of <style> elements that @import stylesheets are active but loading. We need to trigger a full recalc when such loads are done.
  2989. bool hasActiveLoadingStylesheet = false;
  2990. unsigned newStylesheetCount = newStylesheets.size();
  2991. for (unsigned i = 0; i < newStylesheetCount; ++i) {
  2992. if (newStylesheets[i]->isLoading())
  2993. hasActiveLoadingStylesheet = true;
  2994. }
  2995. if (m_hadActiveLoadingStylesheet && !hasActiveLoadingStylesheet) {
  2996. m_hadActiveLoadingStylesheet = false;
  2997. return;
  2998. }
  2999. m_hadActiveLoadingStylesheet = hasActiveLoadingStylesheet;
  3000. if (updateFlag != RecalcStyleIfNeeded)
  3001. return;
  3002. if (!m_styleResolver)
  3003. return;
  3004. // See if we are just adding stylesheets.
  3005. unsigned oldStylesheetCount = m_styleSheets->length();
  3006. if (newStylesheetCount < oldStylesheetCount)
  3007. return;
  3008. for (unsigned i = 0; i < oldStylesheetCount; ++i) {
  3009. if (m_styleSheets->item(i) != newStylesheets[i])
  3010. return;
  3011. }
  3012. requiresStyleResolverReset = false;
  3013. // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs.
  3014. if (!body() || m_hasNodesWithPlaceholderStyle)
  3015. return;
  3016. for (unsigned i = oldStylesheetCount; i < newStylesheetCount; ++i) {
  3017. if (!newStylesheets[i]->isCSSStyleSheet())
  3018. return;
  3019. if (newStylesheets[i]->disabled())
  3020. continue;
  3021. if (testAddedStylesheetRequiresStyleRecalc(static_cast<CSSStyleSheet*>(newStylesheets[i].get())->contents()))
  3022. return;
  3023. }
  3024. requiresFullStyleRecalc = false;
  3025. }
  3026. static bool styleSheetsUseRemUnits(const Vector<RefPtr<StyleSheet> >& sheets)
  3027. {
  3028. for (unsigned i = 0; i < sheets.size(); ++i) {
  3029. if (!sheets[i]->isCSSStyleSheet())
  3030. continue;
  3031. if (static_cast<CSSStyleSheet*>(sheets[i].get())->contents()->usesRemUnits())
  3032. return true;
  3033. }
  3034. return false;
  3035. }
  3036. void Document::notifySeamlessChildDocumentsOfStylesheetUpdate() const
  3037. {
  3038. // If we're not in a frame yet any potential child documents won't have a StyleResolver to update.
  3039. if (!frame())
  3040. return;
  3041. // Seamless child frames are expected to notify their seamless children recursively, so we only do direct children.
  3042. for (Frame* child = frame()->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
  3043. Document* childDocument = child->document();
  3044. if (childDocument->shouldDisplaySeamlesslyWithParent()) {
  3045. ASSERT(childDocument->seamlessParentIFrame()->document() == this);
  3046. childDocument->seamlessParentUpdatedStylesheets();
  3047. }
  3048. }
  3049. }
  3050. bool Document::updateActiveStylesheets(StyleResolverUpdateFlag updateFlag)
  3051. {
  3052. if (m_inStyleRecalc) {
  3053. // SVG <use> element may manage to invalidate style selector in the middle of a style recalc.
  3054. // https://bugs.webkit.org/show_bug.cgi?id=54344
  3055. // FIXME: This should be fixed in SVG and this code replaced with ASSERT(!m_inStyleRecalc).
  3056. m_hasDirtyStyleResolver = true;
  3057. scheduleForcedStyleRecalc();
  3058. return false;
  3059. }
  3060. if (!renderer() || !attached())
  3061. return false;
  3062. StyleSheetVector newStylesheets;
  3063. collectActiveStylesheets(newStylesheets);
  3064. bool requiresStyleResolverReset;
  3065. bool requiresFullStyleRecalc;
  3066. analyzeStylesheetChange(updateFlag, newStylesheets, requiresStyleResolverReset, requiresFullStyleRecalc);
  3067. if (requiresStyleResolverReset)
  3068. clearStyleResolver();
  3069. else {
  3070. m_styleResolver->appendAuthorStylesheets(m_styleSheets->length(), newStylesheets);
  3071. resetCSSFeatureFlags();
  3072. }
  3073. m_styleSheets->swap(newStylesheets);
  3074. m_usesRemUnits = styleSheetsUseRemUnits(m_styleSheets->vector());
  3075. m_didCalculateStyleResolver = true;
  3076. m_hasDirtyStyleResolver = false;
  3077. notifySeamlessChildDocumentsOfStylesheetUpdate();
  3078. return requiresFullStyleRecalc;
  3079. }
  3080. void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
  3081. {
  3082. m_hoverNode = newHoverNode;
  3083. }
  3084. void Document::setActiveNode(PassRefPtr<Node> newActiveNode)
  3085. {
  3086. m_activeNode = newActiveNode;
  3087. }
  3088. void Document::focusedNodeRemoved()
  3089. {
  3090. setFocusedNode(0);
  3091. }
  3092. void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly)
  3093. {
  3094. if (!m_focusedNode || this->inPageCache()) // If the document is in the page cache, then we don't need to clear out the focused node.
  3095. return;
  3096. bool nodeInSubtree = false;
  3097. if (amongChildrenOnly)
  3098. nodeInSubtree = m_focusedNode->isDescendantOf(node);
  3099. else
  3100. nodeInSubtree = (m_focusedNode == node) || m_focusedNode->isDescendantOf(node);
  3101. if (nodeInSubtree)
  3102. document()->focusedNodeRemoved();
  3103. }
  3104. void Document::hoveredNodeDetached(Node* node)
  3105. {
  3106. if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parentNode())))
  3107. return;
  3108. m_hoverNode = node->parentNode();
  3109. while (m_hoverNode && !m_hoverNode->renderer())
  3110. m_hoverNode = m_hoverNode->parentNode();
  3111. if (frame())
  3112. frame()->eventHandler()->scheduleHoverStateUpdate();
  3113. }
  3114. void Document::activeChainNodeDetached(Node* node)
  3115. {
  3116. if (!m_activeNode || (node != m_activeNode && (!m_activeNode->isTextNode() || node != m_activeNode->parentNode())))
  3117. return;
  3118. m_activeNode = node->parentNode();
  3119. while (m_activeNode && !m_activeNode->renderer())
  3120. m_activeNode = m_activeNode->parentNode();
  3121. }
  3122. #if ENABLE(DASHBOARD_SUPPORT)
  3123. const Vector<DashboardRegionValue>& Document::dashboardRegions() const
  3124. {
  3125. return m_dashboardRegions;
  3126. }
  3127. void Document::setDashboardRegions(const Vector<DashboardRegionValue>& regions)
  3128. {
  3129. m_dashboardRegions = regions;
  3130. setDashboardRegionsDirty(false);
  3131. }
  3132. #endif
  3133. bool Document::setFocusedNode(PassRefPtr<Node> prpNewFocusedNode)
  3134. {
  3135. RefPtr<Node> newFocusedNode = prpNewFocusedNode;
  3136. // Make sure newFocusedNode is actually in this document
  3137. if (newFocusedNode && (newFocusedNode->document() != this))
  3138. return true;
  3139. if (m_focusedNode == newFocusedNode)
  3140. return true;
  3141. if (m_inPageCache)
  3142. return false;
  3143. bool focusChangeBlocked = false;
  3144. RefPtr<Node> oldFocusedNode = m_focusedNode;
  3145. m_focusedNode = 0;
  3146. // Remove focus from the existing focus node (if any)
  3147. if (oldFocusedNode) {
  3148. ASSERT(!oldFocusedNode->inDetach());
  3149. if (oldFocusedNode->active())
  3150. oldFocusedNode->setActive(false);
  3151. oldFocusedNode->setFocus(false);
  3152. // Dispatch a change event for text fields or textareas that have been edited
  3153. if (oldFocusedNode->isElementNode()) {
  3154. Element* element = static_cast<Element*>(oldFocusedNode.get());
  3155. if (element->wasChangedSinceLastFormControlChangeEvent())
  3156. element->dispatchFormControlChangeEvent();
  3157. }
  3158. // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
  3159. oldFocusedNode->dispatchBlurEvent(newFocusedNode);
  3160. if (m_focusedNode) {
  3161. // handler shifted focus
  3162. focusChangeBlocked = true;
  3163. newFocusedNode = 0;
  3164. }
  3165. oldFocusedNode->dispatchFocusOutEvent(eventNames().focusoutEvent, newFocusedNode); // DOM level 3 name for the bubbling blur event.
  3166. // FIXME: We should remove firing DOMFocusOutEvent event when we are sure no content depends
  3167. // on it, probably when <rdar://problem/8503958> is resolved.
  3168. oldFocusedNode->dispatchFocusOutEvent(eventNames().DOMFocusOutEvent, newFocusedNode); // DOM level 2 name for compatibility.
  3169. if (m_focusedNode) {
  3170. // handler shifted focus
  3171. focusChangeBlocked = true;
  3172. newFocusedNode = 0;
  3173. }
  3174. if (oldFocusedNode == this && oldFocusedNode->hasOneRef())
  3175. return true;
  3176. if (oldFocusedNode->isRootEditableElement())
  3177. frame()->editor()->didEndEditing();
  3178. if (view()) {
  3179. Widget* oldWidget = widgetForNode(oldFocusedNode.get());
  3180. if (oldWidget)
  3181. oldWidget->setFocus(false);
  3182. else
  3183. view()->setFocus(false);
  3184. }
  3185. }
  3186. if (newFocusedNode) {
  3187. if (newFocusedNode->isRootEditableElement() && !acceptsEditingFocus(newFocusedNode.get())) {
  3188. // delegate blocks focus change
  3189. focusChangeBlocked = true;
  3190. goto SetFocusedNodeDone;
  3191. }
  3192. // Set focus on the new node
  3193. m_focusedNode = newFocusedNode;
  3194. // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
  3195. m_focusedNode->dispatchFocusEvent(oldFocusedNode);
  3196. if (m_focusedNode != newFocusedNode) {
  3197. // handler shifted focus
  3198. focusChangeBlocked = true;
  3199. goto SetFocusedNodeDone;
  3200. }
  3201. m_focusedNode->dispatchFocusInEvent(eventNames().focusinEvent, oldFocusedNode); // DOM level 3 bubbling focus event.
  3202. if (m_focusedNode != newFocusedNode) {
  3203. // handler shifted focus
  3204. focusChangeBlocked = true;
  3205. goto SetFocusedNodeDone;
  3206. }
  3207. // FIXME: We should remove firing DOMFocusInEvent event when we are sure no content depends
  3208. // on it, probably when <rdar://problem/8503958> is m.
  3209. m_focusedNode->dispatchFocusInEvent(eventNames().DOMFocusInEvent, oldFocusedNode); // DOM level 2 for compatibility.
  3210. if (m_focusedNode != newFocusedNode) {
  3211. // handler shifted focus
  3212. focusChangeBlocked = true;
  3213. goto SetFocusedNodeDone;
  3214. }
  3215. m_focusedNode->setFocus(true);
  3216. if (m_focusedNode->isRootEditableElement())
  3217. frame()->editor()->didBeginEditing();
  3218. // eww, I suck. set the qt focus correctly
  3219. // ### find a better place in the code for this
  3220. if (view()) {
  3221. Widget* focusWidget = widgetForNode(m_focusedNode.get());
  3222. if (focusWidget) {
  3223. // Make sure a widget has the right size before giving it focus.
  3224. // Otherwise, we are testing edge cases of the Widget code.
  3225. // Specifically, in WebCore this does not work well for text fields.
  3226. updateLayout();
  3227. // Re-get the widget in case updating the layout changed things.
  3228. focusWidget = widgetForNode(m_focusedNode.get());
  3229. }
  3230. if (focusWidget)
  3231. focusWidget->setFocus(true);
  3232. else
  3233. view()->setFocus(true);
  3234. }
  3235. }
  3236. #if PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM)
  3237. if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) {
  3238. RenderObject* oldFocusedRenderer = 0;
  3239. RenderObject* newFocusedRenderer = 0;
  3240. if (oldFocusedNode)
  3241. oldFocusedRenderer = oldFocusedNode->renderer();
  3242. if (newFocusedNode)
  3243. newFocusedRenderer = newFocusedNode->renderer();
  3244. axObjectCache()->handleFocusedUIElementChanged(oldFocusedRenderer, newFocusedRenderer);
  3245. }
  3246. #endif
  3247. if (!focusChangeBlocked)
  3248. page()->chrome()->focusedNodeChanged(m_focusedNode.get());
  3249. SetFocusedNodeDone:
  3250. updateStyleIfNeeded();
  3251. return !focusChangeBlocked;
  3252. }
  3253. void Document::getFocusableNodes(Vector<RefPtr<Node> >& nodes)
  3254. {
  3255. updateLayout();
  3256. for (Node* node = firstChild(); node; node = node->traverseNextNode()) {
  3257. if (node->isFocusable())
  3258. nodes.append(node);
  3259. }
  3260. }
  3261. void Document::setCSSTarget(Element* n)
  3262. {
  3263. if (m_cssTarget)
  3264. m_cssTarget->setNeedsStyleRecalc();
  3265. m_cssTarget = n;
  3266. if (n)
  3267. n->setNeedsStyleRecalc();
  3268. }
  3269. void Document::registerNodeListCache(DynamicNodeListCacheBase* list)
  3270. {
  3271. if (list->type() != InvalidCollectionType)
  3272. m_nodeListCounts[InvalidateOnIdNameAttrChange]++;
  3273. m_nodeListCounts[list->invalidationType()]++;
  3274. if (list->isRootedAtDocument())
  3275. m_listsInvalidatedAtDocument.add(list);
  3276. }
  3277. void Document::unregisterNodeListCache(DynamicNodeListCacheBase* list)
  3278. {
  3279. if (list->type() != InvalidCollectionType)
  3280. m_nodeListCounts[InvalidateOnIdNameAttrChange]--;
  3281. m_nodeListCounts[list->invalidationType()]--;
  3282. if (list->isRootedAtDocument()) {
  3283. ASSERT(m_listsInvalidatedAtDocument.contains(list));
  3284. m_listsInvalidatedAtDocument.remove(list);
  3285. }
  3286. }
  3287. bool Document::shouldInvalidateNodeListCaches(const QualifiedName* attrName) const
  3288. {
  3289. if (attrName) {
  3290. for (int type = DoNotInvalidateOnAttributeChanges + 1; type < numNodeListInvalidationTypes; type++) {
  3291. if (m_nodeListCounts[type] && DynamicNodeListCacheBase::shouldInvalidateTypeOnAttributeChange(static_cast<NodeListInvalidationType>(type), *attrName))
  3292. return true;
  3293. }
  3294. return false;
  3295. }
  3296. for (int type = 0; type < numNodeListInvalidationTypes; type++) {
  3297. if (m_nodeListCounts[type])
  3298. return true;
  3299. }
  3300. return false;
  3301. }
  3302. void Document::invalidateNodeListCaches(const QualifiedName* attrName)
  3303. {
  3304. HashSet<DynamicNodeListCacheBase*>::iterator end = m_listsInvalidatedAtDocument.end();
  3305. for (HashSet<DynamicNodeListCacheBase*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
  3306. (*it)->invalidateCache(attrName);
  3307. }
  3308. void Document::attachNodeIterator(NodeIterator* ni)
  3309. {
  3310. m_nodeIterators.add(ni);
  3311. }
  3312. void Document::detachNodeIterator(NodeIterator* ni)
  3313. {
  3314. // The node iterator can be detached without having been attached if its root node didn't have a document
  3315. // when the iterator was created, but has it now.
  3316. m_nodeIterators.remove(ni);
  3317. }
  3318. void Document::moveNodeIteratorsToNewDocument(Node* node, Document* newDocument)
  3319. {
  3320. HashSet<NodeIterator*> nodeIteratorsList = m_nodeIterators;
  3321. HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = nodeIteratorsList.end();
  3322. for (HashSet<NodeIterator*>::const_iterator it = nodeIteratorsList.begin(); it != nodeIteratorsEnd; ++it) {
  3323. if ((*it)->root() == node) {
  3324. detachNodeIterator(*it);
  3325. newDocument->attachNodeIterator(*it);
  3326. }
  3327. }
  3328. }
  3329. void Document::updateRangesAfterChildrenChanged(ContainerNode* container)
  3330. {
  3331. if (!m_ranges.isEmpty()) {
  3332. HashSet<Range*>::const_iterator end = m_ranges.end();
  3333. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
  3334. (*it)->nodeChildrenChanged(container);
  3335. }
  3336. }
  3337. void Document::nodeChildrenWillBeRemoved(ContainerNode* container)
  3338. {
  3339. if (!m_ranges.isEmpty()) {
  3340. HashSet<Range*>::const_iterator end = m_ranges.end();
  3341. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
  3342. (*it)->nodeChildrenWillBeRemoved(container);
  3343. }
  3344. HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
  3345. for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it) {
  3346. for (Node* n = container->firstChild(); n; n = n->nextSibling())
  3347. (*it)->nodeWillBeRemoved(n);
  3348. }
  3349. if (Frame* frame = this->frame()) {
  3350. for (Node* n = container->firstChild(); n; n = n->nextSibling()) {
  3351. frame->eventHandler()->nodeWillBeRemoved(n);
  3352. frame->selection()->nodeWillBeRemoved(n);
  3353. frame->page()->dragCaretController()->nodeWillBeRemoved(n);
  3354. }
  3355. }
  3356. }
  3357. void Document::nodeWillBeRemoved(Node* n)
  3358. {
  3359. HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
  3360. for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it)
  3361. (*it)->nodeWillBeRemoved(n);
  3362. if (!m_ranges.isEmpty()) {
  3363. HashSet<Range*>::const_iterator rangesEnd = m_ranges.end();
  3364. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != rangesEnd; ++it)
  3365. (*it)->nodeWillBeRemoved(n);
  3366. }
  3367. if (Frame* frame = this->frame()) {
  3368. frame->eventHandler()->nodeWillBeRemoved(n);
  3369. frame->selection()->nodeWillBeRemoved(n);
  3370. frame->page()->dragCaretController()->nodeWillBeRemoved(n);
  3371. }
  3372. }
  3373. void Document::textInserted(Node* text, unsigned offset, unsigned length)
  3374. {
  3375. if (!m_ranges.isEmpty()) {
  3376. HashSet<Range*>::const_iterator end = m_ranges.end();
  3377. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
  3378. (*it)->textInserted(text, offset, length);
  3379. }
  3380. // Update the markers for spelling and grammar checking.
  3381. m_markers->shiftMarkers(text, offset, length);
  3382. }
  3383. void Document::textRemoved(Node* text, unsigned offset, unsigned length)
  3384. {
  3385. if (!m_ranges.isEmpty()) {
  3386. HashSet<Range*>::const_iterator end = m_ranges.end();
  3387. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
  3388. (*it)->textRemoved(text, offset, length);
  3389. }
  3390. // Update the markers for spelling and grammar checking.
  3391. m_markers->removeMarkers(text, offset, length);
  3392. m_markers->shiftMarkers(text, offset + length, 0 - length);
  3393. }
  3394. void Document::textNodesMerged(Text* oldNode, unsigned offset)
  3395. {
  3396. if (!m_ranges.isEmpty()) {
  3397. NodeWithIndex oldNodeWithIndex(oldNode);
  3398. HashSet<Range*>::const_iterator end = m_ranges.end();
  3399. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
  3400. (*it)->textNodesMerged(oldNodeWithIndex, offset);
  3401. }
  3402. // FIXME: This should update markers for spelling and grammar checking.
  3403. }
  3404. void Document::textNodeSplit(Text* oldNode)
  3405. {
  3406. if (!m_ranges.isEmpty()) {
  3407. HashSet<Range*>::const_iterator end = m_ranges.end();
  3408. for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
  3409. (*it)->textNodeSplit(oldNode);
  3410. }
  3411. // FIXME: This should update markers for spelling and grammar checking.
  3412. }
  3413. // FIXME: eventually, this should return a DOMWindow stored in the document.
  3414. DOMWindow* Document::domWindow() const
  3415. {
  3416. if (!frame())
  3417. return 0;
  3418. // The m_frame pointer is not (not always?) zeroed out when the document is put into b/f cache, so the frame can hold an unrelated document/window pair.
  3419. // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content.
  3420. if (m_frame->document() != this)
  3421. return 0;
  3422. return frame()->domWindow();
  3423. }
  3424. void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
  3425. {
  3426. DOMWindow* domWindow = this->domWindow();
  3427. if (!domWindow)
  3428. return;
  3429. domWindow->setAttributeEventListener(eventType, listener);
  3430. }
  3431. EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType)
  3432. {
  3433. DOMWindow* domWindow = this->domWindow();
  3434. if (!domWindow)
  3435. return 0;
  3436. return domWindow->getAttributeEventListener(eventType);
  3437. }
  3438. void Document::dispatchWindowEvent(PassRefPtr<Event> event, PassRefPtr<EventTarget> target)
  3439. {
  3440. ASSERT(!eventDispatchForbidden());
  3441. DOMWindow* domWindow = this->domWindow();
  3442. if (!domWindow)
  3443. return;
  3444. domWindow->dispatchEvent(event, target);
  3445. }
  3446. void Document::dispatchWindowLoadEvent()
  3447. {
  3448. ASSERT(!eventDispatchForbidden());
  3449. DOMWindow* domWindow = this->domWindow();
  3450. if (!domWindow)
  3451. return;
  3452. domWindow->dispatchLoadEvent();
  3453. m_loadEventFinished = true;
  3454. }
  3455. void Document::enqueueWindowEvent(PassRefPtr<Event> event)
  3456. {
  3457. event->setTarget(domWindow());
  3458. m_eventQueue->enqueueEvent(event);
  3459. }
  3460. void Document::enqueueDocumentEvent(PassRefPtr<Event> event)
  3461. {
  3462. event->setTarget(this);
  3463. m_eventQueue->enqueueEvent(event);
  3464. }
  3465. PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec)
  3466. {
  3467. RefPtr<Event> event = EventFactory::create(eventType);
  3468. if (event)
  3469. return event.release();
  3470. ec = NOT_SUPPORTED_ERR;
  3471. return 0;
  3472. }
  3473. void Document::addListenerTypeIfNeeded(const AtomicString& eventType)
  3474. {
  3475. if (eventType == eventNames().DOMSubtreeModifiedEvent)
  3476. addListenerType(DOMSUBTREEMODIFIED_LISTENER);
  3477. else if (eventType == eventNames().DOMNodeInsertedEvent)
  3478. addListenerType(DOMNODEINSERTED_LISTENER);
  3479. else if (eventType == eventNames().DOMNodeRemovedEvent)
  3480. addListenerType(DOMNODEREMOVED_LISTENER);
  3481. else if (eventType == eventNames().DOMNodeRemovedFromDocumentEvent)
  3482. addListenerType(DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
  3483. else if (eventType == eventNames().DOMNodeInsertedIntoDocumentEvent)
  3484. addListenerType(DOMNODEINSERTEDINTODOCUMENT_LISTENER);
  3485. else if (eventType == eventNames().DOMAttrModifiedEvent)
  3486. addListenerType(DOMATTRMODIFIED_LISTENER);
  3487. else if (eventType == eventNames().DOMCharacterDataModifiedEvent)
  3488. addListenerType(DOMCHARACTERDATAMODIFIED_LISTENER);
  3489. else if (eventType == eventNames().overflowchangedEvent)
  3490. addListenerType(OVERFLOWCHANGED_LISTENER);
  3491. else if (eventType == eventNames().webkitAnimationStartEvent)
  3492. addListenerType(ANIMATIONSTART_LISTENER);
  3493. else if (eventType == eventNames().webkitAnimationEndEvent)
  3494. addListenerType(ANIMATIONEND_LISTENER);
  3495. else if (eventType == eventNames().webkitAnimationIterationEvent)
  3496. addListenerType(ANIMATIONITERATION_LISTENER);
  3497. else if (eventType == eventNames().webkitTransitionEndEvent)
  3498. addListenerType(TRANSITIONEND_LISTENER);
  3499. else if (eventType == eventNames().beforeloadEvent)
  3500. addListenerType(BEFORELOAD_LISTENER);
  3501. #if ENABLE(TOUCH_EVENTS)
  3502. else if (eventType == eventNames().touchstartEvent
  3503. || eventType == eventNames().touchmoveEvent
  3504. || eventType == eventNames().touchendEvent
  3505. || eventType == eventNames().touchcancelEvent) {
  3506. addListenerType(TOUCH_LISTENER);
  3507. if (Page* page = this->page())
  3508. page->chrome()->client()->needTouchEvents(true);
  3509. }
  3510. #endif
  3511. else if (eventType == eventNames().scrollEvent)
  3512. addListenerType(SCROLL_LISTENER);
  3513. else if (eventType == eventNames().webkitRegionLayoutUpdateEvent)
  3514. addListenerType(REGIONLAYOUTUPDATE_LISTENER);
  3515. }
  3516. CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&)
  3517. {
  3518. return 0;
  3519. }
  3520. HTMLFrameOwnerElement* Document::ownerElement() const
  3521. {
  3522. if (!frame())
  3523. return 0;
  3524. return frame()->ownerElement();
  3525. }
  3526. String Document::cookie(ExceptionCode& ec) const
  3527. {
  3528. if (page() && !page()->settings()->cookieEnabled())
  3529. return String();
  3530. // FIXME: The HTML5 DOM spec states that this attribute can raise an
  3531. // INVALID_STATE_ERR exception on getting if the Document has no
  3532. // browsing context.
  3533. if (!securityOrigin()->canAccessCookies()) {
  3534. ec = SECURITY_ERR;
  3535. return String();
  3536. }
  3537. KURL cookieURL = this->cookieURL();
  3538. if (cookieURL.isEmpty())
  3539. return String();
  3540. return cookies(this, cookieURL);
  3541. }
  3542. void Document::setCookie(const String& value, ExceptionCode& ec)
  3543. {
  3544. if (page() && !page()->settings()->cookieEnabled())
  3545. return;
  3546. // FIXME: The HTML5 DOM spec states that this attribute can raise an
  3547. // INVALID_STATE_ERR exception on setting if the Document has no
  3548. // browsing context.
  3549. if (!securityOrigin()->canAccessCookies()) {
  3550. ec = SECURITY_ERR;
  3551. return;
  3552. }
  3553. KURL cookieURL = this->cookieURL();
  3554. if (cookieURL.isEmpty())
  3555. return;
  3556. setCookies(this, cookieURL, value);
  3557. }
  3558. String Document::referrer() const
  3559. {
  3560. if (frame())
  3561. return frame()->loader()->referrer();
  3562. return String();
  3563. }
  3564. String Document::domain() const
  3565. {
  3566. return securityOrigin()->domain();
  3567. }
  3568. void Document::setDomain(const String& newDomain, ExceptionCode& ec)
  3569. {
  3570. if (SchemeRegistry::isDomainRelaxationForbiddenForURLScheme(securityOrigin()->protocol())) {
  3571. ec = SECURITY_ERR;
  3572. return;
  3573. }
  3574. // Both NS and IE specify that changing the domain is only allowed when
  3575. // the new domain is a suffix of the old domain.
  3576. // FIXME: We should add logging indicating why a domain was not allowed.
  3577. // If the new domain is the same as the old domain, still call
  3578. // securityOrigin()->setDomainForDOM. This will change the
  3579. // security check behavior. For example, if a page loaded on port 8000
  3580. // assigns its current domain using document.domain, the page will
  3581. // allow other pages loaded on different ports in the same domain that
  3582. // have also assigned to access this page.
  3583. if (equalIgnoringCase(domain(), newDomain)) {
  3584. securityOrigin()->setDomainFromDOM(newDomain);
  3585. if (m_frame)
  3586. m_frame->script()->updateSecurityOrigin();
  3587. return;
  3588. }
  3589. int oldLength = domain().length();
  3590. int newLength = newDomain.length();
  3591. // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14)
  3592. if (newLength >= oldLength) {
  3593. ec = SECURITY_ERR;
  3594. return;
  3595. }
  3596. String test = domain();
  3597. // Check that it's a subdomain, not e.g. "ebkit.org"
  3598. if (test[oldLength - newLength - 1] != '.') {
  3599. ec = SECURITY_ERR;
  3600. return;
  3601. }
  3602. // Now test is "webkit.org" from domain()
  3603. // and we check that it's the same thing as newDomain
  3604. test.remove(0, oldLength - newLength);
  3605. if (test != newDomain) {
  3606. ec = SECURITY_ERR;
  3607. return;
  3608. }
  3609. securityOrigin()->setDomainFromDOM(newDomain);
  3610. if (m_frame)
  3611. m_frame->script()->updateSecurityOrigin();
  3612. }
  3613. // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-lastmodified
  3614. String Document::lastModified() const
  3615. {
  3616. DateComponents date;
  3617. bool foundDate = false;
  3618. if (m_frame) {
  3619. String httpLastModified;
  3620. if (DocumentLoader* documentLoader = loader())
  3621. httpLastModified = documentLoader->response().httpHeaderField("Last-Modified");
  3622. if (!httpLastModified.isEmpty()) {
  3623. date.setMillisecondsSinceEpochForDateTime(parseDate(httpLastModified));
  3624. foundDate = true;
  3625. }
  3626. }
  3627. // FIXME: If this document came from the file system, the HTML5
  3628. // specificiation tells us to read the last modification date from the file
  3629. // system.
  3630. if (!foundDate)
  3631. date.setMillisecondsSinceEpochForDateTime(currentTimeMS());
  3632. return String::format("%02d/%02d/%04d %02d:%02d:%02d", date.month() + 1, date.monthDay(), date.fullYear(), date.hour(), date.minute(), date.second());
  3633. }
  3634. static bool isValidNameNonASCII(const UChar* characters, unsigned length)
  3635. {
  3636. unsigned i = 0;
  3637. UChar32 c;
  3638. U16_NEXT(characters, i, length, c)
  3639. if (!isValidNameStart(c))
  3640. return false;
  3641. while (i < length) {
  3642. U16_NEXT(characters, i, length, c)
  3643. if (!isValidNamePart(c))
  3644. return false;
  3645. }
  3646. return true;
  3647. }
  3648. template<typename CharType>
  3649. static inline bool isValidNameASCII(const CharType* characters, unsigned length)
  3650. {
  3651. CharType c = characters[0];
  3652. if (!(isASCIIAlpha(c) || c == ':' || c == '_'))
  3653. return false;
  3654. for (unsigned i = 1; i < length; ++i) {
  3655. c = characters[i];
  3656. if (!(isASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' || c == '.'))
  3657. return false;
  3658. }
  3659. return true;
  3660. }
  3661. bool Document::isValidName(const String& name)
  3662. {
  3663. unsigned length = name.length();
  3664. if (!length)
  3665. return false;
  3666. const UChar* characters;
  3667. if (name.is8Bit()) {
  3668. if (isValidNameASCII(name.characters8(), length))
  3669. return true;
  3670. characters = name.characters();
  3671. } else {
  3672. characters = name.characters16();
  3673. if (isValidNameASCII(characters, length))
  3674. return true;
  3675. }
  3676. return isValidNameNonASCII(characters, length);
  3677. }
  3678. bool Document::parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode& ec)
  3679. {
  3680. unsigned length = qualifiedName.length();
  3681. if (!length) {
  3682. ec = INVALID_CHARACTER_ERR;
  3683. return false;
  3684. }
  3685. bool nameStart = true;
  3686. bool sawColon = false;
  3687. int colonPos = 0;
  3688. const UChar* s = qualifiedName.characters();
  3689. for (unsigned i = 0; i < length;) {
  3690. UChar32 c;
  3691. U16_NEXT(s, i, length, c)
  3692. if (c == ':') {
  3693. if (sawColon) {
  3694. ec = NAMESPACE_ERR;
  3695. return false; // multiple colons: not allowed
  3696. }
  3697. nameStart = true;
  3698. sawColon = true;
  3699. colonPos = i - 1;
  3700. } else if (nameStart) {
  3701. if (!isValidNameStart(c)) {
  3702. ec = INVALID_CHARACTER_ERR;
  3703. return false;
  3704. }
  3705. nameStart = false;
  3706. } else {
  3707. if (!isValidNamePart(c)) {
  3708. ec = INVALID_CHARACTER_ERR;
  3709. return false;
  3710. }
  3711. }
  3712. }
  3713. if (!sawColon) {
  3714. prefix = String();
  3715. localName = qualifiedName;
  3716. } else {
  3717. prefix = qualifiedName.substring(0, colonPos);
  3718. if (prefix.isEmpty()) {
  3719. ec = NAMESPACE_ERR;
  3720. return false;
  3721. }
  3722. localName = qualifiedName.substring(colonPos + 1);
  3723. }
  3724. if (localName.isEmpty()) {
  3725. ec = NAMESPACE_ERR;
  3726. return false;
  3727. }
  3728. return true;
  3729. }
  3730. void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder)
  3731. {
  3732. m_decoder = decoder;
  3733. }
  3734. KURL Document::completeURL(const String& url, const KURL& baseURLOverride) const
  3735. {
  3736. // Always return a null URL when passed a null string.
  3737. // FIXME: Should we change the KURL constructor to have this behavior?
  3738. // See also [CSS]StyleSheet::completeURL(const String&)
  3739. if (url.isNull())
  3740. return KURL();
  3741. const KURL& baseURL = ((baseURLOverride.isEmpty() || baseURLOverride == blankURL()) && parentDocument()) ? parentDocument()->baseURL() : baseURLOverride;
  3742. if (!m_decoder)
  3743. return KURL(baseURL, url);
  3744. return KURL(baseURL, url, m_decoder->encoding());
  3745. }
  3746. KURL Document::completeURL(const String& url) const
  3747. {
  3748. return completeURL(url, m_baseURL);
  3749. }
  3750. void Document::setInPageCache(bool flag)
  3751. {
  3752. if (m_inPageCache == flag)
  3753. return;
  3754. m_inPageCache = flag;
  3755. FrameView* v = view();
  3756. if (flag) {
  3757. ASSERT(!m_savedRenderer);
  3758. m_savedRenderer = renderer();
  3759. if (v) {
  3760. v->cacheCurrentScrollPosition();
  3761. if (page() && page()->mainFrame() == m_frame)
  3762. v->resetScrollbarsAndClearContentsSize();
  3763. else
  3764. v->resetScrollbars();
  3765. }
  3766. m_styleRecalcTimer.stop();
  3767. } else {
  3768. ASSERT(!renderer() || renderer() == m_savedRenderer);
  3769. ASSERT(m_renderArena);
  3770. setRenderer(m_savedRenderer);
  3771. m_savedRenderer = 0;
  3772. if (childNeedsStyleRecalc())
  3773. scheduleStyleRecalc();
  3774. }
  3775. }
  3776. void Document::documentWillBecomeInactive()
  3777. {
  3778. #if USE(ACCELERATED_COMPOSITING)
  3779. if (renderer())
  3780. renderView()->willMoveOffscreen();
  3781. #endif
  3782. }
  3783. void Document::documentWillSuspendForPageCache()
  3784. {
  3785. documentWillBecomeInactive();
  3786. HashSet<Element*>::iterator end = m_documentSuspensionCallbackElements.end();
  3787. for (HashSet<Element*>::iterator i = m_documentSuspensionCallbackElements.begin(); i != end; ++i)
  3788. (*i)->documentWillSuspendForPageCache();
  3789. #ifndef NDEBUG
  3790. // Clear the update flag to be able to check if the viewport arguments update
  3791. // is dispatched, after the document is restored from the page cache.
  3792. m_didDispatchViewportPropertiesChanged = false;
  3793. #endif
  3794. }
  3795. void Document::documentDidResumeFromPageCache()
  3796. {
  3797. Vector<Element*> elements;
  3798. copyToVector(m_documentSuspensionCallbackElements, elements);
  3799. Vector<Element*>::iterator end = elements.end();
  3800. for (Vector<Element*>::iterator i = elements.begin(); i != end; ++i)
  3801. (*i)->documentDidResumeFromPageCache();
  3802. #if USE(ACCELERATED_COMPOSITING)
  3803. if (renderer())
  3804. renderView()->didMoveOnscreen();
  3805. #endif
  3806. if (FrameView* frameView = view())
  3807. frameView->setAnimatorsAreActive();
  3808. ASSERT(m_frame);
  3809. m_frame->loader()->client()->dispatchDidBecomeFrameset(isFrameSet());
  3810. }
  3811. void Document::registerForPageCacheSuspensionCallbacks(Element* e)
  3812. {
  3813. m_documentSuspensionCallbackElements.add(e);
  3814. }
  3815. void Document::unregisterForPageCacheSuspensionCallbacks(Element* e)
  3816. {
  3817. m_documentSuspensionCallbackElements.remove(e);
  3818. }
  3819. void Document::mediaVolumeDidChange()
  3820. {
  3821. HashSet<Element*>::iterator end = m_mediaVolumeCallbackElements.end();
  3822. for (HashSet<Element*>::iterator i = m_mediaVolumeCallbackElements.begin(); i != end; ++i)
  3823. (*i)->mediaVolumeDidChange();
  3824. }
  3825. void Document::registerForMediaVolumeCallbacks(Element* e)
  3826. {
  3827. m_mediaVolumeCallbackElements.add(e);
  3828. }
  3829. void Document::unregisterForMediaVolumeCallbacks(Element* e)
  3830. {
  3831. m_mediaVolumeCallbackElements.remove(e);
  3832. }
  3833. void Document::privateBrowsingStateDidChange()
  3834. {
  3835. HashSet<Element*>::iterator end = m_privateBrowsingStateChangedElements.end();
  3836. for (HashSet<Element*>::iterator it = m_privateBrowsingStateChangedElements.begin(); it != end; ++it)
  3837. (*it)->privateBrowsingStateDidChange();
  3838. }
  3839. void Document::registerForPrivateBrowsingStateChangedCallbacks(Element* e)
  3840. {
  3841. m_privateBrowsingStateChangedElements.add(e);
  3842. }
  3843. void Document::unregisterForPrivateBrowsingStateChangedCallbacks(Element* e)
  3844. {
  3845. m_privateBrowsingStateChangedElements.remove(e);
  3846. }
  3847. void Document::setShouldCreateRenderers(bool f)
  3848. {
  3849. m_createRenderers = f;
  3850. }
  3851. bool Document::shouldCreateRenderers()
  3852. {
  3853. return m_createRenderers;
  3854. }
  3855. // Support for Javascript execCommand, and related methods
  3856. static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
  3857. {
  3858. Frame* frame = document->frame();
  3859. if (!frame || frame->document() != document)
  3860. return Editor::Command();
  3861. document->updateStyleIfNeeded();
  3862. return frame->editor()->command(commandName,
  3863. userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM);
  3864. }
  3865. bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
  3866. {
  3867. return command(this, commandName, userInterface).execute(value);
  3868. }
  3869. bool Document::queryCommandEnabled(const String& commandName)
  3870. {
  3871. return command(this, commandName).isEnabled();
  3872. }
  3873. bool Document::queryCommandIndeterm(const String& commandName)
  3874. {
  3875. return command(this, commandName).state() == MixedTriState;
  3876. }
  3877. bool Document::queryCommandState(const String& commandName)
  3878. {
  3879. return command(this, commandName).state() == TrueTriState;
  3880. }
  3881. bool Document::queryCommandSupported(const String& commandName)
  3882. {
  3883. return command(this, commandName).isSupported();
  3884. }
  3885. String Document::queryCommandValue(const String& commandName)
  3886. {
  3887. return command(this, commandName).value();
  3888. }
  3889. KURL Document::openSearchDescriptionURL()
  3890. {
  3891. static const char* const openSearchMIMEType = "application/opensearchdescription+xml";
  3892. static const char* const openSearchRelation = "search";
  3893. // FIXME: Why do only top-level frames have openSearchDescriptionURLs?
  3894. if (!frame() || frame()->tree()->parent())
  3895. return KURL();
  3896. // FIXME: Why do we need to wait for FrameStateComplete?
  3897. if (frame()->loader()->state() != FrameStateComplete)
  3898. return KURL();
  3899. if (!head())
  3900. return KURL();
  3901. RefPtr<HTMLCollection> children = head()->children();
  3902. for (unsigned i = 0; Node* child = children->item(i); i++) {
  3903. if (!child->hasTagName(linkTag))
  3904. continue;
  3905. HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(child);
  3906. if (!equalIgnoringCase(linkElement->type(), openSearchMIMEType) || !equalIgnoringCase(linkElement->rel(), openSearchRelation))
  3907. continue;
  3908. if (linkElement->href().isEmpty())
  3909. continue;
  3910. return linkElement->href();
  3911. }
  3912. return KURL();
  3913. }
  3914. #if ENABLE(XSLT)
  3915. void Document::applyXSLTransform(ProcessingInstruction* pi)
  3916. {
  3917. RefPtr<XSLTProcessor> processor = XSLTProcessor::create();
  3918. processor->setXSLStyleSheet(static_cast<XSLStyleSheet*>(pi->sheet()));
  3919. String resultMIMEType;
  3920. String newSource;
  3921. String resultEncoding;
  3922. if (!processor->transformToString(this, resultMIMEType, newSource, resultEncoding))
  3923. return;
  3924. // FIXME: If the transform failed we should probably report an error (like Mozilla does).
  3925. processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, frame());
  3926. }
  3927. void Document::setTransformSource(PassOwnPtr<TransformSource> source)
  3928. {
  3929. m_transformSource = source;
  3930. }
  3931. #endif
  3932. void Document::setDesignMode(InheritedBool value)
  3933. {
  3934. m_designMode = value;
  3935. for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree()->traverseNext(m_frame))
  3936. frame->document()->scheduleForcedStyleRecalc();
  3937. }
  3938. Document::InheritedBool Document::getDesignMode() const
  3939. {
  3940. return m_designMode;
  3941. }
  3942. bool Document::inDesignMode() const
  3943. {
  3944. for (const Document* d = this; d; d = d->parentDocument()) {
  3945. if (d->m_designMode != inherit)
  3946. return d->m_designMode;
  3947. }
  3948. return false;
  3949. }
  3950. Document* Document::parentDocument() const
  3951. {
  3952. if (!m_frame)
  3953. return 0;
  3954. Frame* parent = m_frame->tree()->parent();
  3955. if (!parent)
  3956. return 0;
  3957. return parent->document();
  3958. }
  3959. Document* Document::topDocument() const
  3960. {
  3961. Document* doc = const_cast<Document *>(this);
  3962. Element* element;
  3963. while ((element = doc->ownerElement()))
  3964. doc = element->document();
  3965. return doc;
  3966. }
  3967. PassRefPtr<Attr> Document::createAttribute(const String& name, ExceptionCode& ec)
  3968. {
  3969. return createAttributeNS(String(), name, ec, true);
  3970. }
  3971. PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec, bool shouldIgnoreNamespaceChecks)
  3972. {
  3973. String prefix, localName;
  3974. if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
  3975. return 0;
  3976. QualifiedName qName(prefix, localName, namespaceURI);
  3977. if (!shouldIgnoreNamespaceChecks && !hasValidNamespaceForAttributes(qName)) {
  3978. ec = NAMESPACE_ERR;
  3979. return 0;
  3980. }
  3981. return Attr::create(this, qName, emptyString());
  3982. }
  3983. #if ENABLE(SVG)
  3984. const SVGDocumentExtensions* Document::svgExtensions()
  3985. {
  3986. return m_svgExtensions.get();
  3987. }
  3988. SVGDocumentExtensions* Document::accessSVGExtensions()
  3989. {
  3990. if (!m_svgExtensions)
  3991. m_svgExtensions = adoptPtr(new SVGDocumentExtensions(this));
  3992. return m_svgExtensions.get();
  3993. }
  3994. bool Document::hasSVGRootNode() const
  3995. {
  3996. return documentElement() && documentElement()->hasTagName(SVGNames::svgTag);
  3997. }
  3998. #endif
  3999. // FIXME: This caching mechanism should be merged that of DynamicNodeList in NodeRareData.
  4000. PassRefPtr<HTMLCollection> Document::cachedCollection(CollectionType type)
  4001. {
  4002. ASSERT(static_cast<unsigned>(type) < NumUnnamedDocumentCachedTypes);
  4003. if (m_collections[type])
  4004. return m_collections[type];
  4005. RefPtr<HTMLCollection> collection;
  4006. if (type == DocAll)
  4007. collection = HTMLAllCollection::create(this);
  4008. else
  4009. collection = HTMLCollection::create(this, type);
  4010. m_collections[type] = collection.get();
  4011. return collection.release();
  4012. }
  4013. void Document::removeCachedHTMLCollection(HTMLCollection* collection, CollectionType type)
  4014. {
  4015. ASSERT_UNUSED(collection, m_collections[type] == collection);
  4016. m_collections[type] = 0;
  4017. }
  4018. PassRefPtr<HTMLCollection> Document::images()
  4019. {
  4020. return cachedCollection(DocImages);
  4021. }
  4022. PassRefPtr<HTMLCollection> Document::applets()
  4023. {
  4024. return cachedCollection(DocApplets);
  4025. }
  4026. PassRefPtr<HTMLCollection> Document::embeds()
  4027. {
  4028. return cachedCollection(DocEmbeds);
  4029. }
  4030. PassRefPtr<HTMLCollection> Document::plugins()
  4031. {
  4032. // This is an alias for embeds() required for the JS DOM bindings.
  4033. return cachedCollection(DocEmbeds);
  4034. }
  4035. PassRefPtr<HTMLCollection> Document::objects()
  4036. {
  4037. return cachedCollection(DocObjects);
  4038. }
  4039. PassRefPtr<HTMLCollection> Document::scripts()
  4040. {
  4041. return cachedCollection(DocScripts);
  4042. }
  4043. PassRefPtr<HTMLCollection> Document::links()
  4044. {
  4045. return cachedCollection(DocLinks);
  4046. }
  4047. PassRefPtr<HTMLCollection> Document::forms()
  4048. {
  4049. return cachedCollection(DocForms);
  4050. }
  4051. PassRefPtr<HTMLCollection> Document::anchors()
  4052. {
  4053. return cachedCollection(DocAnchors);
  4054. }
  4055. PassRefPtr<HTMLCollection> Document::all()
  4056. {
  4057. return cachedCollection(DocAll);
  4058. }
  4059. PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
  4060. {
  4061. NamedCollectionMap::AddResult result = m_windowNamedItemCollections.add(name, 0);
  4062. if (!result.isNewEntry)
  4063. return result.iterator->second;
  4064. RefPtr<HTMLNameCollection> collection = HTMLNameCollection::create(this, WindowNamedItems, name);
  4065. result.iterator->second = collection.get();
  4066. return collection.release();
  4067. }
  4068. PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name)
  4069. {
  4070. NamedCollectionMap::AddResult result = m_documentNamedItemCollections.add(name, 0);
  4071. if (!result.isNewEntry)
  4072. return result.iterator->second;
  4073. RefPtr<HTMLNameCollection> collection = HTMLNameCollection::create(this, DocumentNamedItems, name);
  4074. result.iterator->second = collection.get();
  4075. return collection.release();
  4076. }
  4077. // FIXME: This caching mechanism should be merged that of DynamicNodeList in NodeRareData.
  4078. void Document::removeWindowNamedItemCache(HTMLCollection* collection, const AtomicString& name)
  4079. {
  4080. ASSERT_UNUSED(collection, m_windowNamedItemCollections.get(name) == collection);
  4081. m_windowNamedItemCollections.remove(name);
  4082. }
  4083. void Document::removeDocumentNamedItemCache(HTMLCollection* collection, const AtomicString& name)
  4084. {
  4085. ASSERT_UNUSED(collection, m_documentNamedItemCollections.get(name) == collection);
  4086. m_documentNamedItemCollections.remove(name);
  4087. }
  4088. void Document::finishedParsing()
  4089. {
  4090. ASSERT(!scriptableDocumentParser() || !m_parser->isParsing());
  4091. ASSERT(!scriptableDocumentParser() || m_readyState != Loading);
  4092. setParsing(false);
  4093. if (!m_documentTiming.domContentLoadedEventStart)
  4094. m_documentTiming.domContentLoadedEventStart = monotonicallyIncreasingTime();
  4095. dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false));
  4096. if (!m_documentTiming.domContentLoadedEventEnd)
  4097. m_documentTiming.domContentLoadedEventEnd = monotonicallyIncreasingTime();
  4098. if (RefPtr<Frame> f = frame()) {
  4099. // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
  4100. // resource loads are complete. HTMLObjectElements can start loading their resources from
  4101. // post attach callbacks triggered by recalcStyle(). This means if we parse out an <object>
  4102. // tag and then reach the end of the document without updating styles, we might not have yet
  4103. // started the resource load and might fire the window load event too early. To avoid this
  4104. // we force the styles to be up to date before calling FrameLoader::finishedParsing().
  4105. // See https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
  4106. updateStyleIfNeeded();
  4107. f->loader()->finishedParsing();
  4108. InspectorInstrumentation::domContentLoadedEventFired(f.get());
  4109. }
  4110. }
  4111. PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
  4112. XPathNSResolver* resolver,
  4113. ExceptionCode& ec)
  4114. {
  4115. if (!m_xpathEvaluator)
  4116. m_xpathEvaluator = XPathEvaluator::create();
  4117. return m_xpathEvaluator->createExpression(expression, resolver, ec);
  4118. }
  4119. PassRefPtr<XPathNSResolver> Document::createNSResolver(Node* nodeResolver)
  4120. {
  4121. if (!m_xpathEvaluator)
  4122. m_xpathEvaluator = XPathEvaluator::create();
  4123. return m_xpathEvaluator->createNSResolver(nodeResolver);
  4124. }
  4125. PassRefPtr<XPathResult> Document::evaluate(const String& expression,
  4126. Node* contextNode,
  4127. XPathNSResolver* resolver,
  4128. unsigned short type,
  4129. XPathResult* result,
  4130. ExceptionCode& ec)
  4131. {
  4132. if (!m_xpathEvaluator)
  4133. m_xpathEvaluator = XPathEvaluator::create();
  4134. return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
  4135. }
  4136. const Vector<IconURL>& Document::iconURLs()
  4137. {
  4138. m_iconURLs.clear();
  4139. if (!head() || !(head()->children()))
  4140. return m_iconURLs;
  4141. // Include any icons where type = link, rel = "shortcut icon".
  4142. RefPtr<HTMLCollection> children = head()->children();
  4143. unsigned int length = children->length();
  4144. for (unsigned int i = 0; i < length; ++i) {
  4145. Node* child = children->item(i);
  4146. if (!child->hasTagName(linkTag))
  4147. continue;
  4148. HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(child);
  4149. if (linkElement->iconType() != Favicon)
  4150. continue;
  4151. if (linkElement->href().isEmpty())
  4152. continue;
  4153. // Put it at the front to ensure that icons seen later take precedence as required by the spec.
  4154. IconURL newURL(linkElement->href(), linkElement->iconSizes(), linkElement->type(), linkElement->iconType());
  4155. m_iconURLs.prepend(newURL);
  4156. }
  4157. return m_iconURLs;
  4158. }
  4159. void Document::addIconURL(const String& url, const String& mimeType, const String& sizes, IconType iconType)
  4160. {
  4161. if (url.isEmpty())
  4162. return;
  4163. // FIXME - <rdar://problem/4727645> - At some point in the future, we might actually honor the "mimeType"
  4164. IconURL newURL(KURL(ParsedURLString, url), sizes, mimeType, iconType);
  4165. if (Frame* f = frame()) {
  4166. IconURL iconURL = f->loader()->icon()->iconURL(iconType);
  4167. if (iconURL == newURL)
  4168. f->loader()->didChangeIcons(iconType);
  4169. }
  4170. }
  4171. void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
  4172. {
  4173. if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard)
  4174. return;
  4175. m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard;
  4176. m_frame->selection()->updateSecureKeyboardEntryIfActive();
  4177. }
  4178. bool Document::useSecureKeyboardEntryWhenActive() const
  4179. {
  4180. return m_useSecureKeyboardEntryWhenActive;
  4181. }
  4182. static bool isEligibleForSeamless(Document* parent, Document* child)
  4183. {
  4184. // It should not matter what we return for the top-most document.
  4185. if (!parent)
  4186. return false;
  4187. if (parent->isSandboxed(SandboxSeamlessIframes))
  4188. return false;
  4189. if (child->isSrcdocDocument())
  4190. return true;
  4191. if (parent->securityOrigin()->canAccess(child->securityOrigin()))
  4192. return true;
  4193. return parent->securityOrigin()->canRequest(child->url());
  4194. }
  4195. void Document::initSecurityContext()
  4196. {
  4197. if (haveInitializedSecurityOrigin()) {
  4198. ASSERT(securityOrigin());
  4199. return;
  4200. }
  4201. if (!m_frame) {
  4202. // No source for a security context.
  4203. // This can occur via document.implementation.createDocument().
  4204. m_cookieURL = KURL(ParsedURLString, emptyString());
  4205. setSecurityOrigin(SecurityOrigin::createUnique());
  4206. setContentSecurityPolicy(ContentSecurityPolicy::create(this));
  4207. return;
  4208. }
  4209. // In the common case, create the security context from the currently
  4210. // loading URL with a fresh content security policy.
  4211. m_cookieURL = m_url;
  4212. enforceSandboxFlags(m_frame->loader()->effectiveSandboxFlags());
  4213. setSecurityOrigin(isSandboxed(SandboxOrigin) ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url));
  4214. setContentSecurityPolicy(ContentSecurityPolicy::create(this));
  4215. if (SecurityPolicy::allowSubstituteDataAccessToLocal()) {
  4216. // If this document was loaded with substituteData, then the document can
  4217. // load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756
  4218. // and https://bugs.webkit.org/show_bug.cgi?id=19760 for further
  4219. // discussion.
  4220. // RT-17330: Need to use "m_frame->loader()->documentLoader()" instead
  4221. // of "loader()" as the latter returns NULL while the document is being
  4222. // constructed
  4223. // DocumentLoader* documentLoader = loader();
  4224. DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
  4225. if (documentLoader && documentLoader->substituteData().isValid())
  4226. securityOrigin()->grantLoadLocalResources();
  4227. }
  4228. if (Settings* settings = this->settings()) {
  4229. if (!settings->isWebSecurityEnabled()) {
  4230. // Web security is turned off. We should let this document access every other document. This is used primary by testing
  4231. // harnesses for web sites.
  4232. securityOrigin()->grantUniversalAccess();
  4233. } else if (securityOrigin()->isLocal()) {
  4234. if (settings->allowUniversalAccessFromFileURLs() || m_frame->loader()->client()->shouldForceUniversalAccessFromLocalURL(m_url)) {
  4235. // Some clients want local URLs to have universal access, but that setting is dangerous for other clients.
  4236. securityOrigin()->grantUniversalAccess();
  4237. } else if (!settings->allowFileAccessFromFileURLs()) {
  4238. // Some clients want local URLs to have even tighter restrictions by default, and not be able to access other local files.
  4239. // FIXME 81578: The naming of this is confusing. Files with restricted access to other local files
  4240. // still can have other privileges that can be remembered, thereby not making them unique origins.
  4241. securityOrigin()->enforceFilePathSeparation();
  4242. }
  4243. }
  4244. }
  4245. Document* parentDocument = ownerElement() ? ownerElement()->document() : 0;
  4246. if (parentDocument && m_frame->loader()->shouldTreatURLAsSrcdocDocument(url())) {
  4247. m_isSrcdocDocument = true;
  4248. setBaseURLOverride(parentDocument->baseURL());
  4249. }
  4250. // FIXME: What happens if we inherit the security origin? This check may need to be later.
  4251. // <iframe seamless src="about:blank"> likely won't work as-is.
  4252. m_mayDisplaySeamlessWithParent = isEligibleForSeamless(parentDocument, this);
  4253. if (!shouldInheritSecurityOriginFromOwner(m_url))
  4254. return;
  4255. // If we do not obtain a meaningful origin from the URL, then we try to
  4256. // find one via the frame hierarchy.
  4257. Frame* ownerFrame = m_frame->tree()->parent();
  4258. if (!ownerFrame)
  4259. ownerFrame = m_frame->loader()->opener();
  4260. if (!ownerFrame) {
  4261. didFailToInitializeSecurityOrigin();
  4262. return;
  4263. }
  4264. if (isSandboxed(SandboxOrigin)) {
  4265. // If we're supposed to inherit our security origin from our owner,
  4266. // but we're also sandboxed, the only thing we inherit is the ability
  4267. // to load local resources. This lets about:blank iframes in file://
  4268. // URL documents load images and other resources from the file system.
  4269. if (ownerFrame->document()->securityOrigin()->canLoadLocalResources())
  4270. securityOrigin()->grantLoadLocalResources();
  4271. return;
  4272. }
  4273. m_cookieURL = ownerFrame->document()->cookieURL();
  4274. // We alias the SecurityOrigins to match Firefox, see Bug 15313
  4275. // https://bugs.webkit.org/show_bug.cgi?id=15313
  4276. setSecurityOrigin(ownerFrame->document()->securityOrigin());
  4277. }
  4278. void Document::initContentSecurityPolicy()
  4279. {
  4280. if (!m_frame->tree()->parent() || !shouldInheritSecurityOriginFromOwner(m_url))
  4281. return;
  4282. contentSecurityPolicy()->copyStateFrom(m_frame->tree()->parent()->document()->contentSecurityPolicy());
  4283. }
  4284. void Document::didUpdateSecurityOrigin()
  4285. {
  4286. if (!m_frame)
  4287. return;
  4288. // FIXME: We should remove DOMWindow::m_securityOrigin so that we don't need to keep them in sync.
  4289. // See <https://bugs.webkit.org/show_bug.cgi?id=75793>.
  4290. m_frame->domWindow()->setSecurityOrigin(securityOrigin());
  4291. m_frame->script()->updateSecurityOrigin();
  4292. }
  4293. bool Document::isContextThread() const
  4294. {
  4295. return isMainThread();
  4296. }
  4297. void Document::updateURLForPushOrReplaceState(const KURL& url)
  4298. {
  4299. Frame* f = frame();
  4300. if (!f)
  4301. return;
  4302. setURL(url);
  4303. f->loader()->setOutgoingReferrer(url);
  4304. if (DocumentLoader* documentLoader = loader())
  4305. documentLoader->replaceRequestURLForSameDocumentNavigation(url);
  4306. }
  4307. void Document::statePopped(PassRefPtr<SerializedScriptValue> stateObject)
  4308. {
  4309. if (!frame())
  4310. return;
  4311. // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we
  4312. // defer firing of popstate until we're in the complete state.
  4313. if (m_readyState == Complete)
  4314. enqueuePopstateEvent(stateObject);
  4315. else
  4316. m_pendingStateObject = stateObject;
  4317. }
  4318. void Document::updateFocusAppearanceSoon(bool restorePreviousSelection)
  4319. {
  4320. m_updateFocusAppearanceRestoresSelection = restorePreviousSelection;
  4321. if (!m_updateFocusAppearanceTimer.isActive())
  4322. m_updateFocusAppearanceTimer.startOneShot(0);
  4323. }
  4324. void Document::cancelFocusAppearanceUpdate()
  4325. {
  4326. m_updateFocusAppearanceTimer.stop();
  4327. }
  4328. void Document::updateFocusAppearanceTimerFired(Timer<Document>*)
  4329. {
  4330. Node* node = focusedNode();
  4331. if (!node)
  4332. return;
  4333. if (!node->isElementNode())
  4334. return;
  4335. updateLayout();
  4336. Element* element = static_cast<Element*>(node);
  4337. if (element->isFocusable())
  4338. element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection);
  4339. }
  4340. void Document::attachRange(Range* range)
  4341. {
  4342. ASSERT(!m_ranges.contains(range));
  4343. m_ranges.add(range);
  4344. }
  4345. void Document::detachRange(Range* range)
  4346. {
  4347. // We don't ASSERT m_ranges.contains(range) to allow us to call this
  4348. // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044
  4349. m_ranges.remove(range);
  4350. }
  4351. CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height)
  4352. {
  4353. HTMLCanvasElement* element = getCSSCanvasElement(name);
  4354. if (!element)
  4355. return 0;
  4356. element->setSize(IntSize(width, height));
  4357. return element->getContext(type);
  4358. }
  4359. HTMLCanvasElement* Document::getCSSCanvasElement(const String& name)
  4360. {
  4361. RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, 0).iterator->second;
  4362. if (!element)
  4363. element = HTMLCanvasElement::create(this);
  4364. return element.get();
  4365. }
  4366. void Document::initDNSPrefetch()
  4367. {
  4368. Settings* settings = this->settings();
  4369. m_haveExplicitlyDisabledDNSPrefetch = false;
  4370. m_isDNSPrefetchEnabled = settings && settings->dnsPrefetchingEnabled() && securityOrigin()->protocol() == "http";
  4371. // Inherit DNS prefetch opt-out from parent frame
  4372. if (Document* parent = parentDocument()) {
  4373. if (!parent->isDNSPrefetchEnabled())
  4374. m_isDNSPrefetchEnabled = false;
  4375. }
  4376. }
  4377. void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl)
  4378. {
  4379. if (equalIgnoringCase(dnsPrefetchControl, "on") && !m_haveExplicitlyDisabledDNSPrefetch) {
  4380. m_isDNSPrefetchEnabled = true;
  4381. return;
  4382. }
  4383. m_isDNSPrefetchEnabled = false;
  4384. m_haveExplicitlyDisabledDNSPrefetch = true;
  4385. }
  4386. void Document::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, PassRefPtr<ScriptCallStack> callStack)
  4387. {
  4388. if (!isContextThread()) {
  4389. postTask(AddConsoleMessageTask::create(source, type, level, message));
  4390. return;
  4391. }
  4392. if (DOMWindow* window = domWindow())
  4393. window->console()->addMessage(source, type, level, message, sourceURL, lineNumber, callStack);
  4394. }
  4395. struct PerformTaskContext {
  4396. WTF_MAKE_NONCOPYABLE(PerformTaskContext); WTF_MAKE_FAST_ALLOCATED;
  4397. public:
  4398. PerformTaskContext(PassRefPtr<DocumentWeakReference> documentReference, PassOwnPtr<ScriptExecutionContext::Task> task)
  4399. : documentReference(documentReference)
  4400. , task(task)
  4401. {
  4402. }
  4403. RefPtr<DocumentWeakReference> documentReference;
  4404. OwnPtr<ScriptExecutionContext::Task> task;
  4405. };
  4406. void Document::didReceiveTask(void* untypedContext)
  4407. {
  4408. ASSERT(isMainThread());
  4409. OwnPtr<PerformTaskContext> context = adoptPtr(static_cast<PerformTaskContext*>(untypedContext));
  4410. ASSERT(context);
  4411. Document* document = context->documentReference->document();
  4412. if (!document)
  4413. return;
  4414. Page* page = document->page();
  4415. if ((page && page->defersLoading()) || !document->m_pendingTasks.isEmpty()) {
  4416. document->m_pendingTasks.append(context->task.release());
  4417. return;
  4418. }
  4419. context->task->performTask(document);
  4420. }
  4421. void Document::postTask(PassOwnPtr<Task> task)
  4422. {
  4423. callOnMainThread(didReceiveTask, new PerformTaskContext(m_weakReference, task));
  4424. }
  4425. void Document::pendingTasksTimerFired(Timer<Document>*)
  4426. {
  4427. while (!m_pendingTasks.isEmpty()) {
  4428. OwnPtr<Task> task = m_pendingTasks[0].release();
  4429. m_pendingTasks.remove(0);
  4430. task->performTask(this);
  4431. }
  4432. }
  4433. void Document::suspendScheduledTasks(ActiveDOMObject::ReasonForSuspension reason)
  4434. {
  4435. ASSERT(!m_scheduledTasksAreSuspended);
  4436. suspendScriptedAnimationControllerCallbacks();
  4437. suspendActiveDOMObjects(reason);
  4438. scriptRunner()->suspend();
  4439. m_pendingTasksTimer.stop();
  4440. if (m_parser)
  4441. m_parser->suspendScheduledTasks();
  4442. m_scheduledTasksAreSuspended = true;
  4443. }
  4444. void Document::resumeScheduledTasks()
  4445. {
  4446. ASSERT(m_scheduledTasksAreSuspended);
  4447. if (m_parser)
  4448. m_parser->resumeScheduledTasks();
  4449. if (!m_pendingTasks.isEmpty())
  4450. m_pendingTasksTimer.startOneShot(0);
  4451. scriptRunner()->resume();
  4452. resumeActiveDOMObjects();
  4453. resumeScriptedAnimationControllerCallbacks();
  4454. m_scheduledTasksAreSuspended = false;
  4455. }
  4456. void Document::suspendScriptedAnimationControllerCallbacks()
  4457. {
  4458. #if ENABLE(REQUEST_ANIMATION_FRAME)
  4459. if (m_scriptedAnimationController)
  4460. m_scriptedAnimationController->suspend();
  4461. #endif
  4462. }
  4463. void Document::resumeScriptedAnimationControllerCallbacks()
  4464. {
  4465. #if ENABLE(REQUEST_ANIMATION_FRAME)
  4466. if (m_scriptedAnimationController)
  4467. m_scriptedAnimationController->resume();
  4468. #endif
  4469. }
  4470. void Document::windowScreenDidChange(PlatformDisplayID displayID)
  4471. {
  4472. #if ENABLE(REQUEST_ANIMATION_FRAME)
  4473. if (m_scriptedAnimationController)
  4474. m_scriptedAnimationController->windowScreenDidChange(displayID);
  4475. #else
  4476. UNUSED_PARAM(displayID);
  4477. #endif
  4478. }
  4479. String Document::displayStringModifiedByEncoding(const String& str) const
  4480. {
  4481. if (m_decoder)
  4482. return m_decoder->encoding().displayString(str.impl());
  4483. return str;
  4484. }
  4485. PassRefPtr<StringImpl> Document::displayStringModifiedByEncoding(PassRefPtr<StringImpl> str) const
  4486. {
  4487. if (m_decoder)
  4488. return m_decoder->encoding().displayString(str);
  4489. return str;
  4490. }
  4491. void Document::displayBufferModifiedByEncoding(UChar* buffer, unsigned len) const
  4492. {
  4493. if (m_decoder)
  4494. m_decoder->encoding().displayBuffer(buffer, len);
  4495. }
  4496. void Document::enqueuePageshowEvent(PageshowEventPersistence persisted)
  4497. {
  4498. // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously.
  4499. dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, persisted), this);
  4500. }
  4501. void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL)
  4502. {
  4503. enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL));
  4504. }
  4505. void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject)
  4506. {
  4507. // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously
  4508. dispatchWindowEvent(PopStateEvent::create(stateObject, domWindow() ? domWindow()->history() : 0));
  4509. }
  4510. void Document::addMediaCanStartListener(MediaCanStartListener* listener)
  4511. {
  4512. ASSERT(!m_mediaCanStartListeners.contains(listener));
  4513. m_mediaCanStartListeners.add(listener);
  4514. }
  4515. void Document::removeMediaCanStartListener(MediaCanStartListener* listener)
  4516. {
  4517. ASSERT(m_mediaCanStartListeners.contains(listener));
  4518. m_mediaCanStartListeners.remove(listener);
  4519. }
  4520. MediaCanStartListener* Document::takeAnyMediaCanStartListener()
  4521. {
  4522. HashSet<MediaCanStartListener*>::iterator slot = m_mediaCanStartListeners.begin();
  4523. if (slot == m_mediaCanStartListeners.end())
  4524. return 0;
  4525. MediaCanStartListener* listener = *slot;
  4526. m_mediaCanStartListeners.remove(slot);
  4527. return listener;
  4528. }
  4529. #if ENABLE(FULLSCREEN_API)
  4530. bool Document::fullScreenIsAllowedForElement(Element* element) const
  4531. {
  4532. ASSERT(element);
  4533. return isAttributeOnAllOwners(webkitallowfullscreenAttr, element->document()->ownerElement());
  4534. }
  4535. void Document::requestFullScreenForElement(Element* element, unsigned short flags, FullScreenCheckType checkType)
  4536. {
  4537. // The Mozilla Full Screen API <https://wiki.mozilla.org/Gecko:FullScreenAPI> has different requirements
  4538. // for full screen mode, and do not have the concept of a full screen element stack.
  4539. bool inLegacyMozillaMode = (flags & Element::LEGACY_MOZILLA_REQUEST);
  4540. do {
  4541. if (!element)
  4542. element = documentElement();
  4543. // 1. If any of the following conditions are true, terminate these steps and queue a task to fire
  4544. // an event named fullscreenerror with its bubbles attribute set to true on the context object's
  4545. // node document:
  4546. // The context object is not in a document.
  4547. if (!element->inDocument())
  4548. break;
  4549. // The context object's node document, or an ancestor browsing context's document does not have
  4550. // the fullscreen enabled flag set.
  4551. if (checkType == EnforceIFrameAllowFullScreenRequirement && !fullScreenIsAllowedForElement(element))
  4552. break;
  4553. // The context object's node document fullscreen element stack is not empty and its top element
  4554. // is not an ancestor of the context object. (NOTE: Ignore this requirement if the request was
  4555. // made via the legacy Mozilla-style API.)
  4556. if (!m_fullScreenElementStack.isEmpty() && !m_fullScreenElementStack.first()->contains(element) && !inLegacyMozillaMode)
  4557. break;
  4558. // A descendant browsing context's document has a non-empty fullscreen element stack.
  4559. bool descendentHasNonEmptyStack = false;
  4560. for (Frame* descendant = frame() ? frame()->tree()->traverseNext() : 0; descendant; descendant = descendant->tree()->traverseNext()) {
  4561. if (descendant->document()->webkitFullscreenElement()) {
  4562. descendentHasNonEmptyStack = true;
  4563. break;
  4564. }
  4565. }
  4566. if (descendentHasNonEmptyStack && !inLegacyMozillaMode)
  4567. break;
  4568. // This algorithm is not allowed to show a pop-up:
  4569. // An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either:
  4570. // - an activation behavior is currently being processed whose click event was trusted, or
  4571. // - the event listener for a trusted click event is being handled.
  4572. if (!ScriptController::processingUserGesture())
  4573. break;
  4574. // There is a previously-established user preference, security risk, or platform limitation.
  4575. if (!page() || !page()->settings()->fullScreenEnabled())
  4576. break;
  4577. if (!page()->chrome()->client()->supportsFullScreenForElement(element, flags & Element::ALLOW_KEYBOARD_INPUT))
  4578. break;
  4579. // 2. Let doc be element's node document. (i.e. "this")
  4580. Document* currentDoc = this;
  4581. // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc.
  4582. Deque<Document*> docs;
  4583. do {
  4584. docs.prepend(currentDoc);
  4585. currentDoc = currentDoc->ownerElement() ? currentDoc->ownerElement()->document() : 0;
  4586. } while (currentDoc);
  4587. // 4. For each document in docs, run these substeps:
  4588. Deque<Document*>::iterator current = docs.begin(), following = docs.begin();
  4589. do {
  4590. ++following;
  4591. // 1. Let following document be the document after document in docs, or null if there is no
  4592. // such document.
  4593. Document* currentDoc = *current;
  4594. Document* followingDoc = following != docs.end() ? *following : 0;
  4595. // 2. If following document is null, push context object on document's fullscreen element
  4596. // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
  4597. // set to true on the document.
  4598. if (!followingDoc) {
  4599. currentDoc->pushFullscreenElementStack(element);
  4600. addDocumentToFullScreenChangeEventQueue(currentDoc);
  4601. continue;
  4602. }
  4603. // 3. Otherwise, if document's fullscreen element stack is either empty or its top element
  4604. // is not following document's browsing context container,
  4605. Element* topElement = currentDoc->webkitFullscreenElement();
  4606. if (!topElement || topElement != followingDoc->ownerElement()) {
  4607. // ...push following document's browsing context container on document's fullscreen element
  4608. // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute
  4609. // set to true on document.
  4610. currentDoc->pushFullscreenElementStack(followingDoc->ownerElement());
  4611. addDocumentToFullScreenChangeEventQueue(currentDoc);
  4612. continue;
  4613. }
  4614. // 4. Otherwise, do nothing for this document. It stays the same.
  4615. } while (++current != docs.end());
  4616. // 5. Return, and run the remaining steps asynchronously.
  4617. // 6. Optionally, perform some animation.
  4618. m_areKeysEnabledInFullScreen = flags & Element::ALLOW_KEYBOARD_INPUT;
  4619. page()->chrome()->client()->enterFullScreenForElement(element);
  4620. // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen.
  4621. return;
  4622. } while (0);
  4623. m_fullScreenErrorEventTargetQueue.append(element ? element : documentElement());
  4624. m_fullScreenChangeDelayTimer.startOneShot(0);
  4625. }
  4626. void Document::webkitCancelFullScreen()
  4627. {
  4628. // The Mozilla "cancelFullScreen()" API behaves like the W3C "fully exit fullscreen" behavior, which
  4629. // is defined as:
  4630. // "To fully exit fullscreen act as if the exitFullscreen() method was invoked on the top-level browsing
  4631. // context's document and subsequently empty that document's fullscreen element stack."
  4632. if (!topDocument()->webkitFullscreenElement())
  4633. return;
  4634. // To achieve that aim, remove all the elements from the top document's stack except for the first before
  4635. // calling webkitExitFullscreen():
  4636. Deque<RefPtr<Element> > replacementFullscreenElementStack;
  4637. replacementFullscreenElementStack.prepend(topDocument()->webkitFullscreenElement());
  4638. topDocument()->m_fullScreenElementStack.swap(replacementFullscreenElementStack);
  4639. topDocument()->webkitExitFullscreen();
  4640. }
  4641. void Document::webkitExitFullscreen()
  4642. {
  4643. // The exitFullscreen() method must run these steps:
  4644. // 1. Let doc be the context object. (i.e. "this")
  4645. Document* currentDoc = this;
  4646. // 2. If doc's fullscreen element stack is empty, terminate these steps.
  4647. if (m_fullScreenElementStack.isEmpty())
  4648. return;
  4649. // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen
  4650. // element stack (if any), ordered so that the child of the doc is last and the document furthest
  4651. // away from the doc is first.
  4652. Deque<RefPtr<Document> > descendants;
  4653. for (Frame* descendant = frame() ? frame()->tree()->traverseNext() : 0; descendant; descendant = descendant->tree()->traverseNext()) {
  4654. if (descendant->document()->webkitFullscreenElement())
  4655. descendants.prepend(descendant->document());
  4656. }
  4657. // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a
  4658. // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant.
  4659. for (Deque<RefPtr<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) {
  4660. (*i)->clearFullscreenElementStack();
  4661. addDocumentToFullScreenChangeEventQueue(i->get());
  4662. }
  4663. // 5. While doc is not null, run these substeps:
  4664. Element* newTop = 0;
  4665. while (currentDoc) {
  4666. // 1. Pop the top element of doc's fullscreen element stack.
  4667. currentDoc->popFullscreenElementStack();
  4668. // If doc's fullscreen element stack is non-empty and the element now at the top is either
  4669. // not in a document or its node document is not doc, repeat this substep.
  4670. newTop = currentDoc->webkitFullscreenElement();
  4671. if (newTop && (!newTop->inDocument() || newTop->document() != currentDoc))
  4672. continue;
  4673. // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true
  4674. // on doc.
  4675. Node* target = currentDoc->m_fullScreenElement.get();
  4676. if (!target)
  4677. target = currentDoc;
  4678. addDocumentToFullScreenChangeEventQueue(currentDoc);
  4679. // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context
  4680. // container, set doc to that browsing context container's node document.
  4681. if (!newTop && currentDoc->ownerElement())
  4682. currentDoc = currentDoc->ownerElement()->document();
  4683. // 4. Otherwise, set doc to null.
  4684. currentDoc = 0;
  4685. }
  4686. // 6. Return, and run the remaining steps asynchronously.
  4687. // 7. Optionally, perform some animation.
  4688. // Only exit out of full screen window mode if there are no remaining elements in the
  4689. // full screen stack.
  4690. if (!newTop) {
  4691. page()->chrome()->client()->exitFullScreenForElement(m_fullScreenElement.get());
  4692. return;
  4693. }
  4694. // Otherwise, notify the chrome of the new full screen element.
  4695. page()->chrome()->client()->enterFullScreenForElement(newTop);
  4696. }
  4697. bool Document::webkitFullscreenEnabled() const
  4698. {
  4699. // 4. The fullscreenEnabled attribute must return true if the context object and all ancestor
  4700. // browsing context's documents have their fullscreen enabled flag set, or false otherwise.
  4701. // Top-level browsing contexts are implied to have their allowFullScreen attribute set.
  4702. return isAttributeOnAllOwners(webkitallowfullscreenAttr, ownerElement());
  4703. }
  4704. void Document::webkitWillEnterFullScreenForElement(Element* element)
  4705. {
  4706. if (!attached() || inPageCache())
  4707. return;
  4708. ASSERT(element);
  4709. // Protect against being called after the document has been removed from the page.
  4710. if (!page())
  4711. return;
  4712. ASSERT(page()->settings()->fullScreenEnabled());
  4713. if (m_fullScreenRenderer)
  4714. m_fullScreenRenderer->unwrapRenderer();
  4715. m_fullScreenElement = element;
  4716. #if USE(NATIVE_FULLSCREEN_VIDEO)
  4717. if (element && element->isMediaElement())
  4718. return;
  4719. #endif
  4720. // Create a placeholder block for a the full-screen element, to keep the page from reflowing
  4721. // when the element is removed from the normal flow. Only do this for a RenderBox, as only
  4722. // a box will have a frameRect. The placeholder will be created in setFullScreenRenderer()
  4723. // during layout.
  4724. RenderObject* renderer = m_fullScreenElement->renderer();
  4725. bool shouldCreatePlaceholder = renderer && renderer->isBox();
  4726. if (shouldCreatePlaceholder) {
  4727. m_savedPlaceholderFrameRect = toRenderBox(renderer)->frameRect();
  4728. m_savedPlaceholderRenderStyle = RenderStyle::clone(renderer->style());
  4729. }
  4730. if (m_fullScreenElement != documentElement())
  4731. RenderFullScreen::wrapRenderer(renderer, this);
  4732. m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
  4733. recalcStyle(Force);
  4734. }
  4735. void Document::webkitDidEnterFullScreenForElement(Element*)
  4736. {
  4737. if (!m_fullScreenElement)
  4738. return;
  4739. if (!attached() || inPageCache())
  4740. return;
  4741. m_fullScreenElement->didBecomeFullscreenElement();
  4742. m_fullScreenChangeDelayTimer.startOneShot(0);
  4743. }
  4744. void Document::webkitWillExitFullScreenForElement(Element*)
  4745. {
  4746. if (!m_fullScreenElement)
  4747. return;
  4748. if (!attached() || inPageCache())
  4749. return;
  4750. m_fullScreenElement->willStopBeingFullscreenElement();
  4751. }
  4752. void Document::webkitDidExitFullScreenForElement(Element*)
  4753. {
  4754. if (!m_fullScreenElement)
  4755. return;
  4756. if (!attached() || inPageCache())
  4757. return;
  4758. m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
  4759. m_areKeysEnabledInFullScreen = false;
  4760. if (m_fullScreenRenderer)
  4761. m_fullScreenRenderer->unwrapRenderer();
  4762. m_fullScreenElement = 0;
  4763. scheduleForcedStyleRecalc();
  4764. m_fullScreenChangeDelayTimer.startOneShot(0);
  4765. }
  4766. void Document::setFullScreenRenderer(RenderFullScreen* renderer)
  4767. {
  4768. if (renderer == m_fullScreenRenderer)
  4769. return;
  4770. if (renderer && m_savedPlaceholderRenderStyle)
  4771. renderer->createPlaceholder(m_savedPlaceholderRenderStyle.release(), m_savedPlaceholderFrameRect);
  4772. else if (renderer && m_fullScreenRenderer && m_fullScreenRenderer->placeholder()) {
  4773. RenderBlock* placeholder = m_fullScreenRenderer->placeholder();
  4774. renderer->createPlaceholder(RenderStyle::clone(placeholder->style()), placeholder->frameRect());
  4775. }
  4776. if (m_fullScreenRenderer)
  4777. m_fullScreenRenderer->destroy();
  4778. ASSERT(!m_fullScreenRenderer);
  4779. m_fullScreenRenderer = renderer;
  4780. // This notification can come in after the page has been destroyed.
  4781. if (page())
  4782. page()->chrome()->client()->fullScreenRendererChanged(m_fullScreenRenderer);
  4783. }
  4784. void Document::fullScreenRendererDestroyed()
  4785. {
  4786. m_fullScreenRenderer = 0;
  4787. if (page())
  4788. page()->chrome()->client()->fullScreenRendererChanged(0);
  4789. }
  4790. void Document::setFullScreenRendererSize(const IntSize& size)
  4791. {
  4792. ASSERT(m_fullScreenRenderer);
  4793. if (!m_fullScreenRenderer)
  4794. return;
  4795. if (m_fullScreenRenderer) {
  4796. RefPtr<RenderStyle> newStyle = RenderStyle::clone(m_fullScreenRenderer->style());
  4797. newStyle->setWidth(Length(size.width(), WebCore::Fixed));
  4798. newStyle->setHeight(Length(size.height(), WebCore::Fixed));
  4799. newStyle->setTop(Length(0, WebCore::Fixed));
  4800. newStyle->setLeft(Length(0, WebCore::Fixed));
  4801. m_fullScreenRenderer->setStyle(newStyle);
  4802. updateLayout();
  4803. }
  4804. }
  4805. void Document::setFullScreenRendererBackgroundColor(Color backgroundColor)
  4806. {
  4807. if (!m_fullScreenRenderer)
  4808. return;
  4809. RefPtr<RenderStyle> newStyle = RenderStyle::clone(m_fullScreenRenderer->style());
  4810. newStyle->setBackgroundColor(backgroundColor);
  4811. m_fullScreenRenderer->setStyle(newStyle);
  4812. }
  4813. void Document::fullScreenChangeDelayTimerFired(Timer<Document>*)
  4814. {
  4815. Deque<RefPtr<Node> > changeQueue;
  4816. m_fullScreenChangeEventTargetQueue.swap(changeQueue);
  4817. while (!changeQueue.isEmpty()) {
  4818. RefPtr<Node> node = changeQueue.takeFirst();
  4819. if (!node)
  4820. node = documentElement();
  4821. // If the element was removed from our tree, also message the documentElement.
  4822. if (!contains(node.get()))
  4823. changeQueue.append(documentElement());
  4824. node->dispatchEvent(Event::create(eventNames().webkitfullscreenchangeEvent, true, false));
  4825. }
  4826. Deque<RefPtr<Node> > errorQueue;
  4827. m_fullScreenErrorEventTargetQueue.swap(errorQueue);
  4828. while (!errorQueue.isEmpty()) {
  4829. RefPtr<Node> node = errorQueue.takeFirst();
  4830. if (!node)
  4831. node = documentElement();
  4832. // If the node was removed from our tree, also message the documentElement.
  4833. if (!contains(node.get()))
  4834. errorQueue.append(documentElement());
  4835. node->dispatchEvent(Event::create(eventNames().webkitfullscreenerrorEvent, true, false));
  4836. }
  4837. }
  4838. void Document::fullScreenElementRemoved()
  4839. {
  4840. m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
  4841. webkitCancelFullScreen();
  4842. }
  4843. void Document::removeFullScreenElementOfSubtree(Node* node, bool amongChildrenOnly)
  4844. {
  4845. if (!m_fullScreenElement)
  4846. return;
  4847. bool elementInSubtree = false;
  4848. if (amongChildrenOnly)
  4849. elementInSubtree = m_fullScreenElement->isDescendantOf(node);
  4850. else
  4851. elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement->isDescendantOf(node);
  4852. if (elementInSubtree)
  4853. fullScreenElementRemoved();
  4854. }
  4855. bool Document::isAnimatingFullScreen() const
  4856. {
  4857. return m_isAnimatingFullScreen;
  4858. }
  4859. void Document::setAnimatingFullScreen(bool flag)
  4860. {
  4861. if (m_isAnimatingFullScreen == flag)
  4862. return;
  4863. m_isAnimatingFullScreen = flag;
  4864. if (m_fullScreenElement && m_fullScreenElement->isDescendantOf(this)) {
  4865. m_fullScreenElement->setNeedsStyleRecalc();
  4866. scheduleForcedStyleRecalc();
  4867. }
  4868. }
  4869. void Document::clearFullscreenElementStack()
  4870. {
  4871. m_fullScreenElementStack.clear();
  4872. }
  4873. void Document::popFullscreenElementStack()
  4874. {
  4875. if (m_fullScreenElementStack.isEmpty())
  4876. return;
  4877. m_fullScreenElementStack.removeFirst();
  4878. }
  4879. void Document::pushFullscreenElementStack(Element* element)
  4880. {
  4881. m_fullScreenElementStack.prepend(element);
  4882. }
  4883. void Document::addDocumentToFullScreenChangeEventQueue(Document* doc)
  4884. {
  4885. ASSERT(doc);
  4886. Node* target = doc->webkitFullscreenElement();
  4887. if (!target)
  4888. target = doc->webkitCurrentFullScreenElement();
  4889. if (!target)
  4890. target = doc;
  4891. m_fullScreenChangeEventTargetQueue.append(target);
  4892. }
  4893. #endif
  4894. #if ENABLE(POINTER_LOCK)
  4895. void Document::webkitExitPointerLock()
  4896. {
  4897. if (page())
  4898. page()->pointerLockController()->requestPointerUnlock();
  4899. }
  4900. Element* Document::webkitPointerLockElement() const
  4901. {
  4902. return page() ? page()->pointerLockController()->element() : 0;
  4903. }
  4904. #endif
  4905. void Document::decrementLoadEventDelayCount()
  4906. {
  4907. ASSERT(m_loadEventDelayCount);
  4908. --m_loadEventDelayCount;
  4909. if (frame() && !m_loadEventDelayCount && !m_loadEventDelayTimer.isActive())
  4910. m_loadEventDelayTimer.startOneShot(0);
  4911. }
  4912. void Document::loadEventDelayTimerFired(Timer<Document>*)
  4913. {
  4914. if (frame())
  4915. frame()->loader()->checkCompleted();
  4916. }
  4917. #if ENABLE(REQUEST_ANIMATION_FRAME)
  4918. int Document::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
  4919. {
  4920. if (!m_scriptedAnimationController) {
  4921. #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
  4922. m_scriptedAnimationController = ScriptedAnimationController::create(this, page() ? page()->displayID() : 0);
  4923. #else
  4924. m_scriptedAnimationController = ScriptedAnimationController::create(this, 0);
  4925. #endif
  4926. // It's possible that the Page may have suspended scripted animations before
  4927. // we were created. We need to make sure that we don't start up the animation
  4928. // controller on a background tab, for example.
  4929. if (!page() || page()->scriptedAnimationsSuspended())
  4930. m_scriptedAnimationController->suspend();
  4931. }
  4932. return m_scriptedAnimationController->registerCallback(callback);
  4933. }
  4934. void Document::webkitCancelAnimationFrame(int id)
  4935. {
  4936. if (!m_scriptedAnimationController)
  4937. return;
  4938. m_scriptedAnimationController->cancelCallback(id);
  4939. }
  4940. void Document::serviceScriptedAnimations(DOMTimeStamp time)
  4941. {
  4942. if (!m_scriptedAnimationController)
  4943. return;
  4944. m_scriptedAnimationController->serviceScriptedAnimations(time);
  4945. }
  4946. #endif
  4947. #if ENABLE(TOUCH_EVENTS)
  4948. PassRefPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, int pageX, int pageY, int screenX, int screenY, int radiusX, int radiusY, float rotationAngle, float force, ExceptionCode&) const
  4949. {
  4950. // FIXME: It's not clear from the documentation at
  4951. // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
  4952. // when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS
  4953. // and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
  4954. Frame* frame = window ? window->frame() : this->frame();
  4955. return Touch::create(frame, target, identifier, screenX, screenY, pageX, pageY, radiusX, radiusY, rotationAngle, force);
  4956. }
  4957. #endif
  4958. static void wheelEventHandlerCountChanged(Document* document)
  4959. {
  4960. Page* page = document->page();
  4961. if (!page)
  4962. return;
  4963. ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
  4964. if (!scrollingCoordinator)
  4965. return;
  4966. FrameView* frameView = document->view();
  4967. if (!frameView)
  4968. return;
  4969. scrollingCoordinator->frameViewWheelEventHandlerCountChanged(frameView);
  4970. }
  4971. void Document::didAddWheelEventHandler()
  4972. {
  4973. ++m_wheelEventHandlerCount;
  4974. Frame* mainFrame = page() ? page()->mainFrame() : 0;
  4975. if (mainFrame)
  4976. mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
  4977. wheelEventHandlerCountChanged(this);
  4978. }
  4979. void Document::didRemoveWheelEventHandler()
  4980. {
  4981. ASSERT(m_wheelEventHandlerCount > 0);
  4982. --m_wheelEventHandlerCount;
  4983. Frame* mainFrame = page() ? page()->mainFrame() : 0;
  4984. if (mainFrame)
  4985. mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
  4986. wheelEventHandlerCountChanged(this);
  4987. }
  4988. void Document::didAddTouchEventHandler()
  4989. {
  4990. ++m_touchEventHandlerCount;
  4991. Frame* mainFrame = page() ? page()->mainFrame() : 0;
  4992. if (mainFrame)
  4993. mainFrame->notifyChromeClientTouchEventHandlerCountChanged();
  4994. }
  4995. void Document::didRemoveTouchEventHandler()
  4996. {
  4997. ASSERT(m_touchEventHandlerCount > 0);
  4998. --m_touchEventHandlerCount;
  4999. Frame* mainFrame = page() ? page()->mainFrame() : 0;
  5000. if (mainFrame)
  5001. mainFrame->notifyChromeClientTouchEventHandlerCountChanged();
  5002. }
  5003. HTMLIFrameElement* Document::seamlessParentIFrame() const
  5004. {
  5005. if (!shouldDisplaySeamlesslyWithParent())
  5006. return 0;
  5007. HTMLFrameOwnerElement* ownerElement = this->ownerElement();
  5008. ASSERT(ownerElement->hasTagName(iframeTag));
  5009. return static_cast<HTMLIFrameElement*>(ownerElement);
  5010. }
  5011. bool Document::shouldDisplaySeamlesslyWithParent() const
  5012. {
  5013. #if ENABLE(IFRAME_SEAMLESS)
  5014. HTMLFrameOwnerElement* ownerElement = this->ownerElement();
  5015. if (!ownerElement)
  5016. return false;
  5017. return m_mayDisplaySeamlessWithParent && ownerElement->hasTagName(iframeTag) && ownerElement->fastHasAttribute(seamlessAttr);
  5018. #else
  5019. return false;
  5020. #endif
  5021. }
  5022. DocumentLoader* Document::loader() const
  5023. {
  5024. if (!m_frame)
  5025. return 0;
  5026. DocumentLoader* loader = m_frame->loader()->documentLoader();
  5027. if (!loader)
  5028. return 0;
  5029. if (m_frame->document() != this)
  5030. return 0;
  5031. return loader;
  5032. }
  5033. #if ENABLE(MICRODATA)
  5034. PassRefPtr<NodeList> Document::getItems(const String& typeNames)
  5035. {
  5036. // Since documet.getItem() is allowed for microdata, typeNames will be null string.
  5037. // In this case we need to create an unique string identifier to map such request in the cache.
  5038. String localTypeNames = typeNames.isNull() ? MicroDataItemList::undefinedItemType() : typeNames;
  5039. return ensureRareData()->ensureNodeLists()->addCacheWithName<MicroDataItemList>(this, DynamicNodeList::MicroDataItemListType, localTypeNames);
  5040. }
  5041. #endif
  5042. IntSize Document::viewportSize() const
  5043. {
  5044. if (!view())
  5045. return IntSize();
  5046. return view()->visibleContentRect(/* includeScrollbars */ true).size();
  5047. }
  5048. Node* eventTargetNodeForDocument(Document* doc)
  5049. {
  5050. if (!doc)
  5051. return 0;
  5052. Node* node = doc->focusedNode();
  5053. if (!node && doc->isPluginDocument()) {
  5054. PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc);
  5055. node = pluginDocument->pluginNode();
  5056. }
  5057. if (!node && doc->isHTMLDocument())
  5058. node = doc->body();
  5059. if (!node)
  5060. node = doc->documentElement();
  5061. return node;
  5062. }
  5063. void Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(Vector<FloatQuad>& quads, RenderObject* renderer)
  5064. {
  5065. if (!view())
  5066. return;
  5067. float inverseFrameScale = 1;
  5068. if (frame())
  5069. inverseFrameScale = 1 / frame()->frameScaleFactor();
  5070. LayoutRect visibleContentRect = view()->visibleContentRect();
  5071. for (size_t i = 0; i < quads.size(); ++i) {
  5072. quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
  5073. adjustFloatQuadForAbsoluteZoom(quads[i], renderer);
  5074. if (inverseFrameScale != 1)
  5075. quads[i].scale(inverseFrameScale, inverseFrameScale);
  5076. }
  5077. }
  5078. void Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(FloatRect& rect, RenderObject* renderer)
  5079. {
  5080. if (!view())
  5081. return;
  5082. float inverseFrameScale = 1;
  5083. if (frame())
  5084. inverseFrameScale = 1 / frame()->frameScaleFactor();
  5085. LayoutRect visibleContentRect = view()->visibleContentRect();
  5086. rect.move(-visibleContentRect.x(), -visibleContentRect.y());
  5087. adjustFloatRectForAbsoluteZoom(rect, renderer);
  5088. if (inverseFrameScale != 1)
  5089. rect.scale(inverseFrameScale);
  5090. }
  5091. void Document::setContextFeatures(PassRefPtr<ContextFeatures> features)
  5092. {
  5093. m_contextFeatures = features;
  5094. }
  5095. void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
  5096. {
  5097. MemoryClassInfo<Document> info(memoryObjectInfo, this, MemoryInstrumentation::DOM);
  5098. info.visitBaseClass<ContainerNode>(this);
  5099. info.addVector(m_customFonts);
  5100. info.addString(m_documentURI);
  5101. info.addString(m_baseTarget);
  5102. if (m_pageGroupUserSheets)
  5103. info.addVector(*m_pageGroupUserSheets.get());
  5104. if (m_userSheets)
  5105. info.addVector(*m_userSheets.get());
  5106. info.addHashSet(m_nodeIterators);
  5107. info.addHashSet(m_ranges);
  5108. info.addListHashSet(m_styleSheetCandidateNodes);
  5109. info.addString(m_preferredStylesheetSet);
  5110. info.addString(m_selectedStylesheetSet);
  5111. info.addString(m_title.string());
  5112. info.addString(m_rawTitle.string());
  5113. info.addString(m_xmlEncoding);
  5114. info.addString(m_xmlVersion);
  5115. info.addString(m_contentLanguage);
  5116. info.addHashMap(m_documentNamedItemCollections);
  5117. info.addHashMap(m_windowNamedItemCollections);
  5118. #if ENABLE(DASHBOARD_SUPPORT)
  5119. info.addVector(m_dashboardRegions);
  5120. #endif
  5121. info.addHashMap(m_cssCanvasElements);
  5122. info.addVector(m_iconURLs);
  5123. info.addHashSet(m_documentSuspensionCallbackElements);
  5124. info.addHashSet(m_mediaVolumeCallbackElements);
  5125. info.addHashSet(m_privateBrowsingStateChangedElements);
  5126. info.addHashMap(m_elementsByAccessKey);
  5127. info.addHashSet(m_mediaCanStartListeners);
  5128. info.addVector(m_pendingTasks);
  5129. }
  5130. #if ENABLE(UNDO_MANAGER)
  5131. PassRefPtr<UndoManager> Document::undoManager()
  5132. {
  5133. if (!m_undoManager)
  5134. m_undoManager = UndoManager::create(this);
  5135. return m_undoManager;
  5136. }
  5137. #endif
  5138. } // namespace WebCore