Index: third_party/WebKit/Source/core/frame/RemoteFrameView.cpp |
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp b/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp |
index cef7f48927f9fb50bb9970c0a14370d4b670b5e9..e0a74f61849d18c4dbabe68aa971cca84a380455 100644 |
--- a/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp |
+++ b/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp |
@@ -16,13 +16,25 @@ |
namespace blink { |
RemoteFrameView::RemoteFrameView(RemoteFrame* remote_frame) |
- : remote_frame_(remote_frame) { |
+ : remote_frame_(remote_frame), |
+ parent_(nullptr), |
+ remote_frame_view_state_(kNotAttached) { |
DCHECK(remote_frame); |
} |
RemoteFrameView::~RemoteFrameView() {} |
void RemoteFrameView::SetParent(FrameView* parent) { |
+ if (parent) { |
+ SetFrameOrPluginState(kAttached); |
+ } |
+ if (!parent) { |
+ // Called from deferred ops just before Dispose. |
+ DCHECK(remote_frame_view_state_ == kAttached || |
+ (remote_frame_view_state_ == kDisposed && parent_)); |
+ SetFrameOrPluginState(kNotAttached); |
+ } |
+ |
if (parent == parent_) |
return; |
@@ -33,6 +45,57 @@ void RemoteFrameView::SetParent(FrameView* parent) { |
if (parent && parent->IsVisible()) |
SetParentVisible(true); |
FrameRectsChanged(); |
+ |
+ DCHECK(parent_ == ParentFrameView()); |
+} |
+ |
+FrameView* RemoteFrameView::Parent() const { |
+ if (remote_frame_view_state_ == kNotAttached || |
+ remote_frame_view_state_ == kAttached) |
+ DCHECK(ParentFrameView() == parent_); |
+ |
+ return parent_; |
+} |
+ |
+FrameView* RemoteFrameView::ParentFrameView() const { |
+ if (remote_frame_view_state_ != kAttached) |
+ return nullptr; |
+ |
+ Frame* parent_frame = remote_frame_->Tree().Parent(); |
+ if (parent_frame && parent_frame->IsLocalFrame()) |
+ return ToLocalFrame(parent_frame)->View(); |
+ |
+ return nullptr; |
+} |
+ |
+void RemoteFrameView::SetFrameOrPluginState(FrameOrPluginState state) { |
+ VLOG(1) << "SetFrameOrPluginState " << this << " " << remote_frame_view_state_ |
+ << "->" << state; |
+ if (VLOG_IS_ON(2)) |
+ base::debug::StackTrace(10).Print(); |
+ switch (state) { |
+ case kNotAttached: |
+ DCHECK(remote_frame_view_state_ == kAttached || |
+ remote_frame_view_state_ == kDisposed); |
+ break; |
+ case kAttached: |
+ DCHECK(remote_frame_view_state_ == kNotAttached || |
+ remote_frame_view_state_ == kDisposed); |
+ break; |
+ case kDeferred: |
+ DCHECK(remote_frame_view_state_ == kNotAttached || |
+ remote_frame_view_state_ == kAttached || |
+ remote_frame_view_state_ == kDisposed); |
+ break; |
+ case kDisposed: |
+ DCHECK(remote_frame_view_state_ == kAttached || |
+ remote_frame_view_state_ == kNotAttached || |
+ remote_frame_view_state_ == kDisposed); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ remote_frame_view_state_ = state; |
} |
RemoteFrameView* RemoteFrameView::Create(RemoteFrame* remote_frame) { |
@@ -80,6 +143,8 @@ void RemoteFrameView::UpdateRemoteViewportIntersection() { |
} |
void RemoteFrameView::Dispose() { |
+ SetFrameOrPluginState(kDisposed); |
+ |
HTMLFrameOwnerElement* owner_element = remote_frame_->DeprecatedLocalOwner(); |
// ownerElement can be null during frame swaps, because the |
// RemoteFrameView is disconnected before detachment. |
@@ -111,8 +176,19 @@ void RemoteFrameView::FrameRectsChanged() { |
// containing local frame root. The position of the local root within |
// any remote frames, if any, is accounted for by the embedder. |
IntRect new_rect = frame_rect_; |
- if (parent_) |
- new_rect = parent_->ConvertToRootFrame(parent_->ContentsToFrame(new_rect)); |
+ |
+ // TODO(joelhockey): I don't think it makes sense for this to be called |
+ // when it is not attached. |
+ // This gets called in kNotAttached state from |
+ // SetWidget : UpdateOnWidgetChange : UpdateGeometryInternal : |
+ // FrameRectsChanged however UpdateOnWidgetChange gets called before the |
+ // SetParent which makes this move to kAttached state. This is also called in |
+ // kDeferred state for SetParent(nullptr). |
+ DCHECK(remote_frame_view_state_ == kAttached || |
+ remote_frame_view_state_ == kNotAttached || |
+ remote_frame_view_state_ == kDisposed); |
+ if (FrameView* parent = ParentFrameView()) |
+ new_rect = parent->ConvertToRootFrame(parent->ContentsToFrame(new_rect)); |
remote_frame_->Client()->FrameRectsChanged(new_rect); |
} |
@@ -139,10 +215,20 @@ void RemoteFrameView::SetParentVisible(bool visible) { |
IntRect RemoteFrameView::ConvertFromRootFrame( |
const IntRect& rect_in_root_frame) const { |
- if (parent_) { |
- IntRect parent_rect = parent_->ConvertFromRootFrame(rect_in_root_frame); |
+ // TODO(joelhockey): I think this should only be called when in state |
+ // kAttached. However, it gets called in state kDisposed from |
+ // content_browsertest |
+ // --gtest_filter=SitePerProcessBrowserTest.SubframePendingAndBackToSameSiteInstance |
+ // Called in state kDeferred from |
+ // browser_tests |
+ // --gtest_filter=WebViewTests/WebViewTest.Shim_TestDisplayBlock/1 |
+ DCHECK(remote_frame_view_state_ == kAttached || |
+ remote_frame_view_state_ == kDeferred || |
+ remote_frame_view_state_ == kDisposed); |
+ if (FrameView* parent = ParentFrameView()) { |
+ IntRect parent_rect = parent->ConvertFromRootFrame(rect_in_root_frame); |
parent_rect.SetLocation( |
- parent_->ConvertSelfToChild(*this, parent_rect.Location())); |
+ parent->ConvertSelfToChild(*this, parent_rect.Location())); |
return parent_rect; |
} |
return rect_in_root_frame; |