Switch to new internal chromium branch dev/m38_2114 .
[platform/framework/web/chromium-efl.git] / tizen_src / impl / eweb_context.cc
1 /*
2    Copyright (C) 2014 Samsung Electronics
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include "eweb_context.h"
21
22 #include "base/synchronization/waitable_event.h"
23 #include "content/common/plugin_list.h"
24 #include "content/public/browser/appcache_service.h"
25 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/storage_partition.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/local_storage_usage_info.h"
30 #include "content/public/browser/dom_storage_context.h"
31 #include "browser/favicon/favicon_service.h"
32 #include "net/http/http_cache.h"
33 #include "net/proxy/proxy_config_service_fixed.h"
34 #include "net/proxy/proxy_service.h"
35 #include "webkit/browser/database/database_quota_client.h"
36 #include "webkit/browser/fileapi/file_system_quota_client.h"
37 #include "webkit/browser/quota/quota_manager.h"
38
39 #include "browser_context_efl.h"
40 #include "ewk_global_data.h"
41 #include "memory_purger.h"
42 #include "browser/renderer_host/browsing_data_remover_efl.h"
43 #include "browser/vibration/vibration_provider_client.h"
44 #include "common/render_messages_efl.h"
45 #include "memory_sampler.h"
46
47 #include "tizen_webview/public/tw_security_origin.h"
48 #include "tizen_webview/public/tw_wrt.h"
49 #include "tizen_webview/tw_misc_utility.h"
50
51 using content::BrowserThread;
52 using content::BrowserContext;
53 using content::BrowserContextEfl;
54
55 using std::string;
56 using std::pair;
57 using std::map;
58
59 using tizen_webview::Cache_Model;
60 using tizen_webview::Security_Origin;
61 using tizen_webview::GetGURL;
62 using tizen_webview::GetURL;
63
64 tizen_webview::Mime_Override_Callback EWebContext::mime_override_callback_ = 0;
65
66 namespace {
67
68 /**
69  * @brief Helper class for obtaining WebStorage origins
70  */
71 class WebStorageGetAllOriginsDispatcher: public base::RefCountedThreadSafe<WebStorageGetAllOriginsDispatcher> {
72 public:
73   WebStorageGetAllOriginsDispatcher(tizen_webview::Web_Storage_Origins_Get_Callback callback, void* user_data)
74     : callback_(callback)
75     , user_data_(user_data) {
76     DCHECK(callback_);
77     DCHECK(user_data_);
78   }
79
80   void Dispatch(const std::vector<content::LocalStorageUsageInfo> &local_storage) {
81     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82
83     Eina_List* lorigins = NULL;
84
85     std::vector<content::LocalStorageUsageInfo>::const_iterator it;
86
87     for (it = local_storage.begin(); it != local_storage.end(); it++) {
88       Security_Origin* origin = new Security_Origin(GetURL(it->origin));
89       lorigins = eina_list_append(lorigins, origin);
90     }
91
92     callback_(lorigins, user_data_);
93   }
94
95 private:
96   tizen_webview::Web_Storage_Origins_Get_Callback callback_;
97   void* user_data_;
98 };
99
100 void SetProxyConfigCallbackOnIOThread(base::WaitableEvent* done,
101                             net::URLRequestContextGetter* url_request_context_getter,
102                             const net::ProxyConfig& proxy_config) {
103   net::ProxyService* proxy_service =
104       url_request_context_getter->GetURLRequestContext()->proxy_service();
105   proxy_service->ResetConfigService(
106       new net::ProxyConfigServiceFixed(proxy_config));
107   done->Signal();
108 }
109
110 void OnOriginsWithApplicationCacheObtained(tizen_webview::Web_Application_Cache_Origins_Get_Callback callback,
111                                            void* user_data,
112                                            scoped_refptr<content::AppCacheInfoCollection> collection,
113                                            int result) {
114   Eina_List* origins = 0;
115   for (map<GURL, content::AppCacheInfoVector>::iterator iter = collection->infos_by_origin.begin();
116       iter != collection->infos_by_origin.end();
117       ++iter) {
118     Security_Origin* origin = new Security_Origin(GetURL(iter->first));
119     origins = eina_list_append(origins, origin);
120   }
121   callback(origins, user_data);
122 }
123
124 void OnTemporaryUsageAndQuotaObtained(
125     tizen_webview::Web_Application_Cache_Usage_For_Origin_Get_Callback callback,
126     void* user_data,
127     quota::QuotaStatusCode status_code,
128     int64 usage,
129     int64 quota) {
130   if (status_code != quota::kQuotaStatusOk) {
131     LOG(ERROR) << "Error in retrieving usage information";
132     // We still trigger callback.
133     usage = 0;
134   }
135   BrowserThread::PostTask(BrowserThread::UI,
136                           FROM_HERE,
137                           base::Bind(callback, usage, user_data));
138 }
139
140 void OnGetWebDBOrigins(
141     tizen_webview::Web_Database_Origins_Get_Callback callback,
142     void* user_data,
143     const std::set<GURL>& origins_ref) {
144   Eina_List* origins = 0;
145   for (std::set<GURL>::iterator iter =
146          origins_ref.begin();
147          iter != origins_ref.end(); ++iter) {
148       Security_Origin* sec_origin = new Security_Origin(GetURL(*iter));
149       origins = eina_list_append(origins, sec_origin);
150   }
151   BrowserThread::PostTask(BrowserThread::UI,
152                           FROM_HERE,
153                           base::Bind(callback, origins, user_data));
154 }
155
156 void GetWebDBOriginsOnDBThread(tizen_webview::Web_Database_Origins_Get_Callback callback,
157                                void* user_data,
158                                content::StoragePartition* partition) {
159   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
160   webkit_database::DatabaseQuotaClient client(base::MessageLoopProxy::current().get(), partition->GetDatabaseTracker());
161   client.GetOriginsForType(quota::kStorageTypeTemporary,
162                            base::Bind(&OnGetWebDBOrigins, callback, user_data));
163 }
164
165 void OnGetFileSystemOrigins(
166     tizen_webview::Local_File_System_Origins_Get_Callback callback,
167     void* user_data,
168     const std::set<GURL>& origins_ref) {
169   Eina_List* origins = 0;
170   for (std::set<GURL>::iterator iter =
171          origins_ref.begin();
172          iter != origins_ref.end(); ++iter) {
173       Security_Origin* sec_origin = new Security_Origin(GetURL(*iter));
174       origins = eina_list_append(origins, sec_origin);
175   }
176   BrowserThread::PostTask(BrowserThread::UI,
177                           FROM_HERE,
178                           base::Bind(callback, origins, user_data));
179 }
180
181 void GetFileSystemOriginsOnFILEThread(tizen_webview::Web_Database_Origins_Get_Callback callback,
182                                     void* user_data,
183                                     content::StoragePartition* partition) {
184   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
185   scoped_ptr<fileapi::FileSystemQuotaClient> client( new fileapi::FileSystemQuotaClient(partition->GetFileSystemContext(), false));
186
187   client->GetOriginsForType(quota::kStorageTypeTemporary,
188                             base::Bind(&OnGetFileSystemOrigins, callback, user_data));
189 }
190
191 } // namespace
192
193 void EwkDidStartDownloadCallback::TriggerCallback(const string& url) {
194   if(callback_)
195     (*callback_)(url.c_str(),user_data_);
196 }
197
198 void EWebContext::SendWidgetInfo(int widget_id, double scale, const string &theme, const string &encoded_bundle) {
199 #if !defined(EWK_BRINGUP)
200   content::RenderProcessHost::iterator i(content::RenderProcessHost::AllHostsIterator());
201   for (; !i.IsAtEnd(); i.Advance()) {
202     i.GetCurrentValue()->Send(
203       new EwkViewMsg_SetWidgetInfo(widget_id, scale, theme, encoded_bundle));
204   }
205 #endif
206 }
207
208 void EWebContext::SendWrtMessage(const tizen_webview::WrtIpcMessageData& data) {
209 #if !defined(EWK_BRINGUP)
210   content::RenderProcessHost::iterator i(content::RenderProcessHost::AllHostsIterator());
211   for (; !i.IsAtEnd(); i.Advance()) {
212     i.GetCurrentValue()->Send(new EwkViewMsg_SendWrtMessage(data));
213   }
214 #endif
215 }
216
217 void EWebContext::SetMimeOverrideCallback(
218     tizen_webview::Mime_Override_Callback callback) {
219   mime_override_callback_ = callback;
220 }
221
222 bool EWebContext::ShouldOverrideMimeForURL(
223     const GURL& url, std::string& mime_type) {
224   if (mime_override_callback_) {
225     char *new_mime = NULL;
226     bool overriden = mime_override_callback_(
227         url.spec().c_str(), mime_type.c_str(), &new_mime);
228     if (overriden) {
229       DCHECK(new_mime);
230       mime_type.assign(new_mime);
231       ::free(new_mime);
232       return true;
233     }
234   }
235   return false;
236 }
237
238 EWebContext::EWebContext()
239   : m_pixmap(0) {
240   EwkGlobalData::Ensure();
241
242   browser_context_.reset(new BrowserContextEfl(this));
243   // Notification Service gets init in BrowserMainRunner init,
244   // so cache manager can register for notifications only after that.
245   web_cache_manager_.reset(new WebCacheManagerEfl(browser_context_.get()));
246 }
247
248 EWebContext::~EWebContext() {
249   VibrationProviderClient::DeleteInstance();
250 }
251
252 void EWebContext::ClearNetworkCache() {
253   BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
254   remover->ClearNetworkCache();
255   //remover deletes itself once it is done with clearing operation.
256   return;
257 }
258
259 void EWebContext::ClearWebkitCache() {
260 #if !defined(EWK_BRINGUP)
261   web_cache_manager_->ClearCache();
262 #endif
263 }
264
265 void EWebContext::SetCacheModel(Cache_Model model) {
266 #if !defined(EWK_BRINGUP)
267   web_cache_manager_->SetCacheModel(model);
268 #endif
269 }
270
271 Cache_Model EWebContext::GetCacheModel() const {
272   return web_cache_manager_->GetCacheModel();
273 }
274
275 void EWebContext::SetNetworkCacheEnable(bool enable) {
276   net::URLRequestContext* url_context = browser_context_->GetRequestContext()->GetURLRequestContext();
277   if (!url_context)
278     return;
279
280   net::HttpTransactionFactory* transaction_factory = url_context->http_transaction_factory();
281   if (!transaction_factory)
282     return;
283
284   net::HttpCache* http_cache = transaction_factory->GetCache();
285   if (!http_cache)
286     return;
287
288   if (enable)
289     http_cache->set_mode(net::HttpCache::NORMAL);
290   else
291     http_cache->set_mode(net::HttpCache::DISABLE);
292 }
293
294 bool EWebContext::GetNetworkCacheEnable() const {
295   net::HttpCache* http_cache = browser_context_->GetRequestContext()->GetURLRequestContext()->
296       http_transaction_factory()->GetCache();
297   if (!http_cache)
298     return false;
299
300   return (http_cache->mode() != net::HttpCache::DISABLE);
301 }
302
303 bool EWebContext::HTTPCustomHeaderAdd(const char* name, const char* value) {
304   pair<map<string, string>::iterator,bool> ret;
305   ret = http_custom_headers_.insert(std::make_pair(string(name), string(value)));
306   return ret.second;
307 }
308
309 bool EWebContext::HTTPCustomHeaderRemove(const char* name) {
310   return http_custom_headers_.erase(string(name));
311 }
312
313 void EWebContext::HTTPCustomHeaderClear() {
314   http_custom_headers_.clear();
315 }
316
317 const HTTPCustomHeadersEflMap& EWebContext::GetHTTPCustomHeadersEflMap() const {
318   return http_custom_headers_;
319 }
320
321 void EWebContext::AddExtraPluginDir(const char *path) {
322   content::PluginList::Singleton()->AddExtraPluginDir(base::FilePath(path));
323 }
324
325 void EWebContext::SetCertificate(const char* certificate_file) {
326   browser_context_->SetCertificate(certificate_file);
327 }
328
329 void EWebContext::NotifyLowMemory() {
330   MemoryPurger::PurgeAll(browser_context_.get());
331 }
332
333 void EWebContext::SetProxyUri(const char* uri) {
334   proxy_uri_ = string(uri);
335   net::ProxyConfig config;
336   config.proxy_rules().ParseFromString(proxy_uri_);
337   base::WaitableEvent done(false, false);
338   BrowserThread::PostTask(
339       BrowserThread::IO, FROM_HERE,
340       base::Bind(&SetProxyConfigCallbackOnIOThread, &done,
341                  make_scoped_refptr(browser_context()->GetRequestContext()),
342                  config));
343   done.Wait();
344 }
345
346 void EWebContext::SetDidStartDownloadCallback(tizen_webview::Context_Did_Start_Download_Callback callback,
347                                               void* user_data) {
348   DCHECK(start_download_callback_.get() == NULL);
349   start_download_callback_.reset(new EwkDidStartDownloadCallback(callback,user_data));
350 }
351
352 EwkDidStartDownloadCallback* EWebContext::DidStartDownloadCallback() {
353   return start_download_callback_.get();
354 }
355
356 Ewk_Cookie_Manager* EWebContext::ewkCookieManager() {
357   if (!ewk_cookie_manager_)
358     ewk_cookie_manager_.reset(Ewk_Cookie_Manager::create(browser_context_->GetRequestContextEfl()));
359   return ewk_cookie_manager_.get();
360 }
361
362 void EWebContext::DeleteAllApplicationCache() {
363   BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
364   remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_APPCACHE, GURL());
365 }
366
367 void EWebContext::DeleteApplicationCacheForSite(const tizen_webview::URL& site) {
368   content::StoragePartition* partition = BrowserContext::GetStoragePartitionForSite(browser_context_.get(),
369                                                                                     GetGURL(site));
370   partition->ClearDataForOrigin(content::StoragePartition::REMOVE_DATA_MASK_APPCACHE,
371                                 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
372                                 GetGURL(site),
373                                 partition->GetURLRequestContext(), base::Bind(&base::DoNothing));
374 }
375
376 void EWebContext::GetAllOriginsWithApplicationCache(tizen_webview::Web_Application_Cache_Origins_Get_Callback callback,
377                                                     void* user_data) {
378   content::StoragePartition* partition =
379       BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
380
381   scoped_refptr<content::AppCacheInfoCollection> collection(new content::AppCacheInfoCollection());
382   // As per comments on AppCacheService,
383   // there is only one instance of AppCacheService per profile.(i.e. context in our case).
384   // So, we don't need to iterate over all StoragePartitions.
385   partition->GetAppCacheService()->GetAllAppCacheInfo(collection,
386       base::Bind(&OnOriginsWithApplicationCacheObtained, callback, user_data, collection));
387 }
388
389 void EWebContext::GetApplicationCacheUsage(
390     const tizen_webview::URL& url,
391     tizen_webview::Web_Application_Cache_Usage_For_Origin_Get_Callback callback,
392     void* user_data) {
393   content::StoragePartition* partition =
394         BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
395
396   BrowserThread::PostTask(
397       BrowserThread::IO,
398       FROM_HERE,
399       base::Bind(&quota::QuotaManager::GetUsageAndQuota,
400                  partition->GetQuotaManager(),
401                  GetGURL(url),
402                  quota::kStorageTypeTemporary,
403                  base::Bind(&OnTemporaryUsageAndQuotaObtained, callback, user_data)));
404 }
405
406 void EWebContext::WebStorageDelete() {
407   BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
408   remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_LOCAL_STORAGE, GURL());
409 }
410
411 void EWebContext::WebStorageDelete(const tizen_webview::URL& origin) {
412   content::StoragePartition* partition =
413       BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
414
415   partition->GetDOMStorageContext()->DeleteLocalStorage(GetGURL(origin));
416 }
417
418 void EWebContext::WebStorageOriginsAllGet(tizen_webview::Web_Storage_Origins_Get_Callback callback,
419                                                     void* user_data) {
420   content::StoragePartition* partition =
421       BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
422
423   WebStorageGetAllOriginsDispatcher* dispatcher = new WebStorageGetAllOriginsDispatcher(callback, user_data);
424
425   partition->GetDOMStorageContext()->GetLocalStorageUsage(base::Bind(&WebStorageGetAllOriginsDispatcher::Dispatch, dispatcher));
426 }
427
428 void EWebContext::IndexedDBDelete() {
429   BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
430   remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_INDEXEDDB, GURL());
431 }
432
433 void EWebContext::WebDBDelete(const tizen_webview::URL& host) {
434   BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
435   remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_WEBSQL, GetGURL(host));
436 }
437
438 void EWebContext::GetAllOriginsWithWebDB(tizen_webview::Web_Database_Origins_Get_Callback callback, void* user_data) {
439   content::StoragePartition* partition = BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
440   BrowserThread::PostTask(
441       BrowserThread::DB,
442       FROM_HERE,
443       base::Bind(&GetWebDBOriginsOnDBThread,
444                  callback, user_data, partition));
445 }
446
447 void EWebContext::FileSystemDelete(const tizen_webview::URL& host) {
448   BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
449   remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_FILE_SYSTEMS, GetGURL(host));
450 }
451
452 void EWebContext::GetAllOriginsWithFileSystem(tizen_webview::Local_File_System_Origins_Get_Callback callback, void* user_data) const {
453   content::StoragePartition* partition = BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
454   BrowserThread::PostTask(
455       BrowserThread::FILE,
456       FROM_HERE,
457         base::Bind(&GetFileSystemOriginsOnFILEThread, callback, user_data, partition));
458 }
459
460 bool EWebContext::SetFaviconDatabasePath(const char* path) {
461   FaviconService fs;
462   return fs.SetDatabasePath(path);
463 }
464
465 Evas_Object *EWebContext::AddFaviconObject(const char* uri, Evas* canvas) const {
466   if (uri == NULL || canvas == NULL) {
467     return NULL;
468   }
469   FaviconService fs;
470   SkBitmap bitmap = fs.GetBitmapForPageURL(GURL(uri));
471   if (bitmap.isNull()) {
472     return NULL;
473   }
474
475   Evas_Object *favicon = evas_object_image_filled_add(canvas);
476   evas_object_image_size_set(favicon, bitmap.width(), bitmap.height());
477   evas_object_image_colorspace_set(favicon, EVAS_COLORSPACE_ARGB8888);
478   bitmap.copyPixelsTo(evas_object_image_data_get(favicon, EINA_TRUE), bitmap.getSize());
479
480   return favicon;
481 }
482
483 void EWebContext::StartMemorySampler(double timerInterval) const {
484   WebMemorySampler::shared()->start(timerInterval);
485 }
486
487 void EWebContext::StopMemorySampler() const {
488   WebMemorySampler::shared()->stop();
489 }