Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / browser / application_tizen.cc
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include "xwalk/application/browser/application_tizen.h"
7
8 #include <set>
9 #include <string>
10 #include <vector>
11
12 #include "content/browser/renderer_host/media/audio_renderer_host.h"
13 #include "content/browser/renderer_host/render_process_host_impl.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/screen_orientation_dispatcher_host.h"
17 #include "content/public/browser/screen_orientation_delegate.h"
18 #include "content/public/browser/screen_orientation_provider.h"
19
20 #include "xwalk/runtime/browser/xwalk_browser_context.h"
21 #include "xwalk/runtime/browser/runtime_url_request_context_getter.h"
22 #include "xwalk/runtime/browser/ui/native_app_window.h"
23 #include "xwalk/runtime/browser/ui/native_app_window_tizen.h"
24 #include "xwalk/runtime/common/xwalk_common_messages.h"
25
26 #if defined(USE_OZONE)
27 #include "content/public/browser/render_view_host.h"
28 #include "ui/events/event.h"
29 #include "ui/events/event_constants.h"
30 #include "ui/events/keycodes/keyboard_codes_posix.h"
31 #include "ui/events/platform/platform_event_source.h"
32 #endif
33
34 #include "xwalk/application/common/application_manifest_constants.h"
35 #include "xwalk/application/common/manifest_handlers/tizen_setting_handler.h"
36 #include "xwalk/application/common/manifest_handlers/tizen_splash_screen_handler.h"
37
38 namespace xwalk {
39
40 namespace keys = application_manifest_keys;
41 namespace widget_keys = application_widget_keys;
42
43 namespace application {
44
45 const char kDefaultMediaAppClass[] = "player";
46 namespace {
47 #if defined(OS_TIZEN_MOBILE)
48 void ApplyRootWindowParams(Runtime* runtime,
49                            NativeAppWindow::CreateParams* params) {
50   if (!params->delegate)
51     params->delegate = runtime;
52   if (params->bounds.IsEmpty())
53     params->bounds = gfx::Rect(0, 0, 840, 600);
54
55   unsigned int fullscreen_options = runtime->fullscreen_options();
56   if (params->state == ui::SHOW_STATE_FULLSCREEN)
57     fullscreen_options |= Runtime::FULLSCREEN_FOR_LAUNCH;
58   else
59     fullscreen_options &= ~Runtime::FULLSCREEN_FOR_LAUNCH;
60   runtime->set_fullscreen_options(fullscreen_options);
61 }
62
63 NativeAppWindow* CreateRootWindow(Runtime* runtime,
64                                   const NativeAppWindow::CreateParams& params) {
65   NativeAppWindow::CreateParams effective_params(params);
66   ApplyRootWindowParams(runtime, &effective_params);
67   return NativeAppWindow::Create(effective_params);
68 }
69 #endif
70 }  // namespace
71
72 blink::WebScreenOrientationLockType GetDefaultOrientation(
73     const base::WeakPtr<Application>& app) {
74   TizenSettingInfo* info = static_cast<TizenSettingInfo*>(
75     app->data()->GetManifestData(widget_keys::kTizenSettingKey));
76   if (!info)
77     return blink::WebScreenOrientationLockDefault;
78   switch (info->screen_orientation()) {
79     case TizenSettingInfo::PORTRAIT:
80       return blink::WebScreenOrientationLockPortrait;
81     case TizenSettingInfo::LANDSCAPE:
82       return blink::WebScreenOrientationLockLandscape;
83     case TizenSettingInfo::AUTO:
84       return blink::WebScreenOrientationLockAny;
85     default:
86       NOTREACHED();
87       return blink::WebScreenOrientationLockDefault;
88   }
89 }
90
91 class ScreenOrientationDelegateTizen :
92     public content::ScreenOrientationDelegate {
93  public:
94   ScreenOrientationDelegateTizen(
95       const base::WeakPtr<Application>& app,
96       content::ScreenOrientationDispatcherHost* dispatcher)
97       : app_(app),
98         dispatcher_(dispatcher) {
99     DCHECK(dispatcher_);
100   }
101
102   bool FullScreenRequired(
103       content::WebContents* web_contents) override {
104     if (!app_) {
105       LOG(ERROR) << "Invalid app error";
106       return false;
107     }
108     return app_->IsFullScreenRequired();
109   }
110
111   void Lock(blink::WebScreenOrientationLockType lock) override {
112     if (!app_) {
113       LOG(ERROR) << "Invalid app error";
114       return;
115     }
116     const std::vector<Runtime*>& runtimes = app_->runtimes();
117     DCHECK(!runtimes.empty());
118     // FIXME: Probably need better alignment with
119     // https://w3c.github.io/screen-orientation/#screen-orientation-lock-lifetime
120     for (auto it = runtimes.begin(); it != runtimes.end(); ++it) {
121       NativeAppWindow* window = (*it)->window();
122       if (window && window->IsActive()) {
123         ToNativeAppWindowTizen(window)->LockOrientation(lock);
124         break;
125       }
126     }
127     int request_id = app_->GetRenderProcessHostID();
128     dispatcher_->NotifyLockSuccess(request_id);
129   }
130
131   bool ScreenOrientationProviderSupported() override {
132     return true;
133   }
134
135   void Unlock() override {
136     Lock(GetDefaultOrientation(app_));
137   }
138
139  private:
140   base::WeakPtr<Application> app_;
141   content::ScreenOrientationDispatcherHost* dispatcher_;
142 };
143
144 ApplicationTizen::ApplicationTizen(
145     scoped_refptr<ApplicationData> data,
146     XWalkBrowserContext* browser_context)
147     : Application(data, browser_context),
148 #if defined(OS_TIZEN_MOBILE)
149       root_window_(NULL),
150 #endif
151       is_suspended_(false) {
152 #if defined(USE_OZONE)
153   ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
154 #endif
155   cookie_manager_ = scoped_ptr<CookieManager>(
156       new CookieManager(id(), browser_context_));
157 }
158
159 ApplicationTizen::~ApplicationTizen() {
160 #if defined(USE_OZONE)
161   ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
162 #endif
163 }
164
165 void ApplicationTizen::Hide() {
166   DCHECK(!runtimes_.empty());
167   for (auto it = runtimes_.begin(); it != runtimes_.end(); ++it) {
168     if ((*it)->window())
169       (*it)->window()->Minimize();
170   }
171 }
172
173 void ApplicationTizen::Show() {
174   DCHECK(!runtimes_.empty());
175   for (Runtime* runtime : runtimes_) {
176     if (auto window = runtime->window())
177       window->Restore();
178   }
179 }
180
181 bool ApplicationTizen::Launch(const LaunchParams& launch_params) {
182   if (Application::Launch(launch_params)) {
183 #if defined(OS_TIZEN_MOBILE)
184     if (!runtimes_.empty()) {
185       root_window_ = CreateRootWindow(*(runtimes_.begin()),
186                                       window_show_params_);
187       window_show_params_.parent = root_window_->GetNativeWindow();
188       root_window_->Show();
189     }
190 #endif
191     DCHECK(web_contents_);
192
193     // Get media class of application.
194     const Manifest* manifest = data_->GetManifest();
195     std::string app_class;
196     manifest->GetString(keys::kXWalkMediaAppClass, &app_class);
197     if (app_class.empty())
198       app_class = kDefaultMediaAppClass;
199
200     // Set an application ID and class, which are needed to tag audio
201     // streams in pulseaudio/Murphy.
202     scoped_refptr<content::AudioRendererHost> audio_host =
203         static_cast<content::RenderProcessHostImpl*>(render_process_host_)
204             ->audio_renderer_host();
205     if (audio_host.get())
206       audio_host->SetMediaStreamProperties(id(), app_class);
207
208     content::ScreenOrientationDispatcherHost* host =
209         web_contents_->GetScreenOrientationDispatcherHost();
210     content::ScreenOrientationDelegate* delegate =
211         new ScreenOrientationDelegateTizen(GetWeakPtr(), host);
212     content::ScreenOrientationProvider::SetDelegate(delegate);
213     delegate->Lock(GetDefaultOrientation(GetWeakPtr()));
214     return true;
215   }
216   return false;
217 }
218
219 base::FilePath ApplicationTizen::GetSplashScreenPath() {
220   if (TizenSplashScreenInfo* ss_info = static_cast<TizenSplashScreenInfo*>(
221       data()->GetManifestData(widget_keys::kTizenSplashScreenKey))) {
222     return data()->path().Append(FILE_PATH_LITERAL(ss_info->src()));
223   }
224   return base::FilePath();
225 }
226
227 bool ApplicationTizen::CanBeSuspended() const {
228   if (TizenSettingInfo* setting = static_cast<TizenSettingInfo*>(
229           data()->GetManifestData(widget_keys::kTizenSettingKey))) {
230     return !setting->background_support_enabled();
231   }
232   return true;
233 }
234
235 void ApplicationTizen::Suspend() {
236   if (is_suspended_ || !CanBeSuspended())
237     return;
238
239   DCHECK(render_process_host_);
240   render_process_host_->Send(new ViewMsg_SuspendJSEngine(true));
241
242   DCHECK(!runtimes_.empty());
243   for (auto it = runtimes_.begin(); it != runtimes_.end(); ++it) {
244     if ((*it)->web_contents())
245       (*it)->web_contents()->WasHidden();
246   }
247   is_suspended_ = true;
248 }
249
250 void ApplicationTizen::Resume() {
251   if (!is_suspended_ || !CanBeSuspended())
252     return;
253
254   DCHECK(render_process_host_);
255   render_process_host_->Send(new ViewMsg_SuspendJSEngine(false));
256
257   DCHECK(!runtimes_.empty());
258   for (auto it = runtimes_.begin(); it != runtimes_.end(); ++it) {
259     if ((*it)->web_contents())
260       (*it)->web_contents()->WasShown();
261   }
262   is_suspended_ = false;
263 }
264
265 #if defined(USE_OZONE)
266 void ApplicationTizen::WillProcessEvent(const ui::PlatformEvent& event) {}
267
268 void ApplicationTizen::DidProcessEvent(
269     const ui::PlatformEvent& event) {
270   ui::Event* ui_event = static_cast<ui::Event*>(event);
271   if (!ui_event->IsKeyEvent() || ui_event->type() != ui::ET_KEY_PRESSED)
272     return;
273
274   ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(ui_event);
275
276   // FIXME: Most Wayland devices don't have similar hardware button for 'back'
277   // and 'memu' as Tizen Mobile, even that hardare buttons could be different
278   // across different kinds of Wayland platforms.
279   // Here use external keyboard button 'Backspace' & 'HOME' to emulate 'back'
280   // and 'menu' key. Should change this if there is customized key binding.
281   if (key_event->key_code() != ui::VKEY_BACK &&
282       key_event->key_code() != ui::VKEY_HOME)
283     return;
284
285   TizenSettingInfo* info = static_cast<TizenSettingInfo*>(
286       data()->GetManifestData(widget_keys::kTizenSettingKey));
287   if (info && !info->hwkey_enabled())
288     return;
289
290   for (auto it = runtimes_.begin();
291       it != runtimes_.end(); ++it) {
292     (*it)->web_contents()->GetRenderViewHost()->Send(new ViewMsg_HWKeyPressed(
293         (*it)->web_contents()->GetRoutingID(), key_event->key_code()));
294   }
295 }
296 #endif
297
298 void ApplicationTizen::RemoveAllCookies() {
299   cookie_manager_->RemoveAllCookies();
300 }
301
302 void ApplicationTizen::SetUserAgentString(
303     const std::string& user_agent_string) {
304   cookie_manager_->SetUserAgentString(render_process_host_, user_agent_string);
305 }
306
307 void ApplicationTizen::OnNewRuntimeAdded(Runtime* runtime) {
308   DCHECK(runtime);
309   Application::OnNewRuntimeAdded(runtime);
310 #if defined(OS_TIZEN_MOBILE)
311   if (root_window_ && runtimes_.size() > 1)
312       root_window_->Show();
313 #endif
314 }
315
316 void ApplicationTizen::OnRuntimeClosed(Runtime* runtime) {
317   DCHECK(runtime);
318   Application::OnRuntimeClosed(runtime);
319 #if defined(OS_TIZEN_MOBILE)
320   if (runtimes_.empty() && root_window_) {
321     root_window_->Close();
322     root_window_ = NULL;
323   }
324 #endif
325 }
326
327 }  // namespace application
328 }  // namespace xwalk