summaryrefslogtreecommitdiffstats
path: root/mandoline
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2015-07-23 11:08:18 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-23 18:08:54 +0000
commit4355c0052696928198a1f596a37f02078d6169e5 (patch)
tree4f279b738bb4ff1b7f9a29aeef35a02c4a2b9cf8 /mandoline
parent999e6d00258e17adb6034ce165a59c3288c2003d (diff)
downloadchromium_src-4355c0052696928198a1f596a37f02078d6169e5.zip
chromium_src-4355c0052696928198a1f596a37f02078d6169e5.tar.gz
chromium_src-4355c0052696928198a1f596a37f02078d6169e5.tar.bz2
Adds shared Frames to FrameTreeServer
Prior to this change the FrameTree was only aware of a Frame when the child called Embed on it (in other words it wanted the frame navigated). Not all frames are navigated though. For example, an iframe may be created with srcdoc and never navigated. It's still important to tell other clients in the frame tree about this node even though it hasn't bee navigated yet. With this change any time html_viewer creates a child frame it immediately tells the server about it by way of OnCreatedFrame. This creates a new Frame on the server side and notifies all other clients. It's important to note that from the server sides perspective this frame is special. It may not have a View (because of message pipe ordering there is no guarantee that the FrameTreeServer has been notified of the View yet). And the shared frame does not have a FrameTreeClient. Shared frames share the pipe of the parent. BUG=479172,490221 TEST=covered by tests Review URL: https://codereview.chromium.org/1251323004 Cr-Commit-Position: refs/heads/master@{#340113}
Diffstat (limited to 'mandoline')
-rw-r--r--mandoline/tab/frame.cc155
-rw-r--r--mandoline/tab/frame.h40
-rw-r--r--mandoline/tab/frame_tree.cc25
-rw-r--r--mandoline/tab/frame_tree.h12
-rw-r--r--mandoline/tab/public/interfaces/frame_tree.mojom15
5 files changed, 192 insertions, 55 deletions
diff --git a/mandoline/tab/frame.cc b/mandoline/tab/frame.cc
index e0be378..2c77552 100644
--- a/mandoline/tab/frame.cc
+++ b/mandoline/tab/frame.cc
@@ -28,9 +28,8 @@ const uint32_t kNoParentId = 0u;
FrameDataPtr FrameToFrameData(const Frame* frame) {
FrameDataPtr frame_data(FrameData::New());
- frame_data->frame_id = frame->view()->id();
- frame_data->parent_id =
- frame->parent() ? frame->parent()->view()->id() : kNoParentId;
+ frame_data->frame_id = frame->id();
+ frame_data->parent_id = frame->parent() ? frame->parent()->id() : kNoParentId;
frame_data->name = frame->name();
// TODO(sky): implement me.
frame_data->origin = std::string();
@@ -41,11 +40,13 @@ FrameDataPtr FrameToFrameData(const Frame* frame) {
Frame::Frame(FrameTree* tree,
View* view,
+ uint32_t id,
ViewOwnership view_ownership,
FrameTreeClient* frame_tree_client,
scoped_ptr<FrameUserData> user_data)
: tree_(tree),
- view_(view),
+ view_(nullptr),
+ id_(id),
parent_(nullptr),
view_ownership_(view_ownership),
user_data_(user_data.Pass()),
@@ -53,8 +54,8 @@ Frame::Frame(FrameTree* tree,
loading_(false),
progress_(0.f),
frame_tree_server_binding_(this) {
- view_->SetLocalProperty(kFrame, this);
- view_->AddObserver(this);
+ if (view)
+ SetView(view);
}
Frame::~Frame() {
@@ -64,10 +65,11 @@ Frame::~Frame() {
delete children_[0];
if (parent_)
parent_->Remove(this);
- if (view_)
+ if (view_) {
view_->ClearLocalProperty(kFrame);
- if (view_ownership_ == ViewOwnership::OWNS_VIEW)
- view_->Destroy();
+ if (view_ownership_ == ViewOwnership::OWNS_VIEW)
+ view_->Destroy();
+ }
}
void Frame::Init(Frame* parent) {
@@ -84,7 +86,8 @@ void Frame::Init(Frame* parent) {
// TODO(sky): error handling.
FrameTreeServerPtr frame_tree_server_ptr;
frame_tree_server_binding_.Bind(GetProxy(&frame_tree_server_ptr).Pass());
- frame_tree_client_->OnConnect(frame_tree_server_ptr.Pass(), array.Pass());
+ if (frame_tree_client_)
+ frame_tree_client_->OnConnect(frame_tree_server_ptr.Pass(), array.Pass());
}
// static
@@ -95,7 +98,7 @@ Frame* Frame::FindFirstFrameAncestor(View* view) {
}
const Frame* Frame::FindFrame(uint32_t id) const {
- if (id == view_->id())
+ if (id == id_)
return this;
for (const Frame* child : children_) {
@@ -131,6 +134,14 @@ double Frame::GatherProgress(int* frame_count) const {
return progress_;
}
+void Frame::SetView(mojo::View* view) {
+ DCHECK(!view_);
+ DCHECK_EQ(id_, view->id());
+ view_ = view;
+ view_->SetLocalProperty(kFrame, this);
+ view_->AddObserver(this);
+}
+
void Frame::BuildFrameTree(std::vector<const Frame*>* frames) const {
frames->push_back(this);
for (const Frame* frame : children_)
@@ -156,11 +167,56 @@ void Frame::Remove(Frame* node) {
tree_->root()->NotifyRemoved(this, node);
}
+void Frame::LoadingStartedImpl() {
+ DCHECK(!loading_);
+ loading_ = true;
+ progress_ = 0.f;
+ tree_->LoadingStateChanged();
+}
+
+void Frame::LoadingStoppedImpl() {
+ DCHECK(loading_);
+ loading_ = false;
+ tree_->LoadingStateChanged();
+}
+
+void Frame::ProgressChangedImpl(double progress) {
+ DCHECK(loading_);
+ progress_ = progress;
+ tree_->ProgressChanged();
+}
+
+void Frame::SetFrameNameImpl(const mojo::String& name) {
+ if (name_ == name)
+ return;
+
+ name_ = name;
+ tree_->FrameNameChanged(this);
+}
+
+Frame* Frame::FindTargetFrame(uint32_t frame_id) {
+ if (frame_id == id_)
+ return this; // Common case.
+
+ // TODO(sky): I need a way to sanity check frame_id here, but the connection
+ // id isn't known to us.
+
+ Frame* frame = FindFrame(frame_id);
+ if (frame->frame_tree_client_) {
+ // The frame has it's own client/server pair. It should make requests using
+ // the server it has rather than an ancestor.
+ DVLOG(1) << "ignore request for a frame that has its own client.";
+ return nullptr;
+ }
+
+ return frame;
+}
+
void Frame::NotifyAdded(const Frame* source, const Frame* added_node) {
if (added_node == this)
return;
- if (source != this)
+ if (source != this && frame_tree_client_)
frame_tree_client_->OnFrameAdded(FrameToFrameData(added_node));
for (Frame* child : children_)
@@ -171,22 +227,29 @@ void Frame::NotifyRemoved(const Frame* source, const Frame* removed_node) {
if (removed_node == this)
return;
- if (source != this)
- frame_tree_client_->OnFrameRemoved(removed_node->view_->id());
+ if (source != this && frame_tree_client_)
+ frame_tree_client_->OnFrameRemoved(removed_node->id());
for (Frame* child : children_)
child->NotifyRemoved(source, removed_node);
}
void Frame::NotifyFrameNameChanged(const Frame* source) {
- if (this != source) {
- frame_tree_client_->OnFrameNameChanged(source->view_->id(), source->name_);
- }
+ if (this != source && frame_tree_client_)
+ frame_tree_client_->OnFrameNameChanged(source->id(), source->name_);
for (Frame* child : children_)
child->NotifyFrameNameChanged(source);
}
+void Frame::OnTreeChanged(const TreeChangeParams& params) {
+ if (params.new_parent && this == tree_->root()) {
+ Frame* child_frame = FindFrame(params.target->id());
+ if (child_frame && !child_frame->view_)
+ child_frame->SetView(params.target);
+ }
+}
+
void Frame::OnViewDestroying(mojo::View* view) {
if (parent_)
parent_->Remove(this);
@@ -214,39 +277,53 @@ void Frame::PostMessageEventToFrame(uint32_t frame_id, MessageEventPtr event) {
NOTIMPLEMENTED();
}
-void Frame::NavigateFrame(uint32_t frame_id) {
- NOTIMPLEMENTED();
+void Frame::LoadingStarted(uint32_t frame_id) {
+ Frame* target_frame = FindTargetFrame(frame_id);
+ if (target_frame)
+ target_frame->LoadingStartedImpl();
}
-void Frame::ReloadFrame(uint32_t frame_id) {
- NOTIMPLEMENTED();
+void Frame::LoadingStopped(uint32_t frame_id) {
+ Frame* target_frame = FindTargetFrame(frame_id);
+ if (target_frame)
+ target_frame->LoadingStoppedImpl();
}
-void Frame::LoadingStarted() {
- DCHECK(!loading_);
- loading_ = true;
- progress_ = 0.f;
- tree_->LoadingStateChanged();
+void Frame::ProgressChanged(uint32_t frame_id, double progress) {
+ Frame* target_frame = FindTargetFrame(frame_id);
+ if (target_frame)
+ target_frame->ProgressChangedImpl(progress);
}
-void Frame::LoadingStopped() {
- DCHECK(loading_);
- loading_ = false;
- tree_->LoadingStateChanged();
+void Frame::SetFrameName(uint32_t frame_id, const mojo::String& name) {
+ Frame* target_frame = FindTargetFrame(frame_id);
+ if (target_frame)
+ target_frame->SetFrameNameImpl(name);
}
-void Frame::ProgressChanged(double progress) {
- DCHECK(loading_);
- progress_ = progress;
- tree_->ProgressChanged();
-}
+void Frame::OnCreatedFrame(uint32_t parent_id, uint32_t frame_id) {
+ // TODO(sky): I need a way to verify the id. Unfortunately the code here
+ // doesn't know the connection id of the embedder, so it's not possible to
+ // do it.
-void Frame::SetFrameName(const mojo::String& name) {
- if (name_ == name)
+ if (FindFrame(frame_id)) {
+ // TODO(sky): kill connection here?
+ DVLOG(1) << "OnCreatedLocalFrame supplied id of existing frame.";
+ return;
+ }
+
+ Frame* parent_frame = FindFrame(parent_id);
+ if (!parent_frame) {
+ DVLOG(1) << "OnCreatedLocalFrame supplied invalid parent_id.";
return;
+ }
- name_ = name;
- tree_->FrameNameChanged(this);
+ if (parent_frame != this && parent_frame->frame_tree_client_) {
+ DVLOG(1) << "OnCreatedLocalFrame supplied parent from another connection.";
+ return;
+ }
+
+ tree_->CreateSharedFrame(parent_frame, frame_id);
}
} // namespace mandoline
diff --git a/mandoline/tab/frame.h b/mandoline/tab/frame.h
index 57e7e46..5f516cb 100644
--- a/mandoline/tab/frame.h
+++ b/mandoline/tab/frame.h
@@ -27,10 +27,20 @@ enum class ViewOwnership {
// Frame represents an embedding in a frame. Frames own their children.
// Frames automatically delete themself if the View the frame is associated
// with is deleted.
+//
+// In general each Frame has a View. When a new Frame is created by a client
+// there may be a small amount of time where the View is not yet known to us
+// (separate pipes are used for the view and frame, resulting in undefined
+// message ordering). In this case the view is null and will be set once we
+// see the view (OnTreeChanged()).
+//
+// When the FrameTreeClient creates a new Frame there is no associated
+// FrameTreeClient for the child Frame.
class Frame : public mojo::ViewObserver, public FrameTreeServer {
public:
Frame(FrameTree* tree,
mojo::View* view,
+ uint32_t id,
ViewOwnership view_ownership,
FrameTreeClient* frame_tree_client,
scoped_ptr<FrameUserData> user_data);
@@ -52,6 +62,8 @@ class Frame : public mojo::ViewObserver, public FrameTreeServer {
mojo::View* view() { return view_; }
const mojo::View* view() const { return view_; }
+ uint32_t id() const { return id_; }
+
// Finds the descendant with the specified id.
Frame* FindFrame(uint32_t id) {
return const_cast<Frame*>(const_cast<const Frame*>(this)->FindFrame(id));
@@ -76,6 +88,8 @@ class Frame : public mojo::ViewObserver, public FrameTreeServer {
private:
friend class FrameTree;
+ void SetView(mojo::View* view);
+
// Adds this to |frames| and recurses through the children calling the
// same function.
void BuildFrameTree(std::vector<const Frame*>* frames) const;
@@ -83,31 +97,45 @@ class Frame : public mojo::ViewObserver, public FrameTreeServer {
void Add(Frame* node);
void Remove(Frame* node);
+ // The implementation of the various FrameTreeServer functions that take
+ // frame_id call into these.
+ void LoadingStartedImpl();
+ void LoadingStoppedImpl();
+ void ProgressChangedImpl(double progress);
+ void SetFrameNameImpl(const mojo::String& name);
+
+ // Returns the Frame whose id is |frame_id|. Returns nullptr if |frame_id| is
+ // not from the same connection as this.
+ Frame* FindTargetFrame(uint32_t frame_id);
+
// Notifies the client and all descendants as appropriate.
void NotifyAdded(const Frame* source, const Frame* added_node);
void NotifyRemoved(const Frame* source, const Frame* removed_node);
void NotifyFrameNameChanged(const Frame* source);
// mojo::ViewObserver:
+ void OnTreeChanged(const TreeChangeParams& params) override;
void OnViewDestroying(mojo::View* view) override;
// FrameTreeServer:
void PostMessageEventToFrame(uint32_t frame_id,
MessageEventPtr event) override;
- void NavigateFrame(uint32_t frame_id) override;
- void ReloadFrame(uint32_t frame_id) override;
- void LoadingStarted() override;
- void LoadingStopped() override;
- void ProgressChanged(double progress) override;
- void SetFrameName(const mojo::String& name) override;
+ void LoadingStarted(uint32_t frame_id) override;
+ void LoadingStopped(uint32_t frame_id) override;
+ void ProgressChanged(uint32_t frame_id, double progress) override;
+ void SetFrameName(uint32_t frame_id, const mojo::String& name) override;
+ void OnCreatedFrame(uint32_t parent_id, uint32_t frame_id) override;
FrameTree* const tree_;
+ // WARNING: this may be null. See class description for details.
mojo::View* view_;
+ const uint32_t id_;
Frame* parent_;
ViewOwnership view_ownership_;
std::vector<Frame*> children_;
scoped_ptr<FrameUserData> user_data_;
+ // WARNING: this may be null. See class description for details.
FrameTreeClient* frame_tree_client_;
bool loading_;
diff --git a/mandoline/tab/frame_tree.cc b/mandoline/tab/frame_tree.cc
index 4074ba1..a3387de 100644
--- a/mandoline/tab/frame_tree.cc
+++ b/mandoline/tab/frame_tree.cc
@@ -17,6 +17,7 @@ FrameTree::FrameTree(mojo::View* view,
delegate_(delegate),
root_(this,
view,
+ view->id(),
ViewOwnership::DOESNT_OWN_VIEW,
root_client,
user_data.Pass()),
@@ -31,10 +32,8 @@ Frame* FrameTree::CreateAndAddFrame(mojo::View* view,
Frame* parent,
FrameTreeClient* client,
scoped_ptr<FrameUserData> user_data) {
- Frame* frame =
- new Frame(this, view, ViewOwnership::OWNS_VIEW, client, user_data.Pass());
- frame->Init(parent);
- return frame;
+ return CreateAndAddFrameImpl(view, view->id(), parent, client,
+ user_data.Pass());
}
Frame* FrameTree::CreateOrReplaceFrame(Frame* frame,
@@ -57,6 +56,24 @@ Frame* FrameTree::CreateOrReplaceFrame(Frame* frame,
return CreateAndAddFrame(view, parent, frame_tree_client, user_data.Pass());
}
+void FrameTree::CreateSharedFrame(Frame* parent, uint32_t frame_id) {
+ mojo::View* frame_view = root_.view()->GetChildById(frame_id);
+ // |frame_view| may be null if the View hasn't been created yet. If this is
+ // the case the View will be connected to the Frame in Frame::OnTreeChanged.
+ CreateAndAddFrameImpl(frame_view, frame_id, parent, nullptr, nullptr);
+}
+
+Frame* FrameTree::CreateAndAddFrameImpl(mojo::View* view,
+ uint32_t frame_id,
+ Frame* parent,
+ FrameTreeClient* client,
+ scoped_ptr<FrameUserData> user_data) {
+ Frame* frame = new Frame(this, view, frame_id, ViewOwnership::OWNS_VIEW,
+ client, user_data.Pass());
+ frame->Init(parent);
+ return frame;
+}
+
void FrameTree::LoadingStateChanged() {
bool loading = root_.IsLoading();
if (delegate_)
diff --git a/mandoline/tab/frame_tree.h b/mandoline/tab/frame_tree.h
index eb8a4cd..4600fc8 100644
--- a/mandoline/tab/frame_tree.h
+++ b/mandoline/tab/frame_tree.h
@@ -44,9 +44,21 @@ class FrameTree {
FrameTreeClient* frame_tree_client,
scoped_ptr<FrameUserData> user_data);
+ // Creates a new Frame parented to |parent|. The Frame is considered shared in
+ // that it is sharing the FrameTreeClient/FrameTreeServer of |parent|. There
+ // may or may not be a View identified by |frame_id| yet. See Frame for
+ // details.
+ void CreateSharedFrame(Frame* parent, uint32_t frame_id);
+
private:
friend class Frame;
+ Frame* CreateAndAddFrameImpl(mojo::View* view,
+ uint32_t frame_id,
+ Frame* parent,
+ FrameTreeClient* client,
+ scoped_ptr<FrameUserData> user_data);
+
void LoadingStateChanged();
void ProgressChanged();
void FrameNameChanged(Frame* frame);
diff --git a/mandoline/tab/public/interfaces/frame_tree.mojom b/mandoline/tab/public/interfaces/frame_tree.mojom
index 6965cb8..a73415d 100644
--- a/mandoline/tab/public/interfaces/frame_tree.mojom
+++ b/mandoline/tab/public/interfaces/frame_tree.mojom
@@ -38,20 +38,23 @@ struct MessageEvent {
interface FrameTreeServer {
// TODO(sky): make these real.
PostMessageEventToFrame(uint32 frame_id, MessageEvent event);
- NavigateFrame(uint32 frame_id);
- ReloadFrame(uint32 frame_id);
// Notifies the server that a load has started or stopped in this frame.
// When loading is started, progress is reset to 0, but when loading is
// stopped progress may not have reached 1.0.
- LoadingStarted();
- LoadingStopped();
+ LoadingStarted(uint32 frame_id);
+ LoadingStopped(uint32 frame_id);
// Called when the progress for this frame changes. Will only be called while
// a load is in progress.
- ProgressChanged(double progress);
+ ProgressChanged(uint32 frame_id, double progress);
- SetFrameName(string? name);
+ SetFrameName(uint32 frame_id, string? name);
+
+ // Called when the client creates a new frame. |frame_id| corresponds to
+ // the id of the view hosting the frame, and |parent_id| the id of the
+ // parent.
+ OnCreatedFrame(uint32 parent_id, uint32 frame_id);
};
interface FrameTreeClient {