• 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 
CreateListenerForContext(content::BrowserContext * context)58   void CreateListenerForContext(content::BrowserContext* context) {
59     CEF_REQUIRE_UIT();
60     auto listener =
61         std::make_unique<visitedlink::VisitedLinkEventListener>(context);
62     listener_map_.insert(std::make_pair(context, std::move(listener)));
63   }
64 
RemoveListenerForContext(content::BrowserContext * context)65   void RemoveListenerForContext(content::BrowserContext* context) {
66     CEF_REQUIRE_UIT();
67     ListenerMap::iterator it = listener_map_.find(context);
68     DCHECK(it != listener_map_.end());
69     listener_map_.erase(it);
70   }
71 
72   // visitedlink::VisitedLinkWriter::Listener methods.
73 
NewTable(base::ReadOnlySharedMemoryRegion * table_region)74   void NewTable(base::ReadOnlySharedMemoryRegion* table_region) override {
75     CEF_REQUIRE_UIT();
76     ListenerMap::iterator it = listener_map_.begin();
77     for (; it != listener_map_.end(); ++it)
78       it->second->NewTable(table_region);
79   }
80 
Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint)81   void Add(visitedlink::VisitedLinkCommon::Fingerprint fingerprint) override {
82     CEF_REQUIRE_UIT();
83     ListenerMap::iterator it = listener_map_.begin();
84     for (; it != listener_map_.end(); ++it)
85       it->second->Add(fingerprint);
86   }
87 
Reset(bool invalidate_hashes)88   void Reset(bool invalidate_hashes) override {
89     CEF_REQUIRE_UIT();
90     ListenerMap::iterator it = listener_map_.begin();
91     for (; it != listener_map_.end(); ++it)
92       it->second->Reset(invalidate_hashes);
93   }
94 
95  private:
96   // Map of AlloyBrowserContext to the associated VisitedLinkEventListener.
97   typedef std::map<const content::BrowserContext*,
98                    std::unique_ptr<visitedlink::VisitedLinkEventListener>>
99       ListenerMap;
100   ListenerMap listener_map_;
101 
102   DISALLOW_COPY_AND_ASSIGN(CefVisitedLinkListener);
103 };
104 
AlloyBrowserContext(const CefRequestContextSettings & settings)105 AlloyBrowserContext::AlloyBrowserContext(
106     const CefRequestContextSettings& settings)
107     : CefBrowserContext(settings) {}
108 
~AlloyBrowserContext()109 AlloyBrowserContext::~AlloyBrowserContext() {
110   if (resource_context_) {
111     content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
112                                        resource_context_.release());
113   }
114 }
115 
IsInitialized() const116 bool AlloyBrowserContext::IsInitialized() const {
117   CEF_REQUIRE_UIT();
118   return !!key_;
119 }
120 
StoreOrTriggerInitCallback(base::OnceClosure callback)121 void AlloyBrowserContext::StoreOrTriggerInitCallback(
122     base::OnceClosure callback) {
123   CEF_REQUIRE_UIT();
124   // Initialization is always synchronous.
125   std::move(callback).Run();
126 }
127 
Initialize()128 void AlloyBrowserContext::Initialize() {
129   CefBrowserContext::Initialize();
130 
131   key_ = std::make_unique<ProfileKey>(cache_path_);
132   SimpleKeyMap::GetInstance()->Associate(this, key_.get());
133 
134   // Initialize the PrefService object.
135   pref_service_ = browser_prefs::CreatePrefService(
136       this, cache_path_, !!settings_.persist_user_preferences);
137 
138   // This must be called before creating any services to avoid hitting
139   // DependencyManager::AssertContextWasntDestroyed when creating/destroying
140   // multiple browser contexts (due to pointer address reuse).
141   BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
142       this);
143 
144   const bool extensions_enabled = extensions::ExtensionsEnabled();
145   if (extensions_enabled) {
146     // Create the custom ExtensionSystem first because other KeyedServices
147     // depend on it.
148     extension_system_ = static_cast<extensions::CefExtensionSystem*>(
149         extensions::ExtensionSystem::Get(this));
150     extension_system_->InitForRegularProfile(true);
151 
152     // Make sure the ProcessManager is created so that it receives extension
153     // load notifications. This is necessary for the proper initialization of
154     // background/event pages.
155     extensions::ProcessManager::Get(this);
156   }
157 
158   // Initialize visited links management.
159   base::FilePath visited_link_path;
160   if (!cache_path_.empty())
161     visited_link_path = cache_path_.Append(FILE_PATH_LITERAL("Visited Links"));
162   visitedlink_listener_ = new CefVisitedLinkListener;
163   visitedlink_master_.reset(new visitedlink::VisitedLinkWriter(
164       visitedlink_listener_, this, !visited_link_path.empty(), false,
165       visited_link_path, 0));
166   visitedlink_listener_->CreateListenerForContext(this);
167   visitedlink_master_->Init();
168 
169   // Initialize proxy configuration tracker.
170   pref_proxy_config_tracker_.reset(new PrefProxyConfigTrackerImpl(
171       GetPrefs(), content::GetIOThreadTaskRunner({})));
172 
173   // Spell checking support and possibly other subsystems retrieve the
174   // PrefService associated with a BrowserContext via UserPrefs::Get().
175   PrefService* pref_service = GetPrefs();
176   DCHECK(pref_service);
177   user_prefs::UserPrefs::Set(this, pref_service);
178   key_->SetPrefs(pref_service);
179 
180   if (extensions_enabled)
181     extension_system_->Init();
182 
183   ChromePluginServiceFilter::GetInstance()->RegisterProfile(this);
184 
185   media_device_id_salt_ = new MediaDeviceIDSalt(pref_service);
186 }
187 
Shutdown()188 void AlloyBrowserContext::Shutdown() {
189   CefBrowserContext::Shutdown();
190 
191   // Send notifications to clean up objects associated with this Profile.
192   MaybeSendDestroyedNotification();
193 
194   ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this);
195 
196   // Remove any BrowserContextKeyedServiceFactory associations. This must be
197   // called before the ProxyService owned by AlloyBrowserContext is destroyed.
198   // The SimpleDependencyManager should always be passed after the
199   // BrowserContextDependencyManager. This is because the KeyedService instances
200   // in the BrowserContextDependencyManager's dependency graph can depend on the
201   // ones in the SimpleDependencyManager's graph.
202   DependencyManager::PerformInterlockedTwoPhaseShutdown(
203       BrowserContextDependencyManager::GetInstance(), this,
204       SimpleDependencyManager::GetInstance(), key_.get());
205 
206   key_.reset();
207   SimpleKeyMap::GetInstance()->Dissociate(this);
208 
209   // Shuts down the storage partitions associated with this browser context.
210   // This must be called before the browser context is actually destroyed
211   // and before a clean-up task for its corresponding IO thread residents
212   // (e.g. ResourceContext) is posted, so that the classes that hung on
213   // StoragePartition can have time to do necessary cleanups on IO thread.
214   ShutdownStoragePartitions();
215 
216   visitedlink_listener_->RemoveListenerForContext(this);
217 
218   // The FontFamilyCache references the ProxyService so delete it before the
219   // ProxyService is deleted.
220   SetUserData(&kFontFamilyCacheKey, nullptr);
221 
222   pref_proxy_config_tracker_->DetachFromPrefService();
223 
224   // Delete the download manager delegate here because otherwise we'll crash
225   // when it's accessed from the content::BrowserContext destructor.
226   if (download_manager_delegate_)
227     download_manager_delegate_.reset(nullptr);
228 }
229 
RemoveCefRequestContext(CefRequestContextImpl * context)230 void AlloyBrowserContext::RemoveCefRequestContext(
231     CefRequestContextImpl* context) {
232   CEF_REQUIRE_UIT();
233 
234   if (extensions::ExtensionsEnabled()) {
235     extension_system()->OnRequestContextDeleted(context);
236   }
237 
238   // May result in |this| being deleted.
239   CefBrowserContext::RemoveCefRequestContext(context);
240 }
241 
LoadExtension(const CefString & root_directory,CefRefPtr<CefDictionaryValue> manifest,CefRefPtr<CefExtensionHandler> handler,CefRefPtr<CefRequestContext> loader_context)242 void AlloyBrowserContext::LoadExtension(
243     const CefString& root_directory,
244     CefRefPtr<CefDictionaryValue> manifest,
245     CefRefPtr<CefExtensionHandler> handler,
246     CefRefPtr<CefRequestContext> loader_context) {
247   if (!extensions::ExtensionsEnabled()) {
248     if (handler)
249       handler->OnExtensionLoadFailed(ERR_ABORTED);
250     return;
251   }
252 
253   if (manifest && manifest->GetSize() > 0) {
254     CefDictionaryValueImpl* value_impl =
255         static_cast<CefDictionaryValueImpl*>(manifest.get());
256     extension_system()->LoadExtension(base::WrapUnique(value_impl->CopyValue()),
257                                       root_directory, false /* builtin */,
258                                       loader_context, handler);
259   } else {
260     extension_system()->LoadExtension(root_directory, false /* builtin */,
261                                       loader_context, handler);
262   }
263 }
264 
GetExtensions(std::vector<CefString> & extension_ids)265 bool AlloyBrowserContext::GetExtensions(std::vector<CefString>& extension_ids) {
266   if (!extensions::ExtensionsEnabled())
267     return false;
268 
269   extensions::CefExtensionSystem::ExtensionMap extension_map =
270       extension_system()->GetExtensions();
271   extensions::CefExtensionSystem::ExtensionMap::const_iterator it =
272       extension_map.begin();
273   for (; it != extension_map.end(); ++it)
274     extension_ids.push_back(it->second->GetIdentifier());
275 
276   return true;
277 }
278 
GetExtension(const CefString & extension_id)279 CefRefPtr<CefExtension> AlloyBrowserContext::GetExtension(
280     const CefString& extension_id) {
281   if (!extensions::ExtensionsEnabled())
282     return nullptr;
283 
284   return extension_system()->GetExtension(extension_id);
285 }
286 
UnloadExtension(const CefString & extension_id)287 bool AlloyBrowserContext::UnloadExtension(const CefString& extension_id) {
288   DCHECK(extensions::ExtensionsEnabled());
289   return extension_system()->UnloadExtension(extension_id);
290 }
291 
IsPrintPreviewSupported() const292 bool AlloyBrowserContext::IsPrintPreviewSupported() const {
293   CEF_REQUIRE_UIT();
294   if (!extensions::PrintPreviewEnabled())
295     return false;
296 
297   return !GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled);
298 }
299 
GetResourceContext()300 content::ResourceContext* AlloyBrowserContext::GetResourceContext() {
301   if (!resource_context_) {
302     resource_context_ = std::make_unique<content::ResourceContext>();
303   }
304   return resource_context_.get();
305 }
306 
307 content::ClientHintsControllerDelegate*
GetClientHintsControllerDelegate()308 AlloyBrowserContext::GetClientHintsControllerDelegate() {
309   return nullptr;
310 }
311 
GetZoomLevelPrefs()312 ChromeZoomLevelPrefs* AlloyBrowserContext::GetZoomLevelPrefs() {
313   return static_cast<ChromeZoomLevelPrefs*>(
314       GetStoragePartition(this, nullptr)->GetZoomLevelDelegate());
315 }
316 
317 scoped_refptr<network::SharedURLLoaderFactory>
GetURLLoaderFactory()318 AlloyBrowserContext::GetURLLoaderFactory() {
319   return GetDefaultStoragePartition(this)
320       ->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 
IsOffTheRecord() const342 bool AlloyBrowserContext::IsOffTheRecord() const {
343   // Alloy contexts are never flagged as off-the-record. It causes problems
344   // for the extension system.
345   return false;
346 }
347 
348 content::DownloadManagerDelegate*
GetDownloadManagerDelegate()349 AlloyBrowserContext::GetDownloadManagerDelegate() {
350   if (!download_manager_delegate_) {
351     content::DownloadManager* manager =
352         BrowserContext::GetDownloadManager(this);
353     download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager));
354   }
355   return download_manager_delegate_.get();
356 }
357 
GetGuestManager()358 content::BrowserPluginGuestManager* AlloyBrowserContext::GetGuestManager() {
359   DCHECK(extensions::ExtensionsEnabled());
360   return guest_view::GuestViewManager::FromBrowserContext(this);
361 }
362 
GetSpecialStoragePolicy()363 storage::SpecialStoragePolicy* AlloyBrowserContext::GetSpecialStoragePolicy() {
364   return nullptr;
365 }
366 
GetPushMessagingService()367 content::PushMessagingService* AlloyBrowserContext::GetPushMessagingService() {
368   return nullptr;
369 }
370 
371 content::StorageNotificationService*
GetStorageNotificationService()372 AlloyBrowserContext::GetStorageNotificationService() {
373   return nullptr;
374 }
375 
GetSSLHostStateDelegate()376 content::SSLHostStateDelegate* AlloyBrowserContext::GetSSLHostStateDelegate() {
377   if (!ssl_host_state_delegate_)
378     ssl_host_state_delegate_.reset(new CefSSLHostStateDelegate());
379   return ssl_host_state_delegate_.get();
380 }
381 
382 content::PermissionControllerDelegate*
GetPermissionControllerDelegate()383 AlloyBrowserContext::GetPermissionControllerDelegate() {
384   return nullptr;
385 }
386 
387 content::BackgroundFetchDelegate*
GetBackgroundFetchDelegate()388 AlloyBrowserContext::GetBackgroundFetchDelegate() {
389   return nullptr;
390 }
391 
392 content::BackgroundSyncController*
GetBackgroundSyncController()393 AlloyBrowserContext::GetBackgroundSyncController() {
394   return nullptr;
395 }
396 
397 content::BrowsingDataRemoverDelegate*
GetBrowsingDataRemoverDelegate()398 AlloyBrowserContext::GetBrowsingDataRemoverDelegate() {
399   return nullptr;
400 }
401 
GetMediaDeviceIDSalt()402 std::string AlloyBrowserContext::GetMediaDeviceIDSalt() {
403   return media_device_id_salt_->GetSalt();
404 }
405 
GetPrefs()406 PrefService* AlloyBrowserContext::GetPrefs() {
407   return pref_service_.get();
408 }
409 
GetPrefs() const410 const PrefService* AlloyBrowserContext::GetPrefs() const {
411   return pref_service_.get();
412 }
413 
GetProfileKey() const414 ProfileKey* AlloyBrowserContext::GetProfileKey() const {
415   DCHECK(key_);
416   return key_.get();
417 }
418 
419 policy::SchemaRegistryService*
GetPolicySchemaRegistryService()420 AlloyBrowserContext::GetPolicySchemaRegistryService() {
421   NOTREACHED();
422   return nullptr;
423 }
424 
425 policy::UserCloudPolicyManager*
GetUserCloudPolicyManager()426 AlloyBrowserContext::GetUserCloudPolicyManager() {
427   NOTREACHED();
428   return nullptr;
429 }
430 
431 policy::ProfilePolicyConnector*
GetProfilePolicyConnector()432 AlloyBrowserContext::GetProfilePolicyConnector() {
433   NOTREACHED();
434   return nullptr;
435 }
436 
437 const policy::ProfilePolicyConnector*
GetProfilePolicyConnector() const438 AlloyBrowserContext::GetProfilePolicyConnector() const {
439   NOTREACHED();
440   return nullptr;
441 }
442 
IsNewProfile() const443 bool AlloyBrowserContext::IsNewProfile() const {
444   NOTREACHED();
445   return false;
446 }
447 
RebuildTable(const scoped_refptr<URLEnumerator> & enumerator)448 void AlloyBrowserContext::RebuildTable(
449     const scoped_refptr<URLEnumerator>& enumerator) {
450   // Called when visited links will not or cannot be loaded from disk.
451   enumerator->OnComplete(true);
452 }
453 
GetDownloadPrefs()454 DownloadPrefs* AlloyBrowserContext::GetDownloadPrefs() {
455   CEF_REQUIRE_UIT();
456   if (!download_prefs_) {
457     download_prefs_.reset(new DownloadPrefs(this));
458   }
459   return download_prefs_.get();
460 }
461 
AddVisitedURLs(const std::vector<GURL> & urls)462 void AlloyBrowserContext::AddVisitedURLs(const std::vector<GURL>& urls) {
463   visitedlink_master_->AddURLs(urls);
464 }
465