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"
32 using content::FaviconURL;
33 using content::WebContents;
39 // The default size for web content area size.
40 const int kDefaultWidth = 840;
41 const int kDefaultHeight = 600;
43 static Runtime::Observer* g_observer_for_testing;
48 Runtime* Runtime::Create(
49 RuntimeContext* runtime_context, const GURL& url, Observer* observer) {
50 WebContents::CreateParams params(runtime_context, NULL);
51 params.routing_id = MSG_ROUTING_NONE;
52 WebContents* web_contents = WebContents::Create(params);
54 Runtime* runtime = new Runtime(web_contents, observer);
55 runtime->LoadURL(url);
60 Runtime* Runtime::CreateWithDefaultWindow(
61 RuntimeContext* runtime_context, const GURL& url, Observer* observer) {
62 Runtime* runtime = Runtime::Create(runtime_context, url, observer);
63 runtime->AttachDefaultWindow();
68 Runtime* Runtime::Create(
69 RuntimeContext* runtime_context, Observer* observer) {
70 WebContents::CreateParams params(runtime_context, NULL);
71 params.routing_id = MSG_ROUTING_NONE;
72 WebContents* web_contents = WebContents::Create(params);
74 return new Runtime(web_contents, observer);
78 void Runtime::SetGlobalObserverForTesting(Observer* observer) {
79 g_observer_for_testing = observer;
82 #define FOR_EACH_RUNTIME_OBSERVER(method) \
85 if (g_observer_for_testing) \
86 g_observer_for_testing->method
88 Runtime::Runtime(content::WebContents* web_contents, Observer* observer)
89 : WebContentsObserver(web_contents),
90 web_contents_(web_contents),
92 weak_ptr_factory_(this),
93 fullscreen_options_(NO_FULLSCREEN),
95 web_contents_->SetDelegate(this);
96 runtime_context_ = RuntimeContext::FromWebContents(web_contents);
97 content::NotificationService::current()->Notify(
98 xwalk::NOTIFICATION_RUNTIME_OPENED,
99 content::Source<Runtime>(this),
100 content::NotificationService::NoDetails());
102 FOR_EACH_RUNTIME_OBSERVER(OnRuntimeAdded(this));
105 Runtime::~Runtime() {
106 content::NotificationService::current()->Notify(
107 xwalk::NOTIFICATION_RUNTIME_CLOSED,
108 content::Source<Runtime>(this),
109 content::NotificationService::NoDetails());
110 FOR_EACH_RUNTIME_OBSERVER(OnRuntimeRemoved(this));
113 void Runtime::AttachDefaultWindow() {
114 NativeAppWindow::CreateParams params;
115 params.delegate = this;
116 params.web_contents = web_contents_.get();
117 params.bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
118 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
119 if (cmd_line->HasSwitch(switches::kFullscreen)) {
120 params.state = ui::SHOW_STATE_FULLSCREEN;
121 fullscreen_options_ |= FULLSCREEN_FOR_LAUNCH;
123 AttachWindow(params);
126 void Runtime::AttachWindow(const NativeAppWindow::CreateParams& params) {
127 #if defined(OS_ANDROID)
131 // Set the app icon if it is passed from command line.
132 CommandLine* command_line = CommandLine::ForCurrentProcess();
133 if (command_line->HasSwitch(switches::kAppIcon)) {
134 base::FilePath icon_file =
135 command_line->GetSwitchValuePath(switches::kAppIcon);
136 app_icon_ = xwalk_utils::LoadImageFromFilePath(icon_file);
138 // Otherwise, use the default icon for Crosswalk app.
139 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
140 app_icon_ = rb.GetNativeImageNamed(IDR_XWALK_ICON_48);
144 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
145 content::Source<content::WebContents>(web_contents_.get()));
147 window_ = NativeAppWindow::Create(params);
148 if (!app_icon_.IsEmpty())
149 window_->UpdateIcon(app_icon_);
154 void Runtime::LoadURL(const GURL& url) {
155 content::NavigationController::LoadURLParams params(url);
156 params.transition_type = content::PageTransitionFromInt(
157 content::PAGE_TRANSITION_TYPED |
158 content::PAGE_TRANSITION_FROM_ADDRESS_BAR);
159 web_contents_->GetController().LoadURLWithParams(params);
160 web_contents_->GetView()->Focus();
163 void Runtime::Close() {
167 NativeAppWindow* Runtime::window() const {
171 //////////////////////////////////////////////////////
172 // content::WebContentsDelegate:
173 //////////////////////////////////////////////////////
174 content::WebContents* Runtime::OpenURLFromTab(
175 content::WebContents* source, const content::OpenURLParams& params) {
176 // The only one disposition we would take into consideration.
177 DCHECK(params.disposition == CURRENT_TAB);
178 source->GetController().LoadURL(
179 params.url, params.referrer, params.transition, std::string());
183 void Runtime::LoadingStateChanged(content::WebContents* source) {
186 void Runtime::ToggleFullscreenModeForTab(content::WebContents* web_contents,
187 bool enter_fullscreen) {
188 if (enter_fullscreen)
189 fullscreen_options_ |= FULLSCREEN_FOR_TAB;
191 fullscreen_options_ &= ~FULLSCREEN_FOR_TAB;
193 if (enter_fullscreen) {
194 window_->SetFullscreen(true);
195 } else if (!fullscreen_options_ & FULLSCREEN_FOR_LAUNCH) {
196 window_->SetFullscreen(false);
200 bool Runtime::IsFullscreenForTabOrPending(
201 const content::WebContents* web_contents) const {
202 return (fullscreen_options_ & FULLSCREEN_FOR_TAB) != 0;
205 void Runtime::RequestToLockMouse(content::WebContents* web_contents,
207 bool last_unlocked_by_target) {
208 web_contents->GotResponseToLockMouseRequest(true);
211 void Runtime::CloseContents(content::WebContents* source) {
215 bool Runtime::CanOverscrollContent() const {
219 bool Runtime::PreHandleKeyboardEvent(
220 content::WebContents* source,
221 const content::NativeWebKeyboardEvent& event,
222 bool* is_keyboard_shortcut) {
223 // Escape exits tabbed fullscreen mode.
224 if (event.windowsKeyCode == 27 && IsFullscreenForTabOrPending(source)) {
225 ToggleFullscreenModeForTab(source, false);
231 void Runtime::HandleKeyboardEvent(
232 content::WebContents* source,
233 const content::NativeWebKeyboardEvent& event) {
236 void Runtime::WebContentsCreated(
237 content::WebContents* source_contents,
238 int64 source_frame_id,
239 const string16& frame_name,
240 const GURL& target_url,
241 content::WebContents* new_contents) {
242 Runtime* new_runtime = new Runtime(new_contents, observer_);
243 new_runtime->AttachDefaultWindow();
246 void Runtime::DidNavigateMainFramePostCommit(
247 content::WebContents* web_contents) {
250 content::JavaScriptDialogManager* Runtime::GetJavaScriptDialogManager() {
254 void Runtime::ActivateContents(content::WebContents* contents) {
255 contents->GetRenderViewHost()->Focus();
258 void Runtime::DeactivateContents(content::WebContents* contents) {
259 contents->GetRenderViewHost()->Blur();
262 content::ColorChooser* Runtime::OpenColorChooser(
263 content::WebContents* web_contents,
264 SkColor initial_color) {
265 return xwalk::ShowColorChooser(web_contents, initial_color);
268 void Runtime::RunFileChooser(
269 content::WebContents* web_contents,
270 const content::FileChooserParams& params) {
271 #if defined(USE_AURA) && defined(OS_LINUX)
274 RuntimeFileSelectHelper::RunFileChooser(web_contents, params);
278 void Runtime::EnumerateDirectory(content::WebContents* web_contents,
280 const base::FilePath& path) {
281 #if defined(USE_AURA) && defined(OS_LINUX)
284 RuntimeFileSelectHelper::EnumerateDirectory(web_contents, request_id, path);
288 void Runtime::DidUpdateFaviconURL(int32 page_id,
289 const std::vector<FaviconURL>& candidates) {
290 DLOG(INFO) << "Candidates: ";
291 for (size_t i = 0; i < candidates.size(); ++i)
292 DLOG(INFO) << candidates[i].icon_url.spec();
294 if (candidates.empty())
297 // Avoid using any previous download.
298 weak_ptr_factory_.InvalidateWeakPtrs();
300 // We only select the first favicon as the window app icon.
301 FaviconURL favicon = candidates[0];
302 // Passing 0 as the |image_size| parameter results in only receiving the first
303 // bitmap, according to content/public/browser/web_contents.h
304 web_contents()->DownloadImage(
306 true, // Is a favicon
307 0, // No maximum size
309 &Runtime::DidDownloadFavicon, weak_ptr_factory_.GetWeakPtr()));
312 void Runtime::DidDownloadFavicon(int id,
313 int http_status_code,
314 const GURL& image_url,
315 const std::vector<SkBitmap>& bitmaps,
316 const std::vector<gfx::Size>& sizes) {
319 app_icon_ = gfx::Image::CreateFrom1xBitmap(bitmaps[0]);
320 window_->UpdateIcon(app_icon_);
323 void Runtime::Observe(int type,
324 const content::NotificationSource& source,
325 const content::NotificationDetails& details) {
326 if (type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
327 std::pair<content::NavigationEntry*, bool>* title =
328 content::Details<std::pair<content::NavigationEntry*, bool> >(
332 string16 text = title->first->GetTitle();
333 window_->UpdateTitle(text);
338 void Runtime::OnWindowDestroyed() {
342 void Runtime::RequestMediaAccessPermission(
343 content::WebContents* web_contents,
344 const content::MediaStreamRequest& request,
345 const content::MediaResponseCallback& callback) {
346 XWalkMediaCaptureDevicesDispatcher::RunRequestMediaAccessPermission(
347 web_contents, request, callback);
350 void Runtime::RenderProcessGone(base::TerminationStatus status) {
351 content::RenderProcessHost* rph = web_contents_->GetRenderProcessHost();
352 VLOG(1) << "RenderProcess id: " << rph->GetID() << " is gone!";
353 XWalkRunner::GetInstance()->OnRenderProcessHostGone(rph);