Limit number of opened tabs in brower
[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_privateMode(false)
46     , m_guiParent(nullptr)
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_currentWebView->setURI(uri);
120 }
121
122 std::string WebKitEngineService::getURI() const
123 {
124     M_ASSERT(m_currentWebView);
125     if(m_currentWebView)
126         return m_currentWebView->getURI();
127     else
128         return std::string("");
129 }
130
131 bool WebKitEngineService::isLoadError() const
132 {
133     return m_currentWebView->isLoadError();
134 }
135
136
137 std::string WebKitEngineService::getTitle() const
138 {
139     M_ASSERT(m_currentWebView);
140     if(m_currentWebView)
141         return m_currentWebView->getTitle();
142     else
143         return std::string("");
144 }
145
146 void WebKitEngineService::stopLoading(void)
147 {
148     M_ASSERT(m_currentWebView);
149     m_currentWebView->stopLoading();
150 }
151
152 void WebKitEngineService::reload(void)
153 {
154     M_ASSERT(m_currentWebView);
155     m_currentWebView->reload();
156 }
157
158 void WebKitEngineService::back(void)
159 {
160     M_ASSERT(m_currentWebView);
161     m_currentWebView->back();
162 }
163
164 void WebKitEngineService::forward(void)
165 {
166     M_ASSERT(m_currentWebView);
167     m_currentWebView->forward();
168 }
169
170 bool WebKitEngineService::isBackEnabled() const
171 {
172     M_ASSERT(m_currentWebView);
173     return m_currentWebView->isBackEnabled();
174 }
175
176 bool WebKitEngineService::isForwardEnabled() const
177 {
178     M_ASSERT(m_currentWebView);
179     return m_currentWebView->isForwardEnabled();
180 }
181
182 bool WebKitEngineService::isLoading() const
183 {
184     M_ASSERT(m_currentWebView);
185     return m_currentWebView->isBackEnabled();
186 }
187
188 void WebKitEngineService::_favIconChanged(std::shared_ptr<tizen_browser::tools::BrowserImage> bi)
189 {
190     BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
191     favIconChanged(bi);
192 }
193
194 void WebKitEngineService::_titleChanged(const std::string & title)
195 {
196     titleChanged(title);
197 }
198
199 void WebKitEngineService::_uriChanged(const std::string & uri)
200 {
201     uriChanged(uri);
202 }
203
204 void WebKitEngineService::_uriChangedOnTab(TabId id)
205 {
206     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
207     uriOnTabChanged(id);
208 }
209
210 void WebKitEngineService::_loadFinished()
211 {
212     loadFinished();
213 }
214
215 void WebKitEngineService::_loadStarted()
216 {
217     loadStarted();
218 }
219
220 void WebKitEngineService::_loadStop()
221 {
222     loadStop();
223 }
224
225 void WebKitEngineService::_loadError()
226 {
227     loadError();
228 }
229
230
231 void WebKitEngineService::_forwardEnableChanged(bool enable)
232 {
233     forwardEnableChanged(enable);
234 }
235
236 void WebKitEngineService::_backwardEnableChanged(bool enable)
237 {
238     backwardEnableChanged(enable);
239 }
240
241 void WebKitEngineService::_loadProgress(double d)
242 {
243     loadProgress(d);
244 }
245
246 void WebKitEngineService::_confirmationRequest(WebConfirmationPtr c)
247 {
248     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
249     confirmationRequest(c);
250 }
251
252 int WebKitEngineService::tabsCount() const
253 {
254     return m_tabs.size();
255 }
256
257 TabId WebKitEngineService::currentTabId() const
258 {
259     return m_currentTabId;
260 }
261
262 std::list<TabId> WebKitEngineService::listTabs() const
263 {
264     return m_mostRecentTab;
265 }
266
267 std::vector<std::shared_ptr<TabContent> > WebKitEngineService::getTabContents() const {
268     std::vector<std::shared_ptr<TabContent>> result;
269     for(std::list<TabId>::const_iterator it = m_chronoTabs.begin(); it != m_chronoTabs.end(); it++){
270         WebViewPtr item = m_tabs.find(*it)->second;
271
272         tizen_browser::services::TabThumbCache* thumbCache = tizen_browser::services::TabThumbCache::getInstance();
273         std::shared_ptr<tizen_browser::tools::BrowserImage> thumbnail = thumbCache->getThumb(*it);
274
275         auto tabContent = std::make_shared<TabContent>(*it, item->getTitle(), thumbnail);
276         result.push_back(tabContent);
277     }
278     return result;
279 }
280
281 TabId WebKitEngineService::addTab(const std::string & uri, const TabId * openerId, bool desktopMode)
282 {
283     AbstractWebEngine::checkIfCreate();
284
285     config::DefaultConfig config;
286     config.load("");
287
288     if (tabsCount() >= boost::any_cast<int>(config.get("TAB_LIMIT")))
289         return currentTabId();
290
291     BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
292
293     // searching for next available tabId
294     TabId newTabId;
295     WebViewPtr p = std::make_shared<WebView>(reinterpret_cast<Evas_Object *>(m_guiParent), newTabId);
296     if (openerId)
297         p->init(desktopMode, getTabView(*openerId));
298     else
299         p->init(desktopMode);
300
301     m_tabs[newTabId] = p;
302
303     if (!uri.empty()) {
304         p->setURI(uri);
305     }
306     p->tabIdChecker.connect(boost::bind(&WebKitEngineService::_uriChangedOnTab,this,_1));
307
308     switchToTab(newTabId);
309     AbstractWebEngine::tabCreated();
310     m_chronoTabs.push_front(newTabId);
311
312     return newTabId;
313 }
314
315 Evas_Object* WebKitEngineService::getTabView(TabId id){
316     return m_tabs[id]->getLayout();
317 }
318
319 bool WebKitEngineService::switchToTab(tizen_browser::basic_webengine::TabId newTabId)
320 {
321     BROWSER_LOGD("[%s:%d] newTabId=%s", __PRETTY_FUNCTION__, __LINE__, newTabId.toString().c_str());
322
323     // if there was any running WebView
324     if (m_currentWebView) {
325         disconnectSignals(m_currentWebView);
326     }
327
328     m_currentWebView = m_tabs[newTabId];
329     m_currentTabId = newTabId;
330     m_mostRecentTab.remove(newTabId);
331     m_mostRecentTab.push_back(newTabId);
332
333     connectSignals(m_currentWebView);
334
335     titleChanged(m_currentWebView->getTitle());
336     uriChanged(m_currentWebView->getURI());
337     forwardEnableChanged(m_currentWebView->isForwardEnabled());
338     backwardEnableChanged(m_currentWebView->isBackEnabled());
339     favIconChanged(m_currentWebView->getFavicon());
340     currentTabChanged(m_currentTabId);
341
342     return true;
343 }
344
345 bool WebKitEngineService::closeTab()
346 {
347     BROWSER_LOGD("%s:%d %s closing tab=%s", __FILE__, __LINE__, __func__, m_currentTabId.toString().c_str());
348     bool res = closeTab(m_currentTabId);
349     return res;
350 }
351
352 bool WebKitEngineService::closeTab(TabId id) {
353     BROWSER_LOGD("%s:%d %s closing tab=%s", __FILE__, __LINE__, __func__, id.toString().c_str());
354     BROWSER_LOGD("%s:%d %s NONE tab=%s", __FILE__, __LINE__, __func__, TabId::NONE.toString().c_str());
355
356     TabId closingTabId = id;
357     bool res = true;
358     if(closingTabId == TabId::NONE){
359         return res;
360     }
361     m_tabs.erase(closingTabId);
362     m_chronoTabs.remove(closingTabId);
363     m_mostRecentTab.remove(closingTabId);
364     if (m_tabs.size() == 0) {
365         m_currentTabId = TabId::NONE;
366     }
367     else if (closingTabId == m_currentTabId && m_mostRecentTab.size()){
368         res = switchToTab(m_mostRecentTab.back());
369     }
370
371     tabClosed(closingTabId);
372
373     return res;
374 }
375
376 bool WebKitEngineService::nextTab()
377 {
378     // Empty implementation, with random UUID as ID we cannot distinguish between previous and next tab. Functionality not used.
379     return false;
380 }
381
382 bool WebKitEngineService::prevTab()
383 {
384     // Empty implementation, with random UUID as ID we cannot distinguish between previous and next tab. Functionality not used.
385     return false;
386 }
387
388 void WebKitEngineService::confirmationResult(WebConfirmationPtr c)
389 {
390     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
391     // tabId MUST be set
392     M_ASSERT(c && c->getTabId() != TabId());
393
394     // check if still exists
395     if (m_tabs.find(c->getTabId()) == m_tabs.end()) {
396         return;
397     }
398
399     m_tabs[c->getTabId()]->confirmationResult(c);
400 }
401
402 void WebKitEngineService::setPrivateMode(bool state)
403 {
404     BROWSER_LOGD("%s:%d %s", __FILE__, __LINE__, __func__);
405
406     if (m_privateMode == state) {
407         BROWSER_LOGD("%s:%d %s new privateMode is the same", __FILE__, __LINE__, __func__);
408         return;
409     }
410
411     m_privateMode = state;
412
413     for(std::map<TabId, WebViewPtr>::iterator it = m_tabs.begin(), end = m_tabs.end(); it != end; ++it)
414         it->second->setPrivateMode(state);
415 }
416
417 bool WebKitEngineService::isPrivateMode() const
418 {
419     return m_privateMode;
420 }
421
422 std::shared_ptr<tizen_browser::tools::BrowserImage> WebKitEngineService::getSnapshotData(int width, int height)
423 {
424     M_ASSERT(m_currentWebView);
425     if(m_currentWebView)
426         return m_currentWebView->captureSnapshot(width, height);
427     else
428         return std::make_shared<tizen_browser::tools::BrowserImage>();
429
430 }
431
432 std::shared_ptr<tizen_browser::tools::BrowserImage> WebKitEngineService::getSnapshotData(TabId id, int width, int height){
433    return m_tabs[id]->captureSnapshot(width,height);
434 }
435
436 void WebKitEngineService::setFocus()
437 {
438     M_ASSERT(m_currentWebView);
439     m_currentWebView->setFocus();
440 }
441
442 void WebKitEngineService::clearFocus()
443 {
444     M_ASSERT(m_currentWebView);
445     m_currentWebView->clearFocus();
446 }
447
448 bool WebKitEngineService::hasFocus() const
449 {
450     M_ASSERT(m_currentWebView);
451     return m_currentWebView->hasFocus();
452 }
453
454
455 std::shared_ptr<tizen_browser::tools::BrowserImage> WebKitEngineService::getFavicon()
456 {
457     M_ASSERT(m_currentWebView);
458     if(m_currentWebView)
459         return m_currentWebView->getFavicon();
460     else
461         return std::make_shared<tizen_browser::tools::BrowserImage>();
462 }
463
464 void WebKitEngineService::webViewClicked()
465 {
466     AbstractWebEngine::webViewClicked();
467 }
468
469
470 int WebKitEngineService::getZoomFactor() const
471 {
472     if(!m_currentWebView)
473         return 0;
474     return static_cast<int>(m_currentWebView->getZoomFactor()*100);
475
476 }
477
478 void WebKitEngineService::setZoomFactor(int zoomFactor)
479 {
480     M_ASSERT(m_currentWebView);
481     m_currentWebView->setZoomFactor(0.01*zoomFactor);
482
483 }
484
485 void WebKitEngineService::clearPrivateData()
486 {
487     for(std::map<TabId, WebViewPtr>::const_iterator it = m_tabs.begin(); it != m_tabs.end(); it++){
488             it->second->clearPrivateData();
489         }
490 }
491
492 void WebKitEngineService::searchOnWebsite(const std::string & searchString, int flags)
493 {
494     m_currentWebView->searchOnWebsite(searchString, flags);
495 }
496
497 void WebKitEngineService::_IMEStateChanged(bool enable)
498 {
499     IMEStateChanged(enable);
500 }
501
502 void WebKitEngineService::backButtonClicked() const
503 {
504     M_ASSERT(m_currentWebView);
505     if (isBackEnabled()) {
506         m_currentWebView->back();
507     } else {
508         app_efl_exit();
509     }
510 }
511
512 void WebKitEngineService::switchToDesktopMode()
513 {
514     M_ASSERT(m_currentWebView);
515     m_currentWebView->switchToDesktopMode();
516 }
517
518 void WebKitEngineService::switchToMobileMode()
519 {
520     M_ASSERT(m_currentWebView);
521     m_currentWebView->switchToMobileMode();
522 }
523
524 bool WebKitEngineService::isDesktopMode() const
525 {
526     M_ASSERT(m_currentWebView);
527     return m_currentWebView->isDesktopMode();
528 }
529
530 void WebKitEngineService::scrollView(const int& dx, const int& dy)
531 {
532     m_currentWebView->scrollView(dx, dy);
533 }
534
535 } /* end of webkitengine_service */
536 } /* end of basic_webengine */
537 } /* end of tizen_browser */