Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / runtime.cc
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.
4
5 #include "xwalk/runtime/browser/runtime.h"
6
7 #include <string>
8 #include <utility>
9
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_process_host.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/web_contents.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"
32
33 using content::FaviconURL;
34 using content::WebContents;
35
36 namespace xwalk {
37
38 namespace {
39
40 // The default size for web content area size.
41 const int kDefaultWidth = 840;
42 const int kDefaultHeight = 600;
43
44 }  // namespace
45
46 // static
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();
52   return runtime;
53 }
54
55 // static
56 Runtime* Runtime::Create(RuntimeContext* runtime_context,
57                          Observer* observer,
58                          content::SiteInstance* site) {
59   WebContents::CreateParams params(runtime_context, site);
60   params.routing_id = MSG_ROUTING_NONE;
61   WebContents* web_contents = WebContents::Create(params);
62
63   Runtime* runtime = new Runtime(web_contents, observer);
64 #if defined(OS_TIZEN_MOBILE)
65   runtime->InitRootWindow();
66 #endif
67
68   return runtime;
69 }
70
71 Runtime::Runtime(content::WebContents* web_contents, Observer* observer)
72     : WebContentsObserver(web_contents),
73       web_contents_(web_contents),
74       window_(NULL),
75       weak_ptr_factory_(this),
76       fullscreen_options_(NO_FULLSCREEN),
77       observer_(observer) {
78   web_contents_->SetDelegate(this);
79   runtime_context_ = RuntimeContext::FromWebContents(web_contents);
80   content::NotificationService::current()->Notify(
81        xwalk::NOTIFICATION_RUNTIME_OPENED,
82        content::Source<Runtime>(this),
83        content::NotificationService::NoDetails());
84 #if defined(OS_TIZEN_MOBILE)
85   root_window_ = NULL;
86 #endif
87   if (observer_)
88     observer_->OnRuntimeAdded(this);
89 }
90
91 Runtime::~Runtime() {
92   content::NotificationService::current()->Notify(
93           xwalk::NOTIFICATION_RUNTIME_CLOSED,
94           content::Source<Runtime>(this),
95           content::NotificationService::NoDetails());
96   if (observer_)
97     observer_->OnRuntimeRemoved(this);
98 }
99
100 void Runtime::AttachDefaultWindow() {
101   NativeAppWindow::CreateParams params;
102   AttachWindow(params);
103 }
104
105 void Runtime::AttachWindow(const NativeAppWindow::CreateParams& params) {
106 #if defined(OS_ANDROID)
107   NOTIMPLEMENTED();
108 #else
109   CHECK(!window_);
110   NativeAppWindow::CreateParams effective_params(params);
111   ApplyWindowDefaultParams(&effective_params);
112
113   // Set the app icon if it is passed from command line.
114   CommandLine* command_line = CommandLine::ForCurrentProcess();
115   if (command_line->HasSwitch(switches::kAppIcon)) {
116     base::FilePath icon_file =
117         command_line->GetSwitchValuePath(switches::kAppIcon);
118     app_icon_ = xwalk_utils::LoadImageFromFilePath(icon_file);
119   } else {
120     // Otherwise, use the default icon for Crosswalk app.
121     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
122     app_icon_ = rb.GetNativeImageNamed(IDR_XWALK_ICON_48);
123   }
124
125   registrar_.Add(this,
126         content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
127         content::Source<content::WebContents>(web_contents_.get()));
128
129   window_ = NativeAppWindow::Create(effective_params);
130   if (!app_icon_.IsEmpty())
131     window_->UpdateIcon(app_icon_);
132   window_->Show();
133 #if defined(OS_TIZEN_MOBILE)
134   if (root_window_)
135     root_window_->Show();
136 #endif
137 #endif
138 }
139
140 void Runtime::LoadURL(const GURL& url) {
141   content::NavigationController::LoadURLParams params(url);
142   params.transition_type = content::PageTransitionFromInt(
143       content::PAGE_TRANSITION_TYPED |
144       content::PAGE_TRANSITION_FROM_ADDRESS_BAR);
145   web_contents_->GetController().LoadURLWithParams(params);
146   web_contents_->Focus();
147 }
148
149 void Runtime::Close() {
150   if (window_) {
151     window_->Close();
152     return;
153   }
154   // Runtime should not free itself on Close but be owned
155   // by Application.
156   delete this;
157 }
158
159 content::RenderProcessHost* Runtime::GetRenderProcessHost() {
160   return web_contents_->GetRenderProcessHost();
161 }
162
163 //////////////////////////////////////////////////////
164 // content::WebContentsDelegate:
165 //////////////////////////////////////////////////////
166 content::WebContents* Runtime::OpenURLFromTab(
167     content::WebContents* source, const content::OpenURLParams& params) {
168   // The only one disposition we would take into consideration.
169   DCHECK(params.disposition == CURRENT_TAB);
170   source->GetController().LoadURL(
171       params.url, params.referrer, params.transition, std::string());
172   return source;
173 }
174
175 void Runtime::LoadingStateChanged(content::WebContents* source,
176                                   bool to_different_document) {
177 }
178
179 void Runtime::ToggleFullscreenModeForTab(content::WebContents* web_contents,
180                                          bool enter_fullscreen) {
181   if (enter_fullscreen)
182     fullscreen_options_ |= FULLSCREEN_FOR_TAB;
183   else
184     fullscreen_options_ &= ~FULLSCREEN_FOR_TAB;
185
186   if (enter_fullscreen) {
187     window_->SetFullscreen(true);
188   } else if (!fullscreen_options_ & FULLSCREEN_FOR_LAUNCH) {
189     window_->SetFullscreen(false);
190   }
191 }
192
193 bool Runtime::IsFullscreenForTabOrPending(
194     const content::WebContents* web_contents) const {
195   return (fullscreen_options_ & FULLSCREEN_FOR_TAB) != 0;
196 }
197
198 void Runtime::RequestToLockMouse(content::WebContents* web_contents,
199                                  bool user_gesture,
200                                  bool last_unlocked_by_target) {
201   web_contents->GotResponseToLockMouseRequest(true);
202 }
203
204 void Runtime::CloseContents(content::WebContents* source) {
205   window_->Close();
206 }
207
208 bool Runtime::CanOverscrollContent() const {
209   return false;
210 }
211
212 bool Runtime::PreHandleKeyboardEvent(
213       content::WebContents* source,
214       const content::NativeWebKeyboardEvent& event,
215       bool* is_keyboard_shortcut) {
216   // Escape exits tabbed fullscreen mode.
217   if (event.windowsKeyCode == 27 && IsFullscreenForTabOrPending(source)) {
218     ToggleFullscreenModeForTab(source, false);
219     return true;
220   }
221   return false;
222 }
223
224 void Runtime::HandleKeyboardEvent(
225       content::WebContents* source,
226       const content::NativeWebKeyboardEvent& event) {
227 }
228
229 void Runtime::WebContentsCreated(
230     content::WebContents* source_contents,
231     int opener_render_frame_id,
232     const base::string16& frame_name,
233     const GURL& target_url,
234     content::WebContents* new_contents) {
235   Runtime* new_runtime = new Runtime(new_contents, observer_);
236 #if defined(OS_TIZEN_MOBILE)
237   new_runtime->SetRootWindow(root_window_);
238 #endif
239   new_runtime->AttachDefaultWindow();
240 }
241
242 void Runtime::DidNavigateMainFramePostCommit(
243     content::WebContents* web_contents) {
244 }
245
246 content::JavaScriptDialogManager* Runtime::GetJavaScriptDialogManager() {
247   return NULL;
248 }
249
250 void Runtime::ActivateContents(content::WebContents* contents) {
251   contents->GetRenderViewHost()->Focus();
252 }
253
254 void Runtime::DeactivateContents(content::WebContents* contents) {
255   contents->GetRenderViewHost()->Blur();
256 }
257
258 content::ColorChooser* Runtime::OpenColorChooser(
259     content::WebContents* web_contents,
260     SkColor initial_color,
261     const std::vector<content::ColorSuggestion>& suggestions) {
262   return xwalk::ShowColorChooser(web_contents, initial_color);
263 }
264
265 void Runtime::RunFileChooser(
266     content::WebContents* web_contents,
267     const content::FileChooserParams& params) {
268 #if defined(USE_AURA) && defined(OS_LINUX)
269   NOTIMPLEMENTED();
270 #else
271   RuntimeFileSelectHelper::RunFileChooser(web_contents, params);
272 #endif
273 }
274
275 void Runtime::EnumerateDirectory(content::WebContents* web_contents,
276                                  int request_id,
277                                  const base::FilePath& path) {
278 #if defined(USE_AURA) && defined(OS_LINUX)
279   NOTIMPLEMENTED();
280 #else
281   RuntimeFileSelectHelper::EnumerateDirectory(web_contents, request_id, path);
282 #endif
283 }
284
285 void Runtime::DidUpdateFaviconURL(const std::vector<FaviconURL>& candidates) {
286   DLOG(INFO) << "Candidates: ";
287   for (size_t i = 0; i < candidates.size(); ++i)
288     DLOG(INFO) << candidates[i].icon_url.spec();
289
290   if (candidates.empty())
291     return;
292
293   // Avoid using any previous download.
294   weak_ptr_factory_.InvalidateWeakPtrs();
295
296   // We only select the first favicon as the window app icon.
297   FaviconURL favicon = candidates[0];
298   // Passing 0 as the |image_size| parameter results in only receiving the first
299   // bitmap, according to content/public/browser/web_contents.h
300   web_contents()->DownloadImage(
301       favicon.icon_url,
302       true,  // Is a favicon
303       0,     // No maximum size
304       base::Bind(
305           &Runtime::DidDownloadFavicon, weak_ptr_factory_.GetWeakPtr()));
306 }
307
308 void Runtime::DidDownloadFavicon(int id,
309                                  int http_status_code,
310                                  const GURL& image_url,
311                                  const std::vector<SkBitmap>& bitmaps,
312                                  const std::vector<gfx::Size>& sizes) {
313   if (bitmaps.empty())
314     return;
315   app_icon_ = gfx::Image::CreateFrom1xBitmap(bitmaps[0]);
316   window_->UpdateIcon(app_icon_);
317 }
318
319 void Runtime::Observe(int type,
320                       const content::NotificationSource& source,
321                       const content::NotificationDetails& details) {
322   if (type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
323     std::pair<content::NavigationEntry*, bool>* title =
324         content::Details<std::pair<content::NavigationEntry*, bool> >(
325             details).ptr();
326
327     if (title->first) {
328       base::string16 text = title->first->GetTitle();
329       window_->UpdateTitle(text);
330     }
331   }
332 }
333
334 void Runtime::OnWindowDestroyed() {
335   // Runtime should not free itself on Close but be owned
336   // by Application.
337   delete this;
338 }
339
340 void Runtime::RequestMediaAccessPermission(
341     content::WebContents* web_contents,
342     const content::MediaStreamRequest& request,
343     const content::MediaResponseCallback& callback) {
344   XWalkMediaCaptureDevicesDispatcher::RunRequestMediaAccessPermission(
345       web_contents, request, callback);
346 }
347
348 void Runtime::ApplyWindowDefaultParams(NativeAppWindow::CreateParams* params) {
349   if (!params->delegate)
350     params->delegate = this;
351   if (!params->web_contents)
352     params->web_contents = web_contents_.get();
353   if (params->bounds.IsEmpty())
354     params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
355 #if defined(OS_TIZEN_MOBILE)
356   if (root_window_)
357     params->parent = root_window_->GetNativeWindow();
358 #endif
359   ApplyFullScreenParam(params);
360 }
361
362 void Runtime::ApplyFullScreenParam(NativeAppWindow::CreateParams* params) {
363   DCHECK(params);
364   if (params->state == ui::SHOW_STATE_FULLSCREEN)
365     fullscreen_options_ |= FULLSCREEN_FOR_LAUNCH;
366   else
367     fullscreen_options_ &= ~FULLSCREEN_FOR_LAUNCH;
368 }
369
370 #if defined(OS_TIZEN_MOBILE)
371 void Runtime::CloseRootWindow() {
372   if (root_window_) {
373     root_window_->Close();
374     root_window_ = NULL;
375   }
376 }
377
378 void Runtime::ApplyRootWindowParams(NativeAppWindow::CreateParams* params) {
379   if (!params->delegate)
380     params->delegate = this;
381   if (params->bounds.IsEmpty())
382     params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
383   ApplyFullScreenParam(params);
384 }
385
386 void Runtime::InitRootWindow() {
387   if (root_window_)
388     return;
389
390   NativeAppWindow::CreateParams params;
391   ApplyRootWindowParams(&params);
392   root_window_ = NativeAppWindow::Create(params);
393 }
394
395 void Runtime::SetRootWindow(NativeAppWindow* window) {
396   root_window_= window;
397 }
398
399 #endif
400 }  // namespace xwalk