Commit 4e59f1e3 authored by Ramin Halavati's avatar Ramin Halavati Committed by Commit Bot

Add OTRProfileID to profile class.

For proper support of multiple off-the-record profiles for one regular
profile, an OTRProfileID is added to profile class.

This CL is based on the following design doc:
https://docs.google.com/document/d/1xj21DPfwo1gZ8kagj6i1lSmKwG1dW-4KPt3yvVcsvOg

This is the first step of implementation of this design doc, only adding
OTRProfileID to C++ classes and adding/updating some tests.

Bug: 1033903
Change-Id: Iaed207994c01372f3349ecce1333ee55fea44d2b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2080253Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Reviewed-by: default avatarBoris Sazonov <bsazonov@chromium.org>
Reviewed-by: default avatarMihai Sardarescu <msarda@chromium.org>
Reviewed-by: default avatarBrandon Tolsch <btolsch@chromium.org>
Commit-Queue: Ramin Halavati <rhalavati@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756161}
parent 1e280812
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -52,18 +53,17 @@ IndependentOTRProfileManager::CreateFromOriginalProfile( ...@@ -52,18 +53,17 @@ IndependentOTRProfileManager::CreateFromOriginalProfile(
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
if (!HasDependentProfiles(original_profile)) if (!HasDependentProfiles(original_profile))
observed_original_profiles_.Add(original_profile); observed_original_profiles_.Add(original_profile);
auto* otr_profile = original_profile->CreateOffTheRecordProfile(); // TODO(https://crbug.com/1033903): Receive profile id from the callers.
std::string profile_id = base::StringPrintf("profile::independent-otr-%i",
first_unused_unique_id_++);
auto* otr_profile = original_profile->GetOffTheRecordProfile(
Profile::OTRProfileID(profile_id));
auto entry = refcounts_map_.emplace(otr_profile, 1); auto entry = refcounts_map_.emplace(otr_profile, 1);
auto callback_entry = auto callback_entry =
callbacks_map_.emplace(otr_profile, std::move(callback)); callbacks_map_.emplace(otr_profile, std::move(callback));
DCHECK(entry.second); DCHECK(entry.second);
DCHECK(callback_entry.second); DCHECK(callback_entry.second);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_CREATED,
content::Source<Profile>(otr_profile),
content::NotificationService::NoDetails());
return base::WrapUnique(new OTRProfileRegistration(this, otr_profile)); return base::WrapUnique(new OTRProfileRegistration(this, otr_profile));
} }
...@@ -101,7 +101,8 @@ void IndependentOTRProfileManager::OnBrowserRemoved(Browser* browser) { ...@@ -101,7 +101,8 @@ void IndependentOTRProfileManager::OnBrowserRemoved(Browser* browser) {
} }
} }
IndependentOTRProfileManager::IndependentOTRProfileManager() { IndependentOTRProfileManager::IndependentOTRProfileManager()
: first_unused_unique_id_(0) {
BrowserList::AddObserver(this); BrowserList::AddObserver(this);
} }
......
...@@ -98,6 +98,10 @@ class IndependentOTRProfileManager final : public BrowserListObserver, ...@@ -98,6 +98,10 @@ class IndependentOTRProfileManager final : public BrowserListObserver,
ScopedObserver<Profile, ProfileObserver> observed_original_profiles_{this}; ScopedObserver<Profile, ProfileObserver> observed_original_profiles_{this};
// TODO(https://crbug.com/1033903): Remove after getting unique id from
// owners.
int first_unused_unique_id_;
DISALLOW_COPY_AND_ASSIGN(IndependentOTRProfileManager); DISALLOW_COPY_AND_ASSIGN(IndependentOTRProfileManager);
}; };
......
...@@ -165,72 +165,6 @@ IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, CreateAndDestroy) { ...@@ -165,72 +165,6 @@ IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, CreateAndDestroy) {
EXPECT_TRUE(watcher.destroyed()); EXPECT_TRUE(watcher.destroyed());
} }
IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest,
DeleteWaitsForLastBrowser) {
ProfileDestructionWatcher watcher;
Profile* otr_profile = nullptr;
Browser* otr_browser1 = nullptr;
Browser* otr_browser2 = nullptr;
{
auto profile_registration = manager_->CreateFromOriginalProfile(
browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed));
otr_profile = profile_registration->profile();
otr_browser1 = CreateBrowser(otr_profile);
otr_browser2 = CreateBrowser(otr_profile);
ASSERT_NE(otr_browser1, otr_browser2);
}
base::RunLoop run_loop1;
BrowserRemovedWaiter removed_waiter1(otr_browser1,
run_loop1.QuitWhenIdleClosure());
otr_browser1->window()->Close();
run_loop1.Run();
ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser1));
ASSERT_TRUE(base::Contains(*BrowserList::GetInstance(), otr_browser2));
watcher.Watch(otr_profile);
base::RunLoop run_loop2;
BrowserRemovedWaiter removed_waiter2(otr_browser2,
run_loop2.QuitWhenIdleClosure());
otr_browser2->window()->Close();
run_loop2.Run();
ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser2));
EXPECT_TRUE(watcher.destroyed());
}
IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest,
DeleteImmediatelyWhenBrowsersAlreadyClosed) {
ProfileDestructionWatcher watcher;
{
auto profile_registration = manager_->CreateFromOriginalProfile(
browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed));
auto* otr_profile = profile_registration->profile();
auto* otr_browser1 = CreateBrowser(otr_profile);
auto* otr_browser2 = CreateBrowser(otr_profile);
ASSERT_NE(otr_browser1, otr_browser2);
base::RunLoop run_loop1;
BrowserRemovedWaiter removed_waiter1(otr_browser1,
run_loop1.QuitWhenIdleClosure());
base::RunLoop run_loop2;
BrowserRemovedWaiter removed_waiter2(otr_browser2,
run_loop2.QuitWhenIdleClosure());
otr_browser1->window()->Close();
otr_browser2->window()->Close();
run_loop1.Run();
run_loop2.Run();
ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser1));
ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser2));
watcher.Watch(otr_profile);
}
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(watcher.destroyed());
}
IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest,
CreateTwoFromSameProfile) { CreateTwoFromSameProfile) {
ProfileDestructionWatcher watcher1; ProfileDestructionWatcher watcher1;
...@@ -312,66 +246,6 @@ IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, ...@@ -312,66 +246,6 @@ IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest,
EXPECT_TRUE(watcher2.destroyed()); EXPECT_TRUE(watcher2.destroyed());
} }
IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest,
BrowserClosingDoesntRemoveProfileObserver) {
ProfileDestructionWatcher watcher1;
ProfileDestructionWatcher watcher2;
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
#if defined(OS_CHROMEOS)
EnableProfileHelperTestSettings();
#endif
original_profile_ = Profile::CreateProfile(temp_dir_.GetPath(), nullptr,
Profile::CREATE_MODE_SYNCHRONOUS);
ASSERT_TRUE(original_profile_);
auto profile_owner1 = RegistrationOwner(manager_, original_profile_.get());
auto* otr_profile1 = profile_owner1.profile();
Browser* otr_browser = nullptr;
{
auto profile_owner2 = RegistrationOwner(manager_, original_profile_.get());
auto* otr_profile2 = profile_owner2.profile();
otr_browser = CreateBrowser(otr_profile2);
watcher2.Watch(otr_profile2);
}
base::RunLoop run_loop;
BrowserRemovedWaiter removed_waiter(otr_browser,
run_loop.QuitWhenIdleClosure());
otr_browser->window()->Close();
run_loop.Run();
ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser));
EXPECT_TRUE(watcher2.destroyed());
watcher1.Watch(otr_profile1);
SafelyDestroyOriginalProfile();
EXPECT_TRUE(watcher1.destroyed());
}
IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest,
CallbackNotCalledAfterUnregister) {
ProfileDestructionWatcher watcher;
Browser* otr_browser = nullptr;
Profile* otr_profile = nullptr;
{
auto profile_registration = manager_->CreateFromOriginalProfile(
browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed));
otr_profile = profile_registration->profile();
otr_browser = CreateBrowser(otr_profile);
}
watcher.Watch(otr_profile);
base::RunLoop run_loop;
BrowserRemovedWaiter removed_waiter(otr_browser,
run_loop.QuitWhenIdleClosure());
otr_browser->window()->Close();
run_loop.Run();
ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser));
EXPECT_TRUE(watcher.destroyed());
}
IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, Notifications) { IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, Notifications) {
// Create the OTR profile. // Create the OTR profile.
content::WindowedNotificationObserver profile_created_observer( content::WindowedNotificationObserver profile_created_observer(
......
...@@ -120,8 +120,11 @@ constexpr char kVideoDecodePerfHistoryId[] = "video-decode-perf-history"; ...@@ -120,8 +120,11 @@ constexpr char kVideoDecodePerfHistoryId[] = "video-decode-perf-history";
} // namespace } // namespace
OffTheRecordProfileImpl::OffTheRecordProfileImpl(Profile* real_profile) OffTheRecordProfileImpl::OffTheRecordProfileImpl(
Profile* real_profile,
const OTRProfileID& otr_profile_id)
: profile_(real_profile), : profile_(real_profile),
otr_profile_id_(otr_profile_id),
io_data_(this), io_data_(this),
start_time_(base::Time::Now()), start_time_(base::Time::Now()),
key_(std::make_unique<ProfileKey>(profile_->GetPath(), key_(std::make_unique<ProfileKey>(profile_->GetPath(),
...@@ -295,21 +298,40 @@ bool OffTheRecordProfileImpl::IsOffTheRecord() const { ...@@ -295,21 +298,40 @@ bool OffTheRecordProfileImpl::IsOffTheRecord() const {
return true; return true;
} }
const Profile::OTRProfileID& OffTheRecordProfileImpl::GetOTRProfileID() const {
return otr_profile_id_;
}
bool OffTheRecordProfileImpl::IsIndependentOffTheRecordProfile() { bool OffTheRecordProfileImpl::IsIndependentOffTheRecordProfile() {
return !GetOriginalProfile()->HasOffTheRecordProfile() || return otr_profile_id_ != OTRProfileID::PrimaryID();
GetOriginalProfile()->GetOffTheRecordProfile() != this; }
Profile* OffTheRecordProfileImpl::GetOffTheRecordProfile(
const OTRProfileID& otr_profile_id) {
if (otr_profile_id_ == otr_profile_id)
return this;
return profile_->GetOffTheRecordProfile(otr_profile_id);
} }
Profile* OffTheRecordProfileImpl::GetOffTheRecordProfile() { std::vector<Profile*> OffTheRecordProfileImpl::GetAllOffTheRecordProfiles() {
return this; return profile_->GetAllOffTheRecordProfiles();
} }
void OffTheRecordProfileImpl::DestroyOffTheRecordProfile() { void OffTheRecordProfileImpl::DestroyOffTheRecordProfile(
// Suicide is bad! Profile* /*otr_profile*/) {
// OffTheRecord profiles should be destroyed through a request to their
// original profile.
NOTREACHED(); NOTREACHED();
} }
bool OffTheRecordProfileImpl::HasOffTheRecordProfile() { bool OffTheRecordProfileImpl::HasOffTheRecordProfile(
const OTRProfileID& otr_profile_id) {
if (otr_profile_id_ == otr_profile_id)
return true;
return profile_->HasOffTheRecordProfile(otr_profile_id);
}
bool OffTheRecordProfileImpl::HasAnyOffTheRecordProfile() {
return true; return true;
} }
...@@ -587,7 +609,7 @@ void OffTheRecordProfileImpl::SetCreationTimeForTesting( ...@@ -587,7 +609,7 @@ void OffTheRecordProfileImpl::SetCreationTimeForTesting(
class GuestSessionProfile : public OffTheRecordProfileImpl { class GuestSessionProfile : public OffTheRecordProfileImpl {
public: public:
explicit GuestSessionProfile(Profile* real_profile) explicit GuestSessionProfile(Profile* real_profile)
: OffTheRecordProfileImpl(real_profile) { : OffTheRecordProfileImpl(real_profile, OTRProfileID::PrimaryID()) {
set_is_guest_profile(true); set_is_guest_profile(true);
} }
...@@ -605,17 +627,19 @@ class GuestSessionProfile : public OffTheRecordProfileImpl { ...@@ -605,17 +627,19 @@ class GuestSessionProfile : public OffTheRecordProfileImpl {
}; };
#endif #endif
Profile* Profile::CreateOffTheRecordProfile() { // static
OffTheRecordProfileImpl* profile = NULL; std::unique_ptr<Profile> Profile::CreateOffTheRecordProfile(
Profile* parent,
const OTRProfileID& otr_profile_id) {
std::unique_ptr<OffTheRecordProfileImpl> profile;
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (IsGuestSession()) if (parent->IsGuestSession() && otr_profile_id == OTRProfileID::PrimaryID())
profile = new GuestSessionProfile(this); profile.reset(new GuestSessionProfile(parent));
#endif #endif
if (!profile) if (!profile)
profile = new OffTheRecordProfileImpl(this); profile.reset(new OffTheRecordProfileImpl(parent, otr_profile_id));
profile->Init(); profile->Init();
NotifyOffTheRecordProfileCreated(profile); return std::move(profile);
return profile;
} }
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
......
...@@ -37,16 +37,23 @@ class PrefServiceSyncable; ...@@ -37,16 +37,23 @@ class PrefServiceSyncable;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class OffTheRecordProfileImpl : public Profile { class OffTheRecordProfileImpl : public Profile {
public: public:
explicit OffTheRecordProfileImpl(Profile* real_profile); OffTheRecordProfileImpl(Profile* real_profile,
const OTRProfileID& otr_profile_id);
~OffTheRecordProfileImpl() override; ~OffTheRecordProfileImpl() override;
void Init(); void Init();
// Profile implementation. // Profile implementation.
std::string GetProfileUserName() const override; std::string GetProfileUserName() const override;
ProfileType GetProfileType() const override; ProfileType GetProfileType() const override;
Profile* GetOffTheRecordProfile() override; // TODO(https://crbug.com/1033903): Remove the default value.
void DestroyOffTheRecordProfile() override; Profile* GetOffTheRecordProfile(
bool HasOffTheRecordProfile() override; const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override;
std::vector<Profile*> GetAllOffTheRecordProfiles() override;
void DestroyOffTheRecordProfile(Profile* otr_profile) override;
// TODO(https://crbug.com/1033903): Remove the default value.
bool HasOffTheRecordProfile(
const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override;
bool HasAnyOffTheRecordProfile() override;
Profile* GetOriginalProfile() override; Profile* GetOriginalProfile() override;
const Profile* GetOriginalProfile() const override; const Profile* GetOriginalProfile() const override;
bool IsSupervised() const override; bool IsSupervised() const override;
...@@ -100,6 +107,7 @@ class OffTheRecordProfileImpl : public Profile { ...@@ -100,6 +107,7 @@ class OffTheRecordProfileImpl : public Profile {
scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override; scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override;
bool IsOffTheRecord() override; bool IsOffTheRecord() override;
bool IsOffTheRecord() const override; bool IsOffTheRecord() const override;
const OTRProfileID& GetOTRProfileID() const override;
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
content::ResourceContext* GetResourceContext() override; content::ResourceContext* GetResourceContext() override;
content::BrowserPluginGuestManager* GetGuestManager() override; content::BrowserPluginGuestManager* GetGuestManager() override;
...@@ -142,6 +150,8 @@ class OffTheRecordProfileImpl : public Profile { ...@@ -142,6 +150,8 @@ class OffTheRecordProfileImpl : public Profile {
// The real underlying profile. // The real underlying profile.
Profile* profile_; Profile* profile_;
const OTRProfileID otr_profile_id_;
std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs_; std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs_;
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
......
...@@ -103,6 +103,24 @@ class ChromeVariationsClient : public variations::VariationsClient { ...@@ -103,6 +103,24 @@ class ChromeVariationsClient : public variations::VariationsClient {
} // namespace } // namespace
Profile::OTRProfileID::OTRProfileID(const std::string& profile_id)
: profile_id_(profile_id) {}
// static
const Profile::OTRProfileID Profile::OTRProfileID::PrimaryID() {
return OTRProfileID("profile::primary_otr");
}
const std::string& Profile::OTRProfileID::ToString() const {
return profile_id_;
}
std::ostream& operator<<(std::ostream& out,
const Profile::OTRProfileID& profile_id) {
out << profile_id.ToString();
return out;
}
Profile::Profile() Profile::Profile()
: restored_last_session_(false), : restored_last_session_(false),
sent_destroyed_notification_(false), sent_destroyed_notification_(false),
...@@ -412,3 +430,10 @@ variations::VariationsClient* Profile::GetVariationsClient() { ...@@ -412,3 +430,10 @@ variations::VariationsClient* Profile::GetVariationsClient() {
chrome_variations_client_ = std::make_unique<ChromeVariationsClient>(this); chrome_variations_client_ = std::make_unique<ChromeVariationsClient>(this);
return chrome_variations_client_.get(); return chrome_variations_client_.get();
} }
void Profile::DestroyOffTheRecordProfile() {
OTRProfileID primary_otr_id = OTRProfileID::PrimaryID();
if (!HasOffTheRecordProfile(primary_otr_id))
return;
DestroyOffTheRecordProfile(GetOffTheRecordProfile(primary_otr_id));
}
...@@ -103,6 +103,39 @@ class Profile : public content::BrowserContext { ...@@ -103,6 +103,39 @@ class Profile : public content::BrowserContext {
GUEST_PROFILE, // Guest session's profile GUEST_PROFILE, // Guest session's profile
}; };
class OTRProfileID {
public:
// Creates an OTR profile ID from |profile_id|.
// |profile_id| should follow the following naming scheme:
// "<component>::<subcomponent_id>". For example, "HaTS::WebDialog"
explicit OTRProfileID(const std::string& profile_id);
// ID used by the incognito and guest profiles.
// TODO(https://crbug.com/1033903): To be replaced with |IncognitoID| and
// |GuestID| when the use cases are reduced.
static const OTRProfileID PrimaryID();
bool operator==(const OTRProfileID& other) const {
return profile_id_ == other.profile_id_;
}
bool operator!=(const OTRProfileID& other) const {
return profile_id_ != other.profile_id_;
}
bool operator<(const OTRProfileID& other) const {
return profile_id_ < other.profile_id_;
}
// Returns this OTRProfileID in a string format that can be used for debug
// message.
const std::string& ToString() const;
private:
OTRProfileID() = default;
const std::string profile_id_;
};
class Delegate { class Delegate {
public: public:
virtual ~Delegate(); virtual ~Delegate();
...@@ -150,6 +183,7 @@ class Profile : public content::BrowserContext { ...@@ -150,6 +183,7 @@ class Profile : public content::BrowserContext {
// Note that for Chrome this covers BOTH Incognito mode and Guest sessions. // Note that for Chrome this covers BOTH Incognito mode and Guest sessions.
bool IsOffTheRecord() override = 0; bool IsOffTheRecord() override = 0;
virtual bool IsOffTheRecord() const = 0; virtual bool IsOffTheRecord() const = 0;
virtual const OTRProfileID& GetOTRProfileID() const = 0;
variations::VariationsClient* GetVariationsClient() override; variations::VariationsClient* GetVariationsClient() override;
...@@ -169,27 +203,48 @@ class Profile : public content::BrowserContext { ...@@ -169,27 +203,48 @@ class Profile : public content::BrowserContext {
// implementations, this is usually the Google-services email address. // implementations, this is usually the Google-services email address.
virtual std::string GetProfileUserName() const = 0; virtual std::string GetProfileUserName() const = 0;
// Return the incognito version of this profile. The returned pointer // Return an OffTheRecord version of this profile with the given
// is owned by the receiving profile. If the receiving profile is off the // |otr_profile_id|. The returned pointer is owned by the receiving profile.
// record, the same profile is returned. // If the receiving profile is OffTheRecord, the owner would be its original
// profile.
// //
// WARNING: This will create the OffTheRecord profile if it doesn't already // WARNING I: This will create the OffTheRecord profile if it doesn't already
// exist. If this isn't what you want, you need to check // exist. If this isn't what you want, you need to check
// HasOffTheRecordProfile() first. // HasOffTheRecordProfile() first.
virtual Profile* GetOffTheRecordProfile() = 0; //
// WARNING II: Once a profile is no longer used, use
// ProfileDestroyer::DestroyProfileWhenAppropriate or
// ProfileDestroyer::DestroyOffTheRecordProfileNow to destroy it.
//
// TODO(https://crbug.com/1033903): Remove the default value.
virtual Profile* GetOffTheRecordProfile(
const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) = 0;
// Destroys the incognito profile. // Returns all OffTheRecord profiles.
virtual void DestroyOffTheRecordProfile() = 0; virtual std::vector<Profile*> GetAllOffTheRecordProfiles() = 0;
// True if an incognito profile exists. // Destroys the OffTheRecord profile.
virtual bool HasOffTheRecordProfile() = 0; virtual void DestroyOffTheRecordProfile(Profile* otr_profile) = 0;
// TODO(https://crbug.com/1033903): Remove this function when all the use
// cases are migrated to above version. The parameter-less version destroys
// the primary OffTheRecord profile.
void DestroyOffTheRecordProfile();
// True if an OffTheRecord profile with given id exists.
// TODO(https://crbug.com/1033903): Remove the default value.
virtual bool HasOffTheRecordProfile(
const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) = 0;
// Returns true if the profile has any OffTheRecord profiles.
virtual bool HasAnyOffTheRecordProfile() = 0;
// Return the original "recording" profile. This method returns this if the // Return the original "recording" profile. This method returns this if the
// profile is not incognito. // profile is not OffTheRecord.
virtual Profile* GetOriginalProfile() = 0; virtual Profile* GetOriginalProfile() = 0;
// Return the original "recording" profile. This method returns this if the // Return the original "recording" profile. This method returns this if the
// profile is not incognito. // profile is not OffTheRecord.
virtual const Profile* GetOriginalProfile() const = 0; virtual const Profile* GetOriginalProfile() const = 0;
// Returns whether the profile is supervised (either a legacy supervised // Returns whether the profile is supervised (either a legacy supervised
...@@ -223,11 +278,15 @@ class Profile : public content::BrowserContext { ...@@ -223,11 +278,15 @@ class Profile : public content::BrowserContext {
// Retrieves a pointer to the PrefService that manages the preferences // Retrieves a pointer to the PrefService that manages the preferences
// for OffTheRecord Profiles. This PrefService is lazily created the first // for OffTheRecord Profiles. This PrefService is lazily created the first
// time that this method is called. // time that this method is called.
// TODO(https://crbug.com/1065444): Investigate whether it's possible to
// remove.
virtual PrefService* GetOffTheRecordPrefs() = 0; virtual PrefService* GetOffTheRecordPrefs() = 0;
// Like GetOffTheRecordPrefs but gives a read-only view of prefs that can be // Like GetOffTheRecordPrefs but gives a read-only view of prefs that can be
// used even if there's no OTR profile at the moment // used even if there's no OTR profile at the moment
// (i.e. HasOffTheRecordProfile is false). // (i.e. HasOffTheRecordProfile is false).
// TODO(https://crbug.com/1065444): Investigate whether it's possible to
// remove.
virtual PrefService* GetReadOnlyOffTheRecordPrefs(); virtual PrefService* GetReadOnlyOffTheRecordPrefs();
// Returns the main URLLoaderFactory. // Returns the main URLLoaderFactory.
...@@ -236,7 +295,7 @@ class Profile : public content::BrowserContext { ...@@ -236,7 +295,7 @@ class Profile : public content::BrowserContext {
// Return whether 2 profiles are the same. 2 profiles are the same if they // Return whether 2 profiles are the same. 2 profiles are the same if they
// represent the same profile. This can happen if there is pointer equality // represent the same profile. This can happen if there is pointer equality
// or if one profile is the incognito version of another profile (or vice // or if one profile is the OffTheRecord version of another profile (or vice
// versa). // versa).
virtual bool IsSameProfile(Profile* profile) = 0; virtual bool IsSameProfile(Profile* profile) = 0;
...@@ -330,14 +389,16 @@ class Profile : public content::BrowserContext { ...@@ -330,14 +389,16 @@ class Profile : public content::BrowserContext {
// Returns whether it is an Incognito profile. An Incognito profile is an // Returns whether it is an Incognito profile. An Incognito profile is an
// off-the-record profile that is not a guest profile. // off-the-record profile that is not a guest profile.
//
// TODO(https://crbug.com/1033903): Update to return false for non-primary
// OTRs and update documentation above.
bool IsIncognitoProfile() const; bool IsIncognitoProfile() const;
// Returns true if this is an off the record profile that is independent from // Returns true if this is a non-primary OffTheRecord profile. This type of
// its original regular profile. This covers OTR profiles that are directly // OffTheRecord profiles have limited functionality and cannot be used to
// created using CreateOffTheRecordProfile() (such as done by // create a browser object.
// IndependentOTRProfileManager). Calling GetOffTheRecordProfile on their //
// GetOriginProfile will not point to themselves. // TODO(https://crbug.com/1033903): Rename to |CanSupportBrowsers|.
// This type of usage is not recommended.
virtual bool IsIndependentOffTheRecordProfile() = 0; virtual bool IsIndependentOffTheRecordProfile() = 0;
// Returns whether it is a guest session. This covers both the guest profile // Returns whether it is a guest session. This covers both the guest profile
...@@ -407,11 +468,6 @@ class Profile : public content::BrowserContext { ...@@ -407,11 +468,6 @@ class Profile : public content::BrowserContext {
// ProfileDestroyer, but in tests, some are not. // ProfileDestroyer, but in tests, some are not.
void MaybeSendDestroyedNotification(); void MaybeSendDestroyedNotification();
// Creates an OffTheRecordProfile which points to this Profile. The caller is
// responsible for sending a NOTIFICATION_PROFILE_CREATED when the profile is
// correctly assigned to its owner.
Profile* CreateOffTheRecordProfile();
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
// Convenience method to retrieve the default zoom level for the default // Convenience method to retrieve the default zoom level for the default
// storage partition. // storage partition.
...@@ -435,6 +491,13 @@ class Profile : public content::BrowserContext { ...@@ -435,6 +491,13 @@ class Profile : public content::BrowserContext {
is_system_profile_ = is_system_profile; is_system_profile_ = is_system_profile;
} }
// Creates an OffTheRecordProfile which points to this Profile. The caller is
// responsible for sending a NOTIFICATION_PROFILE_CREATED when the profile is
// correctly assigned to its owner.
static std::unique_ptr<Profile> CreateOffTheRecordProfile(
Profile* parent,
const OTRProfileID& otr_profile_id);
// Returns a newly created ExtensionPrefStore suitable for the supplied // Returns a newly created ExtensionPrefStore suitable for the supplied
// Profile. // Profile.
static PrefStore* CreateExtensionPrefStore(Profile*, static PrefStore* CreateExtensionPrefStore(Profile*,
...@@ -472,4 +535,7 @@ struct ProfileCompare { ...@@ -472,4 +535,7 @@ struct ProfileCompare {
bool operator()(Profile* a, Profile* b) const; bool operator()(Profile* a, Profile* b) const;
}; };
std::ostream& operator<<(std::ostream& out,
const Profile::OTRProfileID& profile_id);
#endif // CHROME_BROWSER_PROFILES_PROFILE_H_ #endif // CHROME_BROWSER_PROFILES_PROFILE_H_
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/task/thread_pool/thread_pool_instance.h" #include "base/task/thread_pool/thread_pool_instance.h"
...@@ -33,8 +34,10 @@ ...@@ -33,8 +34,10 @@
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/chrome_version_service.h" #include "chrome/browser/profiles/chrome_version_service.h"
#include "chrome/browser/profiles/profile_destroyer.h"
#include "chrome/browser/profiles/profile_impl.h" #include "chrome/browser/profiles/profile_impl.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_constants.h"
...@@ -131,6 +134,29 @@ class MockProfileDelegate : public Profile::Delegate { ...@@ -131,6 +134,29 @@ class MockProfileDelegate : public Profile::Delegate {
MOCK_METHOD3(OnProfileCreated, void(Profile*, bool, bool)); MOCK_METHOD3(OnProfileCreated, void(Profile*, bool, bool));
}; };
class ProfileDestructionWatcher : public ProfileObserver {
public:
ProfileDestructionWatcher() = default;
~ProfileDestructionWatcher() override = default;
void Watch(Profile* profile) { observed_profiles_.Add(profile); }
// ProfileObserver:
void OnProfileWillBeDestroyed(Profile* profile) override {
DCHECK(!destroyed_) << "Double profile destruction";
destroyed_ = true;
observed_profiles_.Remove(profile);
}
bool destroyed() const { return destroyed_; }
private:
bool destroyed_ = false;
ScopedObserver<Profile, ProfileObserver> observed_profiles_{this};
DISALLOW_COPY_AND_ASSIGN(ProfileDestructionWatcher);
};
// Creates a prefs file in the given directory. // Creates a prefs file in the given directory.
void CreatePrefsFileInDirectory(const base::FilePath& directory_path) { void CreatePrefsFileInDirectory(const base::FilePath& directory_path) {
base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename)); base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename));
...@@ -684,3 +710,106 @@ IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, Notifications) { ...@@ -684,3 +710,106 @@ IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, Notifications) {
// let them complete before |temp_dir| goes out of scope. // let them complete before |temp_dir| goes out of scope.
FlushIoTaskRunnerAndSpinThreads(); FlushIoTaskRunnerAndSpinThreads();
} }
// Verifies creating an OTR with non-primary id results in a different profile
// from incognito profile.
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateNonPrimaryOTR) {
Profile::OTRProfileID otr_profile_id("profile::otr");
Profile* regular_profile = browser()->profile();
EXPECT_FALSE(regular_profile->HasAnyOffTheRecordProfile());
Profile* otr_profile =
regular_profile->GetOffTheRecordProfile(otr_profile_id);
EXPECT_TRUE(regular_profile->HasAnyOffTheRecordProfile());
EXPECT_TRUE(otr_profile->IsOffTheRecord());
EXPECT_EQ(otr_profile_id, otr_profile->GetOTRProfileID());
EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id));
EXPECT_NE(otr_profile, regular_profile->GetOffTheRecordProfile(
Profile::OTRProfileID::PrimaryID()));
regular_profile->DestroyOffTheRecordProfile(otr_profile);
EXPECT_FALSE(regular_profile->HasOffTheRecordProfile(otr_profile_id));
EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(
Profile::OTRProfileID::PrimaryID()));
EXPECT_TRUE(regular_profile->HasAnyOffTheRecordProfile());
}
// Verifies creating two OTRs with different ids results in different profiles.
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateTwoNonPrimaryOTRs) {
Profile::OTRProfileID otr_profile_id1("profile::otr1");
Profile::OTRProfileID otr_profile_id2("profile::otr2");
Profile* regular_profile = browser()->profile();
Profile* otr_profile1 =
regular_profile->GetOffTheRecordProfile(otr_profile_id1);
Profile* otr_profile2 =
regular_profile->GetOffTheRecordProfile(otr_profile_id2);
EXPECT_NE(otr_profile1, otr_profile2);
EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id1));
EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id2));
regular_profile->DestroyOffTheRecordProfile(otr_profile1);
EXPECT_FALSE(regular_profile->HasOffTheRecordProfile(otr_profile_id1));
EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id2));
}
// Verifies destroying regular profile will result in destruction of OTR
// profiles.
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, DestroyRegularProfileBeforeOTRs) {
Profile::OTRProfileID otr_profile_id1("profile::otr1");
Profile::OTRProfileID otr_profile_id2("profile::otr2");
base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
MockProfileDelegate delegate;
std::unique_ptr<Profile> regular_profile(CreateProfile(
temp_dir.GetPath(), &delegate, Profile::CREATE_MODE_SYNCHRONOUS));
// Creating a profile causes an implicit connection attempt to a Mojo
// service, which occurs as part of a new task. Before deleting |profile|,
// ensure this task runs to prevent a crash.
FlushIoTaskRunnerAndSpinThreads();
Profile* otr_profile1 =
regular_profile->GetOffTheRecordProfile(otr_profile_id1);
Profile* otr_profile2 =
regular_profile->GetOffTheRecordProfile(otr_profile_id2);
ProfileDestructionWatcher watcher1;
ProfileDestructionWatcher watcher2;
watcher1.Watch(otr_profile1);
watcher2.Watch(otr_profile2);
ProfileDestroyer::DestroyProfileWhenAppropriate(regular_profile.release());
EXPECT_TRUE(watcher1.destroyed());
EXPECT_TRUE(watcher2.destroyed());
}
// Tests Profile::GetAllOffTheRecordProfiles
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, TestGetAllOffTheRecordProfiles) {
Profile::OTRProfileID otr_profile_id1("profile::otr1");
Profile::OTRProfileID otr_profile_id2("profile::otr2");
Profile* regular_profile = browser()->profile();
Profile* otr_profile1 =
regular_profile->GetOffTheRecordProfile(otr_profile_id1);
Profile* otr_profile2 =
regular_profile->GetOffTheRecordProfile(otr_profile_id2);
Profile* incognito_profile = regular_profile->GetOffTheRecordProfile(
Profile::OTRProfileID::PrimaryID());
std::vector<Profile*> all_otrs =
regular_profile->GetAllOffTheRecordProfiles();
EXPECT_EQ(3u, all_otrs.size());
EXPECT_TRUE(base::Contains(all_otrs, otr_profile1));
EXPECT_TRUE(base::Contains(all_otrs, otr_profile2));
EXPECT_TRUE(base::Contains(all_otrs, incognito_profile));
}
...@@ -41,7 +41,7 @@ void ProfileDestroyer::DestroyProfileWhenAppropriate(Profile* const profile) { ...@@ -41,7 +41,7 @@ void ProfileDestroyer::DestroyProfileWhenAppropriate(Profile* const profile) {
// anyway, so we can't iterate them via AllHostsIterator anyway. // anyway, so we can't iterate them via AllHostsIterator anyway.
if (profile->AsTestingProfile()) { if (profile->AsTestingProfile()) {
if (profile->IsOffTheRecord()) if (profile->IsOffTheRecord())
profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); profile->GetOriginalProfile()->DestroyOffTheRecordProfile(profile);
else else
delete profile; delete profile;
return; return;
...@@ -64,10 +64,7 @@ void ProfileDestroyer::DestroyProfileWhenAppropriate(Profile* const profile) { ...@@ -64,10 +64,7 @@ void ProfileDestroyer::DestroyProfileWhenAppropriate(Profile* const profile) {
// hosts referring to it are properly terminated. // hosts referring to it are properly terminated.
new ProfileDestroyer(profile, &profile_hosts); new ProfileDestroyer(profile, &profile_hosts);
} else { } else {
if (profile->IsIndependentOffTheRecordProfile()) profile->GetOriginalProfile()->DestroyOffTheRecordProfile(profile);
delete profile;
else
profile->GetOriginalProfile()->DestroyOffTheRecordProfile();
} }
return; return;
} }
...@@ -80,6 +77,8 @@ void ProfileDestroyer::DestroyProfileWhenAppropriate(Profile* const profile) { ...@@ -80,6 +77,8 @@ void ProfileDestroyer::DestroyProfileWhenAppropriate(Profile* const profile) {
profile_has_off_the_record ? profile->GetOffTheRecordProfile() : nullptr; profile_has_off_the_record ? profile->GetOffTheRecordProfile() : nullptr;
#endif // DCHECK_IS_ON() #endif // DCHECK_IS_ON()
// TODO(https://crbug.com/1033903): If profile has OTRs and they have hosts,
// create a |ProfileDestroyer| instead.
delete profile; delete profile;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
...@@ -127,11 +126,7 @@ void ProfileDestroyer::DestroyOffTheRecordProfileNow(Profile* const profile) { ...@@ -127,11 +126,7 @@ void ProfileDestroyer::DestroyOffTheRecordProfileNow(Profile* const profile) {
} }
} }
if (profile->IsIndependentOffTheRecordProfile()) { profile->GetOriginalProfile()->DestroyOffTheRecordProfile(profile);
delete profile;
} else {
profile->GetOriginalProfile()->DestroyOffTheRecordProfile();
}
} }
ProfileDestroyer::ProfileDestroyer(Profile* const profile, HostSet* hosts) ProfileDestroyer::ProfileDestroyer(Profile* const profile, HostSet* hosts)
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
...@@ -776,16 +777,26 @@ ProfileImpl::~ProfileImpl() { ...@@ -776,16 +777,26 @@ ProfileImpl::~ProfileImpl() {
ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this); ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this);
#endif #endif
// Destroy OTR profile and its profile services first. // Destroy all OTR profiles and their profile services first.
if (off_the_record_profile_) { std::vector<Profile*> raw_otr_profiles;
ProfileDestroyer::DestroyOffTheRecordProfileNow( bool primary_otr_available = false;
off_the_record_profile_.get());
} else { // Get a list of existing OTR profiles since |off_the_record_profile_| might
// be modified after the call to |DestroyOffTheRecordProfileNow|.
for (auto& otr_profile : otr_profiles_) {
raw_otr_profiles.push_back(otr_profile.second.get());
primary_otr_available |= (otr_profile.first == OTRProfileID::PrimaryID());
}
for (Profile* otr_profile : raw_otr_profiles)
ProfileDestroyer::DestroyOffTheRecordProfileNow(otr_profile);
#if BUILDFLAG(ENABLE_EXTENSIONS) #if BUILDFLAG(ENABLE_EXTENSIONS)
if (!primary_otr_available) {
ExtensionPrefValueMapFactory::GetForBrowserContext(this) ExtensionPrefValueMapFactory::GetForBrowserContext(this)
->ClearAllIncognitoSessionOnlyPreferences(); ->ClearAllIncognitoSessionOnlyPreferences();
#endif
} }
#endif
FullBrowserTransitionManager::Get()->OnProfileDestroyed(this); FullBrowserTransitionManager::Get()->OnProfileDestroyed(this);
...@@ -858,33 +869,66 @@ bool ProfileImpl::IsOffTheRecord() const { ...@@ -858,33 +869,66 @@ bool ProfileImpl::IsOffTheRecord() const {
return false; return false;
} }
const Profile::OTRProfileID& ProfileImpl::GetOTRProfileID() const {
NOTREACHED();
static base::NoDestructor<OTRProfileID> otr_profile_id(
"ProfileImp::NoOTRProfileID");
return *otr_profile_id;
}
bool ProfileImpl::IsIndependentOffTheRecordProfile() { bool ProfileImpl::IsIndependentOffTheRecordProfile() {
return false; return false;
} }
Profile* ProfileImpl::GetOffTheRecordProfile() { Profile* ProfileImpl::GetOffTheRecordProfile(
if (!off_the_record_profile_) { const OTRProfileID& otr_profile_id) {
std::unique_ptr<Profile> p(CreateOffTheRecordProfile()); if (HasOffTheRecordProfile(otr_profile_id))
off_the_record_profile_.swap(p); return otr_profiles_[otr_profile_id].get();
content::NotificationService::current()->Notify( // Create a new OffTheRecordProfile
chrome::NOTIFICATION_PROFILE_CREATED, std::unique_ptr<Profile> otr_profile =
content::Source<Profile>(off_the_record_profile_.get()), Profile::CreateOffTheRecordProfile(this, otr_profile_id);
content::NotificationService::NoDetails()); Profile* raw_otr_profile = otr_profile.get();
}
return off_the_record_profile_.get(); otr_profiles_[otr_profile_id] = std::move(otr_profile);
NotifyOffTheRecordProfileCreated(raw_otr_profile);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_CREATED,
content::Source<Profile>(raw_otr_profile),
content::NotificationService::NoDetails());
return raw_otr_profile;
}
std::vector<Profile*> ProfileImpl::GetAllOffTheRecordProfiles() {
std::vector<Profile*> raw_otr_profiles;
for (auto& otr : otr_profiles_)
raw_otr_profiles.push_back(otr.second.get());
return raw_otr_profiles;
} }
void ProfileImpl::DestroyOffTheRecordProfile() { void ProfileImpl::DestroyOffTheRecordProfile(Profile* otr_profile) {
off_the_record_profile_.reset(); CHECK(otr_profile);
OTRProfileID profile_id = otr_profile->GetOTRProfileID();
DCHECK(HasOffTheRecordProfile(profile_id));
otr_profiles_.erase(profile_id);
#if BUILDFLAG(ENABLE_EXTENSIONS) #if BUILDFLAG(ENABLE_EXTENSIONS)
ExtensionPrefValueMapFactory::GetForBrowserContext(this) // Extensions are only supported on primary OTR profile.
->ClearAllIncognitoSessionOnlyPreferences(); if (profile_id == OTRProfileID::PrimaryID()) {
ExtensionPrefValueMapFactory::GetForBrowserContext(this)
->ClearAllIncognitoSessionOnlyPreferences();
}
#endif #endif
} }
bool ProfileImpl::HasOffTheRecordProfile() { bool ProfileImpl::HasOffTheRecordProfile(const OTRProfileID& otr_profile_id) {
return off_the_record_profile_.get() != NULL; return base::Contains(otr_profiles_, otr_profile_id);
}
bool ProfileImpl::HasAnyOffTheRecordProfile() {
return !otr_profiles_.empty();
} }
Profile* ProfileImpl::GetOriginalProfile() { Profile* ProfileImpl::GetOriginalProfile() {
...@@ -1297,8 +1341,8 @@ ProfileImpl::GetNativeFileSystemPermissionContext() { ...@@ -1297,8 +1341,8 @@ ProfileImpl::GetNativeFileSystemPermissionContext() {
bool ProfileImpl::IsSameProfile(Profile* profile) { bool ProfileImpl::IsSameProfile(Profile* profile) {
if (profile == static_cast<Profile*>(this)) if (profile == static_cast<Profile*>(this))
return true; return true;
Profile* otr_profile = off_the_record_profile_.get();
return otr_profile && profile == otr_profile; return profile && profile->GetOriginalProfile() == this;
} }
base::Time ProfileImpl::GetStartTime() const { base::Time ProfileImpl::GetStartTime() const {
......
...@@ -114,10 +114,17 @@ class ProfileImpl : public Profile { ...@@ -114,10 +114,17 @@ class ProfileImpl : public Profile {
base::Time GetCreationTime() const override; base::Time GetCreationTime() const override;
bool IsOffTheRecord() override; bool IsOffTheRecord() override;
bool IsOffTheRecord() const override; bool IsOffTheRecord() const override;
const OTRProfileID& GetOTRProfileID() const override;
base::FilePath GetPath() const override; base::FilePath GetPath() const override;
Profile* GetOffTheRecordProfile() override; // TODO(https://crbug.com/1033903): Remove the default value.
void DestroyOffTheRecordProfile() override; Profile* GetOffTheRecordProfile(
bool HasOffTheRecordProfile() override; const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override;
std::vector<Profile*> GetAllOffTheRecordProfiles() override;
void DestroyOffTheRecordProfile(Profile* otr_profile) override;
// TODO(https://crbug.com/1033903): Remove the default value.
bool HasOffTheRecordProfile(
const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override;
bool HasAnyOffTheRecordProfile() override;
Profile* GetOriginalProfile() override; Profile* GetOriginalProfile() override;
const Profile* GetOriginalProfile() const override; const Profile* GetOriginalProfile() const override;
bool IsSupervised() const override; bool IsSupervised() const override;
...@@ -284,7 +291,7 @@ class ProfileImpl : public Profile { ...@@ -284,7 +291,7 @@ class ProfileImpl : public Profile {
base::OneShotTimer create_session_service_timer_; base::OneShotTimer create_session_service_timer_;
#endif #endif
std::unique_ptr<Profile> off_the_record_profile_; std::map<OTRProfileID, std::unique_ptr<Profile>> otr_profiles_;
// See GetStartTime for details. // See GetStartTime for details.
base::Time start_time_; base::Time start_time_;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/location.h" #include "base/location.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/no_destructor.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
...@@ -752,14 +753,29 @@ bool TestingProfile::IsOffTheRecord() const { ...@@ -752,14 +753,29 @@ bool TestingProfile::IsOffTheRecord() const {
return original_profile_; return original_profile_;
} }
void TestingProfile::SetOffTheRecordProfile(std::unique_ptr<Profile> profile) { const Profile::OTRProfileID& TestingProfile::GetOTRProfileID() const {
// TODO(https://crbug.com//1033903): Remove this variable and add support for
// non-primary OTRs.
static base::NoDestructor<Profile::OTRProfileID> incognito_profile_id(
Profile::OTRProfileID::PrimaryID());
DCHECK(IsOffTheRecord());
return *incognito_profile_id;
}
void TestingProfile::SetOffTheRecordProfile(
std::unique_ptr<Profile> otr_profile) {
// TODO(https://crbug.com//1033903): Add support for non-primary OTRs.
DCHECK(!IsOffTheRecord()); DCHECK(!IsOffTheRecord());
if (profile) if (otr_profile)
DCHECK_EQ(this, profile->GetOriginalProfile()); DCHECK_EQ(this, otr_profile->GetOriginalProfile());
incognito_profile_ = std::move(profile); incognito_profile_ = std::move(otr_profile);
} }
Profile* TestingProfile::GetOffTheRecordProfile() { Profile* TestingProfile::GetOffTheRecordProfile(
const OTRProfileID& otr_profile_id) {
// TODO(https://crbug.com//1033903): Add support for non-primary OTRs.
DCHECK(otr_profile_id == OTRProfileID::PrimaryID());
if (IsOffTheRecord()) if (IsOffTheRecord())
return this; return this;
if (!incognito_profile_) if (!incognito_profile_)
...@@ -767,11 +783,34 @@ Profile* TestingProfile::GetOffTheRecordProfile() { ...@@ -767,11 +783,34 @@ Profile* TestingProfile::GetOffTheRecordProfile() {
return incognito_profile_.get(); return incognito_profile_.get();
} }
void TestingProfile::DestroyOffTheRecordProfile() { std::vector<Profile*> TestingProfile::GetAllOffTheRecordProfiles() {
// TODO(https://crbug.com//1033903): Add support for non-primary OTRs.
std::vector<Profile*> otr_profiles;
if (incognito_profile_)
otr_profiles.push_back(incognito_profile_.get());
return otr_profiles;
}
void TestingProfile::DestroyOffTheRecordProfile(Profile* otr_profile) {
// TODO(https://crbug.com//1033903): Add support for non-primary OTRs.
incognito_profile_.reset(); incognito_profile_.reset();
} }
bool TestingProfile::HasOffTheRecordProfile() { void TestingProfile::DestroyOffTheRecordProfile() {
DestroyOffTheRecordProfile(incognito_profile_.get());
}
bool TestingProfile::HasOffTheRecordProfile(
const OTRProfileID& otr_profile_id) {
// TODO(https://crbug.com//1033903): Add support for non-primary OTRs.
DCHECK(otr_profile_id == OTRProfileID::PrimaryID());
return incognito_profile_.get() != nullptr;
}
bool TestingProfile::HasAnyOffTheRecordProfile() {
// TODO(https://crbug.com//1033903): Add support for non-primary OTRs.
return incognito_profile_.get() != nullptr; return incognito_profile_.get() != nullptr;
} }
...@@ -812,8 +851,7 @@ bool TestingProfile::IsLegacySupervised() const { ...@@ -812,8 +851,7 @@ bool TestingProfile::IsLegacySupervised() const {
} }
bool TestingProfile::IsIndependentOffTheRecordProfile() { bool TestingProfile::IsIndependentOffTheRecordProfile() {
return !GetOriginalProfile()->HasOffTheRecordProfile() || return IsOffTheRecord() && GetOTRProfileID() != OTRProfileID::PrimaryID();
GetOriginalProfile()->GetOffTheRecordProfile() != this;
} }
bool TestingProfile::AllowsBrowserWindows() const { bool TestingProfile::AllowsBrowserWindows() const {
......
...@@ -156,6 +156,9 @@ class TestingProfile : public Profile { ...@@ -156,6 +156,9 @@ class TestingProfile : public Profile {
// Build an incognito profile, owned by |original_profile|. Note: unless you // Build an incognito profile, owned by |original_profile|. Note: unless you
// need to customize the Builder, or access TestingProfile member functions, // need to customize the Builder, or access TestingProfile member functions,
// you can use original_profile->GetOffTheRecordProfile(). // you can use original_profile->GetOffTheRecordProfile().
//
// TODO(https://crbug.com/1033903): Add BuildOffTheRecord to add possibility
// of creating non-primary OTRs.
TestingProfile* BuildIncognito(TestingProfile* original_profile); TestingProfile* BuildIncognito(TestingProfile* original_profile);
private: private:
...@@ -268,10 +271,10 @@ class TestingProfile : public Profile { ...@@ -268,10 +271,10 @@ class TestingProfile : public Profile {
void SetNetworkContext( void SetNetworkContext(
std::unique_ptr<network::mojom::NetworkContext> network_context); std::unique_ptr<network::mojom::NetworkContext> network_context);
// Called on the parent of an incognito |profile|. Usually called from the // Called on the parent of an OffTheRecord |otr_profile|. Usually called from
// constructor of an incognito TestingProfile, but can also be used by tests // the constructor of an OffTheRecord TestingProfile, but can also be used by
// to provide an OffTheRecordProfileImpl instance. // tests to provide an OffTheRecordProfileImpl instance.
void SetOffTheRecordProfile(std::unique_ptr<Profile> profile); void SetOffTheRecordProfile(std::unique_ptr<Profile> otr_profile);
void SetSupervisedUserId(const std::string& id); void SetSupervisedUserId(const std::string& id);
...@@ -288,6 +291,7 @@ class TestingProfile : public Profile { ...@@ -288,6 +291,7 @@ class TestingProfile : public Profile {
// profile dynamically. // profile dynamically.
bool IsOffTheRecord() final; bool IsOffTheRecord() final;
bool IsOffTheRecord() const final; bool IsOffTheRecord() const final;
const OTRProfileID& GetOTRProfileID() const override;
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
content::ResourceContext* GetResourceContext() override; content::ResourceContext* GetResourceContext() override;
content::BrowserPluginGuestManager* GetGuestManager() override; content::BrowserPluginGuestManager* GetGuestManager() override;
...@@ -315,9 +319,19 @@ class TestingProfile : public Profile { ...@@ -315,9 +319,19 @@ class TestingProfile : public Profile {
std::string GetProfileUserName() const override; std::string GetProfileUserName() const override;
ProfileType GetProfileType() const override; ProfileType GetProfileType() const override;
Profile* GetOffTheRecordProfile() override; // TODO(https://crbug.com/1033903): Remove the default value.
void DestroyOffTheRecordProfile() override; Profile* GetOffTheRecordProfile(
bool HasOffTheRecordProfile() override; const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override;
std::vector<Profile*> GetAllOffTheRecordProfiles() override;
void DestroyOffTheRecordProfile(Profile* otr_profile) override;
// TODO(https://crbug.com/1033903): Remove this function when all the use
// cases are migrated to above version. The parameter-less version destroys
// the primary off the record profile.
void DestroyOffTheRecordProfile();
// TODO(https://crbug.com/1033903): Remove the default value.
bool HasOffTheRecordProfile(
const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override;
bool HasAnyOffTheRecordProfile() override;
Profile* GetOriginalProfile() override; Profile* GetOriginalProfile() override;
const Profile* GetOriginalProfile() const override; const Profile* GetOriginalProfile() const override;
bool IsSupervised() const override; bool IsSupervised() const override;
......
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