• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium 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/alloy/alloy_browser_context.h"
6 
7 #include <map>
8 #include <utility>
9 
10 #include "libcef/browser/download_manager_delegate.h"
11 #include "libcef/browser/extensions/extension_system.h"
12 #include "libcef/browser/prefs/browser_prefs.h"
13 #include "libcef/browser/ssl_host_state_delegate.h"
14 #include "libcef/browser/thread_util.h"
15 #include "libcef/common/cef_switches.h"
16 #include "libcef/common/extensions/extensions_util.h"
17 
18 #include "base/command_line.h"
19 #include "base/files/file_util.h"
20 #include "base/lazy_instance.h"
21 #include "base/logging.h"
22 #include "base/strings/string_util.h"
23 #include "chrome/browser/font_family_cache.h"
24 #include "chrome/browser/media/media_device_id_salt.h"
25 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
26 #include "chrome/browser/profiles/profile_key.h"
27 #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/guest_view/browser/guest_view_manager.h"
30 #include "components/keyed_service/content/browser_context_dependency_manager.h"
31 #include "components/keyed_service/core/simple_dependency_manager.h"
32 #include "components/keyed_service/core/simple_key_map.h"
33 #include "components/prefs/pref_service.h"
34 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
35 #include "components/user_prefs/user_prefs.h"
36 #include "components/visitedlink/browser/visitedlink_event_listener.h"
37 #include "components/visitedlink/browser/visitedlink_writer.h"
38 #include "components/zoom/zoom_event_manager.h"
39 #include "content/public/browser/browser_task_traits.h"
40 #include "content/public/browser/browser_thread.h"
41 #include "content/public/browser/download_manager.h"
42 #include "content/public/browser/resource_context.h"
43 #include "content/public/browser/storage_partition.h"
44 #include "extensions/browser/extension_protocols.h"
45 #include "extensions/browser/process_manager.h"
46 #include "extensions/common/constants.h"
47 #include "net/proxy_resolution/proxy_config_service.h"
48 #include "services/network/public/mojom/cors_origin_pattern.mojom.h"
49 
50 using content::BrowserThread;
51 
52 // Creates and manages VisitedLinkEventListener objects for each
53 // AlloyBrowserContext sharing the same VisitedLinkWriter.
54 class CefVisitedLinkListener : public visitedlink::VisitedLinkWriter::Listener {
55  public:
CefVisitedLinkListener()56   CefVisitedLinkListener() { DCHECK(listener_map_.empty()); }
57 
58   CefVisitedLinkListener(const CefVisitedLinkListener&) = delete;
59   CefVisitedLinkListener& operator=(const CefVisitedLinkListener&) = delete;
60 
CreateListenerForContext(content::BrowserContext * context)61   void CreateListenerForContext(content::BrowserContext* context) {
62     CEF_REQUIRE_UIT();
63     auto listener =
64         std::make_unique<visitedlink::VisitedLinkEventListener>(context);
65     listener_map_.insert(std::make_pair(context, std::move(listener)));
66   }
67 
RemoveListenerForContext(content::BrowserContext * context)68   void RemoveListenerForContext(content::BrowserContext* context) {
69     CEF_REQUIRE_UIT();
70     ListenerMap::iterator it = listener_map_.find(context);
71     DCHECK(it != listener_map_.end());
72     listener_map_.erase(it);
73   }
74 
75   // visitedlink::VisitedLinkWriter::Listener methods.
76 
NewTable(base::ReadOnlySharedMemoryRegion * table_region)77   void NewTable(base::ReadOnlySharedMemoryRegion* table_region) override {
78     CEF_REQUIRE_UIT();
79     ListenerMap::iterator it = listener_map_.begin();
80     for (; it != listener_map_.end(); ++it)
81       it->second->NewTable(table_region);
82   }
83 
Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint)84   void Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint) override {
85     CEF_REQUIRE_UIT();
86     ListenerMap::iterator it = listener_map_.begin();
87     for (; it != listener_map_.end(); ++it)
88       it->second->Add(fingerprint);
89   }
90 
Reset(bool invalidate_hashes)91   void Reset(bool invalidate_hashes) override {
92     CEF_REQUIRE_UIT();
93     ListenerMap::iterator it = listener_map_.begin();
94     for (; it != listener_map_.end(); ++it)
95       it->second->Reset(invalidate_hashes);
96   }
97 
98  private:
99   // Map of AlloyBrowserContext to the associated VisitedLinkEventListener.
100   using ListenerMap =
101       std::map<const content::BrowserContext*,
102                std::unique_ptr<visitedlink::VisitedLinkEventListener>>;
103   ListenerMap listener_map_;
104 };
105 
AlloyBrowserContext(const CefRequestContextSettings & settings)106 AlloyBrowserContext::AlloyBrowserContext(
107     const CefRequestContextSettings& settings)
108     : CefBrowserContext(settings) {}
109 
~AlloyBrowserContext()110 AlloyBrowserContext::~AlloyBrowserContext() {
111   if (resource_context_) {
112     content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
113                                        resource_context_.release());
114   }
115 }
116 
IsInitialized() const117 bool AlloyBrowserContext::IsInitialized() const {
118   CEF_REQUIRE_UIT();
119   return !!key_;
120 }
121 
StoreOrTriggerInitCallback(base::OnceClosure callback)122 void AlloyBrowserContext::StoreOrTriggerInitCallback(
123     base::OnceClosure callback) {
124   CEF_REQUIRE_UIT();
125   // Initialization is always synchronous.
126   std::move(callback).Run();
127 }
128 
Initialize()129 void AlloyBrowserContext::Initialize() {
130   CefBrowserContext::Initialize();
131 
132   key_ = std::make_unique<ProfileKey>(cache_path_);
133   SimpleKeyMap::GetInstance()->Associate(this, key_.get());
134 
135   // Initialize the PrefService object.
136   pref_service_ = browser_prefs::CreatePrefService(
137       this, cache_path_, !!settings_.persist_user_preferences);
138 
139   // This must be called before creating any services to avoid hitting
140   // DependencyManager::AssertContextWasntDestroyed when creating/destroying
141   // multiple browser contexts (due to pointer address reuse).
142   BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
143       this);
144 
145   const bool extensions_enabled = extensions::ExtensionsEnabled();
146   if (extensions_enabled) {
147     // Create the custom ExtensionSystem first because other KeyedServices
148     // depend on it.
149     extension_system_ = static_cast<extensions::CefExtensionSystem*>(
150         extensions::ExtensionSystem::Get(this));
151     extension_system_->InitForRegularProfile(true);
152 
153     // Make sure the ProcessManager is created so that it receives extension
154     // load notifications. This is necessary for the proper initialization of
155     // background/event pages.
156     extensions::ProcessManager::Get(this);
157   }
158 
159   // Initialize visited links management.
160   base::FilePath visited_link_path;
161   if (!cache_path_.empty())
162     visited_link_path = cache_path_.Append(FILE_PATH_LITERAL("Visited Links"));
163   visitedlink_listener_ = new CefVisitedLinkListener;
164   visitedlink_master_.reset(new visitedlink::VisitedLinkWriter(
165       visitedlink_listener_, this, !visited_link_path.empty(), false,
166       visited_link_path, 0));
167   visitedlink_listener_->CreateListenerForContext(this);
168   visitedlink_master_->Init();
169 
170   // Initialize proxy configuration tracker.
171   pref_proxy_config_tracker_.reset(new PrefProxyConfigTrackerImpl(
172       GetPrefs(), content::GetIOThreadTaskRunner({})));
173 
174   // Spell checking support and possibly other subsystems retrieve the
175   // PrefService associated with a BrowserContext via UserPrefs::Get().
176   PrefService* pref_service = GetPrefs();
177   DCHECK(pref_service);
178   user_prefs::UserPrefs::Set(this, pref_service);
179   key_->SetPrefs(pref_service);
180 
181   if (extensions_enabled)
182     extension_system_->Init();
183 
184   ChromePluginServiceFilter::GetInstance()->RegisterProfile(this);
185 
186   media_device_id_salt_ = new MediaDeviceIDSalt(pref_service);
187 }
188 
Shutdown()189 void AlloyBrowserContext::Shutdown() {
190   CefBrowserContext::Shutdown();
191 
192   // Send notifications to clean up objects associated with this Profile.
193   MaybeSendDestroyedNotification();
194 
195   ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this);
196 
197   // Remove any BrowserContextKeyedServiceFactory associations. This must be
198   // called before the ProxyService owned by AlloyBrowserContext is destroyed.
199   // The SimpleDependencyManager should always be passed after the
200   // BrowserContextDependencyManager. This is because the KeyedService instances
201   // in the BrowserContextDependencyManager's dependency graph can depend on the
202   // ones in the SimpleDependencyManager's graph.
203   DependencyManager::PerformInterlockedTwoPhaseShutdown(
204       BrowserContextDependencyManager::GetInstance(), this,
205       SimpleDependencyManager::GetInstance(), key_.get());
206 
207   key_.reset();
208   SimpleKeyMap::GetInstance()->Dissociate(this);
209 
210   // Shuts down the storage partitions associated with this browser context.
211   // This must be called before the browser context is actually destroyed
212   // and before a clean-up task for its corresponding IO thread residents
213   // (e.g. ResourceContext) is posted, so that the classes that hung on
214   // StoragePartition can have time to do necessary cleanups on IO thread.
215   ShutdownStoragePartitions();
216 
217   visitedlink_listener_->RemoveListenerForContext(this);
218 
219   // The FontFamilyCache references the ProxyService so delete it before the
220   // ProxyService is deleted.
221   SetUserData(&kFontFamilyCacheKey, nullptr);
222 
223   pref_proxy_config_tracker_->DetachFromPrefService();
224 
225   // Delete the download manager delegate here because otherwise we'll crash
226   // when it's accessed from the content::BrowserContext destructor.
227   if (download_manager_delegate_)
228     download_manager_delegate_.reset(nullptr);
229 }
230 
RemoveCefRequestContext(CefRequestContextImpl * context)231 void AlloyBrowserContext::RemoveCefRequestContext(
232     CefRequestContextImpl* context) {
233   CEF_REQUIRE_UIT();
234 
235   if (extensions::ExtensionsEnabled()) {
236     extension_system()->OnRequestContextDeleted(context);
237   }
238 
239   // May result in |this| being deleted.
240   CefBrowserContext::RemoveCefRequestContext(context);
241 }
242 
LoadExtension(const CefString & root_directory,CefRefPtr<CefDictionaryValue> manifest,CefRefPtr<CefExtensionHandler> handler,CefRefPtr<CefRequestContext> loader_context)243 void AlloyBrowserContext::LoadExtension(
244     const CefString& root_directory,
245     CefRefPtr<CefDictionaryValue> manifest,
246     CefRefPtr<CefExtensionHandler> handler,
247     CefRefPtr<CefRequestContext> loader_context) {
248   if (!extensions::ExtensionsEnabled()) {
249     if (handler)
250       handler->OnExtensionLoadFailed(ERR_ABORTED);
251     return;
252   }
253 
254   if (manifest && manifest->GetSize() > 0) {
255     CefDictionaryValueImpl* value_impl =
256         static_cast<CefDictionaryValueImpl*>(manifest.get());
257     extension_system()->LoadExtension(base::WrapUnique(value_impl->CopyValue()),
258                                       root_directory, false /* builtin */,
259                                       loader_context, handler);
260   } else {
261     extension_system()->LoadExtension(root_directory, false /* builtin */,
262                                       loader_context, handler);
263   }
264 }
265 
GetExtensions(std::vector<CefString> & extension_ids)266 bool AlloyBrowserContext::GetExtensions(std::vector<CefString>& extension_ids) {
267   if (!extensions::ExtensionsEnabled())
268     return false;
269 
270   extensions::CefExtensionSystem::ExtensionMap extension_map =
271       extension_system()->GetExtensions();
272   extensions::CefExtensionSystem::ExtensionMap::const_iterator it =
273       extension_map.begin();
274   for (; it != extension_map.end(); ++it)
275     extension_ids.push_back(it->second->GetIdentifier());
276 
277   return true;
278 }
279 
GetExtension(const CefString & extension_id)280 CefRefPtr<CefExtension> AlloyBrowserContext::GetExtension(
281     const CefString& extension_id) {
282   if (!extensions::ExtensionsEnabled())
283     return nullptr;
284 
285   return extension_system()->GetExtension(extension_id);
286 }
287 
UnloadExtension(const CefString & extension_id)288 bool AlloyBrowserContext::UnloadExtension(const CefString& extension_id) {
289   DCHECK(extensions::ExtensionsEnabled());
290   return extension_system()->UnloadExtension(extension_id);
291 }
292 
IsPrintPreviewSupported() const293 bool AlloyBrowserContext::IsPrintPreviewSupported() const {
294   CEF_REQUIRE_UIT();
295   if (!extensions::PrintPreviewEnabled())
296     return false;
297 
298   return !GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled);
299 }
300 
GetResourceContext()301 content::ResourceContext* AlloyBrowserContext::GetResourceContext() {
302   if (!resource_context_) {
303     resource_context_ = std::make_unique<content::ResourceContext>();
304   }
305   return resource_context_.get();
306 }
307 
308 content::ClientHintsControllerDelegate*
GetClientHintsControllerDelegate()309 AlloyBrowserContext::GetClientHintsControllerDelegate() {
310   return nullptr;
311 }
312 
GetZoomLevelPrefs()313 ChromeZoomLevelPrefs* AlloyBrowserContext::GetZoomLevelPrefs() {
314   return static_cast<ChromeZoomLevelPrefs*>(
315       GetStoragePartition(nullptr)->GetZoomLevelDelegate());
316 }
317 
318 scoped_refptr<network::SharedURLLoaderFactory>
GetURLLoaderFactory()319 AlloyBrowserContext::GetURLLoaderFactory() {
320   return GetDefaultStoragePartition()->GetURLLoaderFactoryForBrowserProcess();
321 }
322 
GetPath()323 base::FilePath AlloyBrowserContext::GetPath() {
324   return cache_path_;
325 }
326 
GetPath() const327 base::FilePath AlloyBrowserContext::GetPath() const {
328   return cache_path_;
329 }
330 
331 std::unique_ptr<content::ZoomLevelDelegate>
CreateZoomLevelDelegate(const base::FilePath & partition_path)332 AlloyBrowserContext::CreateZoomLevelDelegate(
333     const base::FilePath& partition_path) {
334   if (cache_path_.empty())
335     return std::unique_ptr<content::ZoomLevelDelegate>();
336 
337   return base::WrapUnique(new ChromeZoomLevelPrefs(
338       GetPrefs(), cache_path_, partition_path,
339       zoom::ZoomEventManager::GetForBrowserContext(this)->GetWeakPtr()));
340 }
341 
342 content::DownloadManagerDelegate*
GetDownloadManagerDelegate()343 AlloyBrowserContext::GetDownloadManagerDelegate() {
344   if (!download_manager_delegate_) {
345     download_manager_delegate_.reset(
346         new CefDownloadManagerDelegate(GetDownloadManager()));
347   }
348   return download_manager_delegate_.get();
349 }
350 
GetGuestManager()351 content::BrowserPluginGuestManager* AlloyBrowserContext::GetGuestManager() {
352   if (!extensions::ExtensionsEnabled())
353     return nullptr;
354   return guest_view::GuestViewManager::FromBrowserContext(this);
355 }
356 
GetSpecialStoragePolicy()357 storage::SpecialStoragePolicy* AlloyBrowserContext::GetSpecialStoragePolicy() {
358   return nullptr;
359 }
360 
361 content::PlatformNotificationService*
GetPlatformNotificationService()362 AlloyBrowserContext::GetPlatformNotificationService() {
363   return nullptr;
364 }
365 
GetPushMessagingService()366 content::PushMessagingService* AlloyBrowserContext::GetPushMessagingService() {
367   return nullptr;
368 }
369 
370 content::StorageNotificationService*
GetStorageNotificationService()371 AlloyBrowserContext::GetStorageNotificationService() {
372   return nullptr;
373 }
374 
GetSSLHostStateDelegate()375 content::SSLHostStateDelegate* AlloyBrowserContext::GetSSLHostStateDelegate() {
376   if (!ssl_host_state_delegate_)
377     ssl_host_state_delegate_.reset(new CefSSLHostStateDelegate());
378   return ssl_host_state_delegate_.get();
379 }
380 
381 content::PermissionControllerDelegate*
GetPermissionControllerDelegate()382 AlloyBrowserContext::GetPermissionControllerDelegate() {
383   return nullptr;
384 }
385 
386 content::BackgroundFetchDelegate*
GetBackgroundFetchDelegate()387 AlloyBrowserContext::GetBackgroundFetchDelegate() {
388   return nullptr;
389 }
390 
391 content::BackgroundSyncController*
GetBackgroundSyncController()392 AlloyBrowserContext::GetBackgroundSyncController() {
393   return nullptr;
394 }
395 
396 content::BrowsingDataRemoverDelegate*
GetBrowsingDataRemoverDelegate()397 AlloyBrowserContext::GetBrowsingDataRemoverDelegate() {
398   return nullptr;
399 }
400 
GetMediaDeviceIDSalt()401 std::string AlloyBrowserContext::GetMediaDeviceIDSalt() {
402   return media_device_id_salt_->GetSalt();
403 }
404 
GetPrefs()405 PrefService* AlloyBrowserContext::GetPrefs() {
406   return pref_service_.get();
407 }
408 
GetPrefs() const409 const PrefService* AlloyBrowserContext::GetPrefs() const {
410   return pref_service_.get();
411 }
412 
GetProfileKey() const413 ProfileKey* AlloyBrowserContext::GetProfileKey() const {
414   DCHECK(key_);
415   return key_.get();
416 }
417 
418 policy::SchemaRegistryService*
GetPolicySchemaRegistryService()419 AlloyBrowserContext::GetPolicySchemaRegistryService() {
420   NOTREACHED();
421   return nullptr;
422 }
423 
424 policy::UserCloudPolicyManager*
GetUserCloudPolicyManager()425 AlloyBrowserContext::GetUserCloudPolicyManager() {
426   NOTREACHED();
427   return nullptr;
428 }
429 
430 policy::ProfilePolicyConnector*
GetProfilePolicyConnector()431 AlloyBrowserContext::GetProfilePolicyConnector() {
432   NOTREACHED();
433   return nullptr;
434 }
435 
436 const policy::ProfilePolicyConnector*
GetProfilePolicyConnector() const437 AlloyBrowserContext::GetProfilePolicyConnector() const {
438   NOTREACHED();
439   return nullptr;
440 }
441 
IsNewProfile() const442 bool AlloyBrowserContext::IsNewProfile() const {
443   NOTREACHED();
444   return false;
445 }
446 
RebuildTable(const scoped_refptr<URLEnumerator> & enumerator)447 void AlloyBrowserContext::RebuildTable(
448     const scoped_refptr<URLEnumerator>& enumerator) {
449   // Called when visited links will not or cannot be loaded from disk.
450   enumerator->OnComplete(true);
451 }
452 
GetDownloadPrefs()453 DownloadPrefs* AlloyBrowserContext::GetDownloadPrefs() {
454   CEF_REQUIRE_UIT();
455   if (!download_prefs_) {
456     download_prefs_.reset(new DownloadPrefs(this));
457   }
458   return download_prefs_.get();
459 }
460 
AddVisitedURLs(const std::vector<GURL> & urls)461 void AlloyBrowserContext::AddVisitedURLs(const std::vector<GURL>& urls) {
462   visitedlink_master_->AddURLs(urls);
463 }
464