Store the dbus connection while launching the service
[platform/core/context/context-service.git] / src / agent / legacy / ContextManager.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <glib.h>
18 #include <list>
19
20 #include <Types.h>
21 #include <DBusTypes.h>
22 #include <CtxJson1.h>
23 #include <ContextProvider.h>
24 #include <CustomRegister.h>
25
26 #include "access_control/Privilege.h"
27 #include "trigger/TemplateManager.h"
28 #include "Server.h"
29 #include "Request.h"
30 #include "ProviderHandler.h"
31 #include "ProviderLoader.h"
32 #include "ContextManager.h"
33
34 using namespace ctx::trigger;
35 using namespace ctx;
36
37 ContextManager::ContextManager()
38 {
39         ContextProvider::__setContextManager(this);
40         CustomRegister::__setCustomRegister(this);
41         ProviderLoader::init();
42 }
43
44 ContextManager::~ContextManager()
45 {
46         release();
47 }
48
49 bool ContextManager::init()
50 {
51         return true;
52 }
53
54 void ContextManager::release()
55 {
56         ProviderHandler::purge();
57 }
58
59 void ContextManager::assignRequest(RequestInfo* request)
60 {
61         std::string subject = request->getSubject();
62         if (subject.empty()) {
63                 _W("Empty subject name");
64                 request->reply(ERR_NOT_SUPPORTED);
65                 delete request;
66                 return;
67         }
68
69         ProviderHandler *handle = ProviderHandler::getInstance(subject, true);
70         if (!handle || !handle->isSupported()) {
71                 request->reply(ERR_NOT_SUPPORTED);
72                 delete request;
73                 return;
74         }
75
76         if (request->getType() != REQ_SUPPORT && !handle->isAllowed(request->getCredentials())) {
77                 _W("Permission denied");
78                 request->reply(ERR_PERMISSION_DENIED);
79                 delete request;
80                 return;
81         }
82
83         switch (request->getType()) {
84         case REQ_SUBSCRIBE:
85                 handle->subscribe(request);
86                 break;
87         case REQ_UNSUBSCRIBE:
88                 handle->unsubscribe(request);
89                 break;
90         case REQ_READ:
91         case REQ_READ_SYNC:
92                 handle->read(request);
93                 break;
94         case REQ_WRITE:
95                 handle->write(request);
96                 break;
97         case REQ_SUPPORT:
98                 request->reply(ERR_NONE);
99                 delete request;
100                 break;
101         default:
102                 _E("Invalid type of request");
103                 delete request;
104         }
105 }
106
107 bool ContextManager::isSupported(const char *subject)
108 {
109         ProviderHandler *handle = ProviderHandler::getInstance(subject, true);
110
111         if (!handle)
112                 return false;
113
114         return handle->isSupported();
115 }
116
117 bool ContextManager::isAllowed(const Credentials *creds, const char *subject)
118 {
119         IF_FAIL_RETURN(creds, true);    /* In case internal requests */
120
121         ProviderHandler *handle = ProviderHandler::getInstance(subject, true);
122
123         if (!handle)
124                 return false;
125
126         return handle->isAllowed(creds);
127 }
128
129 void ContextManager::__publish(const char* subject, CtxJson1 &option, int error, CtxJson1 &dataUpdated)
130 {
131         _I("Publishing '%s'", subject);
132         _J("Option", option);
133
134         ProviderHandler *handle = ProviderHandler::getInstance(subject, false);
135         IF_FAIL_VOID_TAG(handle, _W, "No corresponding provider");
136
137         handle->publish(option, error, dataUpdated);
138 }
139
140 void ContextManager::__replyToRead(const char* subject, CtxJson1 &option, int error, CtxJson1 &dataRead)
141 {
142         _I("Sending data of '%s'", subject);
143         _J("Option", option);
144         _J("Data", dataRead);
145
146         ProviderHandler *handle = ProviderHandler::getInstance(subject, false);
147         IF_FAIL_VOID_TAG(handle, _W, "No corresponding provider");
148
149         handle->replyToRead(option, error, dataRead);
150 }
151
152 struct PublishedData {
153         int type;
154         ContextManager *mgr;
155         std::string subject;
156         int error;
157         CtxJson1 option;
158         CtxJson1 data;
159         PublishedData(int t, ContextManager *m, const char* s, CtxJson1& o, int e, CtxJson1& d)
160                 : type(t), mgr(m), subject(s), error(e)
161         {
162                 option = o.str();
163                 data = d.str();
164         }
165 };
166
167 gboolean ContextManager::__threadSwitcher(gpointer data)
168 {
169         PublishedData *tuple = static_cast<PublishedData*>(data);
170
171         switch (tuple->type) {
172         case REQ_SUBSCRIBE:
173                 tuple->mgr->__publish(tuple->subject.c_str(), tuple->option, tuple->error, tuple->data);
174                 break;
175         case REQ_READ:
176                 tuple->mgr->__replyToRead(tuple->subject.c_str(), tuple->option, tuple->error, tuple->data);
177                 break;
178         default:
179                 _W("Invalid type");
180         }
181
182         delete tuple;
183         return FALSE;
184 }
185
186 bool ContextManager::publish(const char* subject, CtxJson1& option, int error, CtxJson1& dataUpdated)
187 {
188         IF_FAIL_RETURN_TAG(subject, false, _E, "Invalid parameter");
189
190         PublishedData *tuple = new(std::nothrow) PublishedData(REQ_SUBSCRIBE, this, subject, option, error, dataUpdated);
191         IF_FAIL_RETURN_TAG(tuple, false, _E, "Memory allocation failed");
192
193         g_idle_add(__threadSwitcher, tuple);
194
195         return true;
196 }
197
198 bool ContextManager::replyToRead(const char* subject, CtxJson1& option, int error, CtxJson1& dataRead)
199 {
200         IF_FAIL_RETURN_TAG(subject, false, _E, "Invalid parameter");
201
202         PublishedData *tuple = new(std::nothrow) PublishedData(REQ_READ, this, subject, option, error, dataRead);
203         IF_FAIL_RETURN_TAG(tuple, false, _E, "Memory allocation failed");
204
205         g_idle_add(__threadSwitcher, tuple);
206
207         return true;
208 }
209
210 bool ContextManager::popTriggerTemplate(std::string &subject, int &operation, CtxJson1 &attribute, CtxJson1 &option)
211 {
212         return ProviderLoader::popTriggerTemplate(subject, operation, attribute, option);
213 }
214
215 /* Only for explicit request of custom provider */
216 bool ContextManager::registerCustomProvider(const char* subject, int operation, ctx::CtxJson1 &attribute, ctx::CtxJson1 &option, const char* owner)
217 {
218         IF_FAIL_RETURN_TAG(ProviderHandler::getInstance(subject, true), false, _E, "Register provider failed");
219
220         TemplateManager* tmplMgr = TemplateManager::getInstance();
221         IF_FAIL_RETURN_TAG(tmplMgr, false, _E, "Memory allocation failed");
222         tmplMgr->registerTemplate(subject, operation, attribute, option, owner);
223
224         return true;
225 }
226
227 bool ContextManager::unregisterCustomProvider(const char* subject)
228 {
229         TemplateManager* tmplMgr = TemplateManager::getInstance();
230         IF_FAIL_RETURN_TAG(tmplMgr, false, _E, "Memory allocation failed");
231         tmplMgr->unregisterTemplate(subject);
232
233         int error = ProviderHandler::unregisterCustomProvider(subject);
234         IF_FAIL_RETURN_TAG(error == ERR_NONE, false, _E, "Unregister provider failed");
235
236         return true;
237 }