Skip to content

Commit

Permalink
Clear browsing data on exit when instructed by the user.
Browse files Browse the repository at this point in the history
Fixes brave/brave-browser#492

1. Adds a new "On exit" tab to chrome://settings/clearBrowserData dialog
with the same options as on the "Advanced" tab and a "Save" button. By
default all "On exit" options are turned off. When an option is modified
from the current state the Save button becomes enabled and allows the
user to save the "on exit" options. The options are saved to profile's
preferences: new *OnExit preferences have been added for each option.

2. Clear browsing data on exit functionality is triggered from
BraveBrowserMainParts::PreShutdown override. For each loaded profile
the code checks if user selected any on exit options and if so then a
BrowsingDataRemover is called.

3. Adds BraveClearDataOnExitTest and BraveClearDataOnExitTwoBrowsersTest
browser tests that verify that:
- the removal of the browsing data is triggered only when an "on exit"
  preference is set;
- the removal flags are constrcuted correctly;
- the removal is called only when the browser is exiting (tests with
  OTR/Guest/multiple profiles).
  • Loading branch information
mkarolin committed Feb 26, 2019
1 parent 2e81293 commit 5982a91
Show file tree
Hide file tree
Showing 23 changed files with 1,130 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/brave_generated_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,10 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U
<message name="IDS_MD_EXTENSIONS_BRAVE_ITEM_CHROME_WEB_STORE" desc="Label for button to visit the Web Extensions Store.">
View in Web Extensions Store
</message>
<!-- Brave Clear Browsing Data On Exit Settings -->
<message name="IDS_SETTINGS_BRAVE_ON_EXIT" desc="Clear Browsing Data dialog On exit tab label">
On exit
</message>
</messages>
<includes>
<include name="IDR_BRAVE_TAG_SERVICES_POLYFILL" file="resources/js/tag_services_polyfill.js" type="BINDATA" />
Expand Down
4 changes: 4 additions & 0 deletions browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ source_set("browser_process") {
"bookmarks/brave_bookmark_client.h",
"brave_browser_main_extra_parts.cc",
"brave_browser_main_extra_parts.h",
"brave_browser_main_parts.cc",
"brave_browser_main_parts.h",
"brave_browser_main_parts_mac.mm",
"brave_browser_main_parts_mac.h",
"brave_browser_process_impl.cc",
Expand All @@ -34,6 +36,8 @@ source_set("browser_process") {
"brave_rewards/donations_dialog.h",
"browser_context_keyed_service_factories.cc",
"browser_context_keyed_service_factories.h",
"browsing_data/brave_clear_browsing_data.cc",
"browsing_data/brave_clear_browsing_data.h",
"component_updater/brave_component_installer.cc",
"component_updater/brave_component_installer.h",
"component_updater/brave_component_updater_configurator.cc",
Expand Down
12 changes: 12 additions & 0 deletions browser/brave_browser_main_parts.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave/browser/brave_browser_main_parts.h"
#include "brave/browser/browsing_data/brave_clear_browsing_data.h"

void BraveBrowserMainParts::PreShutdown() {
content::BraveClearBrowsingData::ClearOnExit();
ChromeBrowserMainParts::PreShutdown();
}
27 changes: 27 additions & 0 deletions browser/brave_browser_main_parts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_BROWSER_BRAVE_BROWSER_MAIN_PARTS_H_
#define BRAVE_BROWSER_BRAVE_BROWSER_MAIN_PARTS_H_

#include "base/macros.h"
#include "chrome/browser/chrome_browser_main.h"

class BraveBrowserMainParts : public ChromeBrowserMainParts {
public:
using ChromeBrowserMainParts::ChromeBrowserMainParts;
~BraveBrowserMainParts() override = default;

// ChromeBrowserMainParts overrides:
// Marking this method final so that if any of the OS specific subclasses
// (e.g. ChromeBrowserMainPartsWin) decides to override this method in the
// future we would get a compilation error.
void PreShutdown() final;

private:
DISALLOW_COPY_AND_ASSIGN(BraveBrowserMainParts);
};

#endif // BRAVE_BROWSER_BRAVE_BROWSER_MAIN_PARTS_H_
188 changes: 188 additions & 0 deletions browser/browsing_data/brave_clear_browsing_data.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave/browser/browsing_data/brave_clear_browsing_data.h"

#include <vector>

#include "base/run_loop.h"
#include "base/scoped_observer.h"
#include "base/trace_event/common/trace_event_common.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browsing_data_remover.h"

namespace content {

namespace {

using content::BraveClearBrowsingData;

class BrowsingDataRemovalWatcher
: public content::BrowsingDataRemover::Observer {
public:
BrowsingDataRemovalWatcher() : observer_(this) {}

void ClearBrowsingDataForLoadedProfiles(
BraveClearBrowsingData::OnExitTestingCallback* testing_callback);

// BrowsingDataRemover::Observer implementation.
void OnBrowsingDataRemoverDone() override;

private:
bool GetClearBrowsingDataOnExitSettings(const Profile* profile,
int* remove_mask,
int* origin_mask);
void Wait();

int num_profiles_to_clear_ = 0;
base::RunLoop run_loop_;
// Keep track of the set of BrowsingDataRemover instances this object has
// attached itself to as an observer. When ScopedObserver is destroyed it
// removes this object as an observer from all those instances.
ScopedObserver<content::BrowsingDataRemover,
content::BrowsingDataRemover::Observer>
observer_;
};

// See ClearBrowsingDataHandler::HandleClearBrowsingData which constructs the
// remove_mask and the origin_mask for the same functionality not on exit.
bool BrowsingDataRemovalWatcher::GetClearBrowsingDataOnExitSettings(
const Profile* profile,
int* remove_mask,
int* origin_mask) {
DCHECK(remove_mask);
DCHECK(origin_mask);
const PrefService* prefs = profile->GetPrefs();
*remove_mask = 0;
*origin_mask = 0;

int site_data_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_DATA;
// Don't try to clear LSO data if it's not supported.
if (!prefs->GetBoolean(prefs::kClearPluginLSODataEnabled))
site_data_mask &= ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;

if (prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistoryOnExit) &&
prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory))
*remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;

if (prefs->GetBoolean(browsing_data::prefs::kDeleteDownloadHistoryOnExit) &&
prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory))
*remove_mask |= content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS;

if (prefs->GetBoolean(browsing_data::prefs::kDeleteCacheOnExit))
*remove_mask |= content::BrowsingDataRemover::DATA_TYPE_CACHE;

if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookiesOnExit)) {
*remove_mask |= site_data_mask;
*origin_mask |= content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
}

if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswordsOnExit))
*remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;

if (prefs->GetBoolean(browsing_data::prefs::kDeleteFormDataOnExit))
*remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA;

if (prefs->GetBoolean(browsing_data::prefs::kDeleteHostedAppsDataOnExit)) {
*remove_mask |= site_data_mask;
*origin_mask |= content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
}

// Note: this will also delete Brave Shields site-specific settings.
// Corresponds to "Content settings" checkbox in the Clear Browsing Data
// dialog.
if (prefs->GetBoolean(browsing_data::prefs::kDeleteSiteSettingsOnExit))
*remove_mask |=
ChromeBrowsingDataRemoverDelegate::DATA_TYPE_CONTENT_SETTINGS;

return (*remove_mask != 0);
}

// This method will, for each loaded profile that is not off-the-record, gather
// the user specified types of data that need to be cleared. It will then get
// the BrowsingDataRemover for that profile and call its RemoveAndReply method.
// BrowsingDataRemover will create a number of tasks to clear the data. Because
// these tasks, on their own, will neither prevent shutdown nor stop the profile
// from being destroyed, we have to block shutdown execution from proceeding any
// further. Otherwise the tasks will be cancelled and the profiles destroyed.
// Since we can't actually block the UI thread, instead we implement the Wait
// method below, which just runs a RunLoop. When a BrowsingDataRemover finishes
// its tasks it will reply back to us by calling the OnBrowsingDataRemoverDone
// method below. When that happens we decrement the counter of profiles that
// need to be cleared. Once the counter reaches 0 we exit the RunLoop and let
// shutdown proceed.
void BrowsingDataRemovalWatcher::ClearBrowsingDataForLoadedProfiles(
BraveClearBrowsingData::OnExitTestingCallback* testing_callback) {
ProfileManager* profile_manager = g_browser_process->profile_manager();
DCHECK(profile_manager);

std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
for (Profile* profile : profiles) {
if (profile->IsOffTheRecord())
continue;
int remove_mask;
int origin_mask;
if (!GetClearBrowsingDataOnExitSettings(profile, &remove_mask,
&origin_mask))
continue;
++num_profiles_to_clear_;
content::BrowsingDataRemover* remover =
content::BrowserContext::GetBrowsingDataRemover(profile);
observer_.Add(remover);
if (testing_callback)
testing_callback->BeforeClearOnExitRemoveData(remover, remove_mask,
origin_mask);
remover->RemoveAndReply(base::Time(), base::Time::Max(), remove_mask,
origin_mask, this);
}

Wait();
}

void BrowsingDataRemovalWatcher::Wait() {
if (num_profiles_to_clear_ > 0)
run_loop_.Run();
}

void BrowsingDataRemovalWatcher::OnBrowsingDataRemoverDone() {
--num_profiles_to_clear_;
if (num_profiles_to_clear_ > 0)
return;

run_loop_.Quit();
}

} // namespace

BraveClearBrowsingData::OnExitTestingCallback*
BraveClearBrowsingData::on_exit_testing_callback_ = nullptr;

// static
void BraveClearBrowsingData::ClearOnExit() {
TRACE_EVENT0("browser", "BraveClearBrowsingData::ClearOnExit");
// Do not clear browsing data when the OS is ending session (logout/reboot/
// shutdown) to avoid corrupting data if the process is killed.
if (browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION) {
LOG(INFO) << "Will not clear browsing data on exit due to session ending.";
return;
}
BrowsingDataRemovalWatcher watcher;
watcher.ClearBrowsingDataForLoadedProfiles(on_exit_testing_callback_);
}

// static
void BraveClearBrowsingData::SetOnExitTestingCallback(
OnExitTestingCallback* callback) {
on_exit_testing_callback_ = callback;
}

} // namespace content
50 changes: 50 additions & 0 deletions browser/browsing_data/brave_clear_browsing_data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* Copyright (c) 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_BROWSER_BROWSING_DATA_BRAVE_CLEAR_BROWSING_DATA_H_
#define BRAVE_BROWSER_BROWSING_DATA_BRAVE_CLEAR_BROWSING_DATA_H_

#include "base/macros.h"

namespace content {
class BrowsingDataRemover;
}
class Profile;
class BraveClearDataOnExitTest;

namespace content {

class BraveClearBrowsingData {
public:
// Clears browsing data for all loaded non-off-the-record profiles.
// Profile's *OnExit preferences determine what gets cleared.
// Note: this method will wait until browsing data has been cleared.
static void ClearOnExit();

// Used for testing only.
struct OnExitTestingCallback {
// Called from ClearOnExit right before the call to BrowsingDataRemover
// to remove data.
virtual void BeforeClearOnExitRemoveData(
content::BrowsingDataRemover* remover,
int remove_mask,
int origin_mask) = 0;
};

protected:
friend class ::BraveClearDataOnExitTest;

// Used for testing only.
static void SetOnExitTestingCallback(OnExitTestingCallback* callback);

private:
static OnExitTestingCallback* on_exit_testing_callback_;

DISALLOW_COPY_AND_ASSIGN(BraveClearBrowsingData);
};

} // namespace content

#endif // BRAVE_BROWSER_BROWSING_DATA_BRAVE_CLEAR_BROWSING_DATA_H_
Loading

0 comments on commit 5982a91

Please sign in to comment.