Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear browsing data on exit. #1213

Merged
merged 1 commit into from
Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe it's worth to add a note somewhere that enabling this can slowdown the shutdown.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rebron ^^

</message>
</messages>
<includes>
<include name="IDR_BRAVE_TAG_SERVICES_POLYFILL" file="resources/js/tag_services_polyfill.js" type="BINDATA" />
Expand Down
5 changes: 5 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 Expand Up @@ -72,6 +76,7 @@ source_set("browser_process") {
"//brave/components/content_settings/core/browser",
"//brave/components/services:brave_content_manifest_overlays",
"//chrome/common",
"//components/browsing_data/core",
"//components/component_updater",
"//components/prefs",
"//components/safe_browsing/common:safe_browsing_prefs",
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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea


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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

#include "components/prefs/pref_service.h"
#include "content/public/browser/browsing_data_remover.h"

namespace content {

namespace {

using content::BraveClearBrowsingData;
mkarolin marked this conversation as resolved.
Show resolved Hide resolved

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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused. The is a subclass of content::BrowsingDataRemover::Observer, but also has an internal ScopedObserver for content::BrowsingDataRemover::Observer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am following the patter suggested in the comment here: https://cs.chromium.org/chromium/src/content/public/browser/browsing_data_remover.h?l=41 but delegating keeping track of content::BrowsingDataRemover for each profile to ScopedObserver.

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this fact may be important for users, maybe consider adding this to the UI?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bsclifton and I discussed getting @tomlowenthal's input on this in the security review, but may as well do it here. One thing to note, though, is that it behaves the same as the setting in the Advanced tab which even now would clear Shields' site-specific settings without warning the user.

// 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(
bsclifton marked this conversation as resolved.
Show resolved Hide resolved
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();
bsclifton marked this conversation as resolved.
Show resolved Hide resolved
}

} // 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/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, it would be nice to document this somewhere that's user-visible. If it's too much information for the UI, maybe a page on support.brave.com?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@bsclifton bsclifton Feb 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fmarier support.brave.com might not be the right audience for that- but we can definitely document custom trace events in our wiki. @mkarolin I created a stub page, if you wanted to add that (and describe why you'd use it):
https://github.com/brave/brave-browser/wiki/Custom-tracing-events

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bsclifton, I understood it that @fmarier was referring to the comment that we are not clearing browsing data on logout/reboot/shutdown.

Copy link
Member

@bsclifton bsclifton Feb 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkarolin ah- LOL; that makes a lot more sense 😂

cc'ing @Brave-Matt on that one - would be great to document this feature in general 😄 @Brave-Matt: this would be something we're planning for 0.63.x

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, what I was referring to was not the trace events, but the limitation that if you shutdown your computer, it won't clear your history.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a very bad limitation, which would probably surprise a lot of people who use the feature. IMO, we should back this out and fix that problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc: @rebron for the above comment by @tomlowenthal ^^

We may want to compare with Muon- it's possible Muon had that same limitation also. If the current experience is WORSE than Muon (ex: Muon works as expected), then I definitely agree that we should consider hiding this new UI until that problem is resolved

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomlowenthal should brave/brave-browser#3549 cover this use-case also?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that issue is intended to be the new partial fix for this… someday.

// 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;
mkarolin marked this conversation as resolved.
Show resolved Hide resolved
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 {
mkarolin marked this conversation as resolved.
Show resolved Hide resolved
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();
mkarolin marked this conversation as resolved.
Show resolved Hide resolved

// 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:
mkarolin marked this conversation as resolved.
Show resolved Hide resolved
static OnExitTestingCallback* on_exit_testing_callback_;

DISALLOW_COPY_AND_ASSIGN(BraveClearBrowsingData);
};

} // namespace content

#endif // BRAVE_BROWSER_BROWSING_DATA_BRAVE_CLEAR_BROWSING_DATA_H_
Loading