blob: 54e4e79e9176064ab58f88c9a01193f86f8804f4 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/process/kill.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/three_d_api_types.h"
#include "gpu/config/gpu_control_list.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
class GURL;
namespace base {
class CommandLine;
namespace gpu {
struct GpuPreferences;
struct VideoMemoryUsageStats;
namespace content {
class GpuDataManagerImplPrivate;
class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
// Indicates the guilt level of a domain which caused a GPU reset.
// If a domain is 100% known to be guilty of resetting the GPU, then
// it will generally not cause other domains' use of 3D APIs to be
// blocked, unless system stability would be compromised.
enum DomainGuilt {
// Indicates the reason that access to a given client API (like
// WebGL or Pepper 3D) was blocked or not. This state is distinct
// from blacklisting of an entire feature.
enum DomainBlockStatus {
// Getter for the singleton. This will return NULL on failure.
static GpuDataManagerImpl* GetInstance();
// GpuDataManager implementation.
void BlacklistWebGLForTesting() override;
gpu::GPUInfo GetGPUInfo() const override;
bool GpuAccessAllowed(std::string* reason) const override;
void RequestCompleteGpuInfoIfNeeded() override;
bool IsEssentialGpuInfoAvailable() const override;
bool IsCompleteGpuInfoAvailable() const override;
void RequestVideoMemoryUsageStatsUpdate(
const base::Callback<void(const gpu::VideoMemoryUsageStats& stats)>&
callback) const override;
// TODO(kbr): the threading model for the GpuDataManagerObservers is
// not well defined, and it's impossible for callers to correctly
// delete observers from anywhere except in one of the observer's
// notification methods. Observer addition and removal, and their
// callbacks, should probably be required to occur on the UI thread.
void AddObserver(GpuDataManagerObserver* observer) override;
void RemoveObserver(GpuDataManagerObserver* observer) override;
void UnblockDomainFrom3DAPIs(const GURL& url) override;
void SetGLStrings(const std::string& gl_vendor,
const std::string& gl_renderer,
const std::string& gl_version) override;
void DisableHardwareAcceleration() override;
bool HardwareAccelerationEnabled() const override;
void GetDisabledExtensions(std::string* disabled_extensions) const override;
void SetGpuInfo(const gpu::GPUInfo& gpu_info) override;
bool IsGpuFeatureInfoAvailable() const;
gpu::GpuFeatureStatus GetFeatureStatus(gpu::GpuFeatureType feature) const;
// This collects preliminary GPU info, load GpuBlacklist, and compute the
// preliminary blacklisted features; it should only be called at browser
// startup time in UI thread before the IO restriction is turned on.
void Initialize();
// Only update if the current GPUInfo is not finalized. If blacklist is
// loaded, run through blacklist and update blacklisted features.
void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
// Update the GPU feature info. This updates the blacklist and enabled status
// of GPU rasterization. In the future this will be used for more features.
void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info);
gpu::GpuFeatureInfo GetGpuFeatureInfo() const;
// Insert disable-feature switches corresponding to preliminary gpu feature
// flags into the renderer process command line.
void AppendRendererCommandLine(base::CommandLine* command_line) const;
// Insert switches into gpu process command line: kUseGL, etc.
void AppendGpuCommandLine(base::CommandLine* command_line) const;
// Update GpuPreferences based on blacklisting decisions.
void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences) const;
// Returns the reasons for the latest run of blacklisting decisions.
// For the structure of returned value, see documentation for
// GpuBlacklist::GetBlacklistedReasons().
void GetBlacklistReasons(base::ListValue* reasons) const;
// Returns the workarounds that are applied to the current system as
// a vector of strings.
std::vector<std::string> GetDriverBugWorkarounds() const;
void AddLogMessage(int level,
const std::string& header,
const std::string& message);
void ProcessCrashed(base::TerminationStatus exit_code);
// Returns a new copy of the ListValue.
std::unique_ptr<base::ListValue> GetLogMessages() const;
// Called when switching gpu.
void HandleGpuSwitch();
// Maintenance of domains requiring explicit user permission before
// using client-facing 3D APIs (WebGL, Pepper 3D), either because
// the domain has caused the GPU to reset, or because too many GPU
// resets have been observed globally recently, and system stability
// might be compromised.
// The given URL may be a partial URL (including at least the host)
// or a full URL to a page.
// Note that the unblocking API must be part of the content API
// because it is called from Chrome side code.
void BlockDomainFrom3DAPIs(const GURL& url, DomainGuilt guilt);
bool Are3DAPIsBlocked(const GURL& top_origin_url,
int render_process_id,
int render_frame_id,
ThreeDAPIType requester);
// Disables domain blocking for 3D APIs. For use only in tests.
void DisableDomainBlockingFor3DAPIsForTesting();
void Notify3DAPIBlocked(const GURL& top_origin_url,
int render_process_id,
int render_frame_id,
ThreeDAPIType requester);
// Set the active gpu.
// Return true if it's a different GPU from the previous active one.
bool UpdateActiveGpu(uint32_t vendor_id, uint32_t device_id);
// Called when GPU process initialization failed.
void OnGpuProcessInitFailure();
void DisableSwiftShader();
friend class GpuDataManagerImplPrivate;
friend class GpuDataManagerImplPrivateTest;
friend struct base::DefaultSingletonTraits<GpuDataManagerImpl>;
// It's similar to AutoUnlock, but we want to make it a no-op
// if the owner GpuDataManagerImpl is null.
// This should only be used by GpuDataManagerImplPrivate where
// callbacks are called, during which re-entering
// GpuDataManagerImpl is possible.
class UnlockedSession {
explicit UnlockedSession(GpuDataManagerImpl* owner)
: owner_(owner) {
~UnlockedSession() {
GpuDataManagerImpl* owner_;
~GpuDataManagerImpl() override;
mutable base::Lock lock_;
std::unique_ptr<GpuDataManagerImplPrivate> private_;
} // namespace content