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.
5 #include "atom/browser/api/atom_api_app.h"
10 #include "atom/browser/api/atom_api_menu.h"
11 #include "atom/browser/api/atom_api_session.h"
12 #include "atom/browser/api/atom_api_web_contents.h"
13 #include "atom/browser/atom_browser_context.h"
14 #include "atom/browser/atom_browser_main_parts.h"
15 #include "atom/browser/login_handler.h"
16 #include "atom/browser/relauncher.h"
17 #include "atom/common/atom_command_line.h"
18 #include "atom/common/native_mate_converters/callback.h"
19 #include "atom/common/native_mate_converters/file_path_converter.h"
20 #include "atom/common/native_mate_converters/gurl_converter.h"
21 #include "atom/common/native_mate_converters/image_converter.h"
22 #include "atom/common/native_mate_converters/net_converter.h"
23 #include "atom/common/native_mate_converters/value_converter.h"
24 #include "atom/common/node_includes.h"
25 #include "atom/common/options_switches.h"
26 #include "base/command_line.h"
27 #include "base/environment.h"
28 #include "base/files/file_path.h"
29 #include "base/files/file_util.h"
30 #include "base/path_service.h"
31 #include "base/strings/string_util.h"
32 #include "brightray/browser/brightray_paths.h"
33 #include "chrome/browser/browser_process.h"
34 #include "chrome/browser/icon_manager.h"
35 #include "chrome/common/chrome_paths.h"
36 #include "content/public/browser/browser_accessibility_state.h"
37 #include "content/public/browser/client_certificate_delegate.h"
38 #include "content/public/browser/gpu_data_manager.h"
39 #include "content/public/browser/render_frame_host.h"
40 #include "content/public/common/content_switches.h"
41 #include "media/audio/audio_manager.h"
42 #include "native_mate/dictionary.h"
43 #include "native_mate/object_template_builder.h"
44 #include "net/ssl/ssl_cert_request_info.h"
45 #include "tizen/common/env_variables.h"
46 #include "ui/base/l10n/l10n_util.h"
47 #include "ui/gfx/image/image.h"
50 #include "atom/browser/ui/win/jump_list.h"
51 #include "base/strings/utf_string_conversions.h"
60 struct Converter<Browser::UserTask> {
61 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
62 Browser::UserTask* out) {
63 mate::Dictionary dict;
64 if (!ConvertFromV8(isolate, val, &dict))
66 if (!dict.Get("program", &(out->program)) ||
67 !dict.Get("title", &(out->title)))
69 if (dict.Get("iconPath", &(out->icon_path)) &&
70 !dict.Get("iconIndex", &(out->icon_index)))
72 dict.Get("arguments", &(out->arguments));
73 dict.Get("description", &(out->description));
78 using atom::JumpListItem;
79 using atom::JumpListCategory;
80 using atom::JumpListResult;
83 struct Converter<JumpListItem::Type> {
84 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
85 JumpListItem::Type* out) {
86 std::string item_type;
87 if (!ConvertFromV8(isolate, val, &item_type))
90 if (item_type == "task")
91 *out = JumpListItem::Type::TASK;
92 else if (item_type == "separator")
93 *out = JumpListItem::Type::SEPARATOR;
94 else if (item_type == "file")
95 *out = JumpListItem::Type::FILE;
102 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
103 JumpListItem::Type val) {
104 std::string item_type;
106 case JumpListItem::Type::TASK:
110 case JumpListItem::Type::SEPARATOR:
111 item_type = "separator";
114 case JumpListItem::Type::FILE:
118 return mate::ConvertToV8(isolate, item_type);
123 struct Converter<JumpListItem> {
124 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
126 mate::Dictionary dict;
127 if (!ConvertFromV8(isolate, val, &dict))
130 if (!dict.Get("type", &(out->type)))
134 case JumpListItem::Type::TASK:
135 if (!dict.Get("program", &(out->path)) ||
136 !dict.Get("title", &(out->title)))
139 if (dict.Get("iconPath", &(out->icon_path)) &&
140 !dict.Get("iconIndex", &(out->icon_index)))
143 dict.Get("args", &(out->arguments));
144 dict.Get("description", &(out->description));
147 case JumpListItem::Type::SEPARATOR:
150 case JumpListItem::Type::FILE:
151 return dict.Get("path", &(out->path));
158 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
159 const JumpListItem& val) {
160 mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
161 dict.Set("type", val.type);
164 case JumpListItem::Type::TASK:
165 dict.Set("program", val.path);
166 dict.Set("args", val.arguments);
167 dict.Set("title", val.title);
168 dict.Set("iconPath", val.icon_path);
169 dict.Set("iconIndex", val.icon_index);
170 dict.Set("description", val.description);
173 case JumpListItem::Type::SEPARATOR:
176 case JumpListItem::Type::FILE:
177 dict.Set("path", val.path);
180 return dict.GetHandle();
185 struct Converter<JumpListCategory::Type> {
186 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
187 JumpListCategory::Type* out) {
188 std::string category_type;
189 if (!ConvertFromV8(isolate, val, &category_type))
192 if (category_type == "tasks")
193 *out = JumpListCategory::Type::TASKS;
194 else if (category_type == "frequent")
195 *out = JumpListCategory::Type::FREQUENT;
196 else if (category_type == "recent")
197 *out = JumpListCategory::Type::RECENT;
198 else if (category_type == "custom")
199 *out = JumpListCategory::Type::CUSTOM;
206 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
207 JumpListCategory::Type val) {
208 std::string category_type;
210 case JumpListCategory::Type::TASKS:
211 category_type = "tasks";
214 case JumpListCategory::Type::FREQUENT:
215 category_type = "frequent";
218 case JumpListCategory::Type::RECENT:
219 category_type = "recent";
222 case JumpListCategory::Type::CUSTOM:
223 category_type = "custom";
226 return mate::ConvertToV8(isolate, category_type);
231 struct Converter<JumpListCategory> {
232 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
233 JumpListCategory* out) {
234 mate::Dictionary dict;
235 if (!ConvertFromV8(isolate, val, &dict))
238 if (dict.Get("name", &(out->name)) && out->name.empty())
241 if (!dict.Get("type", &(out->type))) {
242 if (out->name.empty())
243 out->type = JumpListCategory::Type::TASKS;
245 out->type = JumpListCategory::Type::CUSTOM;
248 if ((out->type == JumpListCategory::Type::TASKS) ||
249 (out->type == JumpListCategory::Type::CUSTOM)) {
250 if (!dict.Get("items", &(out->items)))
260 struct Converter<JumpListResult> {
261 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, JumpListResult val) {
262 std::string result_code;
264 case JumpListResult::SUCCESS:
268 case JumpListResult::ARGUMENT_ERROR:
269 result_code = "argumentError";
272 case JumpListResult::GENERIC_ERROR:
273 result_code = "error";
276 case JumpListResult::CUSTOM_CATEGORY_SEPARATOR_ERROR:
277 result_code = "invalidSeparatorError";
280 case JumpListResult::MISSING_FILE_TYPE_REGISTRATION_ERROR:
281 result_code = "fileTypeRegistrationError";
284 case JumpListResult::CUSTOM_CATEGORY_ACCESS_DENIED_ERROR:
285 result_code = "customCategoryAccessDeniedError";
288 return ConvertToV8(isolate, result_code);
294 struct Converter<Browser::LoginItemSettings> {
295 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
296 Browser::LoginItemSettings* out) {
297 mate::Dictionary dict;
298 if (!ConvertFromV8(isolate, val, &dict))
301 dict.Get("openAtLogin", &(out->open_at_login));
302 dict.Get("openAsHidden", &(out->open_as_hidden));
303 dict.Get("path", &(out->path));
304 dict.Get("args", &(out->args));
308 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
309 Browser::LoginItemSettings val) {
310 mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
311 dict.Set("openAtLogin", val.open_at_login);
312 dict.Set("openAsHidden", val.open_as_hidden);
313 dict.Set("restoreState", val.restore_state);
314 dict.Set("wasOpenedAtLogin", val.opened_at_login);
315 dict.Set("wasOpenedAsHidden", val.opened_as_hidden);
316 return dict.GetHandle();
321 struct Converter<content::CertificateRequestResultType> {
322 static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
323 content::CertificateRequestResultType* out) {
325 if (!ConvertFromV8(isolate, val, &b))
327 *out = b ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE :
328 content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
341 IconLoader::IconSize GetIconSizeByString(const std::string& size) {
342 if (size == "small") {
343 return IconLoader::IconSize::SMALL;
344 } else if (size == "large") {
345 return IconLoader::IconSize::LARGE;
347 return IconLoader::IconSize::NORMAL;
350 // Return the path constant from string.
351 int GetPathConstant(const std::string& name) {
352 if (name == "appData")
353 return brightray::DIR_APP_DATA;
354 else if (name == "userData")
355 return brightray::DIR_USER_DATA;
356 else if (name == "cache")
357 return brightray::DIR_CACHE;
358 else if (name == "userCache")
359 return brightray::DIR_USER_CACHE;
360 else if (name == "home")
361 return base::DIR_HOME;
362 else if (name == "temp")
363 return base::DIR_TEMP;
364 else if (name == "userDesktop" || name == "desktop")
365 return base::DIR_USER_DESKTOP;
366 else if (name == "exe")
367 return base::FILE_EXE;
368 else if (name == "module")
369 return base::FILE_MODULE;
370 else if (name == "documents")
371 return chrome::DIR_USER_DOCUMENTS;
372 else if (name == "downloads")
373 return chrome::DIR_DEFAULT_DOWNLOADS;
374 else if (name == "music")
375 return chrome::DIR_USER_MUSIC;
376 else if (name == "pictures")
377 return chrome::DIR_USER_PICTURES;
378 else if (name == "videos")
379 return chrome::DIR_USER_VIDEOS;
380 else if (name == "pepperFlashSystemPlugin")
381 return chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN;
386 bool NotificationCallbackWrapper(
387 const ProcessSingleton::NotificationCallback& callback,
388 const base::CommandLine::StringVector& cmd,
389 const base::FilePath& cwd) {
390 // Make sure the callback is called after app gets ready.
391 if (Browser::Get()->is_ready()) {
392 callback.Run(cmd, cwd);
394 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
395 base::ThreadTaskRunnerHandle::Get());
396 task_runner->PostTask(
397 FROM_HERE, base::Bind(base::IgnoreResult(callback), cmd, cwd));
399 // ProcessSingleton needs to know whether current process is quiting.
400 return !Browser::Get()->is_shutting_down();
403 void OnClientCertificateSelected(
404 v8::Isolate* isolate,
405 std::shared_ptr<content::ClientCertificateDelegate> delegate,
406 mate::Arguments* args) {
407 if (args->Length() == 2) {
408 delegate->ContinueWithCertificate(nullptr);
412 v8::Local<v8::Value> val;
415 delegate->ContinueWithCertificate(nullptr);
419 mate::Dictionary cert_data;
420 if (!mate::ConvertFromV8(isolate, val, &cert_data)) {
421 args->ThrowError("Must pass valid certificate object.");
426 if (!cert_data.Get("data", &data))
429 auto certs = net::X509Certificate::CreateCertificateListFromBytes(
430 data.c_str(), data.length(), net::X509Certificate::FORMAT_AUTO);
432 delegate->ContinueWithCertificate(certs[0].get());
435 void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
436 mate::Arguments* args) {
437 base::string16 username, password;
438 if (args->GetNext(&username) && args->GetNext(&password))
439 login_handler->Login(username, password);
441 login_handler->CancelAuth();
444 #if defined(USE_NSS_CERTS)
445 int ImportIntoCertStore(
446 CertificateManagerModel* model,
447 const base::DictionaryValue& options) {
448 std::string file_data, cert_path;
449 base::string16 password;
450 net::CertificateList imported_certs;
452 options.GetString("certificate", &cert_path);
453 options.GetString("password", &password);
455 if (!cert_path.empty()) {
456 if (base::ReadFileToString(base::FilePath(cert_path), &file_data)) {
457 auto module = model->cert_db()->GetPublicModule();
458 rv = model->ImportFromPKCS12(module,
463 if (imported_certs.size() > 1) {
464 auto it = imported_certs.begin();
465 ++it; // skip first which would be the client certificate.
466 for (; it != imported_certs.end(); ++it)
467 rv &= model->SetCertTrust(it->get(),
469 net::NSSCertDatabase::TRUSTED_SSL);
477 void OnIconDataAvailable(v8::Isolate* isolate,
478 const App::FileIconCallback& callback,
480 if (!::tizen::is_single_process)
481 v8::Locker locker(isolate);
482 v8::HandleScope handle_scope(isolate);
484 if (icon && !icon->IsEmpty()) {
485 callback.Run(v8::Null(isolate), *icon);
487 v8::Local<v8::String> error_message =
488 v8::String::NewFromUtf8(isolate, "Failed to get file icon.");
489 callback.Run(v8::Exception::Error(error_message), gfx::Image());
495 App::App(v8::Isolate* isolate) {
496 if (AtomBrowserClient::Get())
497 static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
498 Browser::Get()->AddObserver(this);
499 content::GpuDataManager::GetInstance()->AddObserver(this);
504 static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(
506 Browser::Get()->RemoveObserver(this);
507 content::GpuDataManager::GetInstance()->RemoveObserver(this);
510 void App::OnBeforeQuit(bool* prevent_default) {
511 *prevent_default = Emit("before-quit");
514 void App::OnWillQuit(bool* prevent_default) {
515 *prevent_default = Emit("will-quit");
518 void App::OnWindowAllClosed() {
519 Emit("window-all-closed");
523 int exitCode = AtomBrowserMainParts::Get()->GetExitCode();
524 Emit("quit", exitCode);
526 if (process_singleton_) {
527 process_singleton_->Cleanup();
528 process_singleton_.reset();
532 void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
533 *prevent_default = Emit("open-file", file_path);
536 void App::OnOpenURL(const std::string& url) {
537 Emit("open-url", url);
540 void App::OnActivate(bool has_visible_windows) {
541 Emit("activate", has_visible_windows);
544 void App::OnWillFinishLaunching() {
545 Emit("will-finish-launching");
548 void App::OnFinishLaunching(const base::DictionaryValue& launch_info) {
549 #if defined(OS_LINUX)
550 // Set the application name for audio streams shown in external
551 // applications. Only affects pulseaudio currently.
552 media::AudioManager::SetGlobalAppName(Browser::Get()->GetName());
554 Emit("ready", launch_info);
557 void App::OnAccessibilitySupportChanged() {
558 Emit("accessibility-support-changed", IsAccessibilitySupportEnabled());
561 #if defined(OS_MACOSX)
562 void App::OnContinueUserActivity(
563 bool* prevent_default,
564 const std::string& type,
565 const base::DictionaryValue& user_info) {
566 *prevent_default = Emit("continue-activity", type, user_info);
570 void App::OnLogin(LoginHandler* login_handler,
571 const base::DictionaryValue& request_details) {
572 if (!::tizen::is_single_process)
573 v8::Locker locker(isolate());
574 v8::HandleScope handle_scope(isolate());
575 bool prevent_default = Emit(
577 WebContents::CreateFrom(isolate(), login_handler->GetWebContents()),
579 login_handler->auth_info(),
580 base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
582 // Default behavior is to always cancel the auth.
583 if (!prevent_default)
584 login_handler->CancelAuth();
587 void App::OnCreateWindow(
588 const GURL& target_url,
589 const std::string& frame_name,
590 WindowOpenDisposition disposition,
591 const std::vector<std::string>& features,
592 const scoped_refptr<content::ResourceRequestBodyImpl>& body,
593 int render_process_id,
594 int render_frame_id) {
595 if (!::tizen::is_single_process)
596 v8::Locker locker(isolate());
597 v8::HandleScope handle_scope(isolate());
598 content::RenderFrameHost* rfh =
599 content::RenderFrameHost::FromID(render_process_id, render_frame_id);
600 content::WebContents* web_contents =
601 content::WebContents::FromRenderFrameHost(rfh);
603 auto api_web_contents = WebContents::CreateFrom(isolate(), web_contents);
604 api_web_contents->OnCreateWindow(target_url,
612 void App::AllowCertificateError(
613 content::WebContents* web_contents,
615 const net::SSLInfo& ssl_info,
616 const GURL& request_url,
617 content::ResourceType resource_type,
619 bool strict_enforcement,
620 bool expired_previous_decision,
621 const base::Callback<void(content::CertificateRequestResultType)>&
623 if (!::tizen::is_single_process)
624 v8::Locker locker(isolate());
625 v8::HandleScope handle_scope(isolate());
626 bool prevent_default = Emit("certificate-error",
627 WebContents::CreateFrom(isolate(), web_contents),
629 net::ErrorToString(cert_error),
633 // Deny the certificate by default.
634 if (!prevent_default)
635 callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
638 void App::SelectClientCertificate(
639 content::WebContents* web_contents,
640 net::SSLCertRequestInfo* cert_request_info,
641 std::unique_ptr<content::ClientCertificateDelegate> delegate) {
642 std::shared_ptr<content::ClientCertificateDelegate>
643 shared_delegate(delegate.release());
644 bool prevent_default =
645 Emit("select-client-certificate",
646 WebContents::CreateFrom(isolate(), web_contents),
647 cert_request_info->host_and_port.ToString(),
648 cert_request_info->client_certs,
649 base::Bind(&OnClientCertificateSelected,
653 // Default to first certificate from the platform store.
654 if (!prevent_default)
655 shared_delegate->ContinueWithCertificate(
656 cert_request_info->client_certs[0].get());
659 void App::OnGpuProcessCrashed(base::TerminationStatus status) {
660 Emit("gpu-process-crashed",
661 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
664 base::FilePath App::GetAppPath() const {
668 void App::SetAppPath(const base::FilePath& app_path) {
669 app_path_ = app_path;
672 base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
673 bool succeed = false;
675 int key = GetPathConstant(name);
677 succeed = PathService::Get(key, &path);
679 args->ThrowError("Failed to get '" + name + "' path");
683 void App::SetPath(mate::Arguments* args,
684 const std::string& name,
685 const base::FilePath& path) {
686 if (!path.IsAbsolute()) {
687 args->ThrowError("Path must be absolute");
691 bool succeed = false;
692 int key = GetPathConstant(name);
694 succeed = PathService::OverrideAndCreateIfNeeded(key, path, true, false);
696 args->ThrowError("Failed to set path");
699 void App::SetDesktopName(const std::string& desktop_name) {
700 #if defined(OS_LINUX)
701 std::unique_ptr<base::Environment> env(base::Environment::Create());
702 env->SetVar("CHROME_DESKTOP", desktop_name);
706 std::string App::GetLocale() {
707 return l10n_util::GetApplicationLocale("");
710 bool App::MakeSingleInstance(
711 const ProcessSingleton::NotificationCallback& callback) {
712 if (process_singleton_)
715 base::FilePath user_dir;
716 PathService::Get(brightray::DIR_USER_DATA, &user_dir);
717 process_singleton_.reset(new ProcessSingleton(
718 user_dir, base::Bind(NotificationCallbackWrapper, callback)));
720 switch (process_singleton_->NotifyOtherProcessOrCreate()) {
721 case ProcessSingleton::NotifyResult::LOCK_ERROR:
722 case ProcessSingleton::NotifyResult::PROFILE_IN_USE:
723 case ProcessSingleton::NotifyResult::PROCESS_NOTIFIED:
724 process_singleton_.reset();
726 case ProcessSingleton::NotifyResult::PROCESS_NONE:
727 default: // Shouldn't be needed, but VS warns if it is not there.
732 void App::ReleaseSingleInstance() {
733 if (process_singleton_) {
734 process_singleton_->Cleanup();
735 process_singleton_.reset();
739 bool App::Relaunch(mate::Arguments* js_args) {
741 bool override_argv = false;
742 base::FilePath exec_path;
743 relauncher::StringVector args;
745 mate::Dictionary options;
746 if (js_args->GetNext(&options)) {
747 if (options.Get("execPath", &exec_path) | options.Get("args", &args))
748 override_argv = true;
751 if (!override_argv) {
753 const relauncher::StringVector& argv = atom::AtomCommandLine::wargv();
755 const relauncher::StringVector& argv = atom::AtomCommandLine::argv();
757 return relauncher::RelaunchApp(argv);
760 relauncher::StringVector argv;
761 argv.reserve(1 + args.size());
763 if (exec_path.empty()) {
764 base::FilePath current_exe_path;
765 PathService::Get(base::FILE_EXE, ¤t_exe_path);
766 argv.push_back(current_exe_path.value());
768 argv.push_back(exec_path.value());
771 argv.insert(argv.end(), args.begin(), args.end());
773 return relauncher::RelaunchApp(argv);
776 void App::DisableHardwareAcceleration(mate::Arguments* args) {
777 if (Browser::Get()->is_ready()) {
778 args->ThrowError("app.disableHardwareAcceleration() can only be called "
779 "before app is ready");
782 content::GpuDataManager::GetInstance()->DisableHardwareAcceleration();
785 bool App::IsAccessibilitySupportEnabled() {
786 auto ax_state = content::BrowserAccessibilityState::GetInstance();
787 return ax_state->IsAccessibleBrowser();
790 Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) {
791 Browser::LoginItemSettings options;
792 args->GetNext(&options);
793 return Browser::Get()->GetLoginItemSettings(options);
796 #if defined(USE_NSS_CERTS)
797 void App::ImportCertificate(
798 const base::DictionaryValue& options,
799 const net::CompletionCallback& callback) {
800 auto browser_context = AtomBrowserContext::From("", false);
801 if (!certificate_manager_model_) {
802 std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
803 CertificateManagerModel::Create(
804 browser_context.get(),
805 base::Bind(&App::OnCertificateManagerModelCreated,
806 base::Unretained(this),
812 int rv = ImportIntoCertStore(certificate_manager_model_.get(), options);
816 void App::OnCertificateManagerModelCreated(
817 std::unique_ptr<base::DictionaryValue> options,
818 const net::CompletionCallback& callback,
819 std::unique_ptr<CertificateManagerModel> model) {
820 certificate_manager_model_ = std::move(model);
821 int rv = ImportIntoCertStore(certificate_manager_model_.get(),
828 v8::Local<v8::Value> App::GetJumpListSettings() {
829 JumpList jump_list(Browser::Get()->GetAppUserModelID());
832 std::vector<JumpListItem> removed_items;
833 if (jump_list.Begin(&min_items, &removed_items)) {
834 // We don't actually want to change anything, so abort the transaction.
837 LOG(ERROR) << "Failed to begin Jump List transaction.";
840 auto dict = mate::Dictionary::CreateEmpty(isolate());
841 dict.Set("minItems", min_items);
842 dict.Set("removedItems", mate::ConvertToV8(isolate(), removed_items));
843 return dict.GetHandle();
846 JumpListResult App::SetJumpList(v8::Local<v8::Value> val,
847 mate::Arguments* args) {
848 std::vector<JumpListCategory> categories;
849 bool delete_jump_list = val->IsNull();
850 if (!delete_jump_list &&
851 !mate::ConvertFromV8(args->isolate(), val, &categories)) {
852 args->ThrowError("Argument must be null or an array of categories");
853 return JumpListResult::ARGUMENT_ERROR;
856 JumpList jump_list(Browser::Get()->GetAppUserModelID());
858 if (delete_jump_list) {
859 return jump_list.Delete()
860 ? JumpListResult::SUCCESS
861 : JumpListResult::GENERIC_ERROR;
864 // Start a transaction that updates the JumpList of this application.
865 if (!jump_list.Begin())
866 return JumpListResult::GENERIC_ERROR;
868 JumpListResult result = jump_list.AppendCategories(categories);
869 // AppendCategories may have failed to add some categories, but it's better
870 // to have something than nothing so try to commit the changes anyway.
871 if (!jump_list.Commit()) {
872 LOG(ERROR) << "Failed to commit changes to custom Jump List.";
873 // It's more useful to return the earlier error code that might give
874 // some indication as to why the transaction actually failed, so don't
875 // overwrite it with a "generic error" code here.
876 if (result == JumpListResult::SUCCESS)
877 result = JumpListResult::GENERIC_ERROR;
882 #endif // defined(OS_WIN)
884 void App::GetFileIcon(const base::FilePath& path,
885 mate::Arguments* args) {
886 mate::Dictionary options;
887 IconLoader::IconSize icon_size;
888 FileIconCallback callback;
890 if (!::tizen::is_single_process)
891 v8::Locker locker(isolate());
892 v8::HandleScope handle_scope(isolate());
894 base::FilePath normalized_path = path.NormalizePathSeparators();
896 if (!args->GetNext(&options)) {
897 icon_size = IconLoader::IconSize::NORMAL;
899 std::string icon_size_string;
900 options.Get("size", &icon_size_string);
901 icon_size = GetIconSizeByString(icon_size_string);
904 if (!args->GetNext(&callback)) {
905 args->ThrowError("Missing required callback function");
909 auto icon_manager = g_browser_process->GetIconManager();
911 icon_manager->LookupIconFromFilepath(normalized_path, icon_size);
913 callback.Run(v8::Null(isolate()), *icon);
915 icon_manager->LoadIcon(
916 normalized_path, icon_size,
917 base::Bind(&OnIconDataAvailable, isolate(), callback),
918 &cancelable_task_tracker_);
923 mate::Handle<App> App::Create(v8::Isolate* isolate) {
924 return mate::CreateHandle(isolate, new App(isolate));
928 void App::BuildPrototype(
929 v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
930 prototype->SetClassName(mate::StringToV8(isolate, "App"));
931 auto browser = base::Unretained(Browser::Get());
932 mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
933 .SetMethod("quit", base::Bind(&Browser::Quit, browser))
934 .SetMethod("exit", base::Bind(&Browser::Exit, browser))
935 .SetMethod("focus", base::Bind(&Browser::Focus, browser))
936 .SetMethod("getVersion", base::Bind(&Browser::GetVersion, browser))
937 .SetMethod("setVersion", base::Bind(&Browser::SetVersion, browser))
938 .SetMethod("getName", base::Bind(&Browser::GetName, browser))
939 .SetMethod("setName", base::Bind(&Browser::SetName, browser))
940 .SetMethod("isReady", base::Bind(&Browser::is_ready, browser))
941 .SetMethod("addRecentDocument",
942 base::Bind(&Browser::AddRecentDocument, browser))
943 .SetMethod("clearRecentDocuments",
944 base::Bind(&Browser::ClearRecentDocuments, browser))
945 .SetMethod("setAppUserModelId",
946 base::Bind(&Browser::SetAppUserModelID, browser))
947 .SetMethod("isDefaultProtocolClient",
948 base::Bind(&Browser::IsDefaultProtocolClient, browser))
949 .SetMethod("setAsDefaultProtocolClient",
950 base::Bind(&Browser::SetAsDefaultProtocolClient, browser))
951 .SetMethod("removeAsDefaultProtocolClient",
952 base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
953 .SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
954 .SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
955 .SetMethod("getLoginItemSettings", &App::GetLoginItemSettings)
956 .SetMethod("setLoginItemSettings",
957 base::Bind(&Browser::SetLoginItemSettings, browser))
958 #if defined(OS_MACOSX)
959 .SetMethod("hide", base::Bind(&Browser::Hide, browser))
960 .SetMethod("show", base::Bind(&Browser::Show, browser))
961 .SetMethod("setUserActivity",
962 base::Bind(&Browser::SetUserActivity, browser))
963 .SetMethod("getCurrentActivityType",
964 base::Bind(&Browser::GetCurrentActivityType, browser))
965 .SetMethod("setAboutPanelOptions",
966 base::Bind(&Browser::SetAboutPanelOptions, browser))
969 .SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser))
970 .SetMethod("getJumpListSettings", &App::GetJumpListSettings)
971 .SetMethod("setJumpList", &App::SetJumpList)
973 #if defined(OS_LINUX)
974 .SetMethod("isUnityRunning",
975 base::Bind(&Browser::IsUnityRunning, browser))
977 .SetMethod("setAppPath", &App::SetAppPath)
978 .SetMethod("getAppPath", &App::GetAppPath)
979 .SetMethod("setPath", &App::SetPath)
980 .SetMethod("getPath", &App::GetPath)
981 .SetMethod("setDesktopName", &App::SetDesktopName)
982 .SetMethod("getLocale", &App::GetLocale)
983 #if defined(USE_NSS_CERTS)
984 .SetMethod("importCertificate", &App::ImportCertificate)
986 .SetMethod("makeSingleInstance", &App::MakeSingleInstance)
987 .SetMethod("releaseSingleInstance", &App::ReleaseSingleInstance)
988 .SetMethod("relaunch", &App::Relaunch)
989 .SetMethod("isAccessibilitySupportEnabled",
990 &App::IsAccessibilitySupportEnabled)
991 .SetMethod("disableHardwareAcceleration",
992 &App::DisableHardwareAcceleration)
993 .SetMethod("getFileIcon", &App::GetFileIcon);
1003 void AppendSwitch(const std::string& switch_string, mate::Arguments* args) {
1004 auto command_line = base::CommandLine::ForCurrentProcess();
1006 if (base::EndsWith(switch_string, "-path",
1007 base::CompareCase::INSENSITIVE_ASCII) ||
1008 switch_string == switches::kLogNetLog) {
1009 base::FilePath path;
1010 args->GetNext(&path);
1011 command_line->AppendSwitchPath(switch_string, path);
1016 if (args->GetNext(&value))
1017 command_line->AppendSwitchASCII(switch_string, value);
1019 command_line->AppendSwitch(switch_string);
1022 #if defined(OS_MACOSX)
1023 int DockBounce(const std::string& type) {
1024 int request_id = -1;
1025 if (type == "critical")
1026 request_id = Browser::Get()->DockBounce(Browser::BOUNCE_CRITICAL);
1027 else if (type == "informational")
1028 request_id = Browser::Get()->DockBounce(Browser::BOUNCE_INFORMATIONAL);
1032 void DockSetMenu(atom::api::Menu* menu) {
1033 Browser::Get()->DockSetMenu(menu->model());
1037 void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
1038 v8::Local<v8::Context> context, void* priv) {
1039 v8::Isolate* isolate = context->GetIsolate();
1040 auto command_line = base::CommandLine::ForCurrentProcess();
1042 mate::Dictionary dict(isolate, exports);
1043 dict.Set("App", atom::api::App::GetConstructor(isolate)->GetFunction());
1044 dict.Set("app", atom::api::App::Create(isolate));
1045 dict.SetMethod("appendSwitch", &AppendSwitch);
1046 dict.SetMethod("appendArgument",
1047 base::Bind(&base::CommandLine::AppendArg,
1048 base::Unretained(command_line)));
1049 #if defined(OS_MACOSX)
1050 auto browser = base::Unretained(Browser::Get());
1051 dict.SetMethod("dockBounce", &DockBounce);
1052 dict.SetMethod("dockCancelBounce",
1053 base::Bind(&Browser::DockCancelBounce, browser));
1054 dict.SetMethod("dockDownloadFinished",
1055 base::Bind(&Browser::DockDownloadFinished, browser));
1056 dict.SetMethod("dockSetBadgeText",
1057 base::Bind(&Browser::DockSetBadgeText, browser));
1058 dict.SetMethod("dockGetBadgeText",
1059 base::Bind(&Browser::DockGetBadgeText, browser));
1060 dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser));
1061 dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser));
1062 dict.SetMethod("dockIsVisible", base::Bind(&Browser::DockIsVisible, browser));
1063 dict.SetMethod("dockSetMenu", &DockSetMenu);
1064 dict.SetMethod("dockSetIcon", base::Bind(&Browser::DockSetIcon, browser));
1070 NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_app, Initialize)