1 // Copyright (c) 2013 Intel Corporation. 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 "xwalk/runtime/browser/runtime.h"
10 #include "base/command_line.h"
11 #include "base/message_loop/message_loop.h"
12 #include "xwalk/runtime/browser/image_util.h"
13 #include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
14 #include "xwalk/runtime/browser/runtime_context.h"
15 #include "xwalk/runtime/browser/runtime_file_select_helper.h"
16 #include "xwalk/runtime/browser/ui/color_chooser.h"
17 #include "xwalk/runtime/browser/xwalk_runner.h"
18 #include "xwalk/runtime/common/xwalk_notification_types.h"
19 #include "xwalk/runtime/common/xwalk_switches.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/web_contents_view.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "grit/xwalk_resources.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/gfx/image/image_skia.h"
31 #include "ui/gfx/native_widget_types.h"
33 using content::FaviconURL;
34 using content::WebContents;
40 // The default size for web content area size.
41 const int kDefaultWidth = 840;
42 const int kDefaultHeight = 600;
47 Runtime* Runtime::CreateWithDefaultWindow(
48 RuntimeContext* runtime_context, const GURL& url, Observer* observer) {
49 Runtime* runtime = Runtime::Create(runtime_context, observer);
50 runtime->LoadURL(url);
51 runtime->AttachDefaultWindow();
56 Runtime* Runtime::Create(
57 RuntimeContext* runtime_context, Observer* observer) {
58 WebContents::CreateParams params(runtime_context, NULL);
59 params.routing_id = MSG_ROUTING_NONE;
60 WebContents* web_contents = WebContents::Create(params);
62 Runtime* runtime = new Runtime(web_contents, observer);
64 runtime->InitRootWindow();
70 Runtime::Runtime(content::WebContents* web_contents, Observer* observer)
71 : WebContentsObserver(web_contents),
72 web_contents_(web_contents),
74 weak_ptr_factory_(this),
75 fullscreen_options_(NO_FULLSCREEN),
77 web_contents_->SetDelegate(this);
78 runtime_context_ = RuntimeContext::FromWebContents(web_contents);
79 content::NotificationService::current()->Notify(
80 xwalk::NOTIFICATION_RUNTIME_OPENED,
81 content::Source<Runtime>(this),
82 content::NotificationService::NoDetails());
87 observer_->OnRuntimeAdded(this);
91 content::NotificationService::current()->Notify(
92 xwalk::NOTIFICATION_RUNTIME_CLOSED,
93 content::Source<Runtime>(this),
94 content::NotificationService::NoDetails());
96 observer_->OnRuntimeRemoved(this);
99 void Runtime::AttachDefaultWindow() {
100 NativeAppWindow::CreateParams params;
101 AttachWindow(params);
104 void Runtime::AttachWindow(const NativeAppWindow::CreateParams& params) {
105 #if defined(OS_ANDROID)
109 NativeAppWindow::CreateParams effective_params(params);
110 ApplyWindowDefaultParams(&effective_params);
112 // Set the app icon if it is passed from command line.
113 CommandLine* command_line = CommandLine::ForCurrentProcess();
114 if (command_line->HasSwitch(switches::kAppIcon)) {
115 base::FilePath icon_file =
116 command_line->GetSwitchValuePath(switches::kAppIcon);
117 app_icon_ = xwalk_utils::LoadImageFromFilePath(icon_file);
119 // Otherwise, use the default icon for Crosswalk app.
120 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
121 app_icon_ = rb.GetNativeImageNamed(IDR_XWALK_ICON_48);
125 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
126 content::Source<content::WebContents>(web_contents_.get()));
128 window_ = NativeAppWindow::Create(effective_params);
129 if (!app_icon_.IsEmpty())
130 window_->UpdateIcon(app_icon_);
132 #if defined(OS_TIZEN)
134 root_window_->Show();
139 void Runtime::LoadURL(const GURL& url) {
140 content::NavigationController::LoadURLParams params(url);
141 params.transition_type = content::PageTransitionFromInt(
142 content::PAGE_TRANSITION_TYPED |
143 content::PAGE_TRANSITION_FROM_ADDRESS_BAR);
144 web_contents_->GetController().LoadURLWithParams(params);
145 web_contents_->GetView()->Focus();
148 void Runtime::Close() {
153 // Runtime should not free itself on Close but be owned
158 NativeAppWindow* Runtime::window() const {
162 //////////////////////////////////////////////////////
163 // content::WebContentsDelegate:
164 //////////////////////////////////////////////////////
165 content::WebContents* Runtime::OpenURLFromTab(
166 content::WebContents* source, const content::OpenURLParams& params) {
167 // The only one disposition we would take into consideration.
168 DCHECK(params.disposition == CURRENT_TAB);
169 source->GetController().LoadURL(
170 params.url, params.referrer, params.transition, std::string());
174 void Runtime::LoadingStateChanged(content::WebContents* source) {
177 void Runtime::ToggleFullscreenModeForTab(content::WebContents* web_contents,
178 bool enter_fullscreen) {
179 if (enter_fullscreen)
180 fullscreen_options_ |= FULLSCREEN_FOR_TAB;
182 fullscreen_options_ &= ~FULLSCREEN_FOR_TAB;
184 if (enter_fullscreen) {
185 window_->SetFullscreen(true);
186 } else if (!fullscreen_options_ & FULLSCREEN_FOR_LAUNCH) {
187 window_->SetFullscreen(false);
191 bool Runtime::IsFullscreenForTabOrPending(
192 const content::WebContents* web_contents) const {
193 return (fullscreen_options_ & FULLSCREEN_FOR_TAB) != 0;
196 void Runtime::RequestToLockMouse(content::WebContents* web_contents,
198 bool last_unlocked_by_target) {
199 web_contents->GotResponseToLockMouseRequest(true);
202 void Runtime::CloseContents(content::WebContents* source) {
206 bool Runtime::CanOverscrollContent() const {
210 bool Runtime::PreHandleKeyboardEvent(
211 content::WebContents* source,
212 const content::NativeWebKeyboardEvent& event,
213 bool* is_keyboard_shortcut) {
214 // Escape exits tabbed fullscreen mode.
215 if (event.windowsKeyCode == 27 && IsFullscreenForTabOrPending(source)) {
216 ToggleFullscreenModeForTab(source, false);
222 void Runtime::HandleKeyboardEvent(
223 content::WebContents* source,
224 const content::NativeWebKeyboardEvent& event) {
227 void Runtime::WebContentsCreated(
228 content::WebContents* source_contents,
229 int64 source_frame_id,
230 const base::string16& frame_name,
231 const GURL& target_url,
232 content::WebContents* new_contents) {
233 Runtime* new_runtime = new Runtime(new_contents, observer_);
234 #if defined(OS_TIZEN)
235 new_runtime->SetRootWindow(root_window_);
237 new_runtime->AttachDefaultWindow();
240 void Runtime::DidNavigateMainFramePostCommit(
241 content::WebContents* web_contents) {
244 content::JavaScriptDialogManager* Runtime::GetJavaScriptDialogManager() {
248 void Runtime::ActivateContents(content::WebContents* contents) {
249 contents->GetRenderViewHost()->Focus();
252 void Runtime::DeactivateContents(content::WebContents* contents) {
253 contents->GetRenderViewHost()->Blur();
256 content::ColorChooser* Runtime::OpenColorChooser(
257 content::WebContents* web_contents,
258 SkColor initial_color,
259 const std::vector<content::ColorSuggestion>& suggestions) {
260 return xwalk::ShowColorChooser(web_contents, initial_color);
263 void Runtime::RunFileChooser(
264 content::WebContents* web_contents,
265 const content::FileChooserParams& params) {
266 #if defined(USE_AURA) && defined(OS_LINUX)
269 RuntimeFileSelectHelper::RunFileChooser(web_contents, params);
273 void Runtime::EnumerateDirectory(content::WebContents* web_contents,
275 const base::FilePath& path) {
276 #if defined(USE_AURA) && defined(OS_LINUX)
279 RuntimeFileSelectHelper::EnumerateDirectory(web_contents, request_id, path);
283 void Runtime::DidUpdateFaviconURL(int32 page_id,
284 const std::vector<FaviconURL>& candidates) {
285 DLOG(INFO) << "Candidates: ";
286 for (size_t i = 0; i < candidates.size(); ++i)
287 DLOG(INFO) << candidates[i].icon_url.spec();
289 if (candidates.empty())
292 // Avoid using any previous download.
293 weak_ptr_factory_.InvalidateWeakPtrs();
295 // We only select the first favicon as the window app icon.
296 FaviconURL favicon = candidates[0];
297 // Passing 0 as the |image_size| parameter results in only receiving the first
298 // bitmap, according to content/public/browser/web_contents.h
299 web_contents()->DownloadImage(
301 true, // Is a favicon
302 0, // No maximum size
304 &Runtime::DidDownloadFavicon, weak_ptr_factory_.GetWeakPtr()));
307 void Runtime::DidDownloadFavicon(int id,
308 int http_status_code,
309 const GURL& image_url,
310 const std::vector<SkBitmap>& bitmaps,
311 const std::vector<gfx::Size>& sizes) {
314 app_icon_ = gfx::Image::CreateFrom1xBitmap(bitmaps[0]);
315 window_->UpdateIcon(app_icon_);
318 void Runtime::Observe(int type,
319 const content::NotificationSource& source,
320 const content::NotificationDetails& details) {
321 if (type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
322 std::pair<content::NavigationEntry*, bool>* title =
323 content::Details<std::pair<content::NavigationEntry*, bool> >(
327 base::string16 text = title->first->GetTitle();
328 window_->UpdateTitle(text);
333 void Runtime::OnWindowDestroyed() {
334 // Runtime should not free itself on Close but be owned
339 void Runtime::RequestMediaAccessPermission(
340 content::WebContents* web_contents,
341 const content::MediaStreamRequest& request,
342 const content::MediaResponseCallback& callback) {
343 XWalkMediaCaptureDevicesDispatcher::RunRequestMediaAccessPermission(
344 web_contents, request, callback);
347 void Runtime::RenderProcessGone(base::TerminationStatus status) {
348 content::RenderProcessHost* rph = web_contents_->GetRenderProcessHost();
349 VLOG(1) << "RenderProcess id: " << rph->GetID() << " is gone!";
350 XWalkRunner::GetInstance()->OnRenderProcessHostGone(rph);
353 void Runtime::ApplyWindowDefaultParams(NativeAppWindow::CreateParams* params) {
354 if (!params->delegate)
355 params->delegate = this;
356 if (!params->web_contents)
357 params->web_contents = web_contents_.get();
358 if (params->bounds.IsEmpty())
359 params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
360 #if defined(OS_TIZEN)
362 params->parent = root_window_->GetNativeWindow();
364 ApplyFullScreenParam(params);
367 void Runtime::ApplyFullScreenParam(NativeAppWindow::CreateParams* params) {
369 // TODO(cmarcelo): This is policy that probably should be moved to outside
371 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
372 if (cmd_line->HasSwitch(switches::kFullscreen)) {
373 params->state = ui::SHOW_STATE_FULLSCREEN;
374 fullscreen_options_ |= FULLSCREEN_FOR_LAUNCH;
378 #if defined(OS_TIZEN)
379 void Runtime::CloseRootWindow() {
381 root_window_->Close();
386 void Runtime::ApplyRootWindowParams(NativeAppWindow::CreateParams* params) {
387 if (!params->delegate)
388 params->delegate = this;
389 if (params->bounds.IsEmpty())
390 params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
391 ApplyFullScreenParam(params);
394 void Runtime::InitRootWindow() {
398 NativeAppWindow::CreateParams params;
399 ApplyRootWindowParams(¶ms);
400 root_window_ = NativeAppWindow::Create(params);
403 void Runtime::SetRootWindow(NativeAppWindow* window) {
404 root_window_= window;