1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/html_viewer/frame_tree_manager.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "components/html_viewer/blink_url_request_type_converters.h"
12 #include "components/html_viewer/frame.h"
13 #include "components/html_viewer/frame_tree_manager_delegate.h"
14 #include "components/html_viewer/global_state.h"
15 #include "components/view_manager/public/cpp/view_manager.h"
16 #include "mojo/application/public/cpp/application_connection.h"
17 #include "mojo/application/public/cpp/application_impl.h"
18 #include "third_party/WebKit/public/web/WebLocalFrame.h"
19 #include "third_party/WebKit/public/web/WebRemoteFrame.h"
20 #include "third_party/WebKit/public/web/WebTreeScopeType.h"
21 #include "third_party/WebKit/public/web/WebView.h"
22 #include "ui/gfx/geometry/dip_util.h"
23 #include "ui/gfx/geometry/size.h"
25 namespace html_viewer
{
28 mojo::Target
WebNavigationPolicyToNavigationTarget(
29 blink::WebNavigationPolicy policy
) {
31 case blink::WebNavigationPolicyCurrentTab
:
32 return mojo::TARGET_SOURCE_NODE
;
33 case blink::WebNavigationPolicyNewBackgroundTab
:
34 case blink::WebNavigationPolicyNewForegroundTab
:
35 case blink::WebNavigationPolicyNewWindow
:
36 case blink::WebNavigationPolicyNewPopup
:
37 return mojo::TARGET_NEW_NODE
;
39 return mojo::TARGET_DEFAULT
;
43 bool CanNavigateLocally(blink::WebFrame
* frame
,
44 const blink::WebURLRequest
& request
) {
45 // If we have extraData() it means we already have the url response
46 // (presumably because we are being called via Navigate()). In that case we
47 // can go ahead and navigate locally.
48 if (request
.extraData())
51 // Otherwise we don't know if we're the right app to handle this request. Ask
52 // host to do the navigation for us.
56 // Creates a Frame per FrameData element in |frame_data|.
57 Frame
* BuildFrameTree(FrameTreeManager
* frame_tree_manager
,
58 const mojo::Array
<mandoline::FrameDataPtr
>& frame_data
) {
59 std::vector
<Frame
*> parents
;
60 Frame
* root
= nullptr;
61 Frame
* last_frame
= nullptr;
62 for (size_t i
= 0; i
< frame_data
.size(); ++i
) {
63 if (last_frame
&& frame_data
[i
]->parent_id
== last_frame
->id()) {
64 parents
.push_back(last_frame
);
65 } else if (!parents
.empty()) {
66 while (parents
.back()->id() != frame_data
[i
]->parent_id
)
69 Frame::CreateParams
params(frame_tree_manager
,
70 !parents
.empty() ? parents
.back() : nullptr,
71 frame_data
[i
]->frame_id
);
72 Frame
* frame
= new Frame(params
);
76 DCHECK(frame
->parent());
84 FrameTreeManager::FrameTreeManager(GlobalState
* global_state
,
85 mojo::ApplicationImpl
* app
,
86 mojo::ApplicationConnection
* app_connection
,
87 uint32_t local_frame_id
,
88 mandoline::FrameTreeServerPtr server
)
89 : global_state_(global_state
),
92 local_frame_id_(local_frame_id
),
93 server_(server
.Pass()),
94 navigator_host_(app_connection
->GetServiceProvider()),
98 FrameTreeManager::~FrameTreeManager() {
100 root_
->Close(); // This should call back to OnFrameDestroyed().
104 void FrameTreeManager::Init(mojo::View
* local_view
,
105 mojo::Array
<mandoline::FrameDataPtr
> frame_data
) {
106 root_
= BuildFrameTree(this, frame_data
);
108 Frame
* local_frame
= root_
->FindFrame(local_frame_id_
);
110 local_frame
->SetView(local_view
);
111 InitFrames(local_view
, root_
);
112 local_frame
->UpdateFocus();
115 Frame
* FrameTreeManager::GetLocalFrame() {
116 return root_
->FindFrame(local_frame_id_
);
119 blink::WebLocalFrame
* FrameTreeManager::GetLocalWebFrame() {
120 return GetLocalFrame()->web_frame()->toWebLocalFrame();
123 blink::WebView
* FrameTreeManager::GetWebView() {
124 return root_
->web_view();
127 void FrameTreeManager::InitFrames(mojo::View
* local_view
, Frame
* frame
) {
128 frame
->Init(local_view
);
130 for (Frame
* child_frame
: frame
->children())
131 InitFrames(local_view
, child_frame
);
134 blink::WebNavigationPolicy
FrameTreeManager::DecidePolicyForNavigation(
136 const blink::WebFrameClient::NavigationPolicyInfo
& info
) {
137 if (info
.frame
== frame
->web_frame() && frame
== root_
&& delegate_
&&
138 delegate_
->ShouldNavigateLocallyInMainFrame()) {
139 return info
.defaultPolicy
;
142 if (CanNavigateLocally(info
.frame
, info
.urlRequest
))
143 return info
.defaultPolicy
;
145 // TODO(sky): this is wrong for subframes. In fact NavigatorHost should likely
146 // be merged with Frame.
147 if (navigator_host_
.get()) {
148 mojo::URLRequestPtr url_request
= mojo::URLRequest::From(info
.urlRequest
);
149 navigator_host_
->RequestNavigate(
150 WebNavigationPolicyToNavigationTarget(info
.defaultPolicy
),
154 return blink::WebNavigationPolicyIgnore
;
157 void FrameTreeManager::OnFrameDidFinishLoad(Frame
* frame
) {
159 delegate_
->OnFrameDidFinishLoad(frame
);
162 void FrameTreeManager::OnFrameDidNavigateLocally(Frame
* frame
,
163 const std::string
& url
) {
164 if (navigator_host_
.get() && frame
== root_
)
165 navigator_host_
->DidNavigateLocally(url
);
168 void FrameTreeManager::OnFrameDestroyed(Frame
* frame
) {
169 if (frame
== root_
) {
171 // Shortly after this HTMLDocumentOOPIF should get ViewManagerDestroyed()
176 void FrameTreeManager::OnConnect(
177 mandoline::FrameTreeServerPtr server
,
178 mojo::Array
<mandoline::FrameDataPtr
> frame_data
) {
179 // OnConnection() is only sent once, and has been received (by
180 // DocumentResourceWaiter) by the time we get here.
184 void FrameTreeManager::OnFrameAdded(mandoline::FrameDataPtr frame_data
) {
188 void FrameTreeManager::OnFrameRemoved(uint32_t frame_id
) {