diff options
author | sky <sky@chromium.org> | 2015-08-10 10:37:03 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-10 17:38:04 +0000 |
commit | 3033d1de7158836f0d51df83bc7a901d551b31e7 (patch) | |
tree | 19bc059f824c6878599aee622ee631ef216a23ff /components | |
parent | 197ed7e89063580eeb7cc5d5abf669e1f9cbf7d8 (diff) | |
download | chromium_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.gn | 3 | ||||
-rw-r--r-- | components/html_viewer/ax_provider_apptest.cc | 4 | ||||
-rw-r--r-- | components/html_viewer/html_document_oopif.cc | 4 | ||||
-rw-r--r-- | components/html_viewer/html_document_oopif.h | 1 | ||||
-rw-r--r-- | components/html_viewer/html_frame.cc | 151 | ||||
-rw-r--r-- | components/html_viewer/html_frame.h | 20 | ||||
-rw-r--r-- | components/html_viewer/html_frame_apptest.cc | 112 | ||||
-rw-r--r-- | components/html_viewer/html_frame_properties.cc | 10 | ||||
-rw-r--r-- | components/html_viewer/html_frame_properties.h | 1 | ||||
-rw-r--r-- | components/html_viewer/replicated_frame_state.cc | 51 | ||||
-rw-r--r-- | components/html_viewer/replicated_frame_state.h | 42 | ||||
-rw-r--r-- | components/html_viewer/web_layer_impl.cc | 12 | ||||
-rw-r--r-- | components/html_viewer/web_layer_impl.h | 10 | ||||
-rw-r--r-- | components/test/data/html_viewer/empty_page2.html | 2 |
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> |