Run Tizen Webapps in single process mode
[platform/framework/web/crosswalk-tizen.git] / atom / browser / browser.cc
1 // Copyright (c) 2013 GitHub, Inc.
2 // Use of this source code is governed by the MIT license that can be
3 // found in the LICENSE file.
4
5 #include "atom/browser/browser.h"
6
7 #include <string>
8 #include <app.h>
9
10 #include "atom/browser/atom_browser_main_parts.h"
11 #include "atom/browser/browser_observer.h"
12 #include "atom/browser/native_window.h"
13 #include "atom/browser/window_list.h"
14 #include "base/files/file_util.h"
15 #include "base/path_service.h"
16 #include "base/run_loop.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "brightray/browser/brightray_paths.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_view_host.h"
22
23 #if defined(OS_TIZEN)
24 #include "tizen/common/command_line.h"
25 #include "tizen/common/application_data.h"
26 #include <Elementary.h>
27 #include "wgt_manifest_handlers/launch_screen_handler.h"
28 #endif  // defined(OS_TIZEN)
29
30 #include "tizen/common/env_variables.h"
31
32 namespace atom {
33
34 Browser::Browser()
35     : is_quiting_(false),
36 #if defined(OS_TIZEN)
37       launched_(false),
38       is_electron_launch_(false),
39 #endif
40       is_exiting_(false),
41       is_ready_(false),
42       is_shutdown_(false) {
43   WindowList::AddObserver(this);
44 }
45
46 Browser::~Browser() {
47   WindowList::RemoveObserver(this);
48 }
49
50 #if defined(OS_TIZEN)
51 const char* kAppControlMain = "http://tizen.org/appcontrol/operation/main";
52 const char* kAppControlEventScript =
53     "(function(){"
54     "var __event = document.createEvent(\"CustomEvent\");\n"
55     "__event.initCustomEvent(\"appcontrol\", true, true, null);\n"
56     "document.dispatchEvent(__event);\n"
57     "\n"
58     "for(var i=0; i < window.frames.length; i++)\n"
59     "{ window.frames[i].document.dispatchEvent(__event); }"
60     "})()";
61 const char* kDefaultCSPRule =
62     "default-src *; script-src 'self'; style-src 'self'; object-src 'none';";
63 #endif
64
65 // static
66 Browser* Browser::Get() {
67   if (AtomBrowserMainParts::Get())
68     return AtomBrowserMainParts::Get()->browser();
69   else
70     return AtomBrowserMainParts::GetStaticBrowser();
71 }
72
73 void Browser::Quit() {
74   if (is_quiting_)
75     return;
76
77   is_quiting_ = HandleBeforeQuit();
78   if (!is_quiting_)
79     return;
80
81   if (atom::WindowList::IsEmpty())
82     NotifyAndShutdown();
83   else
84     atom::WindowList::CloseAllWindows();
85 }
86
87 void Browser::Exit(mate::Arguments* args) {
88   int code = 0;
89   args->GetNext(&code);
90
91   if (!AtomBrowserMainParts::Get()->SetExitCode(code)) {
92     // Message loop is not ready, quit directly.
93     exit(code);
94   } else {
95     // Prepare to quit when all windows have been closed.
96     is_quiting_ = true;
97
98     // Remember this caller so that we don't emit unrelated events.
99     is_exiting_ = true;
100
101     // Must destroy windows before quitting, otherwise bad things can happen.
102     if (atom::WindowList::IsEmpty()) {
103       Shutdown();
104     } else {
105       // Unlike Quit(), we do not ask to close window, but destroy the window
106       // without asking.
107       atom::WindowList::DestroyAllWindows();
108     }
109   }
110 }
111
112 void Browser::Shutdown() {
113   if (is_shutdown_)
114     return;
115
116   is_shutdown_ = true;
117   is_quiting_ = true;
118
119   for (BrowserObserver& observer : observers_)
120     observer.OnQuit();
121
122   if (base::ThreadTaskRunnerHandle::IsSet()) {
123     if (::tizen::is_single_process) {
124       base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
125         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), base::TimeDelta::FromSeconds(1));
126     } else {
127       base::ThreadTaskRunnerHandle::Get()->PostTask(
128         FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
129     }
130     ui_app_exit();
131   } else {
132     // There is no message loop available so we are in early stage.
133     exit(0);
134   }
135 }
136
137 #if defined(OS_TIZEN)
138 void Browser::SetElectronAppLaunch() {
139   if (!is_electron_launch_) {
140     auto app_data = common::ApplicationDataManager::GetCurrentAppData();
141     if (app_data->content_info() && !strcmp(app_data->content_info()->src().c_str(), "package.json")) {
142       is_electron_launch_ = true;
143     }
144   } else {
145     is_electron_launch_ = false;
146   }
147 }
148 #endif
149
150 std::string Browser::GetVersion() const {
151   if (version_override_.empty()) {
152     std::string version = GetExecutableFileVersion();
153     if (!version.empty())
154       return version;
155   }
156
157   return version_override_;
158 }
159
160 void Browser::SetVersion(const std::string& version) {
161   version_override_ = version;
162 }
163
164 std::string Browser::GetName() const {
165   if (name_override_.empty()) {
166     std::string name = GetExecutableFileProductName();
167     if (!name.empty())
168       return name;
169   }
170
171   return name_override_;
172 }
173
174 void Browser::SetName(const std::string& name) {
175   name_override_ = name;
176 }
177
178 int Browser::GetBadgeCount() {
179   return badge_count_;
180 }
181
182 bool Browser::OpenFile(const std::string& file_path) {
183   bool prevent_default = false;
184   for (BrowserObserver& observer : observers_)
185     observer.OnOpenFile(&prevent_default, file_path);
186
187   return prevent_default;
188 }
189
190 void Browser::OpenURL(const std::string& url) {
191   for (BrowserObserver& observer : observers_)
192     observer.OnOpenURL(url);
193 }
194
195 void Browser::Activate(bool has_visible_windows) {
196   for (BrowserObserver& observer : observers_)
197     observer.OnActivate(has_visible_windows);
198 }
199
200 void Browser::WillFinishLaunching() {
201 #if defined(OS_TIZEN)
202   SetElectronAppLaunch();
203 #endif
204   for (BrowserObserver& observer : observers_)
205     observer.OnWillFinishLaunching();
206 }
207
208 void Browser::DidFinishLaunching(const base::DictionaryValue& launch_info) {
209   // Make sure the userData directory is created.
210   base::FilePath user_data;
211   if (PathService::Get(brightray::DIR_USER_DATA, &user_data))
212     base::CreateDirectoryAndGetError(user_data, nullptr);
213
214   is_ready_ = true;
215   for (BrowserObserver& observer : observers_)
216     observer.OnFinishLaunching(launch_info);
217 }
218
219 void Browser::OnAccessibilitySupportChanged() {
220   for (BrowserObserver& observer : observers_)
221     observer.OnAccessibilitySupportChanged();
222 }
223
224 void Browser::RequestLogin(
225     LoginHandler* login_handler,
226     std::unique_ptr<base::DictionaryValue> request_details) {
227   for (BrowserObserver& observer : observers_)
228     observer.OnLogin(login_handler, *(request_details.get()));
229 }
230
231 void Browser::NotifyAndShutdown() {
232   if (is_shutdown_)
233     return;
234
235   bool prevent_default = false;
236   for (BrowserObserver& observer : observers_)
237     observer.OnWillQuit(&prevent_default);
238
239   if (prevent_default) {
240     is_quiting_ = false;
241     return;
242   }
243
244   Shutdown();
245 }
246
247 bool Browser::HandleBeforeQuit() {
248   bool prevent_default = false;
249   for (BrowserObserver& observer : observers_)
250     observer.OnBeforeQuit(&prevent_default);
251
252   return !prevent_default;
253 }
254
255 void Browser::OnWindowCloseCancelled(NativeWindow* window) {
256   if (is_quiting_)
257     // Once a beforeunload handler has prevented the closing, we think the quit
258     // is cancelled too.
259     is_quiting_ = false;
260 }
261
262 void Browser::OnWindowAllClosed() {
263   if (is_exiting_) {
264     Shutdown();
265   } else if (is_quiting_) {
266     NotifyAndShutdown();
267   } else {
268     for (BrowserObserver& observer : observers_)
269       observer.OnWindowAllClosed();
270   }
271 }
272
273 #if defined(OS_TIZEN)
274 void Browser::Hide() {
275   NativeWindow *last_window = WindowList::GetLastWindow();
276   if (!last_window)
277     return;
278
279   last_window->NotifySuspend();
280   auto rvh = last_window->web_contents()->GetRenderViewHost();
281   atom::Browser::Get()->Suspend(rvh);
282 }
283
284 void Browser::Show() {
285   NativeWindow *last_window = WindowList::GetLastWindow();
286   if (!last_window)
287     return;
288
289   last_window->NotifyResume();
290   auto rvh = last_window->web_contents()->GetRenderViewHost();
291   atom::Browser::Get()->Resume(rvh);
292 }
293
294 void Browser::AppControl(std::unique_ptr<common::AppControl> appcontrol) {
295   std::unique_ptr<common::ResourceManager::Resource> res =
296       resource_manager_->GetStartResource(appcontrol.get());
297   bool do_reset = res->should_reset();
298   NativeWindow *last_window = WindowList::GetLastWindow();
299   std::string localized_page = res->uri();
300   if (!do_reset) {
301     std::string current_page = last_window->web_contents()->GetURL().spec();
302     if (current_page != localized_page)
303       do_reset = true;
304     else
305       SendAppControlEvent();
306     }
307   if (do_reset && (appcontrol->operation() == kAppControlMain)) {
308     do_reset = false;
309     SendAppControlEvent();
310   }
311   if (do_reset) {
312     //To do :Implementation of ClearViewStack(), SetupWebWindow(),SetupWebWindowCompatibilitySettings() function
313   }
314 }
315
316 void Browser::SendAppControlEvent() {
317   NativeWindow *last_window = WindowList::GetLastWindow();
318
319   if (last_window != NULL) {
320     content::RenderFrameHost* rfh = last_window->web_contents()->GetMainFrame();
321     if (rfh) {
322       rfh->ExecuteJavaScriptWithUserGestureForTests(
323         base::UTF8ToUTF16(kAppControlEventScript));
324     }
325   }
326 }
327
328 void Browser::Launch(std::unique_ptr<common::AppControl> appcontrol) {
329   launched_ = true;
330 //To do:Implementation of relaunching of app
331   std::unique_ptr<common::ResourceManager::Resource> res =
332       resource_manager_->GetStartResource(appcontrol.get());
333   if (res)
334     start_url_ = resource_manager_->GetLocalizedPath(res->uri());
335
336   NativeWindow *last_window = WindowList::GetLastWindow();
337   if (last_window)
338     last_window->NotifyAppControl();
339 }
340
341 void Browser::SetSplashScreen() {
342   auto appdata = common::ApplicationDataManager::GetCurrentAppData();
343   Evas_Object* window_ = elm_win_util_standard_add("", "");
344
345   splash_screen_.reset(
346       new SplashScreen(
347         window_, appdata->splash_screen_info(), appdata->application_path()));
348 }
349
350 void Browser::HideSplashScreen(int reason) {
351   auto appdata = common::ApplicationDataManager::GetCurrentAppData();
352   if (!appdata->splash_screen_info()) {
353     return;
354   }
355
356   splash_screen_->HideSplashScreen(reason);
357 }
358 #endif  // defined(OS_TIZEN)
359
360 }  // namespace atom