Replace LogInfo to LogDebug
[framework/web/wrt-plugins-common.git] / src / 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/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         LogError("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     LogDebug("Requested Property: " << requestedProperty);
75
76     if (!providedObject) {
77         LogError("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             LogError("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             LogError("Failed to get property: " << currentObjectName);
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             LogError("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     LogDebug("'" << providedObjectName << "' <- '" << declaration->getName() << "'");
149
150     std::string fullParentName = declaration->getParentName();
151
152     if (fullParentName == providedObjectName) {
153         return register_(declaration, providedObject, context);
154     }
155
156     LogDebug("Provided object was not matched!!");
157
158     //check if object exists in fullParentName
159     auto pos = fullParentName.find(providedObjectName);
160     if (pos == string::npos) {
161         LogError(
162             "Object: " << declaration->getName()
163                        << " should be child of: " <<
164             declaration->getParentName()
165                        << " but you provided object: " <<
166             providedObjectName);
167
168         return false;
169     }
170
171     if (fullParentName.size() <= pos + providedObjectName.size() + 1) {
172         LogError("Invalid object name");
173         return false;
174     }
175
176     auto currentRequesteProperty =
177         fullParentName.substr(pos + providedObjectName.size() + 1);
178
179     JSObjectPtr jsObject = getProperty(
180             currentRequesteProperty, providedObject);
181
182     if (!jsObject->getObject()) {
183         LogError(
184             "Object: '" << declaration->getName()
185                         << "' should be child of: '" <<
186             declaration->getParentName()
187                         << "'. you provided object: '" <<
188             providedObjectName
189                         << "' but object is null");
190
191         return false;
192     }
193
194     return register_(declaration, jsObject, context);
195 }
196
197 bool Explorer::register_(const JSObjectDeclarationPtr& declaration,
198                          JSObjectPtr parent,
199                          JSGlobalContextRef context)
200 {
201     LogDebug("Registration object: " << declaration->getParentName() <<
202             "<-" << declaration->getName());
203
204     Assert(parent && "parent object is NULL");
205
206     typedef JSObjectDeclaration::Options JO;
207
208     JSGlobalContextRef gContext = (context == NULL) ? m_context : context;
209     JSObjectPtr objectInstance = JavaScriptInterfaceSingleton::Instance().
210             createObject(gContext, declaration);
211
212     JavaScriptInterfaceSingleton::Instance().setObjectProperty(
213         gContext,
214         parent,
215         declaration->getName(),
216         objectInstance);
217
218     //notice
219     if (declaration->getOptions() &&
220         (declaration->getOptions()->getIframeNotice() ==
221          JO::IFrameNotice::AlwaysNotice))
222     {
223         declaration->getOptions()->invokeCallback(gContext,
224                                                   parent->getObject(),
225                                                   objectInstance->getObject());
226     }
227
228     return true;
229 }
230
231 void Explorer::registerObjectIntoIframe(
232     const JSObjectDeclarationPtr& declaration,
233     JSObjectPtr frameObject,
234     JSGlobalContextRef context)
235 {
236     if (declaration->getParentName() == GLOBAL_OBJECT_NAME) {
237         LogDebug("Connect to Global object of IFRAME");
238         register_(declaration, frameObject, context);
239         return;
240     }
241
242     //PIM SUPPORT
243     {
244         LogWarning("Connect to NOT global object of IFRAME");
245         //it should be master object name
246         string masterName = declaration->getParentName();
247         auto pos = masterName.find(".");
248         if (string::npos != pos) {
249             LogError("ParentName not allowed");
250             return;
251         }
252         auto masterObject = getJSObjectProperty(masterName, frameObject);
253         if (!masterObject->getObject()) {
254             LogError("Object not exist in frame");
255             return;
256         }
257         register_(declaration, masterObject, context);
258     }
259 }
260
261 void Explorer::loadFrame(JSGlobalContextRef context)
262 {
263     LogDebug("Frame attached");
264
265     JSObjectPtr frameObject =
266         JavaScriptInterfaceSingleton::Instance().getGlobalObject(context);
267
268     LogDebug("Register main frame");
269     //register main frame;
270
271     if (frameObject->getObject() == m_globalObject->getObject()) {
272         // Main page was already loaded from constructor
273         LogDebug("Main page loaded");
274         return;
275     }
276
277     m_iframeSupport.registerIframe(frameObject);
278
279     auto iframeObjects = m_iframeSupport.getIframeObjects();
280
281     FOREACH(object, iframeObjects)
282     {
283         LogDebug("Register object: " << (*object)->getName() );
284
285         registerObjectIntoIframe(*object, frameObject, context);
286     }
287 }
288
289 void Explorer::unloadFrame(JSGlobalContextRef context)
290 {
291     LogDebug("Frame detached");
292
293     JSObjectPtr frameObject =
294         JavaScriptInterfaceSingleton::Instance().getGlobalObject(context);
295
296     m_iframeSupport.unregisterIframe(frameObject);
297 }
298
299 void Explorer::removePluginsFromIframes()
300 {
301     LogDebug("Remove plugins from iframes");
302
303     if (m_iframeSupport.hasIframes()) {
304         LogDebug("Removing iframes");
305         JavaScriptInterfaceSingleton::Instance().removeIframes(m_context);
306     }
307 }
308
309 void Explorer::deregisterObject(const JSObjectDeclarationPtr& declaration)
310 {
311     LogDebug("Deregister object " << declaration->getName());
312
313     if (GLOBAL_OBJECT_NAME != declaration->getParentName()) {
314         LogWarning("Ignored remove property " << declaration->getName());
315         return;
316     }
317
318     JavaScriptInterfaceSingleton::Instance().
319         removeObjectProperty(m_context,
320                              m_globalObject,
321                              declaration->getName());
322 }
323
324 void Explorer::cleanIframesData()
325 {
326     LogDebug("Clean iframes data");
327     m_iframeSupport.clean();
328 }
329
330 void Explorer::callEventListeners(CustomEventType /*eventType*/, void* /*data*/)
331 {
332 #if 0 // deprecated
333     using namespace WrtPlugins::Tizen;
334     // get iframe objects from javascript global context
335     JavaScriptInterface::ObjectsListPtr frameLists =
336         JavaScriptInterfaceSingleton::Instance().getIframesList(m_context);
337
338     // get main frame object from javascript global context
339     JSObjectRef mainFrame = JSContextGetGlobalObject(m_context);
340     frameLists->push_back(JSObjectPtr(new JSObject(mainFrame)));
341
342     if (eventType == ServiceCustomEvent) {
343         using namespace WrtDeviceApis::TizenServiceEvent::Api;
344         // set user data of js callback function for 'appservice' js event
345         ITizenServiceEventPtr event = ITizenServiceEventPtr(
346                 new TizenServiceEvent());
347         event->setScale(m_propertySupport->getScale());
348         event->setBundle(m_propertySupport->getBundle());
349
350         // call js callback function for 'appservice' js event on each frame
351         FOREACH(it, *frameLists)
352         {
353             JSObjectRef frame = static_cast<JSObjectRef>((*it).Get()->getObject());
354
355             auto eventPriv =
356                 new JSTizenServiceEventPrivateObject(m_context, event);
357             JSObjectRef eventObject =
358                 JSObjectMake(m_context,
359                              JSTizenServiceEvent::getClassRef(), eventPriv);
360
361             AddEventListenerSupport::CallCustomEventListenersFromIFrame(
362                 frame, eventType, eventObject);
363         }
364     } else if (eventType == SoftKeyboardChangeCustomEvent) {
365         using namespace WrtDeviceApis::SoftKeyboardChangeEvent::Api;
366         if (!data) {
367             LogDebug("no ime size");
368             return;
369         }
370
371         // set user data of js callback function for 'softkeyboardchange' js
372         // event
373         SoftKeyboardChangeArgs* args =
374             static_cast<SoftKeyboardChangeArgs *>(data);
375         ISoftKeyboardChangeEventPtr event =
376             ISoftKeyboardChangeEventPtr(
377                 new SoftKeyboardChangeEvent(
378                     args->state,
379                     args->width,
380                     args->height));
381         LogDebug("softkeyboard event's state: " << args->state);
382
383         // call js callback function for 'softkeyboardchange' js event on each
384         // frame
385         FOREACH(it, *frameLists)
386         {
387             JSObjectRef frame = static_cast<JSObjectRef>((*it).Get()->getObject());
388
389             auto eventPriv =
390                 new JSSoftKeyboardChangeEventPrivateObject(m_context, event);
391             JSObjectRef eventObject =
392                 JSObjectMake(
393                     m_context,
394                     JSSoftKeyboardChangeEvent::getClassRef(),
395                     eventPriv);
396
397             AddEventListenerSupport::CallCustomEventListenersFromIFrame(
398                 frame, eventType, eventObject);
399         }
400     } else {
401         LogDebug("Not supported custom event type");
402         return;
403     }
404 #endif
405 }
406
407 WindowPropertySupport* Explorer::getWindowPropertySupport()
408 {
409     return m_propertySupport.get();
410 }