summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2015-08-10 10:37:03 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-10 17:38:04 +0000
commit3033d1de7158836f0d51df83bc7a901d551b31e7 (patch)
tree19bc059f824c6878599aee622ee631ef216a23ff /components
parent197ed7e89063580eeb7cc5d5abf669e1f9cbf7d8 (diff)
downloadchromium_src-3033d1de7158836f0d51df83bc7a901d551b31e7.zip
chromium_src-3033d1de7158836f0d51df83bc7a901d551b31e7.tar.gz
chromium_src-3033d1de7158836f0d51df83bc7a901d551b31e7.tar.bz2
Hooks up cross frame navigation requests
BUG=479172,490221 TEST=covered by tests R=fsamuel@chromium.org TBR=jochen@chromium.org Review URL: https://codereview.chromium.org/1280743004 Cr-Commit-Position: refs/heads/master@{#342642}
Diffstat (limited to 'components')
-rw-r--r--components/html_viewer/BUILD.gn3
-rw-r--r--components/html_viewer/ax_provider_apptest.cc4
-rw-r--r--components/html_viewer/html_document_oopif.cc4
-rw-r--r--components/html_viewer/html_document_oopif.h1
-rw-r--r--components/html_viewer/html_frame.cc151
-rw-r--r--components/html_viewer/html_frame.h20
-rw-r--r--components/html_viewer/html_frame_apptest.cc112
-rw-r--r--components/html_viewer/html_frame_properties.cc10
-rw-r--r--components/html_viewer/html_frame_properties.h1
-rw-r--r--components/html_viewer/replicated_frame_state.cc51
-rw-r--r--components/html_viewer/replicated_frame_state.h42
-rw-r--r--components/html_viewer/web_layer_impl.cc12
-rw-r--r--components/html_viewer/web_layer_impl.h10
-rw-r--r--components/test/data/html_viewer/empty_page2.html2
14 files changed, 326 insertions, 97 deletions
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn
index ab49118..d192378 100644
--- a/components/html_viewer/BUILD.gn
+++ b/components/html_viewer/BUILD.gn
@@ -100,6 +100,8 @@ source_set("lib") {
"media_factory.h",
"mock_web_blob_registry_impl.cc",
"mock_web_blob_registry_impl.h",
+ "replicated_frame_state.cc",
+ "replicated_frame_state.h",
"test_html_viewer_impl.cc",
"test_html_viewer_impl.h",
"touch_handler.cc",
@@ -308,6 +310,7 @@ mojo_native_application("apptests") {
"//components/html_viewer/public/interfaces",
"//components/view_manager/public/cpp/tests:test_support",
"//mandoline/tab",
+ "//mandoline/tab:test_support",
"//mandoline/tab/public/interfaces",
"//mojo/application/public/cpp:test_support",
"//net:test_support",
diff --git a/components/html_viewer/ax_provider_apptest.cc b/components/html_viewer/ax_provider_apptest.cc
index dbc6d15..ecf9eb9 100644
--- a/components/html_viewer/ax_provider_apptest.cc
+++ b/components/html_viewer/ax_provider_apptest.cc
@@ -55,8 +55,8 @@ class TestFrameTreeServer : public mandoline::FrameTreeServer {
uint32_t frame_id,
mojo::Map<mojo::String, mojo::Array<uint8_t>>
client_properties) override {}
- void RequestNavigate(uint32_t frame_id,
- mandoline::NavigationTarget target,
+ void RequestNavigate(mandoline::NavigationTargetType target_type,
+ uint32_t target_frame_id,
mojo::URLRequestPtr request) override {}
void DidNavigateLocally(uint32_t frame_id, const mojo::String& url) override {
}
diff --git a/components/html_viewer/html_document_oopif.cc b/components/html_viewer/html_document_oopif.cc
index abe5392..37b7471 100644
--- a/components/html_viewer/html_document_oopif.cc
+++ b/components/html_viewer/html_document_oopif.cc
@@ -168,6 +168,10 @@ void HTMLDocumentOOPIF::OnEmbed(View* root) {
LoadIfNecessary();
}
+void HTMLDocumentOOPIF::OnUnembed() {
+ frame_->OnViewUnembed();
+}
+
void HTMLDocumentOOPIF::OnViewManagerDestroyed(
mojo::ViewManager* view_manager) {
delete this;
diff --git a/components/html_viewer/html_document_oopif.h b/components/html_viewer/html_document_oopif.h
index 719d89a..c129d7f 100644
--- a/components/html_viewer/html_document_oopif.h
+++ b/components/html_viewer/html_document_oopif.h
@@ -93,6 +93,7 @@ class HTMLDocumentOOPIF
// ViewManagerDelegate:
void OnEmbed(mojo::View* root) override;
+ void OnUnembed() override;
void OnViewManagerDestroyed(mojo::ViewManager* view_manager) override;
// ViewObserver:
diff --git a/components/html_viewer/html_frame.cc b/components/html_viewer/html_frame.cc
index af7ed288..9a166a9 100644
--- a/components/html_viewer/html_frame.cc
+++ b/components/html_viewer/html_frame.cc
@@ -118,18 +118,18 @@ struct TypeConverter<TextInputType, blink::WebTextInputType> {
namespace html_viewer {
namespace {
-mandoline::NavigationTarget WebNavigationPolicyToNavigationTarget(
+mandoline::NavigationTargetType WebNavigationPolicyToNavigationTarget(
blink::WebNavigationPolicy policy) {
switch (policy) {
case blink::WebNavigationPolicyCurrentTab:
- return mandoline::NAVIGATION_TARGET_SOURCE_NODE;
+ return mandoline::NAVIGATION_TARGET_TYPE_EXISTING_FRAME;
case blink::WebNavigationPolicyNewBackgroundTab:
case blink::WebNavigationPolicyNewForegroundTab:
case blink::WebNavigationPolicyNewWindow:
case blink::WebNavigationPolicyNewPopup:
- return mandoline::NAVIGATION_TARGET_NEW_NODE;
+ return mandoline::NAVIGATION_TARGET_TYPE_NEW_FRAME;
default:
- return mandoline::NAVIGATION_TARGET_DEFAULT;
+ return mandoline::NAVIGATION_TARGET_TYPE_NO_PREFERENCE;
}
}
@@ -170,8 +170,8 @@ HTMLFrame::HTMLFrame(const HTMLFrame::CreateParams& params)
id_(params.id),
web_frame_(nullptr),
web_widget_(nullptr),
- scope_(blink::WebTreeScopeType::Document),
delegate_(nullptr),
+ owned_view_(nullptr),
weak_factory_(this) {
if (parent_)
parent_->children_.push_back(this);
@@ -183,15 +183,7 @@ void HTMLFrame::Init(
if (local_view && local_view->id() == id_)
SetView(local_view);
- // Ignore return value and assume Document scope if scope isn't known.
- FrameTreeScopeFromClientProperty(
- GetValueFromClientProperties(kPropertyFrameTreeScope, properties),
- &scope_);
-
- blink::WebSandboxFlags sandbox_flags = blink::WebSandboxFlags::None;
- FrameSandboxFlagsFromClientProperty(
- GetValueFromClientProperties(kPropertyFrameSandboxFlags, properties),
- &sandbox_flags);
+ SetReplicatedFrameStateFromClientProperties(properties, &state_);
if (!parent_) {
CreateRootWebWidget();
@@ -201,7 +193,7 @@ void HTMLFrame::Init(
// . Set as main frame on WebView.
// . Swap to remote (if not local).
blink::WebLocalFrame* local_web_frame =
- blink::WebLocalFrame::create(scope_, this);
+ blink::WebLocalFrame::create(state_.tree_scope, this);
// We need to set the main frame before creating children so that state is
// properly set up in blink.
web_view()->setMainFrame(local_web_frame);
@@ -214,7 +206,7 @@ void HTMLFrame::Init(
web_view()->setDeviceScaleFactor(global_state()->device_pixel_ratio());
if (id_ != local_view->id()) {
blink::WebRemoteFrame* remote_web_frame =
- blink::WebRemoteFrame::create(scope_, this);
+ blink::WebRemoteFrame::create(state_.tree_scope, this);
local_web_frame->swap(remote_web_frame);
web_frame_ = remote_web_frame;
}
@@ -225,15 +217,12 @@ void HTMLFrame::Init(
previous_sibling ? previous_sibling->web_frame() : nullptr;
DCHECK(!parent_->IsLocal());
web_frame_ = parent_->web_frame()->toWebRemoteFrame()->createLocalChild(
- scope_, FrameNameFromClientProperty(GetValueFromClientProperties(
- kPropertyFrameName, properties)),
- sandbox_flags, this, previous_web_frame);
+ state_.tree_scope, state_.name, state_.sandbox_flags, this,
+ previous_web_frame);
CreateLocalRootWebWidget(web_frame_->toWebLocalFrame());
} else if (!parent_->IsLocal()) {
web_frame_ = parent_->web_frame()->toWebRemoteFrame()->createRemoteChild(
- scope_, FrameNameFromClientProperty(GetValueFromClientProperties(
- kPropertyFrameName, properties)),
- sandbox_flags, this);
+ state_.tree_scope, state_.name, state_.sandbox_flags, this);
} else {
// This is hit if we're asked to create a child frame of a local parent.
// This should never happen (if we create a local child we don't call
@@ -245,14 +234,31 @@ void HTMLFrame::Init(
if (!IsLocal()) {
blink::WebRemoteFrame* remote_web_frame = web_frame_->toWebRemoteFrame();
if (remote_web_frame) {
- remote_web_frame->setReplicatedOrigin(FrameOriginFromClientProperty(
- GetValueFromClientProperties(kPropertyFrameOrigin, properties)));
- remote_web_frame->setReplicatedName(FrameNameFromClientProperty(
- GetValueFromClientProperties(kPropertyFrameName, properties)));
+ remote_web_frame->setReplicatedOrigin(state_.origin);
+ remote_web_frame->setReplicatedName(state_.name);
}
}
}
+void HTMLFrame::OnViewUnembed() {
+ // The view we're associated with is being unembedded (the view on the server
+ // side still exists, but we're no longer responsible for rendering to it).
+ // If we're local, we need to swap the frame to remote, unless we're at the
+ // top of the hierarchy, in which case someone else is going to render the
+ // tree.
+ if (!IsLocal() || frame_tree_manager_->local_root_ == this)
+ return;
+
+ // TODO(sky): this may need to reset flags, such as origin.
+ SwapToRemote();
+
+ // TODO(sky): this needs to be part of SwapToRemote().
+ if (view_) {
+ view_->RemoveObserver(this);
+ view_ = nullptr;
+ }
+}
+
void HTMLFrame::Close() {
if (web_widget_) {
// Closing the root widget (WebView) implicitly detaches. For children
@@ -336,11 +342,11 @@ void HTMLFrame::SetValueFromClientProperty(const std::string& name,
// Only the name and origin dynamically change.
if (name == kPropertyFrameOrigin) {
- web_frame_->toWebRemoteFrame()->setReplicatedOrigin(
- FrameOriginFromClientProperty(new_data));
+ state_.origin = FrameOriginFromClientProperty(new_data);
+ web_frame_->toWebRemoteFrame()->setReplicatedOrigin(state_.origin);
} else if (name == kPropertyFrameName) {
- web_frame_->toWebRemoteFrame()->setReplicatedName(
- FrameNameFromClientProperty(new_data));
+ state_.name = FrameNameFromClientProperty(new_data);
+ web_frame_->toWebRemoteFrame()->setReplicatedName(state_.name);
}
}
@@ -359,6 +365,17 @@ mojo::ApplicationImpl* HTMLFrame::GetLocalRootApp() {
return GetLocalRoot()->delegate_->GetApp();
}
+mandoline::FrameTreeServer* HTMLFrame::GetFrameTreeServer() {
+ // Prefer the local root.
+ HTMLFrame* local_root = GetLocalRoot();
+ if (local_root)
+ return local_root->server_.get();
+
+ // No local root. This means we're a remote frame with no local frame
+ // ancestors. Use the local frame from the FrameTreeServer.
+ return frame_tree_manager_->local_root_->server_.get();
+}
+
void HTMLFrame::SetView(mojo::View* view) {
// TODO(sky): figure out way to cleanup view. In particular there may already
// be a view. This happens if we go from local->remote->local.
@@ -419,30 +436,23 @@ void HTMLFrame::UpdateWebViewSizeFromViewSize() {
web_layer_tree_view_impl_->setViewportSize(size_in_pixels);
}
-void HTMLFrame::SwapToRemote(const blink::WebURLRequest& request) {
- CHECK(IsLocal());
- mojo::URLRequestPtr url_request = mojo::URLRequest::From(request);
- view_->EmbedAllowingReembed(url_request.Pass());
-
- // TODO(sky): I tried swapping the frame types here, but that resulted in
- // the view never getting sized. Figure out why.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&HTMLFrame::FinishSwapToRemote, weak_factory_.GetWeakPtr()));
-}
-
-void HTMLFrame::FinishSwapToRemote() {
+void HTMLFrame::SwapToRemote() {
if (web_frame_->isWebRemoteFrame())
return; // We already did the swap.
blink::WebRemoteFrame* remote_frame =
- blink::WebRemoteFrame::create(scope_, this);
+ blink::WebRemoteFrame::create(state_.tree_scope, this);
remote_frame->initializeFromFrame(web_frame_->toWebLocalFrame());
// swap() ends up calling us back and we then close the frame, which deletes
// it.
web_frame_->swap(remote_frame);
- web_layer_.reset(new WebLayerImpl(this));
+ // TODO(sky): this isn't quite right, but WebLayerImpl is temporary.
+ if (owned_view_)
+ web_layer_.reset(new WebLayerImpl(owned_view_));
remote_frame->setRemoteWebLayer(web_layer_.get());
+ remote_frame->setReplicatedName(state_.name);
+ remote_frame->setReplicatedOrigin(state_.origin);
+ remote_frame->setReplicatedSandboxFlags(state_.sandbox_flags);
web_frame_ = remote_frame;
}
@@ -453,20 +463,16 @@ void HTMLFrame::SwapToLocal(
// It doesn't make sense for the root to swap to local.
CHECK(parent_);
SetView(view);
- blink::WebSandboxFlags sandbox_flags = blink::WebSandboxFlags::None;
- FrameSandboxFlagsFromClientProperty(
- GetValueFromClientProperties(kPropertyFrameSandboxFlags, properties),
- &sandbox_flags);
+ SetReplicatedFrameStateFromClientProperties(properties, &state_);
blink::WebLocalFrame* local_web_frame =
- blink::WebLocalFrame::create(blink::WebTreeScopeType::Document, this);
+ blink::WebLocalFrame::create(state_.tree_scope, this);
local_web_frame->initializeToReplaceRemoteFrame(
- web_frame_->toWebRemoteFrame(),
- FrameNameFromClientProperty(
- GetValueFromClientProperties(kPropertyFrameName, properties)),
- sandbox_flags);
+ web_frame_->toWebRemoteFrame(), state_.name, state_.sandbox_flags);
// The swap() ends up calling to frameDetached() and deleting the old.
web_frame_->swap(local_web_frame);
web_frame_ = local_web_frame;
+
+ web_layer_.reset();
}
HTMLFrame* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame* web_frame) {
@@ -657,18 +663,13 @@ blink::WebFrame* HTMLFrame::createChildFrame(
// Create the view that will house the frame now. We embed once we know the
// url (see decidePolicyForNavigation()).
mojo::View* child_view = view_->view_manager()->CreateView();
+ ReplicatedFrameState child_state;
+ child_state.name = frame_name;
+ child_state.tree_scope = scope;
+ child_state.sandbox_flags = sandbox_flags;
mojo::Map<mojo::String, mojo::Array<uint8_t>> client_properties;
client_properties.mark_non_null();
- AddToClientPropertiesIfValid(kPropertyFrameName,
- FrameNameToClientProperty(frame_name).Pass(),
- &client_properties);
- AddToClientPropertiesIfValid(kPropertyFrameTreeScope,
- FrameTreeScopeToClientProperty(scope).Pass(),
- &client_properties);
- AddToClientPropertiesIfValid(
- kPropertyFrameSandboxFlags,
- FrameSandboxFlagsToClientProperty(sandbox_flags).Pass(),
- &client_properties);
+ ClientPropertiesFromReplicatedFrameState(child_state, &client_properties);
child_view->SetVisible(true);
view_->AddChild(child_view);
@@ -678,9 +679,10 @@ blink::WebFrame* HTMLFrame::createChildFrame(
HTMLFrame::CreateParams params(frame_tree_manager_, this, child_view->id());
HTMLFrame* child_frame = new HTMLFrame(params);
- child_frame->scope_ = scope;
+ child_frame->state_ = child_state;
child_frame->SetView(child_view);
+ child_frame->owned_view_ = child_view;
blink::WebLocalFrame* child_web_frame =
blink::WebLocalFrame::create(scope, child_frame);
@@ -711,7 +713,13 @@ blink::WebNavigationPolicy HTMLFrame::decidePolicyForNavigation(
if (parent_ && parent_->IsLocal() && GetLocalRoot() != this) {
// TODO(sky): this may be too early. I might want to wait to see if an embed
// actually happens, and swap then.
- SwapToRemote(info.urlRequest);
+ mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
+ view_->EmbedAllowingReembed(url_request.Pass());
+ // TODO(sky): I tried swapping the frame types here, but that resulted in
+ // the view never getting sized. Figure out why.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&HTMLFrame::SwapToRemote, weak_factory_.GetWeakPtr()));
return blink::WebNavigationPolicyIgnore;
}
@@ -725,7 +733,7 @@ blink::WebNavigationPolicy HTMLFrame::decidePolicyForNavigation(
mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
GetLocalRoot()->server_->RequestNavigate(
- id(), WebNavigationPolicyToNavigationTarget(info.defaultPolicy),
+ WebNavigationPolicyToNavigationTarget(info.defaultPolicy), id_,
url_request.Pass());
return blink::WebNavigationPolicyIgnore;
@@ -775,6 +783,7 @@ void HTMLFrame::didChangeLoadProgress(double load_progress) {
void HTMLFrame::didChangeName(blink::WebLocalFrame* frame,
const blink::WebString& name) {
+ state_.name = name;
GetLocalRoot()->server_->SetClientProperty(id_, kPropertyFrameName,
FrameNameToClientProperty(name));
}
@@ -783,6 +792,7 @@ void HTMLFrame::didCommitProvisionalLoad(
blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type) {
+ state_.origin = FrameOrigin(frame);
GetLocalRoot()->server_->SetClientProperty(
id_, kPropertyFrameOrigin, FrameOriginToClientProperty(frame));
}
@@ -838,7 +848,12 @@ void HTMLFrame::initializeChildFrame(const blink::WebRect& frame_rect,
void HTMLFrame::navigate(const blink::WebURLRequest& request,
bool should_replace_current_entry) {
- NOTIMPLEMENTED();
+ // TODO: support |should_replace_current_entry|.
+ NOTIMPLEMENTED(); // for |should_replace_current_entry
+ mojo::URLRequestPtr url_request = mojo::URLRequest::From(request);
+ GetFrameTreeServer()->RequestNavigate(
+ mandoline::NAVIGATION_TARGET_TYPE_EXISTING_FRAME, id_,
+ url_request.Pass());
}
void HTMLFrame::reload(bool ignore_cache, bool is_client_redirect) {
diff --git a/components/html_viewer/html_frame.h b/components/html_viewer/html_frame.h
index b875aad..902ff5c 100644
--- a/components/html_viewer/html_frame.h
+++ b/components/html_viewer/html_frame.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "components/html_viewer/html_frame_tree_manager.h"
+#include "components/html_viewer/replicated_frame_state.h"
#include "components/view_manager/public/cpp/view_observer.h"
#include "mandoline/tab/public/interfaces/frame_tree.mojom.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
@@ -73,6 +74,10 @@ class HTMLFrame : public blink::WebFrameClient,
void Init(mojo::View* local_view,
const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties);
+ // Called when another app is embedded in the View this Frame is associated
+ // with.
+ void OnViewUnembed();
+
// Closes and deletes this Frame.
void Close();
@@ -132,6 +137,9 @@ class HTMLFrame : public blink::WebFrameClient,
// connection.
HTMLFrame* GetLocalRoot();
+ // Gets the FrameTreeServer to use for this frame.
+ mandoline::FrameTreeServer* GetFrameTreeServer();
+
// Returns the ApplicationImpl from the local root's delegate.
mojo::ApplicationImpl* GetLocalRootApp();
@@ -151,10 +159,7 @@ class HTMLFrame : public blink::WebFrameClient,
// Swaps this frame from a local frame to remote frame. |request| is the url
// to load in the frame.
- void SwapToRemote(const blink::WebURLRequest& request);
-
- // See comment in SwapToRemote() for details on this.
- void FinishSwapToRemote();
+ void SwapToRemote();
// Swaps this frame from a remote frame to a local frame.
void SwapToLocal(
@@ -270,8 +275,6 @@ class HTMLFrame : public blink::WebFrameClient,
scoped_ptr<WebLayerTreeViewImpl> web_layer_tree_view_impl_;
scoped_ptr<TouchHandler> touch_handler_;
- blink::WebTreeScopeType scope_;
-
scoped_ptr<WebLayerImpl> web_layer_;
HTMLFrameDelegate* delegate_;
@@ -279,6 +282,11 @@ class HTMLFrame : public blink::WebFrameClient,
frame_tree_client_binding_;
mandoline::FrameTreeServerPtr server_;
+ ReplicatedFrameState state_;
+
+ // Set to non-null for frames that are created locally.
+ mojo::View* owned_view_;
+
blink::WebTextInputInfo text_input_info_;
base::WeakPtrFactory<HTMLFrame> weak_factory_;
diff --git a/components/html_viewer/html_frame_apptest.cc b/components/html_viewer/html_frame_apptest.cc
index 7d5fce1..c98053e 100644
--- a/components/html_viewer/html_frame_apptest.cc
+++ b/components/html_viewer/html_frame_apptest.cc
@@ -17,6 +17,7 @@
#include "mandoline/tab/frame_connection.h"
#include "mandoline/tab/frame_tree.h"
#include "mandoline/tab/public/interfaces/frame_tree.mojom.h"
+#include "mandoline/tab/test_frame_tree_delegate.h"
#include "mojo/application/public/cpp/application_impl.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom.h"
@@ -87,11 +88,11 @@ class HTMLFrameTest : public ViewManagerTestBase {
// script) a frame showing the same empty page.
Frame* LoadEmptyPageAndCreateFrame() {
View* embed_view = window_manager()->CreateView();
- FrameConnection* root_connection =
- InitFrameTree(embed_view, "http://127.0.0.1:%u/files/empty_page2.html");
+ FrameConnection* root_connection = InitFrameTree(
+ embed_view, nullptr, "http://127.0.0.1:%u/files/empty_page2.html");
const std::string frame_text =
GetFrameText(root_connection->application_connection());
- if (frame_text != "child") {
+ if (frame_text != "child2") {
ADD_FAILURE() << "unexpected text " << frame_text;
return nullptr;
}
@@ -133,14 +134,16 @@ class HTMLFrameTest : public ViewManagerTestBase {
return request.Pass();
}
- FrameConnection* InitFrameTree(View* view, const std::string& url_string) {
+ FrameConnection* InitFrameTree(View* view,
+ mandoline::FrameTreeDelegate* delegate,
+ const std::string& url_string) {
scoped_ptr<FrameConnection> frame_connection(new FrameConnection);
FrameConnection* result = frame_connection.get();
ViewManagerClientPtr view_manager_client;
frame_connection->Init(application_impl(), BuildRequestForURL(url_string),
&view_manager_client);
FrameTreeClient* frame_tree_client = frame_connection->frame_tree_client();
- frame_tree_.reset(new FrameTree(view, nullptr, frame_tree_client,
+ frame_tree_.reset(new FrameTree(view, delegate, frame_tree_client,
frame_connection.Pass()));
view->Embed(view_manager_client.Pass());
return result;
@@ -204,8 +207,9 @@ TEST_F(HTMLFrameTest, PageWithSingleFrame) {
View* embed_view = window_manager()->CreateView();
- FrameConnection* root_connection = InitFrameTree(
- embed_view, "http://127.0.0.1:%u/files/page_with_single_frame.html");
+ FrameConnection* root_connection =
+ InitFrameTree(embed_view, nullptr,
+ "http://127.0.0.1:%u/files/page_with_single_frame.html");
ASSERT_EQ("Page with single frame",
GetFrameText(root_connection->application_connection()));
@@ -227,6 +231,100 @@ TEST_F(HTMLFrameTest, PageWithSingleFrame) {
->application_connection()));
}
+// FrameTreeDelegate that expects one call to RequestNavigate() with a target
+// type of NAVIGATION_TARGET_TYPE_EXISTING_FRAME. The navigation is allowed in
+// the target node.
+class ExistingFrameNavigationDelegate
+ : public mandoline::TestFrameTreeDelegate {
+ public:
+ explicit ExistingFrameNavigationDelegate(mojo::ApplicationImpl* app)
+ : app_(app), frame_tree_(nullptr), got_navigate_(false) {}
+ ~ExistingFrameNavigationDelegate() override {}
+
+ void set_frame_tree(FrameTree* frame_tree) { frame_tree_ = frame_tree; }
+
+ bool WaitForNavigate() {
+ if (got_navigate_)
+ return true;
+
+ return ViewManagerTestBase::DoRunLoopWithTimeout();
+ }
+
+ // TestFrameTreeDelegate:
+ void RequestNavigate(Frame* source,
+ mandoline::NavigationTargetType target_type,
+ Frame* target_frame,
+ mojo::URLRequestPtr request) override {
+ EXPECT_FALSE(got_navigate_);
+ got_navigate_ = true;
+
+ EXPECT_EQ(mandoline::NAVIGATION_TARGET_TYPE_EXISTING_FRAME, target_type);
+ ASSERT_TRUE(target_frame);
+
+ scoped_ptr<FrameConnection> frame_connection(new FrameConnection);
+ mojo::ViewManagerClientPtr view_manager_client;
+ frame_connection->Init(app_, request.Pass(), &view_manager_client);
+ target_frame->view()->Embed(view_manager_client.Pass());
+ FrameTreeClient* frame_tree_client = frame_connection->frame_tree_client();
+ frame_tree_->CreateOrReplaceFrame(target_frame, target_frame->view(),
+ frame_tree_client,
+ frame_connection.Pass());
+
+ ignore_result(ViewManagerTestBase::QuitRunLoop());
+ }
+
+ private:
+ mojo::ApplicationImpl* app_;
+ FrameTree* frame_tree_;
+ bool got_navigate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExistingFrameNavigationDelegate);
+};
+
+// Creates two frames. The parent navigates the child frame by way of changing
+// the location of the child frame.
+TEST_F(HTMLFrameTest, ChangeLocationOfChildFrame) {
+ if (!EnableOOPIFs())
+ return;
+
+ View* embed_view = window_manager()->CreateView();
+
+ ExistingFrameNavigationDelegate frame_tree_delegate(application_impl());
+
+ InitFrameTree(embed_view, &frame_tree_delegate,
+ "http://127.0.0.1:%u/files/page_with_single_frame.html");
+ frame_tree_delegate.set_frame_tree(frame_tree_.get());
+
+ // page_with_single_frame contains a child frame. The child frame should
+ // create a new View and Frame.
+ if (frame_tree_->root()->children().empty() ||
+ !frame_tree_->root()->children().back()->user_data()) {
+ ASSERT_TRUE(WaitForEmbedForDescendant());
+ }
+
+ ASSERT_EQ(
+ "child",
+ GetFrameText(static_cast<FrameConnection*>(
+ frame_tree_->root()->children().back()->user_data())
+ ->application_connection()));
+
+ // Change the location and wait for the navigation to occur.
+ const char kNavigateFrame[] =
+ "window.frames[0].location = "
+ "'http://127.0.0.1:%u/files/empty_page2.html'";
+ ExecuteScript(ApplicationConnectionForFrame(frame_tree_->root()),
+ AddPortToString(kNavigateFrame));
+ ASSERT_TRUE(frame_tree_delegate.WaitForNavigate());
+
+ // The navigation should have changed the text of the frame.
+ ASSERT_EQ(1u, frame_tree_->root()->children().size());
+ Frame* child_frame = frame_tree_->root()->children()[0];
+ ASSERT_TRUE(child_frame->user_data());
+ ASSERT_EQ("child2",
+ GetFrameText(static_cast<FrameConnection*>(child_frame->user_data())
+ ->application_connection()));
+}
+
TEST_F(HTMLFrameTest, DynamicallyAddFrameAndVerifyParent) {
if (!EnableOOPIFs())
return;
diff --git a/components/html_viewer/html_frame_properties.cc b/components/html_viewer/html_frame_properties.cc
index e55a08b..9d6ac92 100644
--- a/components/html_viewer/html_frame_properties.cc
+++ b/components/html_viewer/html_frame_properties.cc
@@ -91,13 +91,17 @@ bool FrameSandboxFlagsFromClientProperty(const mojo::Array<uint8_t>& new_data,
return true;
}
-mojo::Array<uint8_t> FrameOriginToClientProperty(blink::WebFrame* frame) {
+url::Origin FrameOrigin(blink::WebFrame* frame) {
std::string scheme = frame->document().securityOrigin().protocol().utf8();
if (!url::IsStandard(scheme.c_str(),
url::Component(0, static_cast<int>(scheme.length())))) {
- return mojo::Array<uint8_t>();
+ return url::Origin();
}
- const url::Origin origin = frame->document().securityOrigin();
+ return frame->document().securityOrigin();
+}
+
+mojo::Array<uint8_t> FrameOriginToClientProperty(blink::WebFrame* frame) {
+ const url::Origin origin = FrameOrigin(frame);
base::Pickle pickle;
pickle.WriteBool(origin.unique());
pickle.WriteString(origin.scheme());
diff --git a/components/html_viewer/html_frame_properties.h b/components/html_viewer/html_frame_properties.h
index cc62a37..8944d46 100644
--- a/components/html_viewer/html_frame_properties.h
+++ b/components/html_viewer/html_frame_properties.h
@@ -43,6 +43,7 @@ mojo::Array<uint8_t> FrameSandboxFlagsToClientProperty(
bool FrameSandboxFlagsFromClientProperty(const mojo::Array<uint8_t>& new_data,
blink::WebSandboxFlags* flags);
+url::Origin FrameOrigin(blink::WebFrame* frame);
mojo::Array<uint8_t> FrameOriginToClientProperty(blink::WebFrame* frame);
url::Origin FrameOriginFromClientProperty(const mojo::Array<uint8_t>& data);
diff --git a/components/html_viewer/replicated_frame_state.cc b/components/html_viewer/replicated_frame_state.cc
new file mode 100644
index 0000000..c514ad2
--- /dev/null
+++ b/components/html_viewer/replicated_frame_state.cc
@@ -0,0 +1,51 @@
+// Copyright 2015 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 "components/html_viewer/replicated_frame_state.h"
+
+#include "components/html_viewer/html_frame_properties.h"
+
+namespace html_viewer {
+
+ReplicatedFrameState::ReplicatedFrameState()
+ : sandbox_flags(blink::WebSandboxFlags::None),
+ tree_scope(blink::WebTreeScopeType::Document) {}
+
+ReplicatedFrameState::~ReplicatedFrameState() {}
+
+void SetReplicatedFrameStateFromClientProperties(
+ const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties,
+ ReplicatedFrameState* state) {
+ state->name = FrameNameFromClientProperty(
+ GetValueFromClientProperties(kPropertyFrameName, properties));
+ state->origin = FrameOriginFromClientProperty(
+ GetValueFromClientProperties(kPropertyFrameOrigin, properties));
+ if (!FrameSandboxFlagsFromClientProperty(
+ GetValueFromClientProperties(kPropertyFrameSandboxFlags, properties),
+ &(state->sandbox_flags))) {
+ state->sandbox_flags = blink::WebSandboxFlags::None;
+ }
+ if (!FrameTreeScopeFromClientProperty(
+ GetValueFromClientProperties(kPropertyFrameTreeScope, properties),
+ &(state->tree_scope))) {
+ state->tree_scope = blink::WebTreeScopeType::Document;
+ }
+}
+
+void ClientPropertiesFromReplicatedFrameState(
+ const ReplicatedFrameState& state,
+ mojo::Map<mojo::String, mojo::Array<uint8_t>>* properties) {
+ AddToClientPropertiesIfValid(kPropertyFrameName,
+ FrameNameToClientProperty(state.name).Pass(),
+ properties);
+ AddToClientPropertiesIfValid(
+ kPropertyFrameTreeScope,
+ FrameTreeScopeToClientProperty(state.tree_scope).Pass(), properties);
+ AddToClientPropertiesIfValid(
+ kPropertyFrameSandboxFlags,
+ FrameSandboxFlagsToClientProperty(state.sandbox_flags).Pass(),
+ properties);
+}
+
+} // namespace html_viewer
diff --git a/components/html_viewer/replicated_frame_state.h b/components/html_viewer/replicated_frame_state.h
new file mode 100644
index 0000000..eedc59c
--- /dev/null
+++ b/components/html_viewer/replicated_frame_state.h
@@ -0,0 +1,42 @@
+// Copyright 2015 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 COMPONENTS_HTML_VIEWER_REPLICATED_FRAME_STATE_H_
+#define COMPONENTS_HTML_VIEWER_REPLICATED_FRAME_STATE_H_
+
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebSandboxFlags.h"
+#include "third_party/WebKit/public/web/WebTreeScopeType.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/map.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/string.h"
+#include "url/origin.h"
+
+namespace html_viewer {
+
+// Stores state shared with other frames in the tree.
+struct ReplicatedFrameState {
+ public:
+ ReplicatedFrameState();
+ ~ReplicatedFrameState();
+
+ blink::WebString name;
+ url::Origin origin;
+ blink::WebSandboxFlags sandbox_flags;
+ blink::WebTreeScopeType tree_scope;
+};
+
+// Sets |state| from |properties|.
+void SetReplicatedFrameStateFromClientProperties(
+ const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties,
+ ReplicatedFrameState* state);
+
+// Sets |properties| from |state|.
+void ClientPropertiesFromReplicatedFrameState(
+ const ReplicatedFrameState& state,
+ mojo::Map<mojo::String, mojo::Array<uint8_t>>* properties);
+
+} // namespace html_viewer
+
+#endif // COMPONENTS_HTML_VIEWER_REPLICATED_FRAME_STATE_H_
diff --git a/components/html_viewer/web_layer_impl.cc b/components/html_viewer/web_layer_impl.cc
index 3e52a98..b35747e 100644
--- a/components/html_viewer/web_layer_impl.cc
+++ b/components/html_viewer/web_layer_impl.cc
@@ -5,7 +5,7 @@
#include "components/html_viewer/web_layer_impl.h"
#include "cc/layers/layer.h"
-#include "components/html_viewer/html_frame.h"
+#include "components/view_manager/public/cpp/view.h"
#include "ui/mojo/geometry/geometry.mojom.h"
using blink::WebFloatPoint;
@@ -13,21 +13,21 @@ using blink::WebSize;
namespace html_viewer {
-WebLayerImpl::WebLayerImpl(HTMLFrame* frame) : frame_(frame) {}
+WebLayerImpl::WebLayerImpl(mojo::View* view) : view_(view) {}
WebLayerImpl::~WebLayerImpl() {
}
void WebLayerImpl::setBounds(const WebSize& size) {
- mojo::Rect rect = frame_->view()->bounds();
+ mojo::Rect rect = view_->bounds();
rect.width = size.width;
rect.height = size.height;
- frame_->view()->SetBounds(rect);
+ view_->SetBounds(rect);
cc_blink::WebLayerImpl::setBounds(size);
}
void WebLayerImpl::setPosition(const WebFloatPoint& position) {
- mojo::Rect rect = frame_->view()->bounds();
+ mojo::Rect rect = view_->bounds();
rect.x = 0;
rect.y = 0;
// TODO(fsamuel): This is a temporary hack until we have a UI process in
@@ -40,7 +40,7 @@ void WebLayerImpl::setPosition(const WebFloatPoint& position) {
rect.y -= current_layer->scroll_offset().y();
current_layer = current_layer->parent();
}
- frame_->view()->SetBounds(rect);
+ view_->SetBounds(rect);
cc_blink::WebLayerImpl::setPosition(position);
}
diff --git a/components/html_viewer/web_layer_impl.h b/components/html_viewer/web_layer_impl.h
index 0d8c236..fdb3e03 100644
--- a/components/html_viewer/web_layer_impl.h
+++ b/components/html_viewer/web_layer_impl.h
@@ -9,13 +9,15 @@
#include "cc/blink/web_layer_impl.h"
-namespace html_viewer {
+namespace mojo {
+class View;
+}
-class HTMLFrame;
+namespace html_viewer {
class WebLayerImpl : public cc_blink::WebLayerImpl {
public:
- explicit WebLayerImpl(HTMLFrame* frame);
+ explicit WebLayerImpl(mojo::View* view);
~WebLayerImpl() override;
// WebLayer implementation.
@@ -23,7 +25,7 @@ class WebLayerImpl : public cc_blink::WebLayerImpl {
void setPosition(const blink::WebFloatPoint& position) override;
private:
- HTMLFrame* frame_;
+ mojo::View* view_;
DISALLOW_COPY_AND_ASSIGN(WebLayerImpl);
};
diff --git a/components/test/data/html_viewer/empty_page2.html b/components/test/data/html_viewer/empty_page2.html
index a5786ef..3ec7a95 100644
--- a/components/test/data/html_viewer/empty_page2.html
+++ b/components/test/data/html_viewer/empty_page2.html
@@ -1,5 +1,5 @@
<html>
<body style="background-color: red">
- child
+ child2
</body>
</html>