b387a85b7c549806b1e2c7c00e0aa296e6a8d469
[platform/framework/web/crosswalk.git] / src / xwalk / tizen / appcore_context.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/tizen/appcore_context.h"
6
7 #include <appcore-common.h>
8 #include <aul.h>
9 #include <malloc.h>
10 #include <tizen.h>
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13
14 // AppcoreContextImpl uses private Tizen appcore API to reuse Tizen 2.0
15 // implementation.
16 // This private implementation of appcore is a bit huge. We will decide later
17 // whether to maintain the code similar to appcore private implementation
18 // in Crosswalk or not after investigating appcore in Tizen 3.0.
19 extern "C" {
20 // define in app.h
21 int app_get_id(char** id);
22
23 // define in app_private.h
24 int app_get_package_app_name(const char* package, char** name);
25 void app_finalizer_execute(void);
26
27 // define in status.c
28 int aul_status_update(int status);
29
30 // define in appcore-internal.h
31 enum app_event {
32   AE_UNKNOWN,
33   AE_CREATE,
34   AE_TERMINATE,
35   AE_PAUSE,
36   AE_RESUME,
37   AE_RESET,
38   AE_LOWMEM_POST,
39   AE_MEM_FLUSH,
40   AE_MAX
41 };
42
43 struct ui_ops {
44   void* data;
45   void (*cb_app)(enum app_event evnt, void* data, bundle*);
46 };
47 }
48
49 namespace tizen {
50
51 // FIXME: this implementation is not compatible with shared process mode,
52 // because Tizen task switcher cannot recognize multiple tasks per process.
53 // Shared process mode requires one Crosswalk process to include multiple tasks
54 // (= web applications). It is not supported by current task switcher.
55 class AppcoreContextImpl
56     : public AppcoreContext {
57  public:
58   AppcoreContextImpl();
59   virtual ~AppcoreContextImpl();
60
61   bool Initialize();
62
63  private:
64   static void HandleAppcoreEvents(enum app_event, void*, bundle*);
65   void HandleAppcoreEventsInternal(enum app_event, bundle*);
66
67   char* package_;
68   char* application_name_;
69   bool initialized_;
70   struct ui_ops appcore_operations_;
71
72   DISALLOW_COPY_AND_ASSIGN(AppcoreContextImpl);
73 };
74
75 scoped_ptr<AppcoreContext> AppcoreContext::Create() {
76   scoped_ptr<AppcoreContextImpl> context(new AppcoreContextImpl());
77   if (context->Initialize())
78     return context.PassAs<AppcoreContext>();
79   return scoped_ptr<AppcoreContext>();
80 }
81
82 AppcoreContextImpl::AppcoreContextImpl()
83     : package_(NULL),
84       application_name_(NULL),
85       initialized_(false) {
86   appcore_operations_.data = this;
87   appcore_operations_.cb_app = HandleAppcoreEvents;
88 }
89
90 AppcoreContextImpl::~AppcoreContextImpl() {
91   if (initialized_) {
92     app_finalizer_execute();
93     aul_status_update(STATUS_DYING);
94     appcore_exit();
95     DCHECK(package_ && application_name_);
96   }
97
98   // app_get_id() and app_get_package_app_name() allocated them using malloc.
99   free(package_);
100   free(application_name_);
101 }
102
103 bool AppcoreContextImpl::Initialize() {
104   if (app_get_id(&package_) != TIZEN_ERROR_NONE) {
105     LOG(ERROR) << "Failed to get the package: " << package_;
106     return false;
107   }
108
109   if (app_get_package_app_name(package_, &application_name_) !=
110       TIZEN_ERROR_NONE) {
111     LOG(ERROR) << "Failed to get the package's application name: "
112                << application_name_;
113     return false;
114   }
115
116   DCHECK(application_name_ && application_name_[0] != '\0');
117   char* argv[2] = {'\0', };
118   int r = appcore_init(application_name_, &appcore_operations_, 1, argv);
119   if (r == -1) {
120     LOG(ERROR) << "Failed to initialize appcore. application name: "
121                << application_name_;
122     return false;
123   }
124
125   initialized_ = true;
126   return true;
127 }
128
129
130 void AppcoreContextImpl::HandleAppcoreEvents(enum app_event event,
131                                                   void* data,
132                                                   bundle* b) {
133   static_cast<AppcoreContextImpl*>(data)->
134       HandleAppcoreEventsInternal(event, b);
135 }
136
137 void AppcoreContextImpl::HandleAppcoreEventsInternal(enum app_event event,
138                                                           bundle* b) {
139   DCHECK(initialized_);
140   if (event >= AE_MAX)
141     return;
142
143   switch (event) {
144     case AE_TERMINATE:
145       LOG(INFO) << "[XWalk " << getpid() <<"] TERMINATE";
146       base::MessageLoop::current()->QuitNow();
147       break;
148     default:
149       break;
150   }
151 }
152
153 }  // namespace tizen
154