Commit ca06f630 authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

[iOS][web] Add logic to BrowsingDataRemover

This CL adds the logic to clear the browsing data from the web
implementation of the BrowsingDataRemover.

Bug: 619783
Change-Id: Ia4771a61a8482adf296816eed54dafb5498de932
Reviewed-on: https://chromium-review.googlesource.com/c/1477831
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarMohammad Refaat <mrefaat@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635470}
parent 61f80a27
......@@ -88,7 +88,6 @@ class BrowsingDataRemoverImpl : public BrowsingDataRemover {
// Removes the browsing data stored in WKWebsiteDataStore if needed.
void RemoveDataFromWKWebsiteDataStore(base::Time delete_begin,
base::Time delete_end,
BrowsingDataRemoveMask mask);
// Invokes the current task callback that the removal has completed.
......
......@@ -537,7 +537,7 @@ void BrowsingDataRemoverImpl::RemoveImpl(base::Time delete_begin,
AdaptCallbackForRepeating(CreatePendingTaskCompletionClosure()));
// Remove browsing data stored in WKWebsiteDataStore if necessary.
RemoveDataFromWKWebsiteDataStore(delete_begin, delete_end, mask);
RemoveDataFromWKWebsiteDataStore(delete_begin, mask);
// Record the combined deletion of cookies and cache.
CookieOrCacheDeletionChoice choice;
......@@ -561,7 +561,6 @@ void BrowsingDataRemoverImpl::RemoveImpl(base::Time delete_begin,
// new API.
void BrowsingDataRemoverImpl::RemoveDataFromWKWebsiteDataStore(
base::Time delete_begin,
base::Time delete_end,
BrowsingDataRemoveMask mask) {
if (base::FeatureList::IsEnabled(kWebClearBrowsingData)) {
web::ClearBrowsingDataMask types =
......@@ -591,7 +590,8 @@ void BrowsingDataRemoverImpl::RemoveDataFromWKWebsiteDataStore(
types |= web::ClearBrowsingDataMask::kRemoveVisitedLinks;
}
web::ClearBrowsingData(browser_state_, types);
web::ClearBrowsingData(browser_state_, types, delete_begin,
CreatePendingTaskCompletionClosure());
return;
}
......
......@@ -11,7 +11,9 @@ source_set("browsing_data") {
]
deps = [
"//base",
"//ios/web/public",
"//ios/web/web_state/ui:wk_web_view_configuration_provider",
]
configs += [ "//build/config/compiler:enable_arc" ]
......@@ -22,6 +24,7 @@ source_set("browsing_data_unittests") {
testonly = true
deps = [
":browsing_data",
"//base/test:test_support",
"//ios/web/public/test/fakes",
"//testing/gtest",
]
......
......@@ -7,10 +7,14 @@
#import <Foundation/Foundation.h>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "base/time/time.h"
#import "ios/web/public/browsing_data_removing_util.h"
@protocol BrowsingDataRemoverObserver;
@class WKWebView;
namespace web {
......@@ -27,8 +31,11 @@ class BrowsingDataRemover : public base::SupportsUserData::Data {
// the |browser_state|. |browser_state| cannot be a nullptr.
static BrowsingDataRemover* FromBrowserState(BrowserState* browser_state);
// Clears the browsing data.
void ClearBrowsingData(ClearBrowsingDataMask types);
// Clears the browsing data. |modified_since| is the data since which all data
// is removed. |closure| is called when the browsing data have been cleared.
void ClearBrowsingData(ClearBrowsingDataMask types,
base::Time modified_since,
base::OnceClosure closure);
void AddObserver(id<BrowsingDataRemoverObserver> observer);
void RemoveObserver(id<BrowsingDataRemoverObserver> observer);
......@@ -37,6 +44,14 @@ class BrowsingDataRemover : public base::SupportsUserData::Data {
web::BrowserState* browser_state_; // weak, owns this object.
// The list of observers. Holds weak references.
NSHashTable<id<BrowsingDataRemoverObserver>>* observers_list_;
// Dummy WKWebView. A WKWebView object is created before deleting cookies. and
// is deleted after deleting cookies is completed. this is a workaround that
// makes sure that there is a WKWebView object alive while accessing
// WKHTTPCookieStore.
WKWebView* dummy_web_view_ = nil;
base::WeakPtrFactory<BrowsingDataRemover> weak_ptr_factory_;
};
} // namespace web
......
......@@ -4,9 +4,14 @@
#import "ios/web/browsing_data/browsing_data_remover.h"
#import <WebKit/WebKit.h>
#import "base/ios/block_types.h"
#include "base/task/post_task.h"
#import "ios/web/browsing_data/browsing_data_remover_observer.h"
#import "ios/web/public/browser_state.h"
#import "ios/web/public/web_thread.h"
#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -19,7 +24,7 @@ const char kWebBrowsingDataRemoverKeyName[] = "web_browsing_data_remover";
namespace web {
BrowsingDataRemover::BrowsingDataRemover(web::BrowserState* browser_state)
: browser_state_(browser_state) {
: browser_state_(browser_state), weak_ptr_factory_(this) {
DCHECK(browser_state_);
observers_list_ = [NSHashTable weakObjectsHashTable];
}
......@@ -42,8 +47,84 @@ BrowsingDataRemover* BrowsingDataRemover::FromBrowserState(
return browsing_data_remover;
}
void BrowsingDataRemover::ClearBrowsingData(ClearBrowsingDataMask types) {
// TODO(crbug.com/619783):implement this.
void BrowsingDataRemover::ClearBrowsingData(ClearBrowsingDataMask types,
base::Time modified_since,
base::OnceClosure closure) {
__block base::OnceClosure block_closure = std::move(closure);
// Converts browsing data types from ClearBrowsingDataMask to
// WKWebsiteDataStore strings.
NSMutableSet* data_types_to_remove = [[NSMutableSet alloc] init];
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveCacheStorage)) {
[data_types_to_remove addObject:WKWebsiteDataTypeDiskCache];
[data_types_to_remove addObject:WKWebsiteDataTypeMemoryCache];
}
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveAppCache)) {
[data_types_to_remove
addObject:WKWebsiteDataTypeOfflineWebApplicationCache];
}
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveLocalStorage)) {
[data_types_to_remove addObject:WKWebsiteDataTypeSessionStorage];
[data_types_to_remove addObject:WKWebsiteDataTypeLocalStorage];
}
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveWebSQL)) {
[data_types_to_remove addObject:WKWebsiteDataTypeWebSQLDatabases];
}
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveIndexedDB)) {
[data_types_to_remove addObject:WKWebsiteDataTypeIndexedDBDatabases];
}
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveCookies)) {
[data_types_to_remove addObject:WKWebsiteDataTypeCookies];
}
if (![data_types_to_remove count]) {
base::PostTask(FROM_HERE, base::BindOnce(std::move(block_closure)));
return;
}
base::WeakPtr<BrowsingDataRemover> weak_ptr = weak_ptr_factory_.GetWeakPtr();
ProceduralBlock completion_block = ^{
if (BrowsingDataRemover* strong_ptr = weak_ptr.get())
strong_ptr->dummy_web_view_ = nil;
std::move(block_closure).Run();
};
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveVisitedLinks)) {
ProceduralBlock previous_completion_block = completion_block;
// TODO(crbug.com/557963): Purging the WKProcessPool is a workaround for
// the fact that there is no public API to clear visited links in
// WKWebView. Remove this workaround if/when that API is made public.
// Note: Purging the WKProcessPool for clearing visisted links does have
// the side-effect of also losing the in-memory cookies of WKWebView but
// it is not a problem in practice since there is no UI to only have
// visited links be removed but not cookies.
completion_block = ^{
if (BrowsingDataRemover* strong_ptr = weak_ptr.get()) {
web::WKWebViewConfigurationProvider::FromBrowserState(
strong_ptr->browser_state_)
.Purge();
}
previous_completion_block();
};
}
// TODO(crbug.com/661630): |dummy_web_view_| is created to allow
// the -[WKWebsiteDataStore removeDataOfTypes:] API to access the cookiestore
// and clear cookies. This is a workaround for
// https://bugs.webkit.org/show_bug.cgi?id=149078. Remove this
// workaround when it's not needed anymore.
if (IsRemoveDataMaskSet(types, ClearBrowsingDataMask::kRemoveCookies)) {
if (!dummy_web_view_)
dummy_web_view_ = [[WKWebView alloc] initWithFrame:CGRectZero];
}
NSDate* delete_begin_date =
[NSDate dateWithTimeIntervalSince1970:modified_since.ToDoubleT()];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:data_types_to_remove
modifiedSince:delete_begin_date
completionHandler:completion_block];
}
void BrowsingDataRemover::AddObserver(
......
......@@ -4,6 +4,11 @@
#import "ios/web/browsing_data/browsing_data_remover.h"
#import <WebKit/WebKit.h>
#include "base/bind.h"
#import "base/test/ios/wait_util.h"
#include "base/test/scoped_task_environment.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
#include "testing/platform_test.h"
......@@ -11,6 +16,76 @@
#error "This file requires ARC support."
#endif
using base::test::ios::WaitUntilConditionOrTimeout;
using base::test::ios::kWaitForCookiesTimeout;
namespace {
// Adds cookies to the default data store. Returns whether it succeed to add
// cookies. Declare the function to have the "WARN_UNUSED_RESULT".
bool AddCookie() WARN_UNUSED_RESULT;
bool AddCookie() {
WKWebsiteDataStore* data_store = [WKWebsiteDataStore defaultDataStore];
NSHTTPCookie* cookie = [NSHTTPCookie cookieWithProperties:@{
NSHTTPCookiePath : @"path",
NSHTTPCookieName : @"cookieName",
NSHTTPCookieValue : @"value",
NSHTTPCookieOriginURL : @"http://chromium.org"
}];
__block bool cookie_set = false;
[data_store.httpCookieStore setCookie:cookie
completionHandler:^{
cookie_set = true;
}];
return WaitUntilConditionOrTimeout(kWaitForCookiesTimeout, ^bool {
return cookie_set;
});
}
// Checks that the cookies data store has cookies or not, depending on
// |should_have_cookies|. Declare the function to have the "WARN_UNUSED_RESULT".
bool HasCookies(bool should_have_cookies) WARN_UNUSED_RESULT;
bool HasCookies(bool should_have_cookies) {
__block bool has_cookies = false;
__block bool completion_called = false;
[[WKWebsiteDataStore defaultDataStore].httpCookieStore
getAllCookies:^(NSArray<NSHTTPCookie*>* cookies) {
has_cookies = cookies.count > 0;
completion_called = true;
}];
bool completed = WaitUntilConditionOrTimeout(kWaitForCookiesTimeout, ^bool {
return completion_called;
});
return completed && (has_cookies == should_have_cookies);
}
// Removes the |types| from the data remover associated with |browser_state|.
// Returns whether the completion block of the clear browsing data has been
// called. Declare the function to have the "WARN_UNUSED_RESULT".
bool RemoveCookies(web::BrowserState* browser_state,
web::ClearBrowsingDataMask types) WARN_UNUSED_RESULT;
bool RemoveCookies(web::BrowserState* browser_state,
web::ClearBrowsingDataMask types) {
web::BrowsingDataRemover* remover =
web::BrowsingDataRemover::FromBrowserState(browser_state);
__block bool closure_called = false;
base::OnceClosure closure = base::BindOnce(^{
closure_called = true;
});
remover->ClearBrowsingData(
types, base::Time::Now() - base::TimeDelta::FromMinutes(1),
std::move(closure));
return WaitUntilConditionOrTimeout(kWaitForCookiesTimeout, ^bool {
return closure_called;
});
}
} // namespace
namespace web {
class BrowsingDataRemoverTest : public PlatformTest {
......@@ -18,6 +93,8 @@ class BrowsingDataRemoverTest : public PlatformTest {
BrowsingDataRemover* GetRemover() {
return BrowsingDataRemover::FromBrowserState(&browser_state_);
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
TestBrowserState browser_state_;
};
......@@ -37,4 +114,38 @@ TEST_F(BrowsingDataRemoverTest, DifferentRemoverForDifferentBrowserState) {
EXPECT_EQ(remover_1_again, remover_1);
}
// Tests that removing the cookies remove them from the cookie store.
TEST_F(BrowsingDataRemoverTest, RemoveCookie) {
ASSERT_TRUE(AddCookie());
ASSERT_TRUE(HasCookies(true));
// Remove the cookies.
EXPECT_TRUE(
RemoveCookies(&browser_state_, ClearBrowsingDataMask::kRemoveCookies));
EXPECT_TRUE(HasCookies(false));
}
// Tests that removing the anything but cookies leave the cookies in the store.
TEST_F(BrowsingDataRemoverTest, RemoveNothing) {
ASSERT_TRUE(AddCookie());
ASSERT_TRUE(HasCookies(true));
// Remove other things than cookies.
EXPECT_TRUE(RemoveCookies(&browser_state_,
ClearBrowsingDataMask::kRemoveAppCache |
ClearBrowsingDataMask::kRemoveIndexedDB));
EXPECT_TRUE(HasCookies(true));
}
// Tests that removing nothing still call the closure.
TEST_F(BrowsingDataRemoverTest, KeepCookie) {
ASSERT_TRUE(AddCookie());
// Don't remove anything but check that the closure is still called.
EXPECT_TRUE(
RemoveCookies(&browser_state_, ClearBrowsingDataMask::kRemoveNothing));
}
} // namespace web
......@@ -14,9 +14,11 @@
namespace web {
void ClearBrowsingData(BrowserState* browser_state,
ClearBrowsingDataMask types) {
ClearBrowsingDataMask types,
base::Time modified_since,
base::OnceClosure closure) {
BrowsingDataRemover::FromBrowserState(browser_state)
->ClearBrowsingData(types);
->ClearBrowsingData(types, modified_since, std::move(closure));
}
} // namespace web
......@@ -7,6 +7,9 @@
#include <type_traits>
#include "base/callback.h"
#include "base/time/time.h"
namespace web {
class BrowserState;
......@@ -26,9 +29,15 @@ enum class ClearBrowsingDataMask {
};
// Clears the browsing data store in the Web layer.
// Clears the browsing data store in the Web layer. |modified_since| is the data
// since which all data is removed. |closure| is called when the browsing data
// have been cleared.
// TODO(crbug.com/906199): Remove closure once WebStateObserver callback is
// implemented.
void ClearBrowsingData(BrowserState* browser_state,
ClearBrowsingDataMask types);
ClearBrowsingDataMask types,
base::Time modified_since,
base::OnceClosure closure);
// Implementation of bitwise "or", "and" operators and the corresponding
// assignment operators too (as those are not automatically defined for
......
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