Commit 7b4baf80 authored by Jarryd's avatar Jarryd Committed by Commit Bot

Quota: Send storage pressure notification.

Add a bubble view notification that will alert end users when they
are getting low on disk space availability, a state known as storage
pressure. Notification will be triggered when a site attempts to store
something using a quota managed storage API (IndexedDB, FileSystem,
AppCache, or CacheStorage) that would take the user below 15% disk
availability. The notification will be limited to show at most once
per day.

Bug: 997258
Change-Id: I4ef84cbe8679eead70fd79546a392b84d32afad4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1794271Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarCait Phillips <caitkp@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Commit-Queue: Jarryd Goodman <jarrydg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#727392}
parent 89d2d53b
...@@ -4941,6 +4941,17 @@ Keep your key file in a safe place. You will need it to create new versions of y ...@@ -4941,6 +4941,17 @@ Keep your key file in a safe place. You will need it to create new versions of y
usage statistics usage statistics
</message> </message>
<!-- Storage Pressure Notification Infobar/Bubble -->
<message name="IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_TITLE" desc="The title for the notification warning users that they are low on disk space.">
Free up space to continue
</message>
<message name="IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_MESSAGE" desc="The message for the notification warning users that they are low on disk space, asking the user if they would like to go to the settings page and clear some data.">
Some features on <ph name="ORIGIN">$1<ex>site.com</ex></ph> might not work until you clear data that other sites have stored on your device
</message>
<message name="IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_BUTTON_LABEL" desc="Label for default button on storage pressure buble view which will take users to a page to manage site storage.">
Choose sites to clear
</message>
<!-- Bad Flags Infobar--> <!-- Bad Flags Infobar-->
<message name="IDS_BAD_FLAGS_WARNING_MESSAGE" desc="Message shown when an unsupported command-line flag is used. [Keep it short so it fits in the infobar.]"> <message name="IDS_BAD_FLAGS_WARNING_MESSAGE" desc="Message shown when an unsupported command-line flag is used. [Keep it short so it fits in the infobar.]">
You are using an unsupported command-line flag: <ph name="BAD_FLAG">$1<ex>--no-sandbox</ex></ph>. Stability and security will suffer. You are using an unsupported command-line flag: <ph name="BAD_FLAG">$1<ex>--no-sandbox</ex></ph>. Stability and security will suffer.
......
c296cb5d017f7ecb1e2cd3064f82c63cf0d7737b
\ No newline at end of file
c296cb5d017f7ecb1e2cd3064f82c63cf0d7737b
\ No newline at end of file
c296cb5d017f7ecb1e2cd3064f82c63cf0d7737b
\ No newline at end of file
...@@ -1767,10 +1767,6 @@ jumbo_static_library("browser") { ...@@ -1767,10 +1767,6 @@ jumbo_static_library("browser") {
"storage/durable_storage_permission_context.h", "storage/durable_storage_permission_context.h",
"storage/storage_info_fetcher.cc", "storage/storage_info_fetcher.cc",
"storage/storage_info_fetcher.h", "storage/storage_info_fetcher.h",
"storage/storage_notification_service_factory.cc",
"storage/storage_notification_service_factory.h",
"storage/storage_notification_service_impl.cc",
"storage/storage_notification_service_impl.h",
"subresource_filter/chrome_subresource_filter_client.cc", "subresource_filter/chrome_subresource_filter_client.cc",
"subresource_filter/chrome_subresource_filter_client.h", "subresource_filter/chrome_subresource_filter_client.h",
"subresource_filter/subresource_filter_content_settings_manager.cc", "subresource_filter/subresource_filter_content_settings_manager.cc",
...@@ -3547,6 +3543,10 @@ jumbo_static_library("browser") { ...@@ -3547,6 +3543,10 @@ jumbo_static_library("browser") {
"ssl/ssl_client_auth_observer.h", "ssl/ssl_client_auth_observer.h",
"status_icons/desktop_notification_balloon.cc", "status_icons/desktop_notification_balloon.cc",
"status_icons/desktop_notification_balloon.h", "status_icons/desktop_notification_balloon.h",
"storage/storage_notification_service_factory.cc",
"storage/storage_notification_service_factory.h",
"storage/storage_notification_service_impl.cc",
"storage/storage_notification_service_impl.h",
"sync/glue/extension_model_type_controller.cc", "sync/glue/extension_model_type_controller.cc",
"sync/glue/extension_model_type_controller.h", "sync/glue/extension_model_type_controller.h",
"sync/glue/extension_setting_model_type_controller.cc", "sync/glue/extension_setting_model_type_controller.cc",
......
...@@ -1173,7 +1173,11 @@ content::PushMessagingService* ProfileImpl::GetPushMessagingService() { ...@@ -1173,7 +1173,11 @@ content::PushMessagingService* ProfileImpl::GetPushMessagingService() {
content::StorageNotificationService* content::StorageNotificationService*
ProfileImpl::GetStorageNotificationService() { ProfileImpl::GetStorageNotificationService() {
#if defined(OS_ANDROID)
return nullptr;
#else
return StorageNotificationServiceFactory::GetForBrowserContext(this); return StorageNotificationServiceFactory::GetForBrowserContext(this);
#endif
} }
content::SSLHostStateDelegate* ProfileImpl::GetSSLHostStateDelegate() { content::SSLHostStateDelegate* ProfileImpl::GetSSLHostStateDelegate() {
......
...@@ -8,29 +8,14 @@ ...@@ -8,29 +8,14 @@
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/storage_pressure_bubble.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/system_notification_helper.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/grit/generated_resources.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/content_features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/message_center/public/cpp/notification.h"
#endif #endif
base::RepeatingClosure base::RepeatingCallback<void(const url::Origin)>
StorageNotificationServiceImpl::GetStoragePressureNotificationClosure() { StorageNotificationServiceImpl::GetStoragePressureNotificationClosure() {
return base::BindRepeating([](Profile* profile) {}, profile_); return base::BindRepeating(&chrome::ShowStoragePressureBubble);
} }
StorageNotificationServiceImpl::StorageNotificationServiceImpl() {} StorageNotificationServiceImpl::StorageNotificationServiceImpl() = default;
StorageNotificationServiceImpl::~StorageNotificationServiceImpl() = default; StorageNotificationServiceImpl::~StorageNotificationServiceImpl() = default;
...@@ -15,10 +15,8 @@ class StorageNotificationServiceImpl ...@@ -15,10 +15,8 @@ class StorageNotificationServiceImpl
public: public:
StorageNotificationServiceImpl(); StorageNotificationServiceImpl();
~StorageNotificationServiceImpl() override; ~StorageNotificationServiceImpl() override;
base::RepeatingClosure GetStoragePressureNotificationClosure() override; base::RepeatingCallback<void(const url::Origin)>
GetStoragePressureNotificationClosure() override;
private:
Profile* profile_;
}; };
#endif // CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_ #endif // CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
...@@ -44,7 +44,7 @@ TEST_F(StorageNotificationServiceTest, Default) { ...@@ -44,7 +44,7 @@ TEST_F(StorageNotificationServiceTest, Default) {
profile()->GetStorageNotificationService()); profile()->GetStorageNotificationService());
ASSERT_TRUE(storage_notification_service); ASSERT_TRUE(storage_notification_service);
base::RepeatingClosure callback = base::RepeatingCallback<void(const url::Origin)> callback =
storage_notification_service->GetStoragePressureNotificationClosure(); storage_notification_service->GetStoragePressureNotificationClosure();
ASSERT_TRUE(callback); ASSERT_TRUE(callback);
} }
...@@ -173,6 +173,7 @@ jumbo_static_library("ui") { ...@@ -173,6 +173,7 @@ jumbo_static_library("ui") {
"startup/bad_flags_prompt.cc", "startup/bad_flags_prompt.cc",
"startup/bad_flags_prompt.h", "startup/bad_flags_prompt.h",
"status_bubble.h", "status_bubble.h",
"storage_pressure_bubble.h",
"sync/tab_contents_synced_tab_delegate.cc", "sync/tab_contents_synced_tab_delegate.cc",
"sync/tab_contents_synced_tab_delegate.h", "sync/tab_contents_synced_tab_delegate.h",
"tab_contents/chrome_web_contents_view_delegate.h", "tab_contents/chrome_web_contents_view_delegate.h",
...@@ -3185,6 +3186,8 @@ jumbo_static_library("ui") { ...@@ -3185,6 +3186,8 @@ jumbo_static_library("ui") {
"views/simple_message_box_views.h", "views/simple_message_box_views.h",
"views/status_bubble_views.cc", "views/status_bubble_views.cc",
"views/status_bubble_views.h", "views/status_bubble_views.h",
"views/storage/storage_pressure_bubble_view.cc",
"views/storage/storage_pressure_bubble_view.h",
"views/subtle_notification_view.cc", "views/subtle_notification_view.cc",
"views/subtle_notification_view.h", "views/subtle_notification_view.h",
"views/sync/profile_signin_confirmation_dialog_views.cc", "views/sync/profile_signin_confirmation_dialog_views.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_STORAGE_PRESSURE_BUBBLE_H_
#define CHROME_BROWSER_UI_STORAGE_PRESSURE_BUBBLE_H_
#include "url/origin.h"
namespace chrome {
// Shows a BubbleView that alerts the user about storage pressure.
void ShowStoragePressureBubble(const url::Origin origin);
} // namespace chrome
#endif // CHROME_BROWSER_UI_STORAGE_PRESSURE_BUBBLE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/storage/storage_pressure_bubble_view.h"
#include "base/feature_list.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/bubble_anchor_util.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/frame/app_menu_button.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/grit/generated_resources.h"
#include "components/url_formatter/elide_url.h"
#include "content/public/common/content_features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/layout/box_layout.h"
namespace {
const char kAllSitesContentSettingsUrl[] = "chrome://settings/content/all";
} // namespace
namespace chrome {
// static
void ShowStoragePressureBubble(const url::Origin origin) {
StoragePressureBubbleView::ShowBubble(std::move(origin));
}
} // namespace chrome
void StoragePressureBubbleView::ShowBubble(const url::Origin origin) {
Browser* browser = BrowserList::GetInstance()->GetLastActive();
if (!browser || !base::FeatureList::IsEnabled(features::kStoragePressureUI))
return;
StoragePressureBubbleView* bubble = new StoragePressureBubbleView(
BrowserView::GetBrowserViewForBrowser(browser)
->toolbar_button_provider()
->GetAppMenuButton(),
gfx::Rect(), browser, std::move(origin));
views::BubbleDialogDelegateView::CreateBubble(bubble)->Show();
}
StoragePressureBubbleView::StoragePressureBubbleView(
views::View* anchor_view,
const gfx::Rect& anchor_rect,
Browser* browser,
const url::Origin origin)
: BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
browser_(browser),
origin_(std::move(origin)) {
if (!anchor_view) {
SetAnchorRect(anchor_rect);
set_parent_window(
platform_util::GetViewForWindow(browser->window()->GetNativeWindow()));
}
DialogDelegate::set_buttons(ui::DIALOG_BUTTON_OK);
}
base::string16 StoragePressureBubbleView::GetWindowTitle() const {
return l10n_util::GetStringUTF16(
IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_TITLE);
}
bool StoragePressureBubbleView::Accept() {
GetWidget()->Close();
const GURL all_sites_gurl(kAllSitesContentSettingsUrl);
NavigateParams params(browser_, all_sites_gurl,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
Navigate(&params);
return true;
}
bool StoragePressureBubbleView::Close() {
return true;
}
base::string16 StoragePressureBubbleView::GetDialogButtonLabel(
ui::DialogButton button) const {
if (button == ui::DIALOG_BUTTON_OK)
return l10n_util::GetStringUTF16(
IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_BUTTON_LABEL);
return views::DialogDelegateView::GetDialogButtonLabel(button);
}
void StoragePressureBubbleView::Init() {
ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(),
provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL)));
// Description text label.
auto text_label = std::make_unique<views::Label>(l10n_util::GetStringFUTF16(
IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_MESSAGE,
url_formatter::FormatOriginForSecurityDisplay(origin_)));
text_label->SetMultiLine(true);
text_label->SetLineHeight(20);
text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
text_label->SizeToFit(
provider->GetDistanceMetric(
ChromeDistanceMetric::DISTANCE_BUBBLE_PREFERRED_WIDTH) -
margins().width());
AddChildView(std::move(text_label));
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_STORAGE_STORAGE_PRESSURE_BUBBLE_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_STORAGE_STORAGE_PRESSURE_BUBBLE_VIEW_H_
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "url/origin.h"
class Browser;
class StoragePressureBubbleView : public views::BubbleDialogDelegateView {
public:
static void ShowBubble(const url::Origin origin);
private:
StoragePressureBubbleView(views::View* anchor_view,
const gfx::Rect& anchor_rect,
Browser* browser,
const url::Origin origin);
// views::DialogDelegate:
base::string16 GetWindowTitle() const override;
bool Accept() override;
bool Close() override;
base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
// views::BubbleDialogDelegateView:
void Init() override;
Browser* const browser_;
const GURL all_sites_url_ = GURL("chrome://settings/content/all");
const url::Origin origin_;
};
#endif // CHROME_BROWSER_UI_VIEWS_STORAGE_STORAGE_PRESSURE_BUBBLE_VIEW_H_
...@@ -3392,7 +3392,6 @@ test("unit_tests") { ...@@ -3392,7 +3392,6 @@ test("unit_tests") {
"../browser/status_icons/status_icon_unittest.cc", "../browser/status_icons/status_icon_unittest.cc",
"../browser/status_icons/status_tray_unittest.cc", "../browser/status_icons/status_tray_unittest.cc",
"../browser/storage/durable_storage_permission_context_unittest.cc", "../browser/storage/durable_storage_permission_context_unittest.cc",
"../browser/storage/storage_notification_service_unittest.cc",
"../browser/subresource_filter/subresource_filter_abusive_unittest.cc", "../browser/subresource_filter/subresource_filter_abusive_unittest.cc",
"../browser/subresource_filter/subresource_filter_configuration_unittest.cc", "../browser/subresource_filter/subresource_filter_configuration_unittest.cc",
"../browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc", "../browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc",
...@@ -3523,6 +3522,7 @@ test("unit_tests") { ...@@ -3523,6 +3522,7 @@ test("unit_tests") {
if (!is_android) { if (!is_android) {
sources += [ sources += [
"../browser/profiles/profile_avatar_icon_util_unittest.cc", "../browser/profiles/profile_avatar_icon_util_unittest.cc",
"../browser/storage/storage_notification_service_unittest.cc",
"../browser/tab_contents/form_interaction_tab_helper_unittest.cc", "../browser/tab_contents/form_interaction_tab_helper_unittest.cc",
"../browser/ui/autofill/payments/autofill_dialog_models_unittest.cc", "../browser/ui/autofill/payments/autofill_dialog_models_unittest.cc",
"../browser/ui/bookmarks/bookmark_editor_unittest.cc", "../browser/ui/bookmarks/bookmark_editor_unittest.cc",
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include "content/public/browser/network_service_instance.h" #include "content/public/browser/network_service_instance.h"
#include "content/public/browser/permission_controller.h" #include "content/public/browser/permission_controller.h"
#include "content/public/browser/session_storage_usage_info.h" #include "content/public/browser/session_storage_usage_info.h"
#include "content/public/browser/storage_notification_service.h"
#include "content/public/browser/storage_usage_info.h" #include "content/public/browser/storage_usage_info.h"
#include "content/public/common/content_client.h" #include "content/public/common/content_client.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
...@@ -1202,6 +1203,24 @@ void StoragePartitionImpl::Initialize() { ...@@ -1202,6 +1203,24 @@ void StoragePartitionImpl::Initialize() {
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy = scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy =
quota_manager_->proxy(); quota_manager_->proxy();
StorageNotificationService* storage_notification_service =
browser_context_->GetStorageNotificationService();
if (storage_notification_service) {
base::RepeatingCallback<void(const url::Origin)>
send_notification_function = base::BindRepeating(
[](scoped_refptr<base::SequencedTaskRunner> runner,
const base::RepeatingCallback<void(url::Origin)>& callback,
const url::Origin origin) {
base::PostTask(FROM_HERE, {BrowserThread::UI},
base::BindRepeating(callback, std::move(origin)));
},
base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
storage_notification_service
->GetStoragePressureNotificationClosure());
quota_manager_->SetStoragePressureCallback(send_notification_function);
}
// Each consumer is responsible for registering its QuotaClient during // Each consumer is responsible for registering its QuotaClient during
// its construction. // its construction.
filesystem_context_ = filesystem_context_ =
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_BROWSER_STORAGE_NOTIFICATION_SERVICE_H_ #define CONTENT_PUBLIC_BROWSER_STORAGE_NOTIFICATION_SERVICE_H_
#include "base/bind.h" #include "base/bind.h"
#include "url/origin.h"
namespace content { namespace content {
...@@ -23,7 +24,8 @@ class StorageNotificationService { ...@@ -23,7 +24,8 @@ class StorageNotificationService {
// is passed to QuotaManager in StoragePartitionImpl, where it is called // is passed to QuotaManager in StoragePartitionImpl, where it is called
// when QuotaManager determines appropriate to alert the user that the device // when QuotaManager determines appropriate to alert the user that the device
// is in a state of storage pressure. // is in a state of storage pressure.
virtual base::RepeatingClosure GetStoragePressureNotificationClosure() = 0; virtual base::RepeatingCallback<void(const url::Origin)>
GetStoragePressureNotificationClosure() = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(StorageNotificationService); DISALLOW_COPY_AND_ASSIGN(StorageNotificationService);
......
...@@ -50,6 +50,13 @@ const int64_t kMBytes = 1024 * 1024; ...@@ -50,6 +50,13 @@ const int64_t kMBytes = 1024 * 1024;
const int kMinutesInMilliSeconds = 60 * 1000; const int kMinutesInMilliSeconds = 60 * 1000;
const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour const int64_t kReportHistogramInterval = 60 * 60 * 1000; // 1 hour
// Start warning about disk pressure when device has <= 15% disk space
// available.
const double kDiskPressureThresholdRatio = 15;
// Limit notifications to one a day.
const base::TimeDelta kDiskPressureNotificationInterval =
base::TimeDelta::FromDays(1);
} // namespace } // namespace
const int64_t QuotaManager::kNoLimit = INT64_MAX; const int64_t QuotaManager::kNoLimit = INT64_MAX;
...@@ -186,7 +193,7 @@ bool UpdateModifiedTimeOnDBThread(const url::Origin& origin, ...@@ -186,7 +193,7 @@ bool UpdateModifiedTimeOnDBThread(const url::Origin& origin,
return database->SetOriginLastModifiedTime(origin, type, modified_time); return database->SetOriginLastModifiedTime(origin, type, modified_time);
} }
void DidGetUsageAndQuotaForWebApps( void DidGetUsageAndQuotaStripBreakdown(
QuotaManager::UsageAndQuotaCallback callback, QuotaManager::UsageAndQuotaCallback callback,
blink::mojom::QuotaStatusCode status, blink::mojom::QuotaStatusCode status,
int64_t usage, int64_t usage,
...@@ -205,6 +212,7 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { ...@@ -205,6 +212,7 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask {
bool is_unlimited, bool is_unlimited,
bool is_session_only, bool is_session_only,
bool is_incognito, bool is_incognito,
bool should_send_notification,
UsageAndQuotaWithBreakdownCallback callback) UsageAndQuotaWithBreakdownCallback callback)
: QuotaTask(manager), : QuotaTask(manager),
origin_(origin), origin_(origin),
...@@ -212,7 +220,8 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { ...@@ -212,7 +220,8 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask {
type_(type), type_(type),
is_unlimited_(is_unlimited), is_unlimited_(is_unlimited),
is_session_only_(is_session_only), is_session_only_(is_session_only),
is_incognito_(is_incognito) {} is_incognito_(is_incognito),
should_send_notification_(should_send_notification) {}
protected: protected:
void Run() override { void Run() override {
...@@ -283,6 +292,14 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { ...@@ -283,6 +292,14 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask {
} }
} }
if (should_send_notification_) {
const double percent_disk_available =
((total_space_ - available_space_) * 100 / total_space_);
if (percent_disk_available < kDiskPressureThresholdRatio) {
manager()->SendStoragePressureNotification(std::move(origin_));
}
}
std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, host_usage_, std::move(callback_).Run(blink::mojom::QuotaStatusCode::kOk, host_usage_,
host_quota, std::move(host_usage_breakdown_)); host_quota, std::move(host_usage_breakdown_));
if (type_ == StorageType::kTemporary && !is_incognito_ && if (type_ == StorageType::kTemporary && !is_incognito_ &&
...@@ -351,6 +368,7 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask { ...@@ -351,6 +368,7 @@ class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask {
bool is_unlimited_; bool is_unlimited_;
bool is_session_only_; bool is_session_only_;
bool is_incognito_; bool is_incognito_;
bool should_send_notification_;
int64_t available_space_ = 0; int64_t available_space_ = 0;
int64_t total_space_ = 0; int64_t total_space_ = 0;
int64_t desired_host_quota_ = 0; int64_t desired_host_quota_ = 0;
...@@ -921,7 +939,7 @@ void QuotaManager::GetUsageAndQuotaForWebApps(const url::Origin& origin, ...@@ -921,7 +939,7 @@ void QuotaManager::GetUsageAndQuotaForWebApps(const url::Origin& origin,
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
GetUsageAndQuotaWithBreakdown( GetUsageAndQuotaWithBreakdown(
origin, type, origin, type,
base::BindOnce(&DidGetUsageAndQuotaForWebApps, std::move(callback))); base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback)));
} }
void QuotaManager::GetUsageAndQuotaWithBreakdown( void QuotaManager::GetUsageAndQuotaWithBreakdown(
...@@ -945,7 +963,7 @@ void QuotaManager::GetUsageAndQuotaWithBreakdown( ...@@ -945,7 +963,7 @@ void QuotaManager::GetUsageAndQuotaWithBreakdown(
special_storage_policy_->IsStorageSessionOnly(origin.GetURL()); special_storage_policy_->IsStorageSessionOnly(origin.GetURL());
UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer( UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer(
this, origin, type, IsStorageUnlimited(origin, type), is_session_only, this, origin, type, IsStorageUnlimited(origin, type), is_session_only,
is_incognito_, std::move(callback)); is_incognito_, false, std::move(callback));
helper->Start(); helper->Start();
} }
...@@ -960,7 +978,24 @@ void QuotaManager::GetUsageAndQuota(const url::Origin& origin, ...@@ -960,7 +978,24 @@ void QuotaManager::GetUsageAndQuota(const url::Origin& origin,
return; return;
} }
GetUsageAndQuotaForWebApps(origin, type, std::move(callback)); if (!IsSupportedType(type) ||
(is_incognito_ && !IsSupportedIncognitoType(type))) {
std::move(callback).Run(
/*status*/ blink::mojom::QuotaStatusCode::kErrorNotSupported,
/*usage*/ 0,
/*quota*/ 0);
return;
}
LazyInitialize();
bool is_session_only =
type == StorageType::kTemporary && special_storage_policy_ &&
special_storage_policy_->IsStorageSessionOnly(origin.GetURL());
UsageAndQuotaInfoGatherer* helper = new UsageAndQuotaInfoGatherer(
this, origin, type, IsStorageUnlimited(origin, type), is_session_only,
is_incognito_, true,
base::BindOnce(&DidGetUsageAndQuotaStripBreakdown, std::move(callback)));
helper->Start();
} }
void QuotaManager::NotifyStorageAccessed(const url::Origin& origin, void QuotaManager::NotifyStorageAccessed(const url::Origin& origin,
...@@ -1443,6 +1478,33 @@ void QuotaManager::DeleteOriginDataInternal(const url::Origin& origin, ...@@ -1443,6 +1478,33 @@ void QuotaManager::DeleteOriginDataInternal(const url::Origin& origin,
deleter->Start(); deleter->Start();
} }
void QuotaManager::SendStoragePressureNotification(const url::Origin origin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!send_notification_function_) {
// Quota will hold onto a storage pressure notification if no storage
// pressure callback is set.
origin_with_pending_notification_ = std::move(origin);
return;
}
if (base::TimeTicks::Now() - disk_pressure_notification_timestamp_ <
kDiskPressureNotificationInterval) {
return;
}
send_notification_function_.Run(std::move(origin));
disk_pressure_notification_timestamp_ = base::TimeTicks::Now();
}
void QuotaManager::SetStoragePressureCallback(
base::RepeatingCallback<void(url::Origin)> send_notification_function) {
send_notification_function_ = send_notification_function;
if (origin_with_pending_notification_.has_value()) {
QuotaManager::SendStoragePressureNotification(
std::move(origin_with_pending_notification_.value()));
origin_with_pending_notification_ = base::nullopt;
}
}
void QuotaManager::ReportHistogram() { void QuotaManager::ReportHistogram() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!is_incognito_); DCHECK(!is_incognito_);
......
...@@ -249,6 +249,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager ...@@ -249,6 +249,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager
bool ResetUsageTracker(blink::mojom::StorageType type); bool ResetUsageTracker(blink::mojom::StorageType type);
// Called when StoragePartition is initialized if embedder has an
// implementation of StorageNotificationService.
void SetStoragePressureCallback(
base::RepeatingCallback<void(url::Origin)> send_notification_function);
static const int64_t kPerHostPersistentQuotaLimit; static const int64_t kPerHostPersistentQuotaLimit;
static const char kDatabaseName[]; static const char kDatabaseName[];
static const int kThresholdOfErrorsToBeBlacklisted; static const int kThresholdOfErrorsToBeBlacklisted;
...@@ -411,6 +416,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager ...@@ -411,6 +416,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager
void DeleteOnCorrectThread() const; void DeleteOnCorrectThread() const;
void SendStoragePressureNotification(const url::Origin origin);
void PostTaskAndReplyWithResultForDBThread( void PostTaskAndReplyWithResultForDBThread(
const base::Location& from_here, const base::Location& from_here,
base::OnceCallback<bool(QuotaDatabase*)> task, base::OnceCallback<bool(QuotaDatabase*)> task,
...@@ -428,6 +435,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager ...@@ -428,6 +435,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager
const scoped_refptr<QuotaManagerProxy> proxy_; const scoped_refptr<QuotaManagerProxy> proxy_;
bool db_disabled_; bool db_disabled_;
bool eviction_disabled_; bool eviction_disabled_;
base::Optional<url::Origin> origin_with_pending_notification_;
scoped_refptr<base::SingleThreadTaskRunner> io_thread_; scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
scoped_refptr<base::SequencedTaskRunner> db_runner_; scoped_refptr<base::SequencedTaskRunner> db_runner_;
mutable std::unique_ptr<QuotaDatabase> database_; mutable std::unique_ptr<QuotaDatabase> database_;
...@@ -435,8 +443,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager ...@@ -435,8 +443,10 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager
GetQuotaSettingsFunc get_settings_function_; GetQuotaSettingsFunc get_settings_function_;
scoped_refptr<base::TaskRunner> get_settings_task_runner_; scoped_refptr<base::TaskRunner> get_settings_task_runner_;
base::RepeatingCallback<void(url::Origin)> send_notification_function_;
QuotaSettings settings_; QuotaSettings settings_;
base::TimeTicks settings_timestamp_; base::TimeTicks settings_timestamp_;
base::TimeTicks disk_pressure_notification_timestamp_;
CallbackQueue<QuotaSettingsCallback, const QuotaSettings&> CallbackQueue<QuotaSettingsCallback, const QuotaSettings&>
settings_callbacks_; settings_callbacks_;
CallbackQueue<StorageCapacityCallback, int64_t, int64_t> CallbackQueue<StorageCapacityCallback, int64_t, int64_t>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment