-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
iwa: Add Command to get IWA browsing data usage
GetIsolatedWebAppBrowsingDataCommand generates a map of installed IWA origin to total browsing data used by the app. The data usage is computed by creating a CookiesTreeModel and BrowsingDataModel for each StoragePartition owned by the IWA and combining the returned usage. Bug: 1311065 Change-Id: Ib03f2057bade4db1aa1810fc78abb23ceb67b105 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4327127 Reviewed-by: Zelin Liu <zelin@chromium.org> Reviewed-by: Dibyajyoti Pal <dibyapal@chromium.org> Commit-Queue: Robbie McElrath <rmcelrath@chromium.org> Reviewed-by: Christian Dullweber <dullweber@chromium.org> Reviewed-by: Daniel Murphy <dmurph@chromium.org> Cr-Commit-Position: refs/heads/main@{#1116052}
- Loading branch information
Showing
8 changed files
with
446 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
220 changes: 220 additions & 0 deletions
220
.../browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "chrome/browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.h" | ||
|
||
#include <memory> | ||
|
||
#include "base/barrier_closure.h" | ||
#include "base/functional/callback.h" | ||
#include "base/functional/callback_helpers.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "chrome/browser/browsing_data/chrome_browsing_data_model_delegate.h" | ||
#include "chrome/browser/browsing_data/cookies_tree_model.h" | ||
#include "chrome/browser/browsing_data/local_data_container.h" | ||
#include "chrome/browser/profiles/profile.h" | ||
#include "chrome/browser/profiles/profile_observer.h" | ||
#include "chrome/browser/web_applications/locks/full_system_lock.h" | ||
#include "chrome/browser/web_applications/web_app_id.h" | ||
#include "chrome/browser/web_applications/web_app_registrar.h" | ||
#include "components/browsing_data/content/browsing_data_model.h" | ||
#include "content/public/browser/storage_partition_config.h" | ||
#include "ui/base/models/tree_model.h" | ||
#include "url/origin.h" | ||
|
||
namespace web_app { | ||
namespace { | ||
|
||
const char kDebugOriginKey[] = "iwa_origins"; | ||
|
||
// Estimates the size in bytes of a non-default StoragePartition by summing the | ||
// size of all browsing data stored within it. | ||
class StoragePartitionSizeEstimator : private CookiesTreeModel::Observer, | ||
private ProfileObserver { | ||
public: | ||
static void EstimateSize( | ||
Profile* profile, | ||
const content::StoragePartitionConfig& storage_partition_config, | ||
base::OnceCallback<void(int64_t)> complete_callback) { | ||
DCHECK(!storage_partition_config.is_default()); | ||
|
||
// |owning_closure| will own the StoragePartitionSizeEstimator and delete | ||
// it when called or reset. | ||
auto* estimator = new StoragePartitionSizeEstimator(profile); | ||
base::OnceClosure owning_closure = | ||
base::DoNothingWithBoundArgs(base::WrapUnique(estimator)); | ||
|
||
estimator->Start( | ||
storage_partition_config, | ||
std::move(complete_callback).Then(std::move(owning_closure))); | ||
} | ||
|
||
~StoragePartitionSizeEstimator() override { profile_->RemoveObserver(this); } | ||
|
||
private: | ||
explicit StoragePartitionSizeEstimator(Profile* profile) : profile_(profile) { | ||
profile_->AddObserver(this); | ||
} | ||
|
||
void Start(const content::StoragePartitionConfig& storage_partition_config, | ||
base::OnceCallback<void(int64_t)> complete_callback) { | ||
complete_callback_ = std::move(complete_callback); | ||
// Need to wait for both BrowsingDataModel and CookiesTreeModel to load. | ||
int number_of_models_to_load = 2; | ||
model_loaded_closure_ = base::BarrierClosure( | ||
number_of_models_to_load, | ||
base::BindOnce(&StoragePartitionSizeEstimator::ModelsLoaded, | ||
weak_ptr_factory_.GetWeakPtr())); | ||
|
||
content::StoragePartition* storage_partition = | ||
profile_->GetStoragePartition(storage_partition_config); | ||
BrowsingDataModel::BuildFromDisk( | ||
storage_partition, | ||
ChromeBrowsingDataModelDelegate::CreateForProfile(profile_), | ||
base::BindOnce(&StoragePartitionSizeEstimator::BrowsingDataModelLoaded, | ||
weak_ptr_factory_.GetWeakPtr())); | ||
|
||
std::unique_ptr<LocalDataContainer> local_data_container = | ||
LocalDataContainer::CreateFromStoragePartition( | ||
storage_partition, | ||
CookiesTreeModel::GetCookieDeletionDisabledCallback(profile_)); | ||
cookies_tree_model_ = base::WrapUnique( | ||
new CookiesTreeModel(std::move(local_data_container), | ||
/*special_storage_policy=*/nullptr)); | ||
cookies_tree_model_->AddCookiesTreeObserver(this); | ||
} | ||
|
||
void ModelsLoaded() { | ||
int64_t size = cookies_tree_model_->GetRoot()->InclusiveSize(); | ||
for (const BrowsingDataModel::BrowsingDataEntryView& entry : | ||
*browsing_data_model_) { | ||
size += entry.data_details->storage_size; | ||
} | ||
std::move(complete_callback_).Run(size); | ||
} | ||
|
||
void BrowsingDataModelLoaded( | ||
std::unique_ptr<BrowsingDataModel> browsing_data_model) { | ||
browsing_data_model_ = std::move(browsing_data_model); | ||
model_loaded_closure_.Run(); | ||
} | ||
|
||
// CookiesTreeModel::Observer | ||
void TreeModelEndBatchDeprecated( | ||
CookiesTreeModel* cookies_tree_model) override { | ||
cookies_tree_model_->RemoveCookiesTreeObserver(this); | ||
model_loaded_closure_.Run(); | ||
} | ||
|
||
void TreeNodesAdded(ui::TreeModel* model, | ||
ui::TreeModelNode* parent, | ||
size_t start, | ||
size_t count) override {} | ||
void TreeNodesRemoved(ui::TreeModel* model, | ||
ui::TreeModelNode* parent, | ||
size_t start, | ||
size_t count) override {} | ||
void TreeNodeChanged(ui::TreeModel* model, ui::TreeModelNode* node) override { | ||
} | ||
|
||
// ProfileObserver: | ||
void OnProfileWillBeDestroyed(Profile* profile) override { | ||
// Abort if the Profile is being deleted. |complete_callback_| owns the | ||
// object, so resetting it will delete |this|. | ||
complete_callback_.Reset(); | ||
} | ||
|
||
Profile* profile_; | ||
base::OnceCallback<void(int64_t)> complete_callback_; | ||
base::RepeatingClosure model_loaded_closure_; | ||
std::unique_ptr<BrowsingDataModel> browsing_data_model_; | ||
std::unique_ptr<CookiesTreeModel> cookies_tree_model_; | ||
base::WeakPtrFactory<StoragePartitionSizeEstimator> weak_ptr_factory_{this}; | ||
}; | ||
|
||
} // namespace | ||
|
||
GetIsolatedWebAppBrowsingDataCommand::GetIsolatedWebAppBrowsingDataCommand( | ||
Profile* profile, | ||
BrowsingDataCallback callback) | ||
: WebAppCommandTemplate<FullSystemLock>( | ||
"GetIsolatedWebAppBrowsingDataCommand"), | ||
profile_(profile), | ||
callback_(std::move(callback)), | ||
lock_description_(std::make_unique<FullSystemLockDescription>()), | ||
browsing_data_({}) { | ||
debug_data_.Set("profile", profile_->GetDebugName()); | ||
} | ||
|
||
GetIsolatedWebAppBrowsingDataCommand::~GetIsolatedWebAppBrowsingDataCommand() = | ||
default; | ||
|
||
const LockDescription& GetIsolatedWebAppBrowsingDataCommand::lock_description() | ||
const { | ||
return *lock_description_; | ||
} | ||
|
||
base::Value GetIsolatedWebAppBrowsingDataCommand::ToDebugValue() const { | ||
return base::Value(debug_data_.Clone()); | ||
} | ||
|
||
void GetIsolatedWebAppBrowsingDataCommand::StartWithLock( | ||
std::unique_ptr<FullSystemLock> lock) { | ||
lock_ = std::move(lock); | ||
|
||
pending_task_count_++; | ||
const WebAppRegistrar& web_app_registrar = lock_->registrar(); | ||
for (const WebApp& web_app : web_app_registrar.GetApps()) { | ||
const AppId& app_id = web_app.app_id(); | ||
if (!web_app_registrar.IsIsolated(app_id)) { | ||
continue; | ||
} | ||
url::Origin iwa_origin = url::Origin::Create(web_app.scope()); | ||
for (const content::StoragePartitionConfig& storage_partition_config : | ||
web_app_registrar.GetIsolatedWebAppStoragePartitionConfigs(app_id)) { | ||
pending_task_count_++; | ||
debug_data_.EnsureDict(kDebugOriginKey)->Set(iwa_origin.Serialize(), -1); | ||
StoragePartitionSizeEstimator::EstimateSize( | ||
profile_, storage_partition_config, | ||
base::BindOnce(&GetIsolatedWebAppBrowsingDataCommand:: | ||
StoragePartitionSizeFetched, | ||
weak_factory_.GetWeakPtr(), | ||
/*data_key=*/iwa_origin)); | ||
} | ||
} | ||
pending_task_count_--; | ||
|
||
MaybeCompleteCommand(); | ||
} | ||
|
||
void GetIsolatedWebAppBrowsingDataCommand::StoragePartitionSizeFetched( | ||
const url::Origin& iwa_origin, | ||
int64_t size) { | ||
DCHECK_GT(pending_task_count_, 0); | ||
pending_task_count_--; | ||
browsing_data_[iwa_origin] += size; | ||
// Store the size as a double because Value::Dict doesn't support 64-bit | ||
// integers. This should only lead to data loss when size is >2^54. | ||
debug_data_.EnsureDict(kDebugOriginKey) | ||
->Set(iwa_origin.Serialize(), static_cast<double>(size)); | ||
|
||
MaybeCompleteCommand(); | ||
} | ||
|
||
void GetIsolatedWebAppBrowsingDataCommand::MaybeCompleteCommand() { | ||
if (pending_task_count_ == 0) { | ||
SignalCompletionAndSelfDestruct( | ||
CommandResult::kSuccess, | ||
base::BindOnce(std::move(callback_), browsing_data_)); | ||
} | ||
} | ||
|
||
void GetIsolatedWebAppBrowsingDataCommand::OnShutdown() { | ||
SignalCompletionAndSelfDestruct( | ||
CommandResult::kShutdown, | ||
base::BindOnce(std::move(callback_), | ||
base::flat_map<url::Origin, int64_t>())); | ||
} | ||
|
||
} // namespace web_app |
70 changes: 70 additions & 0 deletions
70
...e/browser/web_applications/isolated_web_apps/get_isolated_web_app_browsing_data_command.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_GET_ISOLATED_WEB_APP_BROWSING_DATA_COMMAND_H_ | ||
#define CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_GET_ISOLATED_WEB_APP_BROWSING_DATA_COMMAND_H_ | ||
|
||
#include <memory> | ||
|
||
#include "base/containers/flat_map.h" | ||
#include "base/functional/callback.h" | ||
#include "base/memory/raw_ptr.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "base/values.h" | ||
#include "chrome/browser/web_applications/commands/web_app_command.h" | ||
#include "chrome/browser/web_applications/locks/full_system_lock.h" | ||
|
||
class Profile; | ||
|
||
namespace url { | ||
class Origin; | ||
} // namespace url | ||
|
||
namespace web_app { | ||
|
||
class FullSystemLock; | ||
class FullSystemLockDescription; | ||
class LockDescription; | ||
|
||
// Computes the total browsing data usage in bytes of every installed Isolated | ||
// Web App. | ||
class GetIsolatedWebAppBrowsingDataCommand | ||
: public WebAppCommandTemplate<FullSystemLock> { | ||
public: | ||
using BrowsingDataCallback = | ||
base::OnceCallback<void(base::flat_map<url::Origin, int64_t>)>; | ||
|
||
GetIsolatedWebAppBrowsingDataCommand(Profile* profile, | ||
BrowsingDataCallback callback); | ||
~GetIsolatedWebAppBrowsingDataCommand() override; | ||
|
||
// WebAppCommandTemplate<FullSystemLock>: | ||
const LockDescription& lock_description() const override; | ||
base::Value ToDebugValue() const override; | ||
void StartWithLock(std::unique_ptr<FullSystemLock> lock) override; | ||
void OnShutdown() override; | ||
void OnSyncSourceRemoved() override {} | ||
|
||
private: | ||
void StoragePartitionSizeFetched(const url::Origin& iwa_origin, int64_t size); | ||
void MaybeCompleteCommand(); | ||
|
||
base::raw_ptr<Profile> profile_; | ||
BrowsingDataCallback callback_; | ||
|
||
std::unique_ptr<FullSystemLockDescription> lock_description_; | ||
std::unique_ptr<FullSystemLock> lock_; | ||
|
||
int pending_task_count_ = 0; | ||
base::flat_map<url::Origin, int64_t> browsing_data_; | ||
|
||
base::Value::Dict debug_data_; | ||
|
||
base::WeakPtrFactory<GetIsolatedWebAppBrowsingDataCommand> weak_factory_{ | ||
this}; | ||
}; | ||
|
||
} // namespace web_app | ||
|
||
#endif // CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_GET_ISOLATED_WEB_APP_BROWSING_DATA_COMMAND_H_ |
Oops, something went wrong.