Document.cpp 171 KB
Newer Older
1
/*
kocienda's avatar
kocienda committed
2
3
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
ap's avatar
ap committed
5
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011 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.
kocienda's avatar
kocienda committed
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
ddkilzer's avatar
ddkilzer committed
24
25
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
kocienda's avatar
kocienda committed
26
27
 */

mjs's avatar
mjs committed
28
#include "config.h"
darin's avatar
darin committed
29
#include "Document.h"
darin's avatar
darin committed
30

31
#include "AXObjectCache.h"
weinig@apple.com's avatar
weinig@apple.com committed
32
#include "AnimationController.h"
darin@apple.com's avatar
darin@apple.com committed
33
#include "Attr.h"
34
#include "Attribute.h"
darin's avatar
darin committed
35
#include "CDATASection.h"
weinig's avatar
weinig committed
36
#include "CSSStyleSelector.h"
37
#include "CSSStyleSheet.h"
darin's avatar
darin committed
38
#include "CSSValueKeywords.h"
39
#include "CSSValuePool.h"
weinig@apple.com's avatar
weinig@apple.com committed
40
#include "CachedCSSStyleSheet.h"
41
#include "CachedResourceLoader.h"
42
#include "Chrome.h"
43
#include "ChromeClient.h"
darin's avatar
darin committed
44
#include "Comment.h"
ap@webkit.org's avatar
ap@webkit.org committed
45
#include "Console.h"
46
#include "ContentSecurityPolicy.h"
oliver's avatar
oliver committed
47
#include "CookieJar.h"
darin's avatar
darin committed
48
#include "DOMImplementation.h"
weinig@apple.com's avatar
weinig@apple.com committed
49
#include "DOMWindow.h"
50
#include "DateComponents.h"
51
52
53
54
#include "DeviceMotionController.h"
#include "DeviceMotionEvent.h"
#include "DeviceOrientationController.h"
#include "DeviceOrientationEvent.h"
55
#include "DocumentEventQueue.h"
darin's avatar
darin committed
56
#include "DocumentFragment.h"
darin's avatar
darin committed
57
#include "DocumentLoader.h"
58
#include "DocumentMarkerController.h"
darin's avatar
darin committed
59
60
#include "DocumentType.h"
#include "EditingText.h"
andersca's avatar
andersca committed
61
#include "Editor.h"
62
#include "Element.h"
63
#include "EntityReference.h"
weinig's avatar
   
weinig committed
64
#include "Event.h"
65
#include "EventFactory.h"
darin's avatar
darin committed
66
#include "EventHandler.h"
darin's avatar
darin committed
67
#include "EventListener.h"
darin's avatar
darin committed
68
#include "EventNames.h"
darin's avatar
darin committed
69
#include "ExceptionCode.h"
70
#include "FocusController.h"
71
#include "FormAssociatedElement.h"
mjs's avatar
mjs committed
72
#include "Frame.h"
ggaren's avatar
ggaren committed
73
#include "FrameLoader.h"
ap@apple.com's avatar
ap@apple.com committed
74
#include "FrameLoaderClient.h"
75
#include "FrameSelection.h"
mjs's avatar
mjs committed
76
#include "FrameTree.h"
darin's avatar
darin committed
77
#include "FrameView.h"
78
#include "GeolocationController.h"
79
#include "HashChangeEvent.h"
80
#include "HistogramSupport.h"
81
#include "HTMLAllCollection.h"
82
#include "HTMLAnchorElement.h"
83
#include "HTMLBodyElement.h"
84
#include "HTMLCanvasElement.h"
darin@apple.com's avatar
darin@apple.com committed
85
#include "HTMLCollection.h"
darin's avatar
darin committed
86
87
#include "HTMLDocument.h"
#include "HTMLElementFactory.h"
darin's avatar
darin committed
88
#include "HTMLFrameOwnerElement.h"
darin's avatar
darin committed
89
#include "HTMLHeadElement.h"
90
#include "HTMLIFrameElement.h"
darin's avatar
darin committed
91
#include "HTMLInputElement.h"
92
#include "HTMLLinkElement.h"
93
#include "HTMLMapElement.h"
darin's avatar
darin committed
94
#include "HTMLNameCollection.h"
darin's avatar
darin committed
95
#include "HTMLNames.h"
96
#include "HTMLParserIdioms.h"
97
#include "HTMLStyleElement.h"
bdash's avatar
bdash committed
98
#include "HTMLTitleElement.h"
ap's avatar
ap committed
99
#include "HTTPParsers.h"
weinig's avatar
weinig committed
100
101
#include "HitTestRequest.h"
#include "HitTestResult.h"
zimmermann@webkit.org's avatar
zimmermann@webkit.org committed
102
#include "ImageLoader.h"
103
#include "InspectorInstrumentation.h"
darin's avatar
darin committed
104
#include "Logging.h"
105
106
#include "MediaQueryList.h"
#include "MediaQueryMatcher.h"
darin's avatar
darin committed
107
#include "MouseEventWithHitTestResults.h"
darin's avatar
darin committed
108
#include "NameNodeList.h"
109
#include "NestingLevelIncrementer.h"
110
#include "NewXMLDocumentParser.h"
111
112
#include "NodeFilter.h"
#include "NodeIterator.h"
darin@apple.com's avatar
darin@apple.com committed
113
#include "NodeWithIndex.h"
114
#include "Page.h"
115
#include "PageGroup.h"
ap@apple.com's avatar
ap@apple.com committed
116
#include "PageTransitionEvent.h"
darin's avatar
darin committed
117
#include "PlatformKeyboardEvent.h"
118
#include "PopStateEvent.h"
119
#include "ProcessingInstruction.h"
weinig's avatar
   
weinig committed
120
#include "RegisteredEventListener.h"
darin's avatar
darin committed
121
#include "RenderArena.h"
122
#include "RenderFlowThread.h"
123
#include "RenderLayer.h"
124
#include "RenderLayerBacking.h"
125
#include "RenderTextControl.h"
126
#include "RenderView.h"
127
#include "RenderWidget.h"
128
#include "SchemeRegistry.h"
129
#include "ScopedEventQueue.h"
130
#include "ScriptCallStack.h"
131
#include "ScriptController.h"
mitz@apple.com's avatar
mitz@apple.com committed
132
#include "ScriptElement.h"
133
#include "ScriptEventListener.h"
134
#include "ScriptRunner.h"
weinig's avatar
weinig committed
135
#include "SecurityOrigin.h"
136
#include "SecurityPolicy.h"
darin's avatar
darin committed
137
#include "SegmentedString.h"
ggaren's avatar
ggaren committed
138
#include "Settings.h"
139
#include "ShadowRoot.h"
140
#include "StaticHashSetNodeList.h"
141
#include "StyleSheetList.h"
darin's avatar
darin committed
142
#include "TextResourceDecoder.h"
143
#include "Timer.h"
144
#include "TransformSource.h"
weinig@apple.com's avatar
weinig@apple.com committed
145
#include "TreeWalker.h"
146
#include "UserContentURLPattern.h"
147
#include "WebKitNamedFlow.h"
148
#include "XMLDocumentParser.h"
weinig's avatar
weinig committed
149
#include "XMLHttpRequest.h"
ap@apple.com's avatar
ap@apple.com committed
150
#include "XMLNSNames.h"
eric@webkit.org's avatar
eric@webkit.org committed
151
#include "XMLNames.h"
152
153
154
155
#include "XPathEvaluator.h"
#include "XPathExpression.h"
#include "XPathNSResolver.h"
#include "XPathResult.h"
156
#include "htmlediting.h"
ap@webkit.org's avatar
ap@webkit.org committed
157
#include <wtf/CurrentTime.h>
dsmith@webkit.org's avatar
dsmith@webkit.org committed
158
#include <wtf/HashFunctions.h>
159
160
#include <wtf/MainThread.h>
#include <wtf/PassRefPtr.h>
weinig@apple.com's avatar
weinig@apple.com committed
161
#include <wtf/StdLibExtras.h>
162
#include <wtf/text/StringBuffer.h>
163

164
165
166
167
#if ENABLE(SHARED_WORKERS)
#include "SharedWorkerRepository.h"
#endif

mjs's avatar
mjs committed
168
#if ENABLE(XSLT)
darin's avatar
darin committed
169
#include "XSLTProcessor.h"
170
171
#endif

mjs's avatar
mjs committed
172
#if ENABLE(SVG)
173
#include "SVGDocumentExtensions.h"
eseidel's avatar
eseidel committed
174
#include "SVGElementFactory.h"
175
#include "SVGNames.h"
darin's avatar
darin committed
176
#include "SVGStyleElement.h"
eseidel's avatar
eseidel committed
177
178
#endif

179
#if ENABLE(TOUCH_EVENTS)
180
#include "TouchList.h"
181
182
#endif

183
184
185
186
187
188
#if ENABLE(MATHML)
#include "MathMLElement.h"
#include "MathMLElementFactory.h"
#include "MathMLNames.h"
#endif

189
190
191
192
#if ENABLE(FULLSCREEN_API)
#include "RenderFullScreen.h"
#endif

193
194
#if ENABLE(REQUEST_ANIMATION_FRAME)
#include "RequestAnimationFrameCallback.h"
195
#include "ScriptedAnimationController.h"
196
197
#endif

198
199
200
201
202
#if ENABLE(MICRODATA)
#include "MicroDataItemList.h"
#include "NodeRareData.h"
#endif

darin's avatar
darin committed
203
using namespace std;
darin's avatar
darin committed
204
205
using namespace WTF;
using namespace Unicode;
darin's avatar
darin committed
206

darin's avatar
darin committed
207
208
namespace WebCore {

209
using namespace HTMLNames;
kocienda's avatar
kocienda committed
210

211
// #define INSTRUMENT_LAYOUT_SCHEDULING 1
hyatt's avatar
hyatt committed
212

213
214
static const unsigned cMaxWriteRecursionDepth = 21;

215
216
217
// This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
// FIXME: For faster machines this value can really be lowered to 200.  250 is adequate, but a little high
// for dual G5s. :)
darin's avatar
darin committed
218
static const int cLayoutScheduleThreshold = 250;
219

eseidel's avatar
eseidel committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// DOM Level 2 says (letters added):
//
// a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
// b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
// c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
// 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.
// 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.
// f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
// g) Character #x00B7 is classified as an extender, because the property list so identifies it.
// h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
// i) Characters ':' and '_' are allowed as name-start characters.
// j) Characters '-' and '.' are allowed as name characters.
//
// It also contains complete tables. If we decide it's better, we could include those instead of the following code.

static inline bool isValidNameStart(UChar32 c)
{
    // rule (e) above
    if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
        return true;

    // rule (i) above
    if (c == ':' || c == '_')
        return true;

    // rules (a) and (f) above
darin's avatar
darin committed
246
247
    const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
    if (!(Unicode::category(c) & nameStartMask))
eseidel's avatar
eseidel committed
248
249
250
251
252
253
254
        return false;

    // rule (c) above
    if (c >= 0xF900 && c < 0xFFFE)
        return false;

    // rule (d) above
darin's avatar
darin committed
255
256
    DecompositionType decompType = decompositionType(c);
    if (decompType == DecompositionFont || decompType == DecompositionCompat)
eseidel's avatar
eseidel committed
257
258
259
260
261
262
        return false;

    return true;
}

static inline bool isValidNamePart(UChar32 c)
darin's avatar
darin committed
263
{
eseidel's avatar
eseidel committed
264
265
266
267
268
269
270
271
272
273
274
275
276
    // rules (a), (e), and (i) above
    if (isValidNameStart(c))
        return true;

    // rules (g) and (h) above
    if (c == 0x00B7 || c == 0x0387)
        return true;

    // rule (j) above
    if (c == '-' || c == '.')
        return true;

    // rules (b) and (f) above
darin's avatar
darin committed
277
278
    const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
    if (!(Unicode::category(c) & otherNamePartMask))
eseidel's avatar
eseidel committed
279
280
281
282
        return false;

    // rule (c) above
    if (c >= 0xF900 && c < 0xFFFE)
darin's avatar
darin committed
283
        return false;
eseidel's avatar
eseidel committed
284
285

    // rule (d) above
darin's avatar
darin committed
286
287
    DecompositionType decompType = decompositionType(c);
    if (decompType == DecompositionFont || decompType == DecompositionCompat)
eseidel's avatar
eseidel committed
288
289
        return false;

darin's avatar
darin committed
290
291
292
    return true;
}

293
294
295
296
297
298
299
static bool shouldInheritSecurityOriginFromOwner(const KURL& url)
{
    // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
    //
    // If a Document has the address "about:blank"
    //     The origin of the Document is the origin it was assigned when its browsing context was created.
    //
abarth@webkit.org's avatar
abarth@webkit.org committed
300
    // Note: We generalize this to all "about" URLs and invalid URLs because we
301
302
303
304
305
    // treat all of these URLs as about:blank.
    //
    return !url.isValid() || url.protocolIs("about");
}

ggaren's avatar
ggaren committed
306
static Widget* widgetForNode(Node* focusedNode)
darin@apple.com's avatar
darin@apple.com committed
307
{
ggaren's avatar
ggaren committed
308
309
310
311
312
    if (!focusedNode)
        return 0;
    RenderObject* renderer = focusedNode->renderer();
    if (!renderer || !renderer->isWidget())
        return 0;
313
    return toRenderWidget(renderer)->widget();
ggaren's avatar
ggaren committed
314
315
}

316
static bool acceptsEditingFocus(Node* node)
ggaren's avatar
ggaren committed
317
{
ggaren's avatar
ggaren committed
318
    ASSERT(node);
319
    ASSERT(node->rendererIsEditable());
ggaren's avatar
ggaren committed
320

321
    Node* root = node->rootEditableElement();
ggaren's avatar
ggaren committed
322
323
324
325
326
327
328
    Frame* frame = node->document()->frame();
    if (!frame || !root)
        return false;

    return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
}

adele@apple.com's avatar
adele@apple.com committed
329
330
static bool disableRangeMutation(Page* page)
{
mrowe@apple.com's avatar
mrowe@apple.com committed
331
332
333
    // This check is made on super-hot code paths, so we only want this on Leopard.
#ifdef TARGETING_LEOPARD
    // Disable Range mutation on document modifications in Leopard Mail.
adele@apple.com's avatar
adele@apple.com committed
334
    // See <rdar://problem/5865171>
335
    return page && page->settings()->needsLeopardMailQuirks();
336
#else
337
    UNUSED_PARAM(page);
338
339
    return false;
#endif
adele@apple.com's avatar
adele@apple.com committed
340
341
}

342
static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
343

344
class DocumentWeakReference : public ThreadSafeRefCounted<DocumentWeakReference> {
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
public:
    static PassRefPtr<DocumentWeakReference> create(Document* document)
    {
        return adoptRef(new DocumentWeakReference(document));
    }

    Document* document()
    {
        ASSERT(isMainThread());
        return m_document;
    }

    void clear()
    {
        ASSERT(isMainThread());
        m_document = 0;
    }

private:
    DocumentWeakReference(Document* document)
        : m_document(document)
    {
        ASSERT(isMainThread());
    }

    Document* m_document;
};

373
374
uint64_t Document::s_globalTreeVersion = 0;

375
Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
376
    : TreeScope(0)
377
    , m_guardRefCount(0)
378
379
    , m_compatibilityMode(NoQuirksMode)
    , m_compatibilityModeLocked(false)
380
    , m_domTreeVersion(++s_globalTreeVersion)
381
#if ENABLE(MUTATION_OBSERVERS)
382
    , m_mutationObserverTypes(0)
383
#endif
384
    , m_styleSheets(StyleSheetList::create(this))
385
    , m_hadActiveLoadingStylesheet(false)
386
    , m_readyState(Complete)
387
    , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
388
    , m_pendingStyleRecalcShouldForce(false)
darin@apple.com's avatar
darin@apple.com committed
389
    , m_frameElementsShouldIgnoreScrolling(false)
390
    , m_containsValidityStyleRules(false)
391
    , m_updateFocusAppearanceRestoresSelection(false)
392
    , m_ignoreDestructiveWriteCount(0)
darin's avatar
darin committed
393
    , m_titleSetExplicitly(false)
darin's avatar
darin committed
394
    , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
395
    , m_loadEventFinished(false)
396
397
    , m_startTime(currentTime())
    , m_overMinimumLayoutThreshold(false)
398
    , m_scriptRunner(ScriptRunner::create(this))
ap's avatar
ap committed
399
400
    , m_xmlVersion("1.0")
    , m_xmlStandalone(false)
adele's avatar
adele committed
401
402
    , m_savedRenderer(0)
    , m_designMode(inherit)
ddkilzer@apple.com's avatar
ddkilzer@apple.com committed
403
#if ENABLE(DASHBOARD_SUPPORT)
rjw's avatar
rjw committed
404
    , m_hasDashboardRegions(false)
rjw's avatar
rjw committed
405
    , m_dashboardRegionsDirty(false)
ddkilzer@apple.com's avatar
ddkilzer@apple.com committed
406
#endif
407
408
    , m_createRenderers(true)
    , m_inPageCache(false)
409
    , m_accessKeyMapValid(false)
beidson's avatar
beidson committed
410
    , m_useSecureKeyboardEntryWhenActive(false)
411
    , m_isXHTML(isXHTML)
412
    , m_isHTML(isHTML)
413
    , m_isViewSource(false)
414
    , m_sawElementsInKnownNamespaces(false)
ddkilzer@apple.com's avatar
ddkilzer@apple.com committed
415
    , m_usingGeolocation(false)
416
    , m_eventQueue(DocumentEventQueue::create(this))
417
    , m_weakReference(DocumentWeakReference::create(this))
418
    , m_idAttributeName(idAttr)
419
420
#if ENABLE(FULLSCREEN_API)
    , m_areKeysEnabledInFullScreen(0)
421
422
    , m_fullScreenRenderer(0)
    , m_fullScreenChangeDelayTimer(this, &Document::fullScreenChangeDelayTimerFired)
423
    , m_isAnimatingFullScreen(false)
424
#endif
425
    , m_loadEventDelayCount(0)
426
    , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
jochen@chromium.org's avatar
jochen@chromium.org committed
427
    , m_referrerPolicy(SecurityPolicy::ReferrerPolicyDefault)
428
429
    , m_directionSetOnDocumentElement(false)
    , m_writingModeSetOnDocumentElement(false)
430
431
    , m_writeRecursionIsTooDeep(false)
    , m_writeRecursionDepth(0)
432
    , m_wheelEventHandlerCount(0)
433
    , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
434
{
435
    m_document = this;
436

437
438
    m_pageGroupUserSheetCacheValid = false;

439
    m_printing = false;
440
441
    m_paginatedForScreen = false;

adele@apple.com's avatar
adele@apple.com committed
442
    m_ignoreAutofocus = false;
kocienda's avatar
kocienda committed
443

mjs's avatar
mjs committed
444
    m_frame = frame;
445

446
447
448
449
450
451
    // We depend on the url getting immediately set in subframes, but we
    // also depend on the url NOT getting immediately set in opened windows.
    // See fast/dom/early-frame-url.html
    // and fast/dom/location-new-window-no-crash.html, respectively.
    // FIXME: Can/should we unify this behavior?
    if ((frame && frame->ownerElement()) || !url.isEmpty())
452
453
        setURL(url);

454
    m_axObjectCache = 0;
455

456
    m_markers = adoptPtr(new DocumentMarkerController);
457

458
    m_cachedResourceLoader = adoptPtr(new CachedResourceLoader(this));
kocienda's avatar
kocienda committed
459

460
    m_visuallyOrdered = false;
461
    m_bParsing = false;
ap's avatar
ap committed
462
    m_wellFormed = false;
463

464
    m_textColor = Color::black;
kocienda's avatar
kocienda committed
465
    m_listenerTypes = 0;
466
    setInDocument();
467
    m_inStyleRecalc = false;
468
    m_closeAfterStyleRecalc = false;
hyatt@apple.com's avatar
hyatt@apple.com committed
469

470
    m_usesSiblingRules = false;
471
    m_usesSiblingRulesOverride = false;
472
    m_usesFirstLineRules = false;
weinig's avatar
weinig committed
473
    m_usesFirstLetterRules = false;
474
    m_usesBeforeAfterRules = false;
475
    m_usesBeforeAfterRulesOverride = false;
hyatt@apple.com's avatar
hyatt@apple.com committed
476
    m_usesRemUnits = false;
477
    m_usesLinkRules = false;
hyatt@apple.com's avatar
hyatt@apple.com committed
478

thatcher's avatar
thatcher committed
479
    m_gotoAnchorNeededAfterStylesheetsLoad = false;
480

ddkilzer's avatar
ddkilzer committed
481
    m_didCalculateStyleSelector = false;
482
    m_hasDirtyStyleSelector = false;
hyatt's avatar
hyatt committed
483
    m_pendingStylesheets = 0;
mjs's avatar
mjs committed
484
    m_ignorePendingStylesheets = false;
antti's avatar
antti committed
485
    m_hasNodesWithPlaceholderStyle = false;
486
    m_pendingSheetLayout = NoLayoutWithPendingSheets;
487
488

    m_cssTarget = 0;
489

490
491
492
493
    resetLinkColor();
    resetVisitedLinkColor();
    resetActiveLinkColor();

494
    m_processingLoadEvent = false;
kocienda's avatar
kocienda committed
495
    
abarth@webkit.org's avatar
abarth@webkit.org committed
496
    initSecurityContext();
collinj@webkit.org's avatar
   
collinj@webkit.org committed
497
    initDNSPrefetch();
weinig's avatar
weinig committed
498

499
500
    static int docID = 0;
    m_docID = docID++;
501
502
503
504
    
#ifndef NDEBUG
    m_updatingStyleSelector = false;
#endif
kocienda's avatar
kocienda committed
505
506
}

507
508
static void histogramMutationEventUsage(const unsigned short& listenerTypes)
{
509
510
511
512
513
514
    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMSubtreeModified", static_cast<bool>(listenerTypes & Document::DOMSUBTREEMODIFIED_LISTENER), 2);
    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInserted", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTED_LISTENER), 2);
    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemoved", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVED_LISTENER), 2);
    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemovedFromDocument", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER), 2);
    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInsertedIntoDocument", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER), 2);
    HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMCharacterDataModified", static_cast<bool>(listenerTypes & Document::DOMCHARACTERDATAMODIFIED_LISTENER), 2);
515
516
}

darin's avatar
darin committed
517
Document::~Document()
kocienda's avatar
kocienda committed
518
{
519
520
521
    ASSERT(!renderer());
    ASSERT(!m_inPageCache);
    ASSERT(!m_savedRenderer);
darin@apple.com's avatar
darin@apple.com committed
522
    ASSERT(m_ranges.isEmpty());
523
    ASSERT(!m_styleRecalcTimer.isActive());
524
    ASSERT(!m_parentTreeScope);
525
    ASSERT(!m_guardRefCount);
526

527
    m_scriptRunner.clear();
mitz@apple.com's avatar
mitz@apple.com committed
528

529
530
    histogramMutationEventUsage(m_listenerTypes);

531
    removeAllEventListeners();
darin's avatar
darin committed
532

533
534
535
536
537
538
539
540
    // Currently we believe that Document can never outlive the parser.
    // Although the Document may be replaced synchronously, DocumentParsers
    // generally keep at least one reference to an Element which would in turn
    // has a reference to the Document.  If you hit this ASSERT, then that
    // assumption is wrong.  DocumentParser::detach() should ensure that even
    // if the DocumentParser outlives the Document it won't cause badness.
    ASSERT(!m_parser || m_parser->refCount() == 1);
    detachParser();
541
    m_document = 0;
542
    m_cachedResourceLoader.clear();
543

544
    m_renderArena.clear();
545

harrison@apple.com's avatar
harrison@apple.com committed
546
547
    clearAXObjectCache();

eseidel's avatar
eseidel committed
548
    m_decoder = 0;
549

550
551
    if (m_styleSheets)
        m_styleSheets->documentDestroyed();
552

ap@apple.com's avatar
ap@apple.com committed
553
554
555
556
557
558
559
560
561
562
    if (m_elemSheet)
        m_elemSheet->clearOwnerNode();
    if (m_mappedElementSheet)
        m_mappedElementSheet->clearOwnerNode();
    if (m_pageUserSheet)
        m_pageUserSheet->clearOwnerNode();
    if (m_pageGroupUserSheets) {
        for (size_t i = 0; i < m_pageGroupUserSheets->size(); ++i)
            (*m_pageGroupUserSheets)[i]->clearOwnerNode();
    }
563
564
565
566
    if (m_userSheets) {
        for (size_t i = 0; i < m_userSheets->size(); ++i)
            (*m_userSheets)[i]->clearOwnerNode();
    }
ap@apple.com's avatar
ap@apple.com committed
567

568
    deleteCustomFonts();
569

570
    m_weakReference->clear();
571
572
573
574
575

    if (m_mediaQueryMatcher)
        m_mediaQueryMatcher->documentDestroyed();
}

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
void Document::removedLastRef()
{
    ASSERT(!m_deletionHasBegun);
    if (m_guardRefCount) {
        // If removing a child removes the last self-only ref, we don't
        // want the scope to be destructed until after
        // removeAllChildren returns, so we guard ourselves with an
        // extra self-only ref.
        guardRef();

        // We must make sure not to be retaining any of our children through
        // these extra pointers or we will create a reference cycle.
        m_docType = 0;
        m_focusedNode = 0;
        m_hoverNode = 0;
        m_activeNode = 0;
        m_titleElement = 0;
        m_documentElement = 0;
#if ENABLE(FULLSCREEN_API)
        m_fullScreenElement = 0;
#endif

        // removeAllChildren() doesn't always unregister IDs,
        // so tear down scope information upfront to avoid having stale references in the map.
        destroyTreeScopeData();
        removeAllChildren();

        m_markers->detach();

        detachParser();

        m_cssCanvasElements.clear();

#if ENABLE(REQUEST_ANIMATION_FRAME)
        // FIXME: consider using ActiveDOMObject.
611
612
613
        if (m_scriptedAnimationController)
            m_scriptedAnimationController->clearDocumentPointer();
        m_scriptedAnimationController.clear();
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
#endif

#ifndef NDEBUG
        m_inRemovedLastRefFunction = false;
#endif

        guardDeref();
    } else {
#ifndef NDEBUG
        m_deletionHasBegun = true;
#endif
        delete this;
    }
}

629
630
631
632
633
Element* Document::getElementById(const AtomicString& id) const
{
    return TreeScope::getElementById(id);
}

634
635
636
637
638
639
640
641
642
643
644
Element* Document::getElementByAccessKey(const String& key)
{
    if (key.isEmpty())
        return 0;
    if (!m_accessKeyMapValid) {
        buildAccessKeyMap(this);
        m_accessKeyMapValid = true;
    }
    return m_elementsByAccessKey.get(key.impl());
}

645
void Document::buildAccessKeyMap(TreeScope* root)
646
647
648
649
650
{
     for (Node* n = root; n; n = n->traverseNextNode(root)) {
        if (!n->isElementNode())
            continue;
        Element* element = static_cast<Element*>(n);
651
        const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
652
653
654
655
656
657
658
659
660
661
662
663
        if (!accessKey.isEmpty())
            m_elementsByAccessKey.set(accessKey.impl(), element);
        buildAccessKeyMap(element->shadowRoot());
    }
}

void Document::invalidateAccessKeyMap()
{
    m_accessKeyMapValid = false;
    m_elementsByAccessKey.clear();
}

664
665
666
667
668
MediaQueryMatcher* Document::mediaQueryMatcher()
{
    if (!m_mediaQueryMatcher)
        m_mediaQueryMatcher = MediaQueryMatcher::create(this);
    return m_mediaQueryMatcher.get();
kocienda's avatar
kocienda committed
669
670
}

671
672
673
674
void Document::setCompatibilityMode(CompatibilityMode mode)
{
    if (m_compatibilityModeLocked || mode == m_compatibilityMode)
        return;
675
    ASSERT(!m_styleSheets->length());
676
677
678
679
680
681
682
683
684
    bool wasInQuirksMode = inQuirksMode();
    m_compatibilityMode = mode;
    if (inQuirksMode() != wasInQuirksMode) {
        // All user stylesheets have to reparse using the different mode.
        clearPageUserSheet();
        clearPageGroupUserSheets();
    }
}

685
686
687
688
689
String Document::compatMode() const
{
    return inQuirksMode() ? "BackCompat" : "CSS1Compat";
}

darin's avatar
darin committed
690
void Document::resetLinkColor()
691
{
692
    m_linkColor = Color(0, 0, 238);
693
694
}

darin's avatar
darin committed
695
void Document::resetVisitedLinkColor()
696
{
697
    m_visitedLinkColor = Color(85, 26, 139);    
698
699
}

darin's avatar
darin committed
700
void Document::resetActiveLinkColor()
701
{
702
    m_activeLinkColor.setNamedColor("red");
703
}
704

darin's avatar
darin committed
705
void Document::setDocType(PassRefPtr<DocumentType> docType)
706
{
707
708
    // This should never be called more than once.
    ASSERT(!m_docType || !docType);
709
    m_docType = docType;
710
    if (m_docType)
711
        this->adoptIfNeeded(m_docType.get());
712
    // Doctype affects the interpretation of the stylesheets.
713
    clearStyleSelector();
kocienda's avatar
kocienda committed
714
715
}

716
DOMImplementation* Document::implementation()
kocienda's avatar
kocienda committed
717
{
weinig@apple.com's avatar
weinig@apple.com committed
718
    if (!m_implementation)
719
        m_implementation = DOMImplementation::create(this);
darin's avatar
darin committed
720
    return m_implementation.get();
kocienda's avatar
kocienda committed
721
722
}

723
void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
thatcher's avatar
thatcher committed
724
{
725
    TreeScope::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
726
    
727
728
729
730
731
    Element* newDocumentElement = firstElementChild(this);
    if (newDocumentElement == m_documentElement)
        return;
    m_documentElement = newDocumentElement;
    // The root style used for media query matching depends on the document element.
732
    clearStyleSelector();
kocienda's avatar
kocienda committed
733
734
}

735
PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
kocienda's avatar
kocienda committed
736
{
eric@webkit.org's avatar
eric@webkit.org committed
737
738
739
740
741
742
    if (!isValidName(name)) {
        ec = INVALID_CHARACTER_ERR;
        return 0;
    }

    if (m_isXHTML)
743
        return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), this, 0, false);
kmccullo's avatar
kmccullo committed
744

jchaffraix@webkit.org's avatar
jchaffraix@webkit.org committed
745
    return createElement(QualifiedName(nullAtom, name, nullAtom), false);
kocienda's avatar
kocienda committed
746
747
}

darin's avatar
darin committed
748
PassRefPtr<DocumentFragment> Document::createDocumentFragment()
749
{
750
    return DocumentFragment::create(document());
751
752
}

darin@apple.com's avatar
darin@apple.com committed
753
PassRefPtr<Text> Document::createTextNode(const String& data)
754
{
755
    return Text::create(this, data);
756
757
}

darin@apple.com's avatar
darin@apple.com committed
758
PassRefPtr<Comment> Document::createComment(const String& data)
759
{
760
    return Comment::create(this, data);
761
762
}

darin@apple.com's avatar
darin@apple.com committed
763
PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
764
{
darin's avatar
darin committed
765
    if (isHTMLDocument()) {
darin's avatar
darin committed
766
        ec = NOT_SUPPORTED_ERR;
darin's avatar
darin committed
767
        return 0;
darin's avatar
darin committed
768
    }
769
    return CDATASection::create(this, data);
770
771
}

darin@apple.com's avatar
darin@apple.com committed
772
PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
773
{
darin's avatar
darin committed
774
    if (!isValidName(target)) {
darin's avatar
darin committed
775
        ec = INVALID_CHARACTER_ERR;
776
        return 0;
darin's avatar
darin committed
777
778
    }
    if (isHTMLDocument()) {
darin's avatar
darin committed
779
        ec = NOT_SUPPORTED_ERR;
780
        return 0;
darin's avatar
darin committed
781
    }
782
    return ProcessingInstruction::create(this, target, data);
783
784
}

darin@apple.com's avatar
darin@apple.com committed
785
PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec)
786
{
darin's avatar
darin committed
787
    if (!isValidName(name)) {
darin's avatar
darin committed
788
        ec = INVALID_CHARACTER_ERR;
darin's avatar
darin committed
789
        return 0;
darin's avatar
darin committed
790
791
    }
    if (isHTMLDocument()) {
darin's avatar
darin committed
792
        ec = NOT_SUPPORTED_ERR;
darin's avatar
darin committed
793
        return 0;
darin's avatar
darin committed
794
    }
795
    return EntityReference::create(this, name);
796
797
}

darin@apple.com's avatar
darin@apple.com committed
798
PassRefPtr<EditingText> Document::createEditingTextNode(const String& text)
kocienda's avatar
kocienda committed
799
{
800
    return EditingText::create(this, text);
kocienda's avatar
kocienda committed
801
802
}

darin's avatar
darin committed
803
PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
kocienda's avatar
kocienda committed
804
{
darin@apple.com's avatar
darin@apple.com committed
805
    return CSSMutableStyleDeclaration::create();
kocienda's avatar
kocienda committed
806
807
}

darin's avatar
darin committed
808
PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
809
{
darin's avatar
darin committed
810
    ec = 0;
ggaren's avatar
ggaren committed
811
    
oliver's avatar
oliver committed
812
    if (!importedNode
ddkilzer@apple.com's avatar
ddkilzer@apple.com committed
813
#if ENABLE(SVG) && ENABLE(DASHBOARD_SUPPORT)
oliver's avatar
oliver committed
814
815
816
        || (importedNode->isSVGElement() && page() && page()->settings()->usesDashboardBackwardCompatibilityMode())
#endif
        ) {
ggaren's avatar
ggaren committed
817
818
819
        ec = NOT_SUPPORTED_ERR;
        return 0;
    }
darin's avatar
darin committed
820

darin's avatar
darin committed
821
    switch (importedNode->nodeType()) {
822
823
824
825
826
827
828
829
830
831
832
833
    case TEXT_NODE:
        return createTextNode(importedNode->nodeValue());
    case CDATA_SECTION_NODE:
        return createCDATASection(importedNode->nodeValue(), ec);
    case ENTITY_REFERENCE_NODE:
        return createEntityReference(importedNode->nodeName(), ec);
    case PROCESSING_INSTRUCTION_NODE:
        return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec);
    case COMMENT_NODE:
        return createComment(importedNode->nodeValue());
    case ELEMENT_NODE: {
        Element* oldElement = static_cast<Element*>(importedNode);
834
835
        // FIXME: The following check might be unnecessary. Is it possible that
        // oldElement has mismatched prefix/namespace?
836
        if (!hasValidNamespaceForElements(oldElement->tagQName())) {
837
838
839
840
            ec = NAMESPACE_ERR;
            return 0;
        }
        RefPtr<Element> newElement = createElement(oldElement->tagQName(), ec);
841
842
843
844
845
846
847
848
        if (ec)
            return 0;

        NamedNodeMap* attrs = oldElement->attributes(true);
        if (attrs) {
            unsigned length = attrs->length();
            for (unsigned i = 0; i < length; i++) {
                Attribute* attr = attrs->attributeItem(i);