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/web_view/web_view_impl.h"
7 #include "base/command_line.h"
8 #include "components/devtools_service/public/cpp/switches.h"
9 #include "components/mus/public/cpp/scoped_view_ptr.h"
10 #include "components/mus/public/cpp/view.h"
11 #include "components/mus/public/cpp/view_tree_connection.h"
12 #include "components/web_view/frame.h"
13 #include "components/web_view/frame_connection.h"
14 #include "components/web_view/frame_devtools_agent.h"
15 #include "components/web_view/frame_tree.h"
16 #include "components/web_view/pending_web_view_load.h"
17 #include "components/web_view/url_request_cloneable.h"
18 #include "mojo/application/public/cpp/application_impl.h"
19 #include "mojo/converters/geometry/geometry_type_converters.h"
25 bool EnableRemoteDebugging() {
26 return base::CommandLine::ForCurrentProcess()->HasSwitch(
27 devtools_service::kRemoteDebuggingPort
);
32 using web_view::mojom::ButtonState
;
34 ////////////////////////////////////////////////////////////////////////////////
35 // WebViewImpl, public:
37 WebViewImpl::WebViewImpl(mojo::ApplicationImpl
* app
,
38 mojom::WebViewClientPtr client
,
39 mojo::InterfaceRequest
<mojom::WebView
> request
)
41 client_(client
.Pass()),
42 binding_(this, request
.Pass()),
45 if (EnableRemoteDebugging())
46 devtools_agent_
.reset(new FrameDevToolsAgent(app_
, this));
49 WebViewImpl::~WebViewImpl() {
51 content_
->RemoveObserver(this);
53 root_
->RemoveObserver(this);
54 mojo::ScopedViewPtr::DeleteViewOrViewManager(root_
);
58 void WebViewImpl::OnLoad() {
59 scoped_ptr
<PendingWebViewLoad
> pending_load(pending_load_
.Pass());
60 scoped_ptr
<FrameConnection
> frame_connection(
61 pending_load
->frame_connection());
62 mojo::ViewTreeClientPtr view_tree_client
=
63 frame_connection
->GetViewTreeClient();
65 Frame::ClientPropertyMap client_properties
;
66 if (devtools_agent_
) {
67 devtools_service::DevToolsAgentPtr forward_agent
;
68 frame_connection
->application_connection()->ConnectToService(
70 devtools_agent_
->AttachFrame(forward_agent
.Pass(), &client_properties
);
73 FrameTreeClient
* frame_tree_client
= frame_connection
->frame_tree_client();
74 const uint32_t content_handler_id
= frame_connection
->GetContentHandlerID();
75 frame_tree_
.reset(new FrameTree(
76 content_handler_id
, content_
, view_tree_client
.Pass(), this,
77 frame_tree_client
, frame_connection
.Pass(), client_properties
));
80 void WebViewImpl::LoadRequestImpl(mojo::URLRequestPtr request
) {
81 client_
->BackForwardChanged(
82 back_list_
.empty() ? ButtonState::BUTTON_STATE_DISABLED
83 : ButtonState::BUTTON_STATE_ENABLED
,
84 forward_list_
.empty() ? ButtonState::BUTTON_STATE_DISABLED
85 : ButtonState::BUTTON_STATE_ENABLED
);
87 current_page_request_
.reset(new URLRequestCloneable(request
.Pass()));
88 pending_load_
.reset(new PendingWebViewLoad(this));
89 pending_load_
->Init(current_page_request_
->Clone());
92 ////////////////////////////////////////////////////////////////////////////////
93 // WebViewImpl, WebView implementation:
95 void WebViewImpl::LoadRequest(mojo::URLRequestPtr request
) {
96 // Clear the forward list when performing a top level load request.
97 forward_list_
.clear();
99 if (current_page_request_
) {
100 // TODO(erg): This doesn't deal with redirect chains. If you navigate to a
101 // site, and it 300s, we put both the url which caused the 300 and the
102 // target url here, when we should not add the redirect url to the back
104 back_list_
.push_back(current_page_request_
.Pass());
107 LoadRequestImpl(request
.Pass());
110 void WebViewImpl::GetViewTreeClient(
111 mojo::InterfaceRequest
<mojo::ViewTreeClient
> view_tree_client
) {
112 mojo::ViewTreeConnection::Create(this, view_tree_client
.Pass());
115 void WebViewImpl::GoBack() {
116 if (back_list_
.empty())
119 // Take the current page request and put it in the forward list.
120 forward_list_
.push_back(current_page_request_
.Pass());
122 mojo::URLRequestPtr new_request
= back_list_
.back()->Clone();
123 back_list_
.resize(back_list_
.size() - 1);
125 LoadRequestImpl(new_request
.Pass());
128 void WebViewImpl::GoForward() {
129 if (forward_list_
.empty())
132 back_list_
.push_back(current_page_request_
.Pass());
134 mojo::URLRequestPtr new_request
= forward_list_
.back()->Clone();
135 forward_list_
.resize(forward_list_
.size() - 1);
137 LoadRequestImpl(new_request
.Pass());
140 ////////////////////////////////////////////////////////////////////////////////
141 // WebViewImpl, mojo::ViewTreeDelegate implementation:
143 void WebViewImpl::OnEmbed(mojo::View
* root
) {
144 // We must have been granted embed root priviledges, otherwise we can't
145 // Embed() in any descendants.
146 DCHECK(root
->connection()->IsEmbedRoot());
147 root
->AddObserver(this);
149 content_
= root
->connection()->CreateView();
150 content_
->SetBounds(*mojo::Rect::From(gfx::Rect(0, 0, root
->bounds().width
,
151 root
->bounds().height
)));
152 root
->AddChild(content_
);
153 content_
->SetVisible(true);
154 content_
->AddObserver(this);
156 if (pending_load_
&& pending_load_
->is_content_handler_id_valid())
160 void WebViewImpl::OnConnectionLost(mojo::ViewTreeConnection
* connection
) {
164 ////////////////////////////////////////////////////////////////////////////////
165 // WebViewImpl, mojo::ViewObserver implementation:
167 void WebViewImpl::OnViewBoundsChanged(mojo::View
* view
,
168 const mojo::Rect
& old_bounds
,
169 const mojo::Rect
& new_bounds
) {
170 if (view
!= content_
) {
172 rect
.width
= new_bounds
.width
;
173 rect
.height
= new_bounds
.height
;
174 content_
->SetBounds(rect
);
178 void WebViewImpl::OnViewDestroyed(mojo::View
* view
) {
179 // |FrameTree| cannot outlive the content view.
180 if (view
== content_
) {
186 ////////////////////////////////////////////////////////////////////////////////
187 // WebViewImpl, FrameTreeDelegate implementation:
189 bool WebViewImpl::CanPostMessageEventToFrame(const Frame
* source
,
191 HTMLMessageEvent
* event
) {
195 void WebViewImpl::LoadingStateChanged(bool loading
) {
196 client_
->LoadingStateChanged(loading
);
199 void WebViewImpl::ProgressChanged(double progress
) {
200 client_
->ProgressChanged(progress
);
203 void WebViewImpl::TitleChanged(const mojo::String
& title
) {
204 client_
->TitleChanged(title
);
207 void WebViewImpl::NavigateTopLevel(Frame
* source
, mojo::URLRequestPtr request
) {
208 client_
->TopLevelNavigate(request
.Pass());
211 void WebViewImpl::CanNavigateFrame(Frame
* target
,
212 mojo::URLRequestPtr request
,
213 const CanNavigateFrameCallback
& callback
) {
214 FrameConnection::CreateConnectionForCanNavigateFrame(
215 app_
, target
, request
.Pass(), callback
);
218 void WebViewImpl::DidStartNavigation(Frame
* frame
) {}
220 ////////////////////////////////////////////////////////////////////////////////
221 // WebViewImpl, FrameDevToolsAgentDelegate implementation:
223 void WebViewImpl::HandlePageNavigateRequest(const GURL
& url
) {
224 mojo::URLRequestPtr
request(mojo::URLRequest::New());
225 request
->url
= url
.spec();
226 client_
->TopLevelNavigate(request
.Pass());
229 } // namespace web_view