const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- UsageAndQuotaCallback callback) override {
+ UsageAndQuotaCallback callback,
+ storage::QuotaClientType id,
+ int64_t transaction_size) override {
DCHECK(callback_task_runner);
// While this DCHECK is true, the PostTask() below isn't strictly necessary.
bucket_locator_.storage_key, blink::mojom::StorageType::kTemporary,
indexed_db_context_->IDBTaskRunner(),
base::BindOnce(&TransactionImpl::OnGotUsageAndQuotaForCommit,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr()),
+ storage::QuotaClientType::kIndexedDatabase, transaction_->size());
}
void TransactionImpl::OnGotUsageAndQuotaForCommit(
// Values are not expected to be persisted or logged. Enum members may be added,
// removed, and reordered without warning.
enum class QuotaClientType {
+ kUnknown = 0,
kFileSystem = 1,
kDatabase = 2,
kIndexedDatabase = 3,
manager()->GetStorageCapacity(
base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotCapacity,
weak_factory_.GetWeakPtr(), barrier));
+#if BUILDFLAG(IS_TIZEN)
+ // max quota size is 2 GB on Tizen
+ SetDesiredStorageKeyQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
+ 2 * 1024 * kMBytes);
+#else
SetDesiredStorageKeyQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
kNoLimit);
+#endif
} else if (type_ == StorageType::kSyncable) {
SetDesiredStorageKeyQuota(barrier, blink::mojom::QuotaStatusCode::kOk,
kSyncableStorageDefaultHostQuota);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(callback);
+#if !BUILDFLAG(IS_TIZEN)
+ // it needs maximum quota for unlimitedstorage policy. the max quota will be
+ // calculated in GetUsageAndQuotaForWebApps().
if (IsStorageUnlimited(storage_key, type)) {
// TODO(michaeln): This seems like a non-obvious odd behavior, probably for
// apps/extensions, but it would be good to eliminate this special case.
std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0, kNoLimit);
return;
}
+#endif
GetUsageAndQuotaWithBreakdown(
storage_key, type,
base::SysInfo::AmountOfFreeDiskSpace(path));
}
+#if BUILDFLAG(IS_TIZEN)
+void QuotaManagerImpl::GetTizenUnlimitedStoragePrivilege(
+ const GURL& origin,
+ QuotaClientType id,
+ int64_t transaction_size,
+ UsageAndQuotaCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota) {
+ if (id == storage::QuotaClientType::kIndexedDatabase &&
+ status == blink::mojom::QuotaStatusCode::kOk &&
+ transaction_size + usage > quota) {
+ if (special_storage_policy_.get()) {
+ special_storage_policy_->RequestUnlimitedStoragePolicy(
+ origin, quota,
+ base::BindOnce(
+ &QuotaManagerImpl::DidGetTizenUnlimitedStoragePrivilege,
+ weak_factory_.GetWeakPtr(), origin, std::move(callback), status,
+ usage, quota));
+ // callback will be invoked after checking unlimitedstorage privilege.
+ return;
+ }
+ }
+ std::move(callback).Run(status, usage, quota);
+}
+
+void QuotaManagerImpl::DidGetTizenUnlimitedStoragePrivilege(
+ const GURL& origin,
+ UsageAndQuotaCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota,
+ bool policy_changed) {
+ if (policy_changed)
+ GetUsageAndQuota(StorageKey(url::Origin::Create(origin)),
+ StorageType::kTemporary, std::move(callback));
+ else
+ std::move(callback).Run(status, usage, quota);
+}
+#endif
+
} // namespace storage
// DevTools clients/QuotaOverrideHandle with an active override.
void WithdrawOverridesForHandle(int handle_id);
+#if BUILDFLAG(IS_TIZEN)
+ void GetTizenUnlimitedStoragePrivilege(const GURL& origin,
+ QuotaClientType id,
+ int64_t transaction_size,
+ UsageAndQuotaCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota);
+
+ void DidGetTizenUnlimitedStoragePrivilege(
+ const GURL& origin,
+ UsageAndQuotaCallback callback,
+ blink::mojom::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota,
+ bool policy_changed);
+#endif
+
// Cap size for per-host persistent quota determined by the histogram.
// Cap size for per-host persistent quota determined by the histogram.
// This is a bit lax value because the histogram says nothing about per-host
#include "storage/browser/quota/storage_directory_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
+#include "url/gurl.h"
using ::blink::StorageKey;
const StorageKey& storage_key,
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- UsageAndQuotaCallback callback) {
+ UsageAndQuotaCallback callback,
+ QuotaClientType id,
+ int64_t transaction_size) {
DCHECK(callback_task_runner);
DCHECK(callback);
FROM_HERE,
base::BindOnce(&QuotaManagerProxy::GetUsageAndQuota, this, storage_key,
type, std::move(callback_task_runner),
- std::move(callback)));
+ std::move(callback), id, transaction_size));
return;
}
return;
}
- quota_manager_impl_->GetUsageAndQuota(storage_key, type, std::move(respond));
+ UsageAndQuotaCallback wrapped_callback =
+#if BUILDFLAG(IS_TIZEN)
+ (type == blink::mojom::StorageType::kTemporary)
+ ? base::BindOnce(&QuotaManagerImpl::GetTizenUnlimitedStoragePrivilege,
+ quota_manager_impl_, storage_key.origin().GetURL(),
+ id, transaction_size, std::move(callback))
+ :
+#endif
+ std::move(callback);
+
+ quota_manager_impl_->GetUsageAndQuota(storage_key, type, std::move(wrapped_callback));
}
void QuotaManagerProxy::GetBucketUsageAndQuota(
const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- UsageAndQuotaCallback callback);
+ UsageAndQuotaCallback callback,
+ QuotaClientType id = QuotaClientType::kUnknown,
+ int64_t transaction_size = 0);
void GetBucketUsageAndQuota(
const BucketInfo& bucket,
#ifndef STORAGE_BROWSER_QUOTA_SPECIAL_STORAGE_POLICY_H_
#define STORAGE_BROWSER_QUOTA_SPECIAL_STORAGE_POLICY_H_
+#include "base/callback.h"
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
: public base::RefCountedThreadSafe<SpecialStoragePolicy> {
public:
REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
+ using QuotaExceededReplyCallback =
+ base::OnceCallback<void(bool policy_changed)>;
using StoragePolicy = int;
enum ChangeFlags {
// Returns true if some origins are only allowed session-only storage.
virtual bool HasSessionOnlyOrigins() = 0;
+#if BUILDFLAG(IS_TIZEN)
+ virtual void RequestUnlimitedStoragePolicy(
+ const GURL& origin,
+ int64_t quota,
+ QuotaExceededReplyCallback callback) {
+ return;
+ }
+#endif
+
// Adds/removes an observer, the policy does not take
// ownership of the observer. Should only be called on the IO thread.
void AddObserver(Observer* observer);
const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- QuotaManager::UsageAndQuotaCallback callback) {
+ QuotaManager::UsageAndQuotaCallback callback,
+ QuotaClientType id,
+ int64_t transaction_size) {
if (mock_quota_manager_) {
mock_quota_manager_->GetUsageAndQuota(storage_key, type,
std::move(callback));
const blink::StorageKey& storage_key,
blink::mojom::StorageType type,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
- UsageAndQuotaCallback callback) override;
+ UsageAndQuotaCallback callback,
+ QuotaClientType id = QuotaClientType::kUnknown,
+ int64_t transaction_size = 0) override;
void GetUsageAndQuota(
const storage::BucketLocator& bucket_locator,
"browser/sound_effect.cc",
"browser/sound_effect.h",
"browser/sound_effect_tizen.cc",
+ "browser/special_storage_policy_efl.cc",
+ "browser/special_storage_policy_efl.h",
"browser/ssl_host_state_delegate_efl.cc",
"browser/ssl_host_state_delegate_efl.h",
"browser/tizen_extensible_host.cc",
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "special_storage_policy_efl.h"
+
+#include "base/containers/contains.h"
+#include "base/stl_util.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "url/origin.h"
+
+using content::BrowserThread;
+
+SpecialStoragePolicyEfl::SpecialStoragePolicyEfl() {}
+
+SpecialStoragePolicyEfl::~SpecialStoragePolicyEfl() {
+ quota_exceeded_callback_.Reset();
+}
+
+bool SpecialStoragePolicyEfl::IsStorageUnlimited(const GURL& origin) {
+ base::AutoLock locker(lock_);
+ if (!base::Contains(unlimited_, origin))
+ return false;
+ return unlimited_.find(origin)->second;
+}
+
+#if BUILDFLAG(IS_TIZEN)
+void SpecialStoragePolicyEfl::RequestUnlimitedStoragePolicy(
+ const GURL& origin,
+ int64_t quota,
+ QuotaExceededReplyCallback callback) {
+ {
+ base::AutoLock locker(lock_);
+ if (base::Contains(unlimited_, origin) ||
+ quota_exceeded_callback_.is_null()) {
+ LOG(INFO) << __func__ << " unlimited.";
+ std::move(callback).Run(false /* policy_changed */);
+ return;
+ }
+ }
+ LOG(INFO) << __func__ << " quota exceeded callback run.";
+ std::move(quota_exceeded_callback_).Run(origin, quota);
+ quota_exceeded_reply_callback_ = std::move(callback);
+}
+#endif
+
+void SpecialStoragePolicyEfl::SetQuotaExceededCallback(
+ QuotaExceededCallback callback) {
+ quota_exceeded_callback_ = std::move(callback);
+}
+
+void SpecialStoragePolicyEfl::SetUnlimitedStoragePolicy(const GURL& origin,
+ bool allow) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
+ base::BindOnce(&SpecialStoragePolicyEfl::SetUnlimitedStoragePolicy,
+ base::Unretained(this), origin, allow));
+ return;
+ }
+
+ bool policy_changed = IsStorageUnlimited(origin) != allow;
+ LOG(INFO) << __func__ << "() allow:" << allow
+ << ", changed:" << policy_changed;
+ {
+ base::AutoLock locker(lock_);
+ unlimited_[origin] = allow;
+ }
+ if (policy_changed) {
+ if (allow)
+ NotifyGranted(url::Origin::Create(origin),
+ SpecialStoragePolicy::STORAGE_UNLIMITED);
+ else
+ NotifyRevoked(url::Origin::Create(origin),
+ SpecialStoragePolicy::STORAGE_UNLIMITED);
+ }
+ if (!quota_exceeded_reply_callback_.is_null()) {
+ LOG(INFO) << __func__ << " quota exceeded reply callback run.";
+ std::move(quota_exceeded_reply_callback_).Run(policy_changed);
+ }
+}
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SPECIAL_STORAGE_POLICY_EFL_H_
+#define SPECIAL_STORAGE_POLICY_EFL_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/synchronization/lock.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "url/gurl.h"
+
+class SpecialStoragePolicyEfl : public storage::SpecialStoragePolicy {
+ public:
+ using QuotaExceededCallback =
+ base::OnceCallback<void(const GURL& origin, int64_t quota)>;
+ SpecialStoragePolicyEfl();
+
+ // storage::SpecialStoragePolicy implementation.
+ bool IsStorageProtected(const GURL& origin) override { return false; }
+ bool IsStorageUnlimited(const GURL& origin) override;
+ bool IsStorageSessionOnly(const GURL& origin) override { return false; }
+ bool HasIsolatedStorage(const GURL& origin) override { return false; }
+ bool HasSessionOnlyOrigins() override { return false; }
+ bool IsStorageDurable(const GURL& origin) override { return false; }
+
+// for quota exceeded callback
+#if BUILDFLAG(IS_TIZEN)
+ void RequestUnlimitedStoragePolicy(
+ const GURL& origin,
+ int64_t quota,
+ QuotaExceededReplyCallback callback) override;
+#endif
+ void SetQuotaExceededCallback(QuotaExceededCallback callback);
+ void SetUnlimitedStoragePolicy(const GURL& origin, bool allow);
+
+ protected:
+ ~SpecialStoragePolicyEfl() override;
+
+ SpecialStoragePolicyEfl(const SpecialStoragePolicyEfl&) = delete;
+ SpecialStoragePolicyEfl& operator=(const SpecialStoragePolicyEfl&) = delete;
+
+ private:
+ base::Lock lock_;
+ std::map<GURL, bool> unlimited_;
+ QuotaExceededCallback quota_exceeded_callback_;
+ QuotaExceededReplyCallback quota_exceeded_reply_callback_;
+};
+
+#endif // SPECIAL_STORAGE_POLICY_EFL_H_
BrowserContextEfl::GetBrowsingDataRemoverDelegate() {
return nullptr;
}
+
+SpecialStoragePolicyEfl* BrowserContextEfl::GetSpecialStoragePolicyEfl() {
+ if (!special_storage_policy_efl_.get())
+ special_storage_policy_efl_ = new SpecialStoragePolicyEfl();
+ return special_storage_policy_efl_.get();
+}
}
#include "base/files/scoped_temp_dir.h"
#include "base/synchronization/lock.h"
#include "browser/geolocation/geolocation_permission_context_efl.h"
+#include "browser/special_storage_policy_efl.h"
#include "browser/ssl_host_state_delegate_efl.h"
#include "components/visitedlink/browser/visitedlink_delegate.h"
#include "content/public/browser/browser_context.h"
}
BrowserPluginGuestManager* GetGuestManager() override { return 0; }
storage::SpecialStoragePolicy* GetSpecialStoragePolicy() override {
- return 0;
+ return GetSpecialStoragePolicyEfl();
}
+ SpecialStoragePolicyEfl* GetSpecialStoragePolicyEfl();
PushMessagingService* GetPushMessagingService() override { return 0; }
base::FilePath GetPath() override;
base::FilePath GetCachePath() const;
std::unique_ptr<SSLHostStateDelegateEfl> ssl_host_state_delegate_;
std::unique_ptr<BackgroundSyncController> background_sync_controller_;
std::unique_ptr<PermissionControllerDelegate> permission_controller_delegate_;
+ scoped_refptr<SpecialStoragePolicyEfl> special_storage_policy_efl_;
};
}
void* user_data) {
callback(evas_object_, manifest, user_data);
}
+
+void EWebView::SetExceededIndexedDatabaseQuotaCallback(
+ Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback,
+ void* user_data) {
+ exceeded_indexed_db_quota_callback_.Set(callback, user_data);
+ content::BrowserContextEfl* browser_context =
+ static_cast<content::BrowserContextEfl*>(
+ web_contents_->GetBrowserContext());
+ if (browser_context) {
+ browser_context->GetSpecialStoragePolicyEfl()->SetQuotaExceededCallback(
+ base::BindOnce(&EWebView::InvokeExceededIndexedDatabaseQuotaCallback,
+ base::Unretained(this)));
+ }
+}
+
+void EWebView::InvokeExceededIndexedDatabaseQuotaCallback(
+ const GURL& origin,
+ int64_t current_quota) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ base::ThreadPool::PostTask(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&EWebView::InvokeExceededIndexedDatabaseQuotaCallback,
+ base::Unretained(this), origin, current_quota));
+ return;
+ }
+ LOG(INFO) << __func__ << "()" << origin << ", " << current_quota;
+ CHECK(!exceeded_indexed_db_quota_origin_.get());
+ exceeded_indexed_db_quota_origin_.reset(new Ewk_Security_Origin(origin));
+ exceeded_indexed_db_quota_callback_.Run(
+ evas_object_, exceeded_indexed_db_quota_origin_.get(), current_quota);
+}
+
+void EWebView::ExceededIndexedDatabaseQuotaReply(bool allow) {
+ if (!exceeded_indexed_db_quota_origin_.get()) {
+ LOG(WARNING) << __func__ << "() : callback is not invoked!";
+ return;
+ }
+ LOG(INFO) << __func__ << "()" << exceeded_indexed_db_quota_origin_->GetURL()
+ << ", " << allow;
+ content::BrowserContextEfl* browser_context =
+ static_cast<content::BrowserContextEfl*>(
+ web_contents_->GetBrowserContext());
+ if (browser_context) {
+ browser_context->GetSpecialStoragePolicyEfl()->SetUnlimitedStoragePolicy(
+ exceeded_indexed_db_quota_origin_->GetURL(), allow);
+ }
+ exceeded_indexed_db_quota_origin_.reset();
+}
void* user_data_;
};
+template <typename CallbackPtr, typename... CallbackParameter>
+class WebViewExceededQuotaCallback {
+ public:
+ WebViewExceededQuotaCallback() { Set(nullptr, nullptr); }
+
+ void Set(CallbackPtr cb, void* data) {
+ callback_ = cb;
+ user_data_ = data;
+ }
+
+ bool IsCallbackSet() const { return callback_; }
+
+ /* LCOV_EXCL_START */
+ void Run(Evas_Object* webview, CallbackParameter... param) {
+ if (IsCallbackSet())
+ callback_(webview, param..., user_data_);
+ }
+ /* LCOV_EXCL_STOP */
+
+ private:
+ CallbackPtr callback_;
+ void* user_data_;
+};
+
class WebApplicationIconUrlGetCallback {
public:
WebApplicationIconUrlGetCallback(Ewk_Web_App_Icon_URL_Get_Callback func,
return gin_native_bridge_dispatcher_host_.get();
}
+ void SetExceededIndexedDatabaseQuotaCallback(
+ Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback,
+ void* user_data);
+ void InvokeExceededIndexedDatabaseQuotaCallback(const GURL& origin,
+ int64_t current_quota);
+ void ExceededIndexedDatabaseQuotaReply(bool allow);
+
/// ---- Event handling
bool HandleShow();
bool HandleHide();
std::unique_ptr<content::GinNativeBridgeDispatcherHost>
gin_native_bridge_dispatcher_host_;
+ WebViewExceededQuotaCallback<
+ Ewk_View_Exceeded_Indexed_Database_Quota_Callback,
+ Ewk_Security_Origin*,
+ long long>
+ exceeded_indexed_db_quota_callback_;
+ std::unique_ptr<Ewk_Security_Origin> exceeded_indexed_db_quota_origin_;
+
#if BUILDFLAG(IS_TIZEN)
blink::mojom::FileChooserParams::Mode filechooser_mode_;
#endif
LOG_EWK_API_MOCKUP("Not Supported by chromium");
}
-void ewk_view_exceeded_indexed_database_quota_callback_set(Evas_Object* ewkView, Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback, void* userData)
+void ewk_view_exceeded_indexed_database_quota_callback_set(Evas_Object* view, Ewk_View_Exceeded_Indexed_Database_Quota_Callback callback, void* user_data)
{
// Chromium does not support quota for Indexed DB only.
// IndexedDB uses temporary storage that is shared
// between other features.
- LOG_EWK_API_MOCKUP("Not Supported by chromium");
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->SetExceededIndexedDatabaseQuotaCallback(callback, user_data);
}
-void ewk_view_exceeded_indexed_database_quota_reply(Evas_Object* ewkView, Eina_Bool allow)
+void ewk_view_exceeded_indexed_database_quota_reply(Evas_Object* view, Eina_Bool allow)
{
// Chromium does not support quota for Indexed DB only.
// IndexedDB uses temporary storage that is shared
// between other features.
- LOG_EWK_API_MOCKUP("Not Supported by chromium");
+ EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+ impl->ExceededIndexedDatabaseQuotaReply(allow);
}
Eina_Bool ewk_view_text_find(Evas_Object *view, const char *text, Ewk_Find_Options options, unsigned int max_match_count)
web_view_, &Window::OnQuotaPermissionRequest, this);
ewk_view_did_change_theme_color_callback_set(
web_view_, &Window::OnThemeColorChanged, this);
+ ewk_view_exceeded_indexed_database_quota_callback_set(
+ web_view_, Window::OnQuotaExceededIndexedDB, this);
ewk_settings_form_profile_data_enabled_set(GetEwkSettings(), true);
ewk_settings_form_candidate_data_enabled_set(GetEwkSettings(), true);
log_info("Screenshot image could not be saved");
}
+void Window::OnQuotaExceededIndexedDB(Evas_Object*,
+ Ewk_Security_Origin* origin,
+ long long currentQuota,
+ void* data) {
+ log_trace("%s", __PRETTY_FUNCTION__);
+ Window* thiz = static_cast<Window*>(data);
+ ewk_view_exceeded_indexed_database_quota_reply(thiz->web_view_, true);
+}
+
void Window::Exit() const {
browser_.Exit();
}
#include <Ecore_Evas.h>
#include <ewk_settings_internal.h>
#include <ewk_quota_permission_request_internal.h>
+#include <ewk_view_internal.h>
#include "build/build_config.h"
static void OnOrientationChanged(void*, Evas_Object*, void*);
static void OnNewWindowPolicyDecide(void*, Evas_Object*, void*);
static void OnBackForwardListChanged(void*, Evas_Object*, void*);
+ static void OnQuotaExceededIndexedDB(Evas_Object*,
+ Ewk_Security_Origin* origin,
+ long long currentQuota,
+ void* data);
static void OnQuotaPermissionRequest(Evas_Object*, const Ewk_Quota_Permission_Request*, void*);
static void OnScreenshotCaptured(Evas_Object*, void*);
static void OnUserMediaPermissionRequest(void* data, Evas_Object*, void* event_info);