Initialize Tizen 2.3
[framework/web/wrt-plugins-common.git] / src_mobile / plugin-loading / explorer.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file    explorer.cpp
18  * @author  Grzegorz Krawczyk (g.krawczyk@samgsung.com)
19  * @author  Yunchan Cho (yunchan.cho@samgsung.com)
20  * @version
21  * @brief
22  */
23
24 #include <algorithm>
25 #include <dpl/foreach.h>
26 #include <dpl/log/secure_log.h>
27 #include "explorer.h"
28 #include "plugin_property_support.h"
29
30 // JS overlay
31 #include <js_overlay_types.h>
32
33 namespace {
34 //const char* SEPARATOR = ".";
35 const std::string GLOBAL_OBJECT_NAME = "GLOBAL_OBJECT";
36 }
37
38 using namespace std;
39 using namespace PluginModule;
40 using namespace WrtPlugins::W3C;
41
42 Explorer::Explorer(JSGlobalContextRef context) :
43     m_context(context)
44 {
45     if (!context) {
46         _W("Context is NULL");
47         return;
48     }
49
50     m_globalObject =
51         JavaScriptInterfaceSingleton::Instance().getGlobalObject(context);
52
53     //register main frame;
54     m_iframeSupport.registerIframe(m_globalObject);
55
56     m_propertySupport.reset(new WindowPropertySupport(m_context));
57 }
58
59 Explorer::~Explorer()
60 {
61 }
62
63 JSObjectPtr Explorer::getJSObjectProperty(const std::string& propertyName,
64                                           JSObjectPtr object)
65 {
66     return JavaScriptInterfaceSingleton::Instance().getJSObjectProperty(
67                m_context, object, propertyName);
68 }
69
70 JSObjectPtr Explorer::getProperty(
71     const string& requestedProperty,
72     JSObjectPtr providedObject)
73 {
74     _D("Requested Property: %s", requestedProperty.c_str());
75
76     if (!providedObject) {
77         _W("Provided object is empty");
78         return JSObjectPtr();
79     }
80
81     std::string currentObjectName;
82     std::string currentPropertyRequested = requestedProperty;
83     JSObjectPtr currentObject = providedObject;
84
85     while (true) {
86         auto pos = currentPropertyRequested.find(".");
87         if (pos == string::npos) {
88             return getJSObjectProperty(currentPropertyRequested, currentObject);
89         }
90
91         //check if requested object has child
92         currentObjectName = currentPropertyRequested.substr(0, pos);
93
94         if (currentPropertyRequested.size() <= pos + 1) {
95             _W("Wrong name of requested property");
96             return JSObjectPtr();
97         }
98         currentPropertyRequested = currentPropertyRequested.substr(pos + 1);
99
100         currentObject = getJSObjectProperty(currentObjectName, currentObject);
101         if (!currentObject) {
102             _W("Failed to get property: %s", currentObjectName.c_str());
103             return JSObjectPtr();
104         }
105     }
106 }
107
108 bool Explorer::registerObject(const JSObjectDeclarationPtr& declaration,
109                               JSGlobalContextRef context)
110 {
111     bool retValue;
112
113     if (declaration->getParentName() == GLOBAL_OBJECT_NAME) {
114         retValue = register_(declaration, m_globalObject, context);
115     } else { //PIM support
116         //it should be master object name
117         string masterName = declaration->getParentName();
118         auto pos = masterName.find(".");
119         if (string::npos != pos) {
120             _W("ParentName not allowed");
121             return false;
122         }
123         auto masterObject = getJSObjectProperty(masterName, m_globalObject);
124         if (masterObject->getObject() == 0) {
125             return false;
126         }
127         retValue = registerObject(declaration,
128                                   masterName,
129                                   masterObject,
130                                   context);
131     }
132
133     if (declaration->checkIframesSupported()) {
134         m_iframeSupport.registerDeclaration(declaration);
135         //        m_iframeSupport.invokeCallbackForMainFrame(m_context,
136         //                                                   declaration,
137         //                                                   newObject);
138     }
139
140     return retValue;
141 }
142
143 bool Explorer::registerObject(const JSObjectDeclarationPtr& declaration,
144                               const std::string& providedObjectName,
145                               JSObjectPtr providedObject,
146                               JSGlobalContextRef context)
147 {
148     _D("%s <- %s", providedObjectName.c_str(), declaration->getName().c_str());
149     std::string fullParentName = declaration->getParentName();
150
151     if (fullParentName == providedObjectName) {
152         \r_D("Provided object was matched!!");
153         return register_(declaration, providedObject, context);
154     }
155
156     //check if object exists in fullParentName
157     auto pos = fullParentName.find(providedObjectName);
158     if (pos == string::npos) {
159         _W("Object: %s should be child of: %s but you provided object: %s",
160            declaration->getName().c_str(),
161            declaration->getParentName().c_str(),
162            providedObjectName.c_str());
163         return false;
164     }
165
166     if (fullParentName.size() <= pos + providedObjectName.size() + 1) {
167         _W("Invalid object name");
168         return false;
169     }
170
171     auto currentRequesteProperty =
172         fullParentName.substr(pos + providedObjectName.size() + 1);
173
174     JSObjectPtr jsObject = getProperty(
175             currentRequesteProperty, providedObject);
176
177     if (!jsObject->getObject()) {
178         _W("Object: %s should be child of: %s. you provided object: %s but object is null",
179            declaration->getName().c_str(),
180            declaration->getParentName().c_str(),
181            providedObjectName.c_str());
182         return false;
183     }
184
185     return register_(declaration, jsObject, context);
186 }
187
188 bool Explorer::register_(const JSObjectDeclarationPtr& declaration,
189                          JSObjectPtr parent,
190                          JSGlobalContextRef context)
191 {
192     _D("Registration object: %s <- %s",
193        declaration->getParentName().c_str(),
194        declaration->getName().c_str());
195     Assert(parent && "parent object is NULL");
196
197     typedef JSObjectDeclaration::Options JO;
198
199     JSGlobalContextRef gContext = (context == NULL) ? m_context : context;
200     JSObjectPtr objectInstance = JavaScriptInterfaceSingleton::Instance().
201             createObject(gContext, declaration);
202
203     JavaScriptInterfaceSingleton::Instance().setObjectProperty(
204         gContext,
205         parent,
206         declaration->getName(),
207         objectInstance);
208
209     //notice
210     if (declaration->getOptions() &&
211         (declaration->getOptions()->getIframeNotice() ==
212          JO::IFrameNotice::AlwaysNotice))
213     {
214         declaration->getOptions()->invokeCallback(gContext,
215                                                   parent->getObject(),
216                                                   objectInstance->getObject());
217     }
218
219     return true;
220 }
221
222 void Explorer::registerObjectIntoIframe(
223     const JSObjectDeclarationPtr& declaration,
224     JSObjectPtr frameObject,
225     JSGlobalContextRef context)
226 {
227     if (declaration->getParentName() == GLOBAL_OBJECT_NAME) {
228         _D("Connect to Global object of IFRAME");
229         register_(declaration, frameObject, context);
230         return;
231     }
232
233     //PIM SUPPORT
234     {
235         _D("Connect to NOT global object of IFRAME");
236         //it should be master object name
237         string masterName = declaration->getParentName();
238         auto pos = masterName.find(".");
239         if (string::npos != pos) {
240             _W("ParentName not allowed");
241             return;
242         }
243         auto masterObject = getJSObjectProperty(masterName, frameObject);
244         if (!masterObject->getObject()) {
245             _W("Object not exist in frame");
246             return;
247         }
248         register_(declaration, masterObject, context);
249     }
250 }
251
252 void Explorer::loadFrame(JSGlobalContextRef context)
253 {
254     JSObjectPtr frameObject =
255         JavaScriptInterfaceSingleton::Instance().getGlobalObject(context);
256
257     if (frameObject->getObject() == m_globalObject->getObject()) {
258         // Main page was already loaded from constructor
259         _W("Main page loaded");
260         return;
261     }
262
263     m_iframeSupport.registerIframe(frameObject);
264
265     auto iframeObjects = m_iframeSupport.getIframeObjects();
266
267     FOREACH(object, iframeObjects)
268     {
269         _D("Register object: %s", (*object)->getName().c_str());
270         registerObjectIntoIframe(*object, frameObject, context);
271     }
272 }
273
274 void Explorer::unloadFrame(JSGlobalContextRef context)
275 {
276     JSObjectPtr frameObject =
277         JavaScriptInterfaceSingleton::Instance().getGlobalObject(context);
278     m_iframeSupport.unregisterIframe(frameObject);
279 }
280
281 void Explorer::removePluginsFromIframes()
282 {
283     if (m_iframeSupport.hasIframes()) {
284         JavaScriptInterfaceSingleton::Instance().removeIframes(m_context);
285     }
286 }
287
288 void Explorer::deregisterObject(const JSObjectDeclarationPtr& declaration)
289 {
290     if (GLOBAL_OBJECT_NAME != declaration->getParentName()) {
291         _W("Ignored remove property %s", declaration->getName().c_str());
292         return;
293     }
294
295     JavaScriptInterfaceSingleton::Instance().
296         removeObjectProperty(m_context,
297                              m_globalObject,
298                              declaration->getName());
299 }
300
301 void Explorer::cleanIframesData()
302 {
303     m_iframeSupport.clean();
304 }
305
306 void Explorer::callEventListeners(CustomEventType /*eventType*/, void* /*data*/)
307 {
308 #if 0 // deprecated
309     using namespace WrtPlugins::Tizen;
310     // get iframe objects from javascript global context
311     JavaScriptInterface::ObjectsListPtr frameLists =
312         JavaScriptInterfaceSingleton::Instance().getIframesList(m_context);
313
314     // get main frame object from javascript global context
315     JSObjectRef mainFrame = JSContextGetGlobalObject(m_context);
316     frameLists->push_back(JSObjectPtr(new JSObject(mainFrame)));
317
318     if (eventType == ServiceCustomEvent) {
319         using namespace WrtDeviceApis::TizenServiceEvent::Api;
320         // set user data of js callback function for 'appservice' js event
321         ITizenServiceEventPtr event = ITizenServiceEventPtr(
322                 new TizenServiceEvent());
323         event->setScale(m_propertySupport->getScale());
324         event->setBundle(m_propertySupport->getBundle());
325
326         // call js callback function for 'appservice' js event on each frame
327         FOREACH(it, *frameLists)
328         {
329             JSObjectRef frame = static_cast<JSObjectRef>((*it).Get()->getObject());
330
331             auto eventPriv =
332                 new JSTizenServiceEventPrivateObject(m_context, event);
333             JSObjectRef eventObject =
334                 JSObjectMake(m_context,
335                              JSTizenServiceEvent::getClassRef(), eventPriv);
336
337             AddEventListenerSupport::CallCustomEventListenersFromIFrame(
338                 frame, eventType, eventObject);
339         }
340     } else if (eventType == SoftKeyboardChangeCustomEvent) {
341         using namespace WrtDeviceApis::SoftKeyboardChangeEvent::Api;
342         if (!data) {
343             LogDebug("no ime size");
344             return;
345         }
346
347         // set user data of js callback function for 'softkeyboardchange' js
348         // event
349         SoftKeyboardChangeArgs* args =
350             static_cast<SoftKeyboardChangeArgs *>(data);
351         ISoftKeyboardChangeEventPtr event =
352             ISoftKeyboardChangeEventPtr(
353                 new SoftKeyboardChangeEvent(
354                     args->state,
355                     args->width,
356                     args->height));
357         LogDebug("softkeyboard event's state: " << args->state);
358
359         // call js callback function for 'softkeyboardchange' js event on each
360         // frame
361         FOREACH(it, *frameLists)
362         {
363             JSObjectRef frame = static_cast<JSObjectRef>((*it).Get()->getObject());
364
365             auto eventPriv =
366                 new JSSoftKeyboardChangeEventPrivateObject(m_context, event);
367             JSObjectRef eventObject =
368                 JSObjectMake(
369                     m_context,
370                     JSSoftKeyboardChangeEvent::getClassRef(),
371                     eventPriv);
372
373             AddEventListenerSupport::CallCustomEventListenersFromIFrame(
374                 frame, eventType, eventObject);
375         }
376     } else {
377         LogDebug("Not supported custom event type");
378         return;
379     }
380 #endif
381 }
382
383 WindowPropertySupport* Explorer::getWindowPropertySupport()
384 {
385     return m_propertySupport.get();
386 }