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 "mandoline/ui/browser/browser.h"
7 #include "base/command_line.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/view_manager/public/cpp/view.h"
10 #include "components/view_manager/public/cpp/view_manager_init.h"
11 #include "mandoline/tab/frame.h"
12 #include "mandoline/tab/frame_connection.h"
13 #include "mandoline/tab/frame_tree.h"
14 #include "mandoline/ui/browser/browser_delegate.h"
15 #include "mandoline/ui/browser/browser_ui.h"
16 #include "mojo/application/public/cpp/application_runner.h"
17 #include "mojo/common/common_type_converters.h"
18 #include "mojo/converters/geometry/geometry_type_converters.h"
19 #include "third_party/mojo/src/mojo/public/c/system/main.h"
20 #include "ui/gfx/geometry/size.h"
25 gfx::Size
GetInitialViewportSize() {
26 #if defined(OS_ANDROID)
27 // Resize to match the Nexus 5 aspect ratio:
28 return gfx::Size(320, 640);
30 return gfx::Size(1280, 800);
36 Browser::Browser(mojo::ApplicationImpl
* app
,
37 BrowserDelegate
* delegate
,
38 const GURL
& default_url
)
39 : view_manager_init_(app
, this, this),
43 default_url_(default_url
),
44 navigator_host_(this),
47 ui_
.reset(BrowserUI::Create(this, app
));
51 // Destruct ui_ manually while |this| is alive and reset the pointer first.
52 // This is to avoid a double delete when OnViewManagerDestroyed gets
57 void Browser::ReplaceContentWithRequest(mojo::URLRequestPtr request
) {
58 Embed(request
.Pass());
61 mojo::ApplicationConnection
* Browser::GetViewManagerConnectionForTesting() {
62 return view_manager_init_
.connection();
65 void Browser::OnEmbed(mojo::View
* root
) {
66 // Browser does not support being embedded more than once.
69 // Make it so we get OnWillEmbed() for any Embed()s done by other apps we
71 root
->view_manager()->SetEmbedRoot();
73 // TODO(beng): still unhappy with the fact that both this class & the UI class
74 // know so much about these views. Figure out how to shift more to
78 delegate_
->InitUIIfNecessary(this, root_
);
80 content_
= root_
->view_manager()->CreateView();
83 view_manager_init_
.view_manager_root()->SetViewportSize(
84 mojo::Size::From(GetInitialViewportSize()));
86 root_
->AddChild(content_
);
87 content_
->SetVisible(true);
89 view_manager_init_
.view_manager_root()->AddAccelerator(
90 mojo::KEYBOARD_CODE_BROWSER_BACK
, mojo::EVENT_FLAGS_NONE
);
92 // Now that we're ready, either load a pending url or the default url.
93 if (pending_request_
) {
94 Embed(pending_request_
.Pass());
95 } else if (default_url_
.is_valid()) {
96 mojo::URLRequestPtr
request(mojo::URLRequest::New());
97 request
->url
= mojo::String::From(default_url_
.spec());
98 Embed(request
.Pass());
102 void Browser::OnEmbedForDescendant(mojo::View
* view
,
103 mojo::URLRequestPtr request
,
104 mojo::ViewManagerClientPtr
* client
) {
105 // TODO(sky): move this to Frame/FrameTree.
106 Frame
* frame
= Frame::FindFirstFrameAncestor(view
);
107 if (!frame
|| !frame
->HasAncestor(frame_tree_
->root())) {
108 // TODO(sky): add requestor url so that we can return false if it's not
110 mojo::ApplicationConnection
* connection
=
111 app_
->ConnectToApplication(request
.Pass());
112 connection
->ConnectToService(client
);
116 scoped_ptr
<FrameConnection
> frame_connection(new FrameConnection
);
117 frame_connection
->Init(app_
, request
.Pass(), client
);
118 FrameTreeClient
* frame_tree_client
= frame_connection
->frame_tree_client();
119 frame_tree_
->CreateOrReplaceFrame(frame
, view
, frame_tree_client
,
120 frame_connection
.Pass());
123 void Browser::OnViewManagerDestroyed(mojo::ViewManager
* view_manager
) {
126 delegate_
->BrowserClosed(this);
129 void Browser::OnAccelerator(mojo::EventPtr event
) {
130 DCHECK_EQ(mojo::KEYBOARD_CODE_BROWSER_BACK
,
131 event
->key_data
->windows_key_code
);
132 navigator_host_
.RequestNavigateHistory(-1);
135 void Browser::OpenURL(const mojo::String
& url
) {
136 omnibox_
->SetVisible(false);
137 mojo::URLRequestPtr
request(mojo::URLRequest::New());
138 request
->url
= mojo::String::From(url
);
139 ReplaceContentWithRequest(request
.Pass());
142 void Browser::Embed(mojo::URLRequestPtr request
) {
143 const std::string string_url
= request
->url
.To
<std::string
>();
144 if (string_url
== "mojo:omnibox") {
145 ShowOmnibox(request
.Pass());
149 // We can get Embed calls before we've actually been
150 // embedded into the root view and content_ is created.
151 // Just save the last url, we'll embed it when we're ready.
153 pending_request_
= request
.Pass();
157 GURL
gurl(string_url
);
158 bool changed
= current_url_
!= gurl
;
163 scoped_ptr
<FrameConnection
> frame_connection(new FrameConnection
);
164 mojo::ViewManagerClientPtr view_manager_client
;
165 frame_connection
->Init(app_
, request
.Pass(), &view_manager_client
);
166 frame_connection
->application_connection()->AddService
<mojo::NavigatorHost
>(
168 FrameTreeClient
* frame_tree_client
= frame_connection
->frame_tree_client();
169 frame_tree_
.reset(new FrameTree(content_
, this, frame_tree_client
,
170 frame_connection
.Pass()));
171 content_
->Embed(view_manager_client
.Pass());
172 LoadingStateChanged(true);
174 navigator_host_
.RecordNavigation(gurl
.spec());
177 bool Browser::CanPostMessageEventToFrame(const Frame
* source
,
179 MessageEvent
* event
) {
183 void Browser::LoadingStateChanged(bool loading
) {
184 ui_
->LoadingStateChanged(loading
);
187 void Browser::ProgressChanged(double progress
) {
188 ui_
->ProgressChanged(progress
);
191 void Browser::Create(mojo::ApplicationConnection
* connection
,
192 mojo::InterfaceRequest
<mojo::NavigatorHost
> request
) {
193 navigator_host_
.Bind(request
.Pass());
196 void Browser::Create(mojo::ApplicationConnection
* connection
,
197 mojo::InterfaceRequest
<ViewEmbedder
> request
) {
198 view_embedder_bindings_
.AddBinding(this, request
.Pass());
201 void Browser::ShowOmnibox(mojo::URLRequestPtr request
) {
203 omnibox_
= root_
->view_manager()->CreateView();
204 root_
->AddChild(omnibox_
);
205 omnibox_
->SetBounds(root_
->bounds());
207 mojo::ViewManagerClientPtr view_manager_client
;
208 mojo::ApplicationConnection
* connection
=
209 app_
->ConnectToApplication(request
.Pass());
210 connection
->AddService
<ViewEmbedder
>(this);
211 connection
->ConnectToService(&view_manager_client
);
212 omnibox_
->Embed(view_manager_client
.Pass());
213 omnibox_
->SetVisible(true);
216 void Browser::RequestNavigate(Frame
* source
,
217 NavigationTarget target
,
218 mojo::URLRequestPtr request
) {
219 // TODO(sky): we shouldn't always do a top level navigation here.
220 ReplaceContentWithRequest(request
.Pass());
223 } // namespace mandoline