WebViewEvasEventHandler does not rely on tizen_webview::WebView anymore
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / private / ewk_view_private.cc
1 // Copyright 2014 Samsung Electronics. 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 "ewk_view_private.h"
6
7 #include <cassert>
8
9 #include "eweb_view.h"
10 #include "tizen_webview/public/tw_webview_delegate.h"
11 #include "private/ewk_context_private.h"
12 #include "private/webview_delegate_ewk.h"
13
14
15 using tizen_webview::WebView;
16 using tizen_webview::WebViewDelegate;
17
18 // -------- EwkViewImpl
19 struct EwkViewImpl  {
20   explicit EwkViewImpl(tizen_webview::WebView* wv) : wv_(wv) {}
21   ~EwkViewImpl() { tizen_webview::WebView::Delete(wv_); }
22   tizen_webview::WebView* GetTizenWebView() { return wv_; }
23   const tizen_webview::WebView* GetTizenWebView() const { return wv_; }
24  private:
25   tizen_webview::WebView* wv_;
26   DISALLOW_COPY_AND_ASSIGN(EwkViewImpl);
27 };
28
29 Evas_Smart_Class parent_smart_class_ = EVAS_SMART_CLASS_INIT_NULL;
30
31 namespace {
32
33 Evas_Smart* DefaultSmartClassInstance()
34 {
35   static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION(EwkViewSmartClassName);
36   static Evas_Smart* smart = 0;
37   if (!smart) {
38     InitSmartClassInterface(api);
39     smart = evas_smart_class_new(&api.sc);
40   }
41
42   return smart;
43 }
44
45 void SmartDataChanged(Ewk_View_Smart_Data* d)
46 {
47   assert(d);
48   if (d->changed.any)
49     return;
50   d->changed.any = true;
51   evas_object_smart_changed(d->self);
52 }
53
54 // Evas_Smart_Class callback interface:
55 void handleEvasObjectAdd(Evas_Object* evas_object)
56 {
57   const Evas_Smart* smart = evas_object_smart_smart_get(evas_object);
58   const Evas_Smart_Class* smart_class = evas_smart_class_get(smart);
59   const Ewk_View_Smart_Class* api = reinterpret_cast<const Ewk_View_Smart_Class*>(smart_class);
60   assert(api);
61
62   Ewk_View_Smart_Data* d = GetEwkViewSmartDataFromEvasObject(evas_object);
63
64   if (!d) {
65     // Allocating with 'calloc' as the API contract is that it should be deleted with 'free()'.
66     d = static_cast<Ewk_View_Smart_Data*>(calloc(1, sizeof(Ewk_View_Smart_Data)));
67     evas_object_smart_data_set(evas_object, d);
68   }
69   d->self = evas_object;
70   d->api = api;
71
72   parent_smart_class_.add(evas_object);
73
74   d->priv = 0; // Will be initialized later.
75 }
76
77 // Ewk_View_Smart_Class callback interface:
78 void handleEvasObjectDelete(Evas_Object* evas_object)
79 {
80   Ewk_View_Smart_Data* smart_data = GetEwkViewSmartDataFromEvasObject(evas_object);
81   if (smart_data) {
82     delete smart_data->priv;
83     smart_data->priv = NULL;
84   }
85   parent_smart_class_.del(evas_object);
86 }
87
88 void handleEvasObjectShow(Evas_Object* o)
89 {
90   Ewk_View_Smart_Data* d = GetEwkViewSmartDataFromEvasObject(o);
91   WebView* wv = GetWebViewFromSmartData(d);
92   if (!wv) {
93     return;
94   }
95   // WebKit bails here if widget accelerated compositing is used.
96   // TODO: consider this when we will have AC support.
97   if (evas_object_clipees_get(d->base.clipper))
98     evas_object_show(d->base.clipper);
99   wv->HandleShow();
100 }
101
102 void handleEvasObjectHide(Evas_Object* o)
103 {
104   Ewk_View_Smart_Data* d = GetEwkViewSmartDataFromEvasObject(o);
105   WebView* wv = GetWebViewFromSmartData(d);
106   if (!wv) {
107     return;
108   }
109   evas_object_hide(d->base.clipper);
110   // Deleting view by app results in calling hide method.
111   // We assert that, RWHV is null only when renderer has crashed.
112   /*if (!ToEWebView(d)->rwhv()) {
113      DLOG_ASSERT is used because it is controlled by NDEBUG
114     DLOG_ASSERT(ToEWebView(d)->renderer_crashed_);
115     return;
116   }*/
117   wv->HandleHide();
118 }
119
120 void handleEvasObjectMove(Evas_Object* o, Evas_Coord x, Evas_Coord y)
121 {
122   Ewk_View_Smart_Data* d = GetEwkViewSmartDataFromEvasObject(o);
123   WebView* wv = GetWebViewFromSmartData(d);
124   if (!wv) {
125     return;
126   }
127   wv->HandleMove(x, y);
128   SmartDataChanged(d);
129 }
130
131 void handleEvasObjectResize(Evas_Object* o, Evas_Coord width, Evas_Coord height)
132 {
133   Ewk_View_Smart_Data* d = GetEwkViewSmartDataFromEvasObject(o);
134   WebView* wv = GetWebViewFromSmartData(d);
135   if (!wv) {
136     return;
137   }
138   d->view.w = width;
139   d->view.h = height;
140   wv->HandleResize(width, height);
141   SmartDataChanged(d);
142 }
143
144 void handleEvasObjectCalculate(Evas_Object* o)
145 {
146   Ewk_View_Smart_Data* d = GetEwkViewSmartDataFromEvasObject(o);
147   WebView* wv = GetWebViewFromSmartData(d);
148   if (!wv) {
149     return;
150   }
151   Evas_Coord x, y, width, height;
152   evas_object_geometry_get(o, &x, &y, &width, &height);
153   d->view.x = x;
154   d->view.y = y;
155   d->view.w = width;
156   d->view.h = height;
157 }
158
159 void handleEvasObjectColorSet(Evas_Object*, int red, int green, int blue, int alpha)
160 {
161   // FIXME: implement.
162 }
163
164 Eina_Bool handleTextSelectionDown(Ewk_View_Smart_Data* d, int x, int y)
165 {
166   WebView* wv = GetWebViewFromSmartData(d);
167   if (!wv)
168     return false;
169   return wv->HandleTextSelectionDown(x, y);
170 }
171
172 Eina_Bool handleTextSelectionUp(Ewk_View_Smart_Data* d, int x, int y)
173 {
174   WebView* wv = GetWebViewFromSmartData(d);
175   if (!wv)
176     return false;
177   return wv->HandleTextSelectionUp(x, y);
178 }
179
180 unsigned long long handleExceededDatabaseQuota(Ewk_View_Smart_Data *sd, const char *databaseName, const char *displayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage)
181 {
182   // Chromium does not support quota per origin right now, this API can't be implemented
183   NOTIMPLEMENTED();
184   return EINA_FALSE;
185 }
186
187 } // namespace
188
189
190 // --------- public API --------------
191
192 bool IsWebViewObject(const Evas_Object* evas_object)
193 {
194   if (!evas_object) {
195     return false;
196   }
197
198   const char* object_type = evas_object_type_get(evas_object);
199   const Evas_Smart* evas_smart = evas_object_smart_smart_get(evas_object);
200   if (!evas_smart) {
201     EINA_LOG_CRIT("%p (%s) is not a smart object!", evas_object,
202                   object_type ? object_type : "(null)");
203     return false;
204   }
205
206   const Evas_Smart_Class* smart_class = evas_smart_class_get(evas_smart);
207   if (!smart_class) {
208     EINA_LOG_CRIT("%p (%s) is not a smart class object!", evas_object,
209                   object_type ? object_type : "(null)");
210     return false;
211   }
212
213   if (smart_class->data != EwkViewSmartClassName) {
214     EINA_LOG_CRIT("%p (%s) is not of an ewk_view (need %p, got %p)!",
215                   evas_object, object_type ? object_type : "(null)",
216                   EwkViewSmartClassName, smart_class->data);
217     return false;
218   }
219   return true;
220 }
221
222 Ewk_View_Smart_Data* GetEwkViewSmartDataFromEvasObject(const Evas_Object* evas_object)
223 {
224   assert(evas_object);
225   assert(IsWebViewObject(evas_object));
226   return static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(evas_object));
227 }
228
229 WebView* GetWebViewFromSmartData(const Ewk_View_Smart_Data* smartData)
230 {
231   if (smartData && smartData->priv) {
232     return smartData->priv->GetTizenWebView();
233   }
234   return NULL;
235 }
236
237 WebView* GetWebViewFromEvasObject(const Evas_Object* eo) {
238   if (!IsWebViewObject(eo)) {
239     return NULL;
240   }
241   Ewk_View_Smart_Data* sd = GetEwkViewSmartDataFromEvasObject(eo);
242   return GetWebViewFromSmartData(sd);
243 }
244
245 Evas_Object* CreateWebViewAsEvasObject(Ewk_Context* context,
246                                        Evas* canvas,
247                                        Evas_Smart* smart /*= 0*/) {
248   if(!WebViewDelegate::IsDelegateRegistered()) {
249     WebViewDelegate::RegisterDelegate(
250       const_cast<WebViewDelegateEwk*>(&WebViewDelegateEwk::GetInstance()));
251   }
252
253   smart = smart ? smart : DefaultSmartClassInstance();
254   Evas_Object* wv_evas_object = evas_object_smart_add(canvas, smart);
255   WebView* view = WebView::Create(context, wv_evas_object);
256   if (!view) {
257     return NULL;
258   }
259   Ewk_View_Smart_Data* sd = GetEwkViewSmartDataFromEvasObject(wv_evas_object);
260   if (!sd) {
261     WebView::Delete(view);
262     return NULL;
263   }
264   // attach webview as a member of smart data
265   sd->priv = new EwkViewImpl(view);
266   view->Initialize();
267   return wv_evas_object;
268 }
269
270
271 bool InitSmartClassInterface(Ewk_View_Smart_Class& api)
272 {
273   if (api.version != EWK_VIEW_SMART_CLASS_VERSION) {
274     EINA_LOG_CRIT("Ewk_View_Smart_Class %p is version %lu while %lu was expected.",
275                   &api, api.version, EWK_VIEW_SMART_CLASS_VERSION);
276     return false;
277   }
278
279   if (!parent_smart_class_.add)
280     evas_object_smart_clipped_smart_set(&parent_smart_class_);
281
282   evas_object_smart_clipped_smart_set(&api.sc);
283
284   // Set Evas_Smart_Class callbacks.
285   api.sc.add = &handleEvasObjectAdd;
286   api.sc.del = &handleEvasObjectDelete;
287   api.sc.move = &handleEvasObjectMove;
288   api.sc.resize = &handleEvasObjectResize;
289   api.sc.show = &handleEvasObjectShow;
290   api.sc.hide = &handleEvasObjectHide;
291   api.sc.calculate = &handleEvasObjectCalculate;
292   api.sc.color_set = &handleEvasObjectColorSet;
293
294   // Set Ewk_View_Smart_Class callbacks.
295   api.text_selection_down = &handleTextSelectionDown;
296   api.text_selection_up = &handleTextSelectionUp;
297
298   api.exceeded_database_quota = &handleExceededDatabaseQuota;
299
300   // Type identifier.
301   api.sc.data = EwkViewSmartClassName;
302
303   return true;
304 }