1 // Copyright 2014-2015 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.
5 #include "eweb_context.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "components/autofill/content/browser/content_autofill_driver.h"
9 #include "content/public/browser/appcache_service.h"
10 #include "content/public/browser/browser_context.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/storage_partition.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/local_storage_usage_info.h"
15 #include "content/public/browser/dom_storage_context.h"
16 #include "browser/favicon/favicon_service.h"
17 #include "browser/webdata/web_data_service_factory.h"
18 #include "ui/gl/gl_shared_context_efl.h"
19 #include "net/http/http_cache.h"
20 #include "net/proxy/proxy_config_service_fixed.h"
21 #include "net/proxy/proxy_service.h"
22 #include "storage/browser/database/database_quota_client.h"
23 #include "storage/browser/fileapi/file_system_quota_client.h"
24 #include "storage/browser/quota/quota_manager.h"
26 #if defined(ENABLE_PLUGINS)
27 #include "content/common/plugin_list.h"
30 #include "browser_context_efl.h"
31 #include "ewk_global_data.h"
32 #include "memory_purger.h"
33 #include "browser/password_manager/password_manager.h"
34 #include "browser/password_manager/password_store_factory.h"
35 #include "browser/browsing_data_remover_efl.h"
36 #include "browser/vibration/vibration_provider_client.h"
37 #include "content/common/render_messages_efl.h"
38 #include "private/ewk_security_origin_private.h"
39 #include "wrt/wrt_widget_host.h"
41 using content::BrowserThread;
42 using content::BrowserContext;
43 using content::BrowserContextEfl;
49 EWebContext* EWebContext::default_context_ = NULL;
53 static const char* tizenExtensibleAPINames[] = {
54 "background,music", "csp", "encrypted,database", "fullscreen",
55 "fullscreen,forbid,auto,exit", "mediastream,record", "media,volume,control",
56 "prerendering,for,rotation", "rotate,camera,view", "rotation,lock",
57 "sound,mode", "support,fullscreen", "visibility,suspend",
58 "xwindow,for,fullscreen,video", "support,multimedia"};
61 * @brief Helper class for obtaining WebStorage origins
63 class WebStorageGetAllOriginsDispatcher: public base::RefCountedThreadSafe<WebStorageGetAllOriginsDispatcher> {
65 WebStorageGetAllOriginsDispatcher(Ewk_Web_Storage_Origins_Get_Callback callback, void* user_data)
67 , user_data_(user_data) {
72 void Dispatch(const std::vector<content::LocalStorageUsageInfo> &local_storage) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
75 Eina_List* lorigins = NULL;
77 std::vector<content::LocalStorageUsageInfo>::const_iterator it;
79 for (it = local_storage.begin(); it != local_storage.end(); it++) {
80 _Ewk_Security_Origin* origin = new _Ewk_Security_Origin(it->origin);
81 lorigins = eina_list_append(lorigins, origin);
84 callback_(lorigins, user_data_);
88 Ewk_Web_Storage_Origins_Get_Callback callback_;
92 void SetProxyConfigCallbackOnIOThread(base::WaitableEvent* done,
93 net::URLRequestContextGetter* url_request_context_getter,
94 const net::ProxyConfig& proxy_config) {
95 net::ProxyService* proxy_service =
96 url_request_context_getter->GetURLRequestContext()->proxy_service();
97 proxy_service->ResetConfigService(
98 make_scoped_ptr(new net::ProxyConfigServiceFixed(proxy_config)));
102 void OnOriginsWithApplicationCacheObtained(Ewk_Web_Application_Cache_Origins_Get_Callback callback,
104 scoped_refptr<content::AppCacheInfoCollection> collection,
106 Eina_List* origins = 0;
107 for (map<GURL, content::AppCacheInfoVector>::iterator iter = collection->infos_by_origin.begin();
108 iter != collection->infos_by_origin.end();
110 _Ewk_Security_Origin* origin = new _Ewk_Security_Origin(iter->first);
111 origins = eina_list_append(origins, origin);
113 callback(origins, user_data);
116 void OnTemporaryUsageAndQuotaObtained(
117 Ewk_Web_Application_Cache_Usage_For_Origin_Get_Callback callback,
119 storage::QuotaStatusCode status_code,
122 if (status_code != storage::kQuotaStatusOk) {
123 LOG(ERROR) << "Error in retrieving usage information";
124 // We still trigger callback.
127 BrowserThread::PostTask(BrowserThread::UI,
129 base::Bind(callback, usage, user_data));
132 void OnGetWebDBOrigins(
133 Ewk_Web_Database_Origins_Get_Callback callback,
135 const std::set<GURL>& origins_ref) {
136 Eina_List* origins = 0;
137 for (std::set<GURL>::iterator iter =
139 iter != origins_ref.end(); ++iter) {
140 _Ewk_Security_Origin* sec_origin = new _Ewk_Security_Origin(*iter);
141 origins = eina_list_append(origins, sec_origin);
143 BrowserThread::PostTask(BrowserThread::UI,
145 base::Bind(callback, origins, user_data));
148 void GetWebDBOriginsOnDBThread(Ewk_Web_Database_Origins_Get_Callback callback,
150 content::StoragePartition* partition) {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
152 storage::DatabaseQuotaClient client(
153 base::ThreadTaskRunnerHandle::Get().get(),
154 partition->GetDatabaseTracker());
155 client.GetOriginsForType(storage::kStorageTypeTemporary,
156 base::Bind(&OnGetWebDBOrigins, callback, user_data));
159 void OnGetFileSystemOrigins(
160 Ewk_Local_File_System_Origins_Get_Callback callback,
162 const std::set<GURL>& origins_ref) {
163 Eina_List* origins = 0;
164 for (std::set<GURL>::iterator iter =
166 iter != origins_ref.end(); ++iter) {
167 _Ewk_Security_Origin* sec_origin = new _Ewk_Security_Origin(*iter);
168 origins = eina_list_append(origins, sec_origin);
170 BrowserThread::PostTask(BrowserThread::UI,
172 base::Bind(callback, origins, user_data));
175 void GetFileSystemOriginsOnFILEThread(Ewk_Web_Database_Origins_Get_Callback callback,
177 content::StoragePartition* partition) {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
179 scoped_ptr<storage::FileSystemQuotaClient> client( new storage::FileSystemQuotaClient(partition->GetFileSystemContext(), false));
181 client->GetOriginsForType(storage::kStorageTypeTemporary,
182 base::Bind(&OnGetFileSystemOrigins, callback, user_data));
187 void EwkDidStartDownloadCallback::TriggerCallback(const string& url) {
189 (*callback_)(url.c_str(),user_data_);
192 bool EwkMimeOverrideCallback::TriggerCallback(const std::string& url_spec,
193 const std::string& mime_type,
194 char** new_mime_type) const {
197 Eina_Bool result = (*callback_)(url_spec.c_str(), mime_type.c_str(),
198 new_mime_type, user_data_);
202 void EWebContext::SendWidgetInfo(const std::string& tizen_id, double scale, const string &theme, const string &encoded_bundle) {
203 tizen_id_ = tizen_id;
204 widget_scale_ = scale;
205 widget_theme_ = theme;
206 widget_encoded_bundle_ = encoded_bundle;
209 void EWebContext::SendWrtMessage(const Ewk_Wrt_Message_Data& data) {
210 WrtWidgetHost::Get()->SendWrtMessage(data);
213 void EWebContext::SetMimeOverrideCallback(
214 Ewk_Context_Override_Mime_For_Url_Callback callback, void* user_data) {
215 mime_override_callback_.reset(new EwkMimeOverrideCallback(callback,
219 bool EWebContext::OverrideMimeForURL(const std::string& url_spec,
220 const std::string& mime_type,
221 std::string& new_mime_type) const {
222 if (!mime_override_callback_)
224 char *new_mime_type_string = NULL;
225 bool overridden = mime_override_callback_->TriggerCallback(
226 url_spec, mime_type, &new_mime_type_string);
228 DCHECK(new_mime_type_string);
229 new_mime_type.assign(new_mime_type_string);
230 ::free(new_mime_type_string);
236 EWebContext::EWebContext(bool incognito)
238 inspector_server_(NULL),
240 CHECK(EwkGlobalData::GetInstance());
242 browser_context_.reset(new BrowserContextEfl(this, incognito));
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 notification_cb_.reset(
247 new EWebContextNotificationCallback(nullptr, nullptr, nullptr, nullptr));
250 EWebContext::EWebContext(const std::string& injectedBundlePath)
251 : injected_bundle_path_(injectedBundlePath),
253 inspector_server_(NULL) {
254 CHECK(EwkGlobalData::GetInstance());
256 // WRT does not really care about incognito, so set it to false
257 browser_context_.reset(new BrowserContextEfl(this, false));
258 web_cache_manager_.reset(new WebCacheManagerEfl(browser_context_.get()));
259 notification_cb_.reset(
260 new EWebContextNotificationCallback(nullptr, nullptr, nullptr, nullptr));
263 EWebContext::~EWebContext() {
266 void EWebContext::ClearNetworkCache() {
267 BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
268 remover->ClearNetworkCache();
269 //remover deletes itself once it is done with clearing operation.
273 void EWebContext::ClearWebkitCache() {
274 if (web_cache_manager_)
275 web_cache_manager_->ClearCache();
278 void EWebContext::SetCacheModel(Ewk_Cache_Model model) {
279 if (web_cache_manager_)
280 web_cache_manager_->SetCacheModel(model);
283 Ewk_Cache_Model EWebContext::GetCacheModel() const {
284 return web_cache_manager_->GetCacheModel();
287 void EWebContext::SetNetworkCacheEnable(bool enable) {
288 net::URLRequestContext* url_context = browser_context_->GetRequestContext()->GetURLRequestContext();
292 net::HttpTransactionFactory* transaction_factory = url_context->http_transaction_factory();
293 if (!transaction_factory)
296 net::HttpCache* http_cache = transaction_factory->GetCache();
301 http_cache->set_mode(net::HttpCache::NORMAL);
303 http_cache->set_mode(net::HttpCache::DISABLE);
306 bool EWebContext::GetNetworkCacheEnable() const {
307 net::HttpCache* http_cache = browser_context_->GetRequestContext()->GetURLRequestContext()->
308 http_transaction_factory()->GetCache();
312 return (http_cache->mode() != net::HttpCache::DISABLE);
315 void EWebContext::AddExtraPluginDir(const char *path) {
316 #if defined(ENABLE_PLUGINS)
317 content::PluginList::Singleton()->AddExtraPluginDir(base::FilePath(path));
321 void EWebContext::SetCertificate(const char* certificate_file) {
322 browser_context_->SetCertificate(certificate_file);
325 void EWebContext::NotifyLowMemory() {
326 MemoryPurger::PurgeAll(browser_context_.get());
329 void EWebContext::SetProxyUri(const char* uri) {
330 proxy_uri_ = string(uri);
331 net::ProxyConfig config;
332 config.proxy_rules().ParseFromString(proxy_uri_);
333 base::WaitableEvent done(false, false);
334 BrowserThread::PostTask(
335 BrowserThread::IO, FROM_HERE,
336 base::Bind(&SetProxyConfigCallbackOnIOThread, &done,
337 make_scoped_refptr(browser_context()->GetRequestContext()),
342 void EWebContext::SetDidStartDownloadCallback(Ewk_Context_Did_Start_Download_Callback callback,
344 DCHECK(start_download_callback_.get() == NULL);
345 start_download_callback_.reset(new EwkDidStartDownloadCallback(callback,user_data));
348 EwkDidStartDownloadCallback* EWebContext::DidStartDownloadCallback() {
349 return start_download_callback_.get();
352 Ewk_Cookie_Manager* EWebContext::ewkCookieManager() {
353 if (!ewk_cookie_manager_)
354 ewk_cookie_manager_.reset(Ewk_Cookie_Manager::create());
355 return ewk_cookie_manager_.get();
358 void EWebContext::DeleteAllApplicationCache() {
359 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
360 BrowserThread::PostTask(
361 BrowserThread::UI, FROM_HERE,
362 base::Bind(&EWebContext::DeleteAllApplicationCache,
363 base::Unretained(this)));
366 BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
367 remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_APPCACHE, GURL());
370 void EWebContext::DeleteApplicationCacheForSite(const GURL& site) {
371 content::StoragePartition* partition = BrowserContext::GetStoragePartitionForSite(browser_context_.get(),
373 partition->ClearDataForOrigin(content::StoragePartition::REMOVE_DATA_MASK_APPCACHE,
374 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
376 partition->GetURLRequestContext(), base::Bind(&base::DoNothing));
379 void EWebContext::GetAllOriginsWithApplicationCache(Ewk_Web_Application_Cache_Origins_Get_Callback callback,
381 content::StoragePartition* partition =
382 BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
384 scoped_refptr<content::AppCacheInfoCollection> collection(new content::AppCacheInfoCollection());
385 // As per comments on AppCacheService,
386 // there is only one instance of AppCacheService per profile.(i.e. context in our case).
387 // So, we don't need to iterate over all StoragePartitions.
388 partition->GetAppCacheService()->GetAllAppCacheInfo(collection.get(),
389 base::Bind(&OnOriginsWithApplicationCacheObtained, callback, user_data, collection));
392 void EWebContext::GetApplicationCacheUsage(
394 Ewk_Web_Application_Cache_Usage_For_Origin_Get_Callback callback,
396 content::StoragePartition* partition =
397 BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
399 BrowserThread::PostTask(
402 base::Bind(&storage::QuotaManager::GetUsageAndQuota,
403 partition->GetQuotaManager(),
405 storage::kStorageTypeTemporary,
406 base::Bind(&OnTemporaryUsageAndQuotaObtained, callback, user_data)));
409 void EWebContext::WebStorageDelete() {
410 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
411 BrowserThread::PostTask(
412 BrowserThread::UI, FROM_HERE,
413 base::Bind(&EWebContext::WebStorageDelete,
414 base::Unretained(this)));
417 BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
418 remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_LOCAL_STORAGE, GURL());
421 void EWebContext::WebStorageDeleteForOrigin(const GURL& origin) {
422 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
423 BrowserThread::PostTask(
424 BrowserThread::UI, FROM_HERE,
425 base::Bind(&EWebContext::WebStorageDeleteForOrigin,
426 base::Unretained(this), origin));
429 content::StoragePartition* partition =
430 BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
432 partition->GetDOMStorageContext()->DeleteLocalStorage(origin);
435 void EWebContext::WebStorageOriginsAllGet(Ewk_Web_Storage_Origins_Get_Callback callback,
437 content::StoragePartition* partition =
438 BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
440 WebStorageGetAllOriginsDispatcher* dispatcher = new WebStorageGetAllOriginsDispatcher(callback, user_data);
442 partition->GetDOMStorageContext()->GetLocalStorageUsage(base::Bind(&WebStorageGetAllOriginsDispatcher::Dispatch, dispatcher));
445 void EWebContext::IndexedDBDelete() {
446 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
447 BrowserThread::PostTask(
448 BrowserThread::UI, FROM_HERE,
449 base::Bind(&EWebContext::IndexedDBDelete,
450 base::Unretained(this)));
453 BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
454 remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_INDEXEDDB, GURL());
457 void EWebContext::WebDBDelete(const GURL& host) {
458 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
459 BrowserThread::PostTask(
460 BrowserThread::UI, FROM_HERE,
461 base::Bind(&EWebContext::WebDBDelete,
462 base::Unretained(this), host));
465 BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
466 remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_WEBSQL, host);
469 void EWebContext::GetAllOriginsWithWebDB(Ewk_Web_Database_Origins_Get_Callback callback, void* user_data) {
470 content::StoragePartition* partition = BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
471 BrowserThread::PostTask(
474 base::Bind(&GetWebDBOriginsOnDBThread,
475 callback, user_data, partition));
478 void EWebContext::FileSystemDelete(const GURL& host) {
479 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
480 BrowserThread::PostTask(
481 BrowserThread::UI, FROM_HERE,
482 base::Bind(&EWebContext::FileSystemDelete,
483 base::Unretained(this), host));
486 BrowsingDataRemoverEfl* remover = BrowsingDataRemoverEfl::CreateForUnboundedRange(browser_context_.get());
487 remover->RemoveImpl(BrowsingDataRemoverEfl::REMOVE_FILE_SYSTEMS, host);
490 void EWebContext::GetAllOriginsWithFileSystem(Ewk_Local_File_System_Origins_Get_Callback callback, void* user_data) const {
491 content::StoragePartition* partition = BrowserContext::GetStoragePartition(browser_context_.get(), NULL);
492 BrowserThread::PostTask(
495 base::Bind(&GetFileSystemOriginsOnFILEThread, callback, user_data, partition));
498 bool EWebContext::SetFaviconDatabasePath(const char* path) {
500 return fs.SetDatabasePath(path);
503 #if defined(OS_TIZEN_TV)
504 FaviconDatabase* EWebContext::GetFaviconDatabase() {
505 return FaviconService::GetFaviconDatabase();
509 Evas_Object *EWebContext::AddFaviconObject(const char* uri, Evas* canvas) const {
510 if (uri == NULL || canvas == NULL) {
514 SkBitmap bitmap = fs.GetBitmapForPageURL(GURL(uri));
515 if (bitmap.isNull()) {
519 Evas_Object *favicon = evas_object_image_filled_add(canvas);
520 evas_object_image_size_set(favicon, bitmap.width(), bitmap.height());
521 evas_object_image_colorspace_set(favicon, EVAS_COLORSPACE_ARGB8888);
522 evas_object_image_fill_set(favicon, 0, 0, bitmap.width(), bitmap.height());
523 evas_object_image_filled_set(favicon, EINA_TRUE);
524 evas_object_image_alpha_set(favicon, EINA_TRUE);
525 void* pixels = evas_object_image_data_get(favicon, EINA_TRUE);
527 bitmap.copyPixelsTo(pixels, bitmap.getSize());
528 evas_object_image_data_set(favicon, pixels);
534 void EWebContext::ClearCandidateData() {
535 #if defined(TIZEN_AUTOFILL_SUPPORT)
536 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
537 BrowserThread::PostTask(
538 BrowserThread::UI, FROM_HERE,
539 base::Bind(&EWebContext::ClearCandidateData,
540 base::Unretained(this)));
543 WebDataServiceFactory* webDataServiceInstance =
544 WebDataServiceFactory::GetInstance();
545 scoped_refptr<autofill::AutofillWebDataService> autofillWebDataService =
546 webDataServiceInstance->GetAutofillWebDataForProfile();
547 if (autofillWebDataService.get()) {
548 // RemoveFormElementsAddedBetween will schedule task on proper thread,
549 // it is done in WebDatabaseService::ScheduleDBTask
550 autofillWebDataService->RemoveFormElementsAddedBetween(
554 DLOG(WARNING) << "AutofillWebDataService is NULL";
557 DLOG(WARNING) << "TIZEN_AUTOFILL_SUPPORT is not enabled";
561 void EWebContext::ClearPasswordData() {
562 #if defined(TIZEN_AUTOFILL_SUPPORT)
563 scoped_refptr<password_manager::PasswordStore> store =
564 password_manager::PasswordStoreFactory::GetPasswordStore();
566 store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(), base::Closure());
568 DLOG(WARNING) << "TIZEN_AUTOFILL_SUPPORT is not enabled";
572 unsigned int EWebContext::InspectorServerStart(unsigned int port) {
573 InspectorServerStop();
574 inspector_server_ = new devtools_http_handler::DevToolsDelegateEfl(port);
575 return inspector_server_ ? inspector_server_->port() : 0;
578 bool EWebContext::InspectorServerStop() {
579 if (!inspector_server_)
581 // The call below destroys inspector_server_.
582 inspector_server_->Stop();
583 inspector_server_ = NULL;
587 void EWebContext::SetNotificationCallbacks(
588 Ewk_Context* context,
589 Ewk_Context_Notification_Show_Callback show_callback,
590 Ewk_Context_Notification_Cancel_Callback cancel_callback,
592 notification_cb_.reset(
593 new EWebContextNotificationCallback(
594 context, show_callback, cancel_callback, user_data));
597 bool EWebContext::HasNotificationCallbacks() const {
598 return notification_cb_->HasShowCallback() &&
599 notification_cb_->HasCancelCallback();
602 bool EWebContext::NotificationShowCallback(Ewk_Notification* notification) {
603 return notification_cb_->RunShowCallback(notification);
606 bool EWebContext::NotificationCancelCallback(uint64_t notification_id) {
607 return notification_cb_->RunCancelCallback(notification_id);
610 int EWebContext::GetExtensibleAPIEnumFromName(const char* extensible_api_name) const {
611 if (extensible_api_name == NULL)
613 string extensible_string(extensible_api_name);
614 std::transform(extensible_string.begin(),
615 extensible_string.end(),
616 extensible_string.begin(),
618 for (int i = 0; i < static_cast<int>(EWK_MAX_EXTENSIBLE_API); ++i) {
619 if (extensible_string.compare(tizenExtensibleAPINames[i]) == 0)
625 bool EWebContext::SetExtensibleAPI(int extensible_api, bool enable) {
626 if (!tizen_extensible_)
627 tizen_extensible_.reset(TizenExtensible::create());
629 return tizen_extensible_->SetAPI(
630 static_cast<ExtensibleAPI>(extensible_api), enable);
633 bool EWebContext::GetExtensibleAPI(int extensible_api) {
634 if (!tizen_extensible_)
635 tizen_extensible_.reset(TizenExtensible::create());
637 return tizen_extensible_->GetAPI(
638 static_cast<ExtensibleAPI>(extensible_api));