Chromium Code Reviews| Index: third_party/WebKit/Source/core/page/FrameTree.cpp |
| diff --git a/third_party/WebKit/Source/core/page/FrameTree.cpp b/third_party/WebKit/Source/core/page/FrameTree.cpp |
| index c218e8b0f95a0bb7b3a1206b5158dc434674bcae..42101c999ad6364732c0ee3cfd3c1e371a642c67 100644 |
| --- a/third_party/WebKit/Source/core/page/FrameTree.cpp |
| +++ b/third_party/WebKit/Source/core/page/FrameTree.cpp |
| @@ -27,6 +27,8 @@ |
| #include "core/frame/RemoteFrame.h" |
| #include "core/frame/RemoteFrameView.h" |
| #include "core/page/Page.h" |
| +#include "wtf/Assertions.h" |
| +#include "wtf/CryptographicallyRandomNumber.h" |
| #include "wtf/Vector.h" |
| #include "wtf/text/CString.h" |
| #include "wtf/text/StringBuilder.h" |
| @@ -54,15 +56,22 @@ FrameTree::~FrameTree() |
| void FrameTree::setName(const AtomicString& name, const AtomicString& fallbackName) |
| { |
| m_name = name; |
| - if (!parent()) { |
| - m_uniqueName = name; |
| - return; |
| - } |
| - // Remove our old frame name so it's not considered in calculateUniqueNameForChildFrame. |
| + // Remove our old frame name so it's not considered in calculateUniqueNameForChildFrame |
| + // and ensureUniquenessOfUniqueName calls below. |
| m_uniqueName = AtomicString(); |
| - m_uniqueName = parent()->tree().calculateUniqueNameForChildFrame(true, name, fallbackName); |
| + // Calculate a new unique name based on inputs. |
| + if (parent()) { |
| + setUniqueName( |
| + parent()->tree().calculateUniqueNameForChildFrame(true, name, fallbackName)); |
| + } else if (name.isEmpty()) { |
| + // Only main frame can have an empty unique name, so for main frames |
| + // emptiness guarantees uniquness. |
| + setUniqueName(name); |
| + } else { |
| + setUniqueName(ensureUniquenessOfUniqueName(name)); |
| + } |
| } |
| void FrameTree::setPrecalculatedName(const AtomicString& name, const AtomicString& uniqueName) |
| @@ -74,6 +83,12 @@ void FrameTree::setPrecalculatedName(const AtomicString& name, const AtomicStrin |
| } |
| m_name = name; |
| + |
| + // TODO(lukasza): We would like to assert uniqueness below (i.e. by calling |
| + // setUniqueName), 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 |uniqueName| - see https://crbug.com/558680#c14. |
| m_uniqueName = uniqueName; |
| } |
| @@ -125,6 +140,12 @@ Frame* FrameTree::lastChild() const |
| bool FrameTree::uniqueNameExists(const AtomicString& name) const |
| { |
| + // Before recalculating or checking unique name, we set m_uniqueName |
| + // to an empty string (so the soon-to-be-removed name does not count |
| + // as a collision). This means that uniqueNameExists would return |
| + // false positives when called with an empty |name|. |
| + ASSERT(!name.isEmpty()); |
| + |
| for (Frame* frame = top(); frame; frame = frame->tree().traverseNext()) { |
| if (frame->tree().uniqueName() == name) |
| return true; |
| @@ -183,7 +204,32 @@ AtomicString FrameTree::calculateUniqueNameForChildFrame( |
| uniqueName.appendNumber(childCount() - (existingChildFrame ? 1 : 0)); |
| uniqueName.appendLiteral("-->-->"); |
| - return uniqueName.toAtomicString(); |
| + return ensureUniquenessOfUniqueName(uniqueName.toAtomicString()); |
| +} |
| + |
| +AtomicString FrameTree::ensureUniquenessOfUniqueName(const AtomicString& potentiallyUniqueName) const |
| +{ |
| + if (!uniqueNameExists(potentiallyUniqueName)) |
| + return potentiallyUniqueName; |
| + |
| + StringBuilder uniqueNameBuilder; |
| + uniqueNameBuilder.append(potentiallyUniqueName); |
| + do { |
| + uniqueNameBuilder.append('-'); |
| + uniqueNameBuilder.appendNumber(cryptographicallyRandomNumber()); |
| + } while (uniqueNameExists(uniqueNameBuilder.toAtomicString())); |
|
dcheng
2016/05/12 05:31:18
So according to the spec, a valid name cannot star
|
| + return uniqueNameBuilder.toAtomicString(); |
| +} |
| + |
| +void FrameTree::setUniqueName(const AtomicString& uniqueName) |
| +{ |
| + if (parent()) { |
| + ASSERT(!uniqueName.isEmpty() && !uniqueNameExists(uniqueName)); |
| + } else { |
| + ASSERT(uniqueName.isEmpty() || !uniqueNameExists(uniqueName)); |
| + } |
| + |
| + m_uniqueName = uniqueName; |
| } |
| Frame* FrameTree::scopedChild(unsigned index) const |