Fixed navigating using 'Backspace' key
[profile/tv/apps/web/browser.git] / services / WebKitEngineService / WebKitEngineService.cpp
1 /*
2  * Copyright (c) 2014 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 /*
18  * WebKitEngineService.cpp
19  *
20  *  Created on: Apr 1, 2014
21  *      Author: p.rafalski
22  */
23
24 #include "browser_config.h"
25 #include "WebKitEngineService.h"
26 #include "AbstractWebEngine/TabThumbCache.h"
27
28 #include <Evas.h>
29 #include <memory>
30 #include <BrowserImage.h>
31 #include <app.h>
32
33 #include "BrowserAssert.h"
34 #include "BrowserLogger.h"
35 #include "WebView.h"
36
37 namespace tizen_browser {
38 namespace basic_webengine {
39 namespace webkitengine_service {
40
41 EXPORT_SERVICE(WebKitEngineService, "org.tizen.browser.webkitengineservice")
42
43 WebKitEngineService::WebKitEngineService()
44     : m_initialised(false)
45     , m_guiParent(nullptr)
46     , m_stopped(false)
47     , m_currentTabId(TabId::NONE)
48 {
49     m_mostRecentTab.clear();
50     m_tabs.clear();
51     m_chronoTabs.clear();
52 }
53
54 WebKitEngineService::~WebKitEngineService()
55 {
56 }
57
58 Evas_Object * WebKitEngineService::getLayout()
59 {
60     M_ASSERT(m_currentWebView);
61     return m_currentWebView->getLayout();
62 }
63
64 void WebKitEngineService::init(void * guiParent)
65 {
66     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
67     if (!m_initialised) {
68         m_guiParent = guiParent;
69         m_initialised = true;
70     }
71 }
72
73 void WebKitEngineService::connectSignals(std::shared_ptr<WebView> webView)
74 {
75     M_ASSERT(webView);
76     webView->favIconChanged.connect(boost::bind(&WebKitEngineService::_favIconChanged, this, _1));
77     webView->titleChanged.connect(boost::bind(&WebKitEngineService::_titleChanged, this, _1));
78     webView->uriChanged.connect(boost::bind(&WebKitEngineService::_uriChanged, this, _1));
79     webView->loadFinished.connect(boost::bind(&WebKitEngineService::_loadFinished, this));
80     webView->loadStarted.connect(boost::bind(&WebKitEngineService::_loadStarted, this));
81     webView->loadStop.connect(boost::bind(&WebKitEngineService::_loadStop, this));
82     webView->loadProgress.connect(boost::bind(&WebKitEngineService::_loadProgress, this, _1));
83     webView->loadError.connect(boost::bind(&WebKitEngineService::_loadError, this));
84     webView->forwardEnableChanged.connect(boost::bind(&WebKitEngineService::_forwardEnableChanged, this, _1));
85     webView->backwardEnableChanged.connect(boost::bind(&WebKitEngineService::_backwardEnableChanged, this, _1));
86     webView->cofirmationRequest.connect(boost::bind(&WebKitEngineService::_confirmationRequest, this, _1));
87     webView->ewkViewClicked.connect(boost::bind(&WebKitEngineService::webViewClicked, this));
88     webView->IMEStateChanged.connect(boost::bind(&WebKitEngineService::_IMEStateChanged, this, _1));
89 }
90
91 void WebKitEngineService::disconnectSignals(std::shared_ptr<WebView> webView)
92 {
93     M_ASSERT(webView);
94     webView->favIconChanged.disconnect(boost::bind(&WebKitEngineService::_favIconChanged, this));
95     webView->titleChanged.disconnect(boost::bind(&WebKitEngineService::_titleChanged, this, _1));
96     webView->uriChanged.disconnect(boost::bind(&WebKitEngineService::_uriChanged, this, _1));
97     webView->loadFinished.disconnect(boost::bind(&WebKitEngineService::_loadFinished, this));
98     webView->loadStarted.disconnect(boost::bind(&WebKitEngineService::_loadStarted, this));
99     webView->loadStop.disconnect(boost::bind(&WebKitEngineService::_loadStop, this));
100     webView->loadProgress.disconnect(boost::bind(&WebKitEngineService::_loadProgress, this, _1));
101     webView->loadError.disconnect(boost::bind(&WebKitEngineService::_loadError, this));
102     webView->forwardEnableChanged.disconnect(boost::bind(&WebKitEngineService::_forwardEnableChanged, this, _1));
103     webView->backwardEnableChanged.disconnect(boost::bind(&WebKitEngineService::_backwardEnableChanged, this, _1));
104     webView->cofirmationRequest.disconnect(boost::bind(&WebKitEngineService::_confirmationRequest, this, _1));
105     webView->ewkViewClicked.disconnect(boost::bind(&WebKitEngineService::webViewClicked, this));
106     webView->IMEStateChanged.disconnect(boost::bind(&WebKitEngineService::_IMEStateChanged, this, _1));
107 }
108
109 void WebKitEngineService::disconnectCurrentWebViewSignals()
110 {
111     if(m_currentWebView.get())
112         disconnectSignals(m_currentWebView);
113 }
114
115 void WebKitEngineService::setURI(const std::string & uri)
116 {
117     BROWSER_LOGD("%s:%d %s uri=%s", __FILE__, __LINE__, __func__, uri.c_str());
118     M_ASSERT(m_currentWebView);
119     m_stopped = false;
120     m_currentWebView->setURI(uri);
121 }
122
123 std::string WebKitEngineService::getURI() const
124 {
125     M_ASSERT(m_currentWebView);
126     if(m_currentWebView)
127         return m_currentWebView->getURI();
128     else
129         return std::string("");
130 }
131
132 bool WebKitEngineService::isLoadError() const
133 {
134     return m_currentWebView->isLoadError();
135 }
136
137
138 std::string WebKitEngineService::getTitle() const
139 {
140     M_ASSERT(m_currentWebView);
141     if (m_currentWebView) {
142         if (m_stopped)
143             return m_currentWebView->getURI();
144         else
145             return m_currentWebView->getTitle();
146     } else
147         return std::string("");
148 }
149
150 void WebKitEngineService::suspend()
151 {
152     if(tabsCount()>0) {
153         M_ASSERT(m_currentWebView);
154         m_currentWebView->suspend();
155     }
156 }
157
158 void WebKitEngineService::resume()
159 {
160     if(tabsCount()>0) {
161         M_ASSERT(m_currentWebView);
162         m_currentWebView->resume();
163     }
164 }
165
166 bool WebKitEngineService::isSuspended() const
167 {
168     M_ASSERT(m_currentWebView);
169     return m_currentWebView->isSuspended();
170 }
171
172 void WebKitEngineService::stopLoading(void)
173 {
174     M_ASSERT(m_currentWebView);
175     m_stopped = true;
176     m_currentWebView->stopLoading();
177 }
178
179 void WebKitEngineService::reload(void)
180 {
181     M_ASSERT(m_currentWebView);
182     m_stopped = false;
183     m_currentWebView->reload();
184 }
185
186 void WebKitEngineService::back(void)
187 {
188     M_ASSERT(m_currentWebView);
189     m_stopped = false;
190     m_currentWebView->back();
191 }
192
193 void WebKitEngineService::forward(void)
194 {
195     M_ASSERT(m_currentWebView);
196     m_stopped = false;
197     m_currentWebView->forward();
198 }
199
200 bool WebKitEngineService::isBackEnabled() const
201 {
202     M_ASSERT(m_currentWebView);
203     return m_currentWebView->isBackEnabled();
204 }
205
206 bool WebKitEngineService::isForwardEnabled() const
207 {
208     M_ASSERT(m_currentWebView);
209     return m_currentWebView->isForwardEnabled();
210 }
211
212 bool WebKitEngineService::isLoading() const
213 {
214     M_ASSERT(m_currentWebView);
215     return m_currentWebView->isBackEnabled();
216 }
217
218 void WebKitEngineService::_favIconChanged(std::shared_ptr<tizen_browser::tools::BrowserImage> bi)
219 {
220     BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
221     favIconChanged(bi);
222 }
223
224 void WebKitEngineService::_titleChanged(const std::string & title)
225 {
226     titleChanged(title);
227 }
228
229 void WebKitEngineService::_uriChanged(const std::string & uri)
230 {
231     uriChanged(uri);
232 }
233
234 void WebKitEngineService::_loadFinished()
235 {
236     loadFinished();
237 }
238
239 void WebKitEngineService::_loadStarted()
240 {
241     loadStarted();
242 }
243
244 void WebKitEngineService::_loadStop()
245 {
246     loadStop();
247 }
248
249 void WebKitEngineService::_loadError()
250 {
251     loadError();
252 }
253
254
255 void WebKitEngineService::_forwardEnableChanged(bool enable)
256 {
257     forwardEnableChanged(enable);
258 }
259
260 void WebKitEngineService::_backwardEnableChanged(bool enable)
261 {
262     backwardEnableChanged(enable);
263 }
264
265 void WebKitEngineService::_loadProgress(double d)
266 {
267     loadProgress(d);
268 }
269
270 void WebKitEngineService::_confirmationRequest(WebConfirmationPtr c)
271 {
272     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
273     confirmationRequest(c);
274 }
275
276 int WebKitEngineService::tabsCount() const
277 {
278     return m_tabs.size();
279 }
280
281 TabId WebKitEngineService::currentTabId() const
282 {
283     return m_currentTabId;
284 }
285
286 std::list<TabId> WebKitEngineService::listTabs() const
287 {
288     return m_mostRecentTab;
289 }
290
291 std::vector<std::shared_ptr<TabContent> > WebKitEngineService::getTabContents() const {
292     std::vector<std::shared_ptr<TabContent>> result;
293     for(std::list<TabId>::const_iterator it = m_chronoTabs.begin(); it != m_chronoTabs.end(); it++){
294         WebViewPtr item = m_tabs.find(*it)->second;
295
296         tizen_browser::services::TabThumbCache* thumbCache = tizen_browser::services::TabThumbCache::getInstance();
297         std::shared_ptr<tizen_browser::tools::BrowserImage> thumbnail = thumbCache->getThumb(*it);
298
299         auto tabContent = std::make_shared<TabContent>(*it, item->getTitle(), thumbnail);
300         result.push_back(tabContent);
301     }
302     return result;
303 }
304
305 TabId WebKitEngineService::addTab(const std::string & uri, const TabId * openerId, bool desktopMode, bool incognitoMode)
306 {
307     AbstractWebEngine::checkIfCreate();
308
309     config::DefaultConfig config;
310     config.load("");
311
312     if (tabsCount() >= boost::any_cast<int>(config.get("TAB_LIMIT")))
313         return currentTabId();
314
315     BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
316
317     // searching for next available tabId
318     TabId newTabId;
319     WebViewPtr p = std::make_shared<WebView>(reinterpret_cast<Evas_Object *>(m_guiParent), newTabId, incognitoMode);
320     if (openerId)
321         p->init(desktopMode, getTabView(*openerId));
322     else
323         p->init(desktopMode);
324
325     m_tabs[newTabId] = p;
326
327     if (!uri.empty()) {
328         p->setURI(uri);
329     }
330
331     switchToTab(newTabId);
332     AbstractWebEngine::tabCreated();
333     m_chronoTabs.push_front(newTabId);
334
335     return newTabId;
336 }
337
338 Evas_Object* WebKitEngineService::getTabView(TabId id){
339     return m_tabs[id]->getLayout();
340 }
341
342 bool WebKitEngineService::switchToTab(tizen_browser::basic_webengine::TabId newTabId)
343 {
344     BROWSER_LOGD("[%s:%d] newTabId=%s", __PRETTY_FUNCTION__, __LINE__, newTabId.toString().c_str());
345
346     // if there was any running WebView
347     if (m_currentWebView) {
348         disconnectSignals(m_currentWebView);
349         suspend();
350     }
351
352     m_currentWebView = m_tabs[newTabId];
353     m_currentTabId = newTabId;
354     m_mostRecentTab.remove(newTabId);
355     m_mostRecentTab.push_back(newTabId);
356
357     connectSignals(m_currentWebView);
358     resume();
359
360     titleChanged(m_currentWebView->getTitle());
361     uriChanged(m_currentWebView->getURI());
362     forwardEnableChanged(m_currentWebView->isForwardEnabled());
363     backwardEnableChanged(m_currentWebView->isBackEnabled());
364     favIconChanged(m_currentWebView->getFavicon());
365     currentTabChanged(m_currentTabId);
366
367     return true;
368 }
369
370 bool WebKitEngineService::closeTab()
371 {
372     BROWSER_LOGD("%s:%d %s closing tab=%s", __FILE__, __LINE__, __func__, m_currentTabId.toString().c_str());
373     bool res = closeTab(m_currentTabId);
374     return res;
375 }
376
377 bool WebKitEngineService::closeTab(TabId id) {
378     BROWSER_LOGD("%s:%d %s closing tab=%s", __FILE__, __LINE__, __func__, id.toString().c_str());
379     BROWSER_LOGD("%s:%d %s NONE tab=%s", __FILE__, __LINE__, __func__, TabId::NONE.toString().c_str());
380
381     TabId closingTabId = id;
382     bool res = true;
383     if(closingTabId == TabId::NONE){
384         return res;
385     }
386     m_tabs.erase(closingTabId);
387     m_chronoTabs.remove(closingTabId);
388     m_mostRecentTab.remove(closingTabId);
389     if (m_tabs.size() == 0) {
390         m_currentTabId = TabId::NONE;
391     }
392     else if (closingTabId == m_currentTabId && m_mostRecentTab.size()){
393         res = switchToTab(m_mostRecentTab.back());
394     }
395
396     tabClosed(closingTabId);
397
398     return res;
399 }
400
401 bool WebKitEngineService::nextTab()
402 {
403     // Empty implementation, with random UUID as ID we cannot distinguish between previous and next tab. Functionality not used.
404     return false;
405 }
406
407 bool WebKitEngineService::prevTab()
408 {
409     // Empty implementation, with random UUID as ID we cannot distinguish between previous and next tab. Functionality not used.
410     return false;
411 }
412
413 void WebKitEngineService::confirmationResult(WebConfirmationPtr c)
414 {
415     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
416     // tabId MUST be set
417     M_ASSERT(c && c->getTabId() != TabId());
418
419     // check if still exists
420     if (m_tabs.find(c->getTabId()) == m_tabs.end()) {
421         return;
422     }
423
424     m_tabs[c->getTabId()]->confirmationResult(c);
425 }
426
427 bool WebKitEngineService::isPrivateMode(const TabId& id)
428 {
429     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
430     return m_tabs[id]->isPrivateMode();
431 }
432
433 std::shared_ptr<tizen_browser::tools::BrowserImage> WebKitEngineService::getSnapshotData(int width, int height)
434 {
435     M_ASSERT(m_currentWebView);
436     if(m_currentWebView)
437         return m_currentWebView->captureSnapshot(width, height);
438     else
439         return std::make_shared<tizen_browser::tools::BrowserImage>();
440
441 }
442
443 std::shared_ptr<tizen_browser::tools::BrowserImage> WebKitEngineService::getSnapshotData(TabId id, int width, int height){
444    return m_tabs[id]->captureSnapshot(width,height);
445 }
446
447 void WebKitEngineService::setFocus()
448 {
449     M_ASSERT(m_currentWebView);
450     m_currentWebView->setFocus();
451 }
452
453 void WebKitEngineService::clearFocus()
454 {
455     M_ASSERT(m_currentWebView);
456     m_currentWebView->clearFocus();
457 }
458
459 bool WebKitEngineService::hasFocus() const
460 {
461     M_ASSERT(m_currentWebView);
462     return m_currentWebView->hasFocus();
463 }
464
465
466 std::shared_ptr<tizen_browser::tools::BrowserImage> WebKitEngineService::getFavicon()
467 {
468     M_ASSERT(m_currentWebView);
469     if (m_currentWebView) {
470         if (m_stopped)
471             return std::make_shared<tizen_browser::tools::BrowserImage>();
472         else
473             return m_currentWebView->getFavicon();
474     } else
475         return std::make_shared<tizen_browser::tools::BrowserImage>();
476 }
477
478 void WebKitEngineService::webViewClicked()
479 {
480     AbstractWebEngine::webViewClicked();
481 }
482
483
484 int WebKitEngineService::getZoomFactor() const
485 {
486     if(!m_currentWebView)
487         return 0;
488     return static_cast<int>(m_currentWebView->getZoomFactor()*100);
489
490 }
491
492 void WebKitEngineService::setZoomFactor(int zoomFactor)
493 {
494     M_ASSERT(m_currentWebView);
495     m_currentWebView->setZoomFactor(0.01*zoomFactor);
496
497 }
498
499 void WebKitEngineService::clearPrivateData()
500 {
501     for(std::map<TabId, WebViewPtr>::const_iterator it = m_tabs.begin(); it != m_tabs.end(); it++){
502             it->second->clearPrivateData();
503         }
504 }
505
506 void WebKitEngineService::searchOnWebsite(const std::string & searchString, int flags)
507 {
508     m_currentWebView->searchOnWebsite(searchString, flags);
509 }
510
511 void WebKitEngineService::_IMEStateChanged(bool enable)
512 {
513     IMEStateChanged(enable);
514 }
515
516 void WebKitEngineService::backButtonClicked()
517 {
518     M_ASSERT(m_currentWebView);
519     if (isBackEnabled()) {
520         m_currentWebView->back();
521     } else if (m_currentWebView->isPrivateMode()) {
522         closeTab();
523         switchToWebPage();
524     } else {
525         app_efl_exit();
526     }
527 }
528
529 void WebKitEngineService::switchToDesktopMode()
530 {
531     M_ASSERT(m_currentWebView);
532     m_currentWebView->switchToDesktopMode();
533 }
534
535 void WebKitEngineService::switchToMobileMode()
536 {
537     M_ASSERT(m_currentWebView);
538     m_currentWebView->switchToMobileMode();
539 }
540
541 bool WebKitEngineService::isDesktopMode() const
542 {
543     M_ASSERT(m_currentWebView);
544     return m_currentWebView->isDesktopMode();
545 }
546
547 void WebKitEngineService::scrollView(const int& dx, const int& dy)
548 {
549     m_currentWebView->scrollView(dx, dy);
550 }
551
552 } /* end of webkitengine_service */
553 } /* end of basic_webengine */
554 } /* end of tizen_browser */