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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
// Copyright 2017 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.
#ifndef CONTENT_COMMON_UNIQUE_NAME_HELPER_H_
#define CONTENT_COMMON_UNIQUE_NAME_HELPER_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
namespace content {
// Frame helper that manages the details of generating a quasi-stable unique
// name for the frame. The name is unique within a page, and is used for:
// - matching up session history items with recreated frames
// - layout test results
//
// Description of the current unique name format
// ---------------------------------------------
// Changing the format of unique name has a high cost, because it breaks
// backwards compatibility of session history (which stores unique names
// generated in the past on user's disk). The evolution of unique name in a
// mostly backwards-compatible way has resulted in the rather baroque format...
//
// uniqueName ::= <nullForMainFrame> | <assignedName> | <generatedName>
// Note: generatedName is used if assignedName is non-unique / conflicts with
// other frame's unique name.
//
// assignedName ::= value of iframe's name attribute
// or value assigned to window.name
// Note: The name must be assigned *before* the first real commit: afterwards,
// the unique name is immutable.
//
// generatedName ::= oldGeneratedName newUniqueSuffix?
// Note: newUniqueSuffix is only present if oldGeneratedName is not unique.
//
// oldGeneratedName ::= "<!--framePath //" ancestorChain
// "/<!--frame" childCount "-->-->"
// Note: oldGeneratedName is generated by the internal GenerateCandidate()
// method.
//
// childCount ::= current number of siblings
//
// ancestorChain ::= concatenated unique names of ancestor chain,
// terminated on the first ancestor (if any) starting with
// "<!--framePath"; each ancestor's unique name is
// separated by "/" character
// Note: Two examples are provided below, with each portion of the name from a
// distinct ancestor annotated.
//
// Example ancestor chain #1:
// "grandparent/parent"
// | #1 | #2 |
// Example ancestor chain #2:
// "<!--framePath //foo/bar/<!--frame42-->-->/blah/foobar"
// | #1 | #2 | #3 |
//
// newUniqueSuffix ::= "<!--framePosition" framePosition "/" retryNumber "-->"
//
// framePosition ::= "-" numberOfSiblingsBeforeChild
// [ framePosition-forParent? ]
//
// retryNumber ::= smallest non-negative integer resulting in unique name
class UniqueNameHelper {
public:
// Adapter class so UniqueNameHelper can be used with both RenderFrameImpl and
// ExplodedFrameState.
class FrameAdapter {
public:
FrameAdapter() {}
virtual ~FrameAdapter();
virtual bool IsMainFrame() const = 0;
virtual bool IsCandidateUnique(const std::string& name) const = 0;
// Returns the number of sibling frames of this frame. Note this should not
// include this frame in the count.
virtual int GetSiblingCount() const = 0;
virtual int GetChildCount() const = 0;
// Sets the reference point for iterations that walk up the frame tree.
enum class BeginPoint {
// This should be the default: it indicates the logical iteration
// operation began on this frame and the walking logic should retrieve the
// parent frame as normal.
kParentFrame,
// For implementing the pending child frame adapter, which delegates to
// its future parent's FrameAdapter. Walking up the tree should not skip
// this frame; instead it should treat this frame as the parent, since the
// logical iteration began with a pending child frame.
kThisFrame,
};
// Returns a vector of the strings representing the name of each frame in
// the chain from this frame to the root frame. |begin_point| indicates the
// reference point for starting the collection. |should_stop| is a
// boolean predicate that indicates when to stop collection of names.
virtual std::vector<base::StringPiece> CollectAncestorNames(
BeginPoint begin_point,
bool (*should_stop)(base::StringPiece)) const = 0;
// Returns a vector of ints representing the child index of each frame in
// the chain from this frame to the root.
virtual std::vector<int> GetFramePosition(BeginPoint begin_point) const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(FrameAdapter);
};
explicit UniqueNameHelper(FrameAdapter* frame);
~UniqueNameHelper();
// Returns the generated unique name.
const std::string& value() const { return unique_name_; }
// Used to propagate an already calculated unique name.
//
// TODO(lukasza): It would be nice to assert uniqueness of the propagated
// name here but:
// 1) uniqueness is currently violated by provisional/old frame pairs.
// 2) there is an unresolved race between 2 OOPIFs, that can result in a
// non-unique unique name: see https://crbug.com/558680#c14.
void set_propagated_name(const std::string& name) { unique_name_ = name; }
// Note: when creating a new child frame, the unique name needs to be
// calculated before the child frame is created. To avoid this chicken and
// egg problem, this method is designed to be called on the *parent* frame of
// the future new child frame and return the value the new child frame should
// use.
std::string GenerateNameForNewChildFrame(const std::string& name) const;
// Called after a browsing context name change to generate a new name. Note
// that this should not be called if the frame is no longer displaying the
// initial empty document, as unique name changes after that point will break
// history navigations. See https://crbug.com/607205.
void UpdateName(const std::string& name);
private:
FrameAdapter* const frame_;
std::string unique_name_;
DISALLOW_COPY_AND_ASSIGN(UniqueNameHelper);
};
} // namespace content
#endif // CONTENT_COMMON_UNIQUE_NAME_HELPER_H_
|