File: ChildFrameDisconnector.cpp

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (106 lines) | stat: -rw-r--r-- 3,394 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/dom/ChildFrameDisconnector.h"

#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "wtf/Assertions.h"

namespace blink {

#if ENABLE(ASSERT)
static unsigned checkConnectedSubframeCountIsConsistent(Node&);
#endif

void ChildFrameDisconnector::disconnect(DisconnectPolicy policy)
{
#if ENABLE(ASSERT)
    checkConnectedSubframeCountIsConsistent(root());
#endif

    if (!root().connectedSubframeCount())
        return;

    if (policy == RootAndDescendants) {
        collectFrameOwners(root());
    } else {
        for (Node* child = root().firstChild(); child; child = child->nextSibling())
            collectFrameOwners(*child);
    }

    disconnectCollectedFrameOwners();
}

void ChildFrameDisconnector::collectFrameOwners(Node& root)
{
    if (!root.connectedSubframeCount())
        return;

    if (root.isHTMLElement() && root.isFrameOwnerElement())
        m_frameOwners.append(&toHTMLFrameOwnerElement(root));

    for (Node* child = root.firstChild(); child; child = child->nextSibling())
        collectFrameOwners(*child);

    ElementShadow* shadow = root.isElementNode() ? toElement(root).shadow() : 0;
    if (shadow)
        collectFrameOwners(*shadow);
}

void ChildFrameDisconnector::disconnectCollectedFrameOwners()
{
    // Must disable frame loading in the subtree so an unload handler cannot
    // insert more frames and create loaded frames in detached subtrees.
    SubframeLoadingDisabler disabler(root());

    for (unsigned i = 0; i < m_frameOwners.size(); ++i) {
        HTMLFrameOwnerElement* owner = m_frameOwners[i].get();
        // Don't need to traverse up the tree for the first owner since no
        // script could have moved it.
        if (!i || root().containsIncludingShadowDOM(owner))
            owner->disconnectContentFrame();
    }
}

void ChildFrameDisconnector::collectFrameOwners(ElementShadow& shadow)
{
    for (ShadowRoot* root = shadow.youngestShadowRoot(); root; root = root->olderShadowRoot())
        collectFrameOwners(*root);
}

#if ENABLE(ASSERT)
static unsigned checkConnectedSubframeCountIsConsistent(Node& node)
{
    unsigned count = 0;

    if (node.isElementNode()) {
        if (node.isFrameOwnerElement() && toHTMLFrameOwnerElement(node).contentFrame())
            count++;

        if (ElementShadow* shadow = toElement(node).shadow()) {
            for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
                count += checkConnectedSubframeCountIsConsistent(*root);
        }
    }

    for (Node* child = node.firstChild(); child; child = child->nextSibling())
        count += checkConnectedSubframeCountIsConsistent(*child);

    // If we undercount there's possibly a security bug since we'd leave frames
    // in subtrees outside the document.
    ASSERT(node.connectedSubframeCount() >= count);

    // If we overcount it's safe, but not optimal because it means we'll traverse
    // through the document in ChildFrameDisconnector looking for frames that have
    // already been disconnected.
    ASSERT(node.connectedSubframeCount() == count);

    return count;
}
#endif

}