• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Embedded Framework Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "libcef/browser/chrome/chrome_browser_context.h"
6 
7 #include "libcef/browser/thread_util.h"
8 
9 #include "base/threading/thread_restrictions.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
12 #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
13 #include "chrome/browser/profiles/off_the_record_profile_impl.h"
14 
ChromeBrowserContext(const CefRequestContextSettings & settings)15 ChromeBrowserContext::ChromeBrowserContext(
16     const CefRequestContextSettings& settings)
17     : CefBrowserContext(settings), weak_ptr_factory_(this) {}
18 
19 ChromeBrowserContext::~ChromeBrowserContext() = default;
20 
AsBrowserContext()21 content::BrowserContext* ChromeBrowserContext::AsBrowserContext() {
22   CHECK(!destroyed_);
23   return profile_;
24 }
25 
AsProfile()26 Profile* ChromeBrowserContext::AsProfile() {
27   CHECK(!destroyed_);
28   return profile_;
29 }
30 
IsInitialized() const31 bool ChromeBrowserContext::IsInitialized() const {
32   CEF_REQUIRE_UIT();
33   CHECK(!destroyed_);
34   return !!profile_;
35 }
36 
StoreOrTriggerInitCallback(base::OnceClosure callback)37 void ChromeBrowserContext::StoreOrTriggerInitCallback(
38     base::OnceClosure callback) {
39   CEF_REQUIRE_UIT();
40   if (IsInitialized()) {
41     std::move(callback).Run();
42   } else {
43     init_callbacks_.emplace_back(std::move(callback));
44   }
45 }
46 
InitializeAsync(base::OnceClosure initialized_cb)47 void ChromeBrowserContext::InitializeAsync(base::OnceClosure initialized_cb) {
48   init_callbacks_.emplace_back(std::move(initialized_cb));
49 
50   CefBrowserContext::Initialize();
51 
52   if (!cache_path_.empty()) {
53     auto* profile_manager = g_browser_process->profile_manager();
54     const auto& user_data_dir = profile_manager->user_data_dir();
55 
56     if (cache_path_ == user_data_dir) {
57       // Use the default disk-based profile.
58       auto profile = profile_manager->GetPrimaryUserProfile();
59       ProfileCreated(profile, Profile::CreateStatus::CREATE_STATUS_INITIALIZED);
60       return;
61     } else if (cache_path_.DirName() == user_data_dir) {
62       // Create or load a specific disk-based profile. May continue
63       // synchronously or asynchronously.
64       profile_manager->CreateProfileAsync(
65           cache_path_,
66           base::BindRepeating(&ChromeBrowserContext::ProfileCreated,
67                               weak_ptr_factory_.GetWeakPtr()));
68       return;
69     } else {
70       // All profile directories must be relative to |user_data_dir|.
71       LOG(ERROR) << "Cannot create profile at path "
72                  << cache_path_.AsUTF8Unsafe();
73     }
74   }
75 
76   // Default to creating a new/unique OffTheRecord profile.
77   ProfileCreated(nullptr, Profile::CreateStatus::CREATE_STATUS_LOCAL_FAIL);
78 }
79 
Shutdown()80 void ChromeBrowserContext::Shutdown() {
81   CefBrowserContext::Shutdown();
82 
83   // Allow potential deletion of the Profile at some future point (controlled
84   // by ProfileManager).
85   profile_keep_alive_.reset();
86 
87   // |g_browser_process| may be nullptr during shutdown.
88   if (g_browser_process) {
89     if (should_destroy_) {
90       g_browser_process->profile_manager()
91           ->GetPrimaryUserProfile()
92           ->DestroyOffTheRecordProfile(profile_);
93     } else if (profile_) {
94       OnProfileWillBeDestroyed(profile_);
95     }
96   }
97 }
98 
ProfileCreated(Profile * profile,Profile::CreateStatus status)99 void ChromeBrowserContext::ProfileCreated(Profile* profile,
100                                           Profile::CreateStatus status) {
101   Profile* parent_profile = nullptr;
102   OffTheRecordProfileImpl* otr_profile = nullptr;
103 
104   if (status != Profile::CreateStatus::CREATE_STATUS_CREATED &&
105       status != Profile::CreateStatus::CREATE_STATUS_INITIALIZED) {
106     CHECK(!profile);
107     CHECK(!profile_);
108 
109     // Profile creation may access the filesystem.
110     base::ScopedAllowBlockingForTesting allow_blocking;
111 
112     // Creation of a disk-based profile failed for some reason. Create a
113     // new/unique OffTheRecord profile instead.
114     const auto& profile_id = Profile::OTRProfileID::CreateUniqueForCEF();
115     parent_profile =
116         g_browser_process->profile_manager()->GetPrimaryUserProfile();
117     profile_ = parent_profile->GetOffTheRecordProfile(
118         profile_id, /*create_if_needed=*/true);
119     otr_profile = static_cast<OffTheRecordProfileImpl*>(profile_);
120     status = Profile::CreateStatus::CREATE_STATUS_INITIALIZED;
121     should_destroy_ = true;
122   } else if (profile && !profile_) {
123     // May be CREATE_STATUS_CREATED or CREATE_STATUS_INITIALIZED since
124     // *CREATED isn't always sent for a disk-based profile that already
125     // exists.
126     profile_ = profile;
127     profile_->AddObserver(this);
128     profile_keep_alive_.reset(new ScopedProfileKeepAlive(
129         profile_, ProfileKeepAliveOrigin::kAppWindow));
130   }
131 
132   if (status == Profile::CreateStatus::CREATE_STATUS_INITIALIZED) {
133     CHECK(profile_);
134 
135     // Must set |profile_| before Init() calls
136     // ChromeContentBrowserClientCef::ConfigureNetworkContextParams so that
137     // CefBrowserContext::FromBrowserContext can find us.
138     if (otr_profile) {
139       otr_profile->Init();
140       parent_profile->NotifyOffTheRecordProfileCreated(otr_profile);
141     }
142 
143     if (!init_callbacks_.empty()) {
144       for (auto& callback : init_callbacks_) {
145         std::move(callback).Run();
146       }
147       init_callbacks_.clear();
148     }
149   }
150 }
151 
OnProfileWillBeDestroyed(Profile * profile)152 void ChromeBrowserContext::OnProfileWillBeDestroyed(Profile* profile) {
153   CHECK_EQ(profile_, profile);
154   profile_->RemoveObserver(this);
155   profile_ = nullptr;
156   destroyed_ = true;
157 }
158