swiftshader_component_installer.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved. 247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// Use of this source code is governed by a BSD-style license that can be 347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// found in the LICENSE file. 447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "chrome/browser/component_updater/swiftshader_component_installer.h" 647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/base_paths.h" 847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/bind.h" 947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/compiler_specific.h" 1047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/cpu.h" 1147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/file_util.h" 1247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/files/file_enumerator.h" 1347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/files/file_path.h" 1447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/logging.h" 1547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/path_service.h" 1647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/strings/string_util.h" 1747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "base/values.h" 1847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "chrome/browser/component_updater/component_updater_service.h" 1947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "chrome/common/chrome_paths.h" 2047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "content/public/browser/browser_thread.h" 2147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "content/public/browser/gpu_data_manager.h" 2247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "content/public/browser/gpu_data_manager_observer.h" 2347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org#include "gpu/config/gpu_feature_type.h" 2447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 2547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgusing content::BrowserThread; 2647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgusing content::GpuDataManager; 2747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 2847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgnamespace { 2947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 3047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// CRX hash. The extension id is: nhfgdggnnopgbfdlpeoalgcjdgfafocg. 3147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgconst uint8 kSha2Hash[] = {0xd7, 0x56, 0x36, 0x6d, 0xde, 0xf6, 0x15, 0x3b, 3247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 0xf4, 0xe0, 0xb6, 0x29, 0x36, 0x50, 0x5e, 0x26, 3347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 0xbd, 0x77, 0x8b, 0x8e, 0x35, 0xc2, 0x7e, 0x43, 3447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 0x52, 0x47, 0x62, 0xed, 0x12, 0xca, 0xcc, 0x6a}; 3547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 3647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// File name of the internal SwiftShader plugin on different platforms. 3747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgconst base::FilePath::CharType kSwiftShaderEglName[] = 3847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org FILE_PATH_LITERAL("libegl.dll"); 3947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgconst base::FilePath::CharType kSwiftShaderGlesName[] = 4047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org FILE_PATH_LITERAL("libglesv2.dll"); 4147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 4247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgconst char kSwiftShaderManifestName[] = "SwiftShader"; 4347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 4447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgconst base::FilePath::CharType kSwiftShaderBaseDirectory[] = 4547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org FILE_PATH_LITERAL("SwiftShader"); 4647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 4747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// If we don't have a SwiftShader component, this is the version we claim. 4847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgconst char kNullVersion[] = "0.0.0.0"; 4947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 5047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// The base directory on windows looks like: 5147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\. 5247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgbase::FilePath GetSwiftShaderBaseDirectory() { 5347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org base::FilePath result; 5447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org PathService::Get(chrome::DIR_USER_DATA, &result); 5547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org return result.Append(kSwiftShaderBaseDirectory); 5647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org} 5747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 5847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// SwiftShader has version encoded in the path itself 5947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// so we need to enumerate the directories to find the full path. 6047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// On success it returns something like: 6147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org// <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\10.3.44.555\. 6247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgbool GetLatestSwiftShaderDirectory(base::FilePath* result, 6347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org Version* latest, 6447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org std::vector<base::FilePath>* older_dirs) { 6547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org base::FilePath base_dir = GetSwiftShaderBaseDirectory(); 6647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org bool found = false; 6747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org base::FileEnumerator 6847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); 6947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); 7047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org path = file_enumerator.Next()) { 7147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org Version version(path.BaseName().MaybeAsASCII()); 7247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org if (!version.IsValid()) 7347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org continue; 7447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org if (version.CompareTo(*latest) > 0 && 7547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org base::PathExists(path.Append(kSwiftShaderEglName)) && 7647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org base::PathExists(path.Append(kSwiftShaderGlesName))) { 7747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org if (found && older_dirs) 7847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org older_dirs->push_back(*result); 7947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org *latest = version; 8047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org *result = path; 8147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org found = true; 8247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org } else { 8347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org if (older_dirs) 8447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org older_dirs->push_back(path); 8547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org } 8647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org } 8747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org return found; 8847401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org} 8947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 9047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgvoid RegisterSwiftShaderWithChrome(const base::FilePath& path) { 9147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 9247401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org GpuDataManager::GetInstance()->RegisterSwiftShaderPath(path); 9347401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org} 9447401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 9547401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org} // namespace 9647401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 9747401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.orgclass SwiftShaderComponentInstaller : public ComponentInstaller { 98ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org public: 9947401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org explicit SwiftShaderComponentInstaller(const Version& version); 10047401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org 10147401354074549d8591da7fa115241766d3ee3d2commit-bot@chromium.org virtual ~SwiftShaderComponentInstaller() {} 102 103 virtual void OnUpdateError(int error) OVERRIDE; 104 105 virtual bool Install(const base::DictionaryValue& manifest, 106 const base::FilePath& unpack_path) OVERRIDE; 107 108 virtual bool GetInstalledFile(const std::string& file, 109 base::FilePath* installed_file) OVERRIDE; 110 111 private: 112 Version current_version_; 113}; 114 115SwiftShaderComponentInstaller::SwiftShaderComponentInstaller( 116 const Version& version) : current_version_(version) { 117 DCHECK(version.IsValid()); 118} 119 120void SwiftShaderComponentInstaller::OnUpdateError(int error) { 121 NOTREACHED() << "SwiftShader update error: " << error; 122} 123 124bool SwiftShaderComponentInstaller::Install( 125 const base::DictionaryValue& manifest, 126 const base::FilePath& unpack_path) { 127 std::string name; 128 manifest.GetStringASCII("name", &name); 129 if (name != kSwiftShaderManifestName) 130 return false; 131 std::string proposed_version; 132 manifest.GetStringASCII("version", &proposed_version); 133 Version version(proposed_version.c_str()); 134 if (!version.IsValid()) 135 return false; 136 if (current_version_.CompareTo(version) >= 0) 137 return false; 138 if (!base::PathExists(unpack_path.Append(kSwiftShaderEglName)) || 139 !base::PathExists(unpack_path.Append(kSwiftShaderGlesName))) 140 return false; 141 // Passed the basic tests. Time to install it. 142 base::FilePath path = 143 GetSwiftShaderBaseDirectory().AppendASCII(version.GetString()); 144 if (base::PathExists(path)) 145 return false; 146 if (!base::Move(unpack_path, path)) 147 return false; 148 // Installation is done. Now tell the rest of chrome. 149 current_version_ = version; 150 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 151 base::Bind(&RegisterSwiftShaderWithChrome, path)); 152 return true; 153} 154 155bool SwiftShaderComponentInstaller::GetInstalledFile( 156 const std::string& file, base::FilePath* installed_file) { 157 return false; 158} 159 160void FinishSwiftShaderUpdateRegistration(ComponentUpdateService* cus, 161 const Version& version) { 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 163 164 CrxComponent swiftshader; 165 swiftshader.name = "Swift Shader"; 166 swiftshader.installer = new SwiftShaderComponentInstaller(version); 167 swiftshader.version = version; 168 swiftshader.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); 169 if (cus->RegisterComponent(swiftshader) != ComponentUpdateService::kOk) { 170 NOTREACHED() << "SwiftShader component registration fail"; 171 } 172} 173 174class UpdateChecker : public content::GpuDataManagerObserver { 175 public: 176 explicit UpdateChecker(ComponentUpdateService* cus); 177 178 virtual void OnGpuInfoUpdate() OVERRIDE; 179 180 private: 181 ComponentUpdateService* cus_; 182}; 183 184UpdateChecker::UpdateChecker(ComponentUpdateService* cus) 185 : cus_(cus) { 186} 187 188void UpdateChecker::OnGpuInfoUpdate() { 189 GpuDataManager *gpu_data_manager = GpuDataManager::GetInstance(); 190 191 if (!gpu_data_manager->GpuAccessAllowed(NULL) || 192 gpu_data_manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) || 193 gpu_data_manager->ShouldUseSwiftShader()) { 194 gpu_data_manager->RemoveObserver(this); 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 196 base::FilePath path = GetSwiftShaderBaseDirectory(); 197 198 Version version(kNullVersion); 199 GetLatestSwiftShaderDirectory(&path, &version, NULL); 200 201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 202 base::Bind(&FinishSwiftShaderUpdateRegistration, cus_, version)); 203 } 204} 205 206// Check if there already is a version of swiftshader installed, 207// and if so register it. 208void RegisterSwiftShaderPath(ComponentUpdateService* cus) { 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 210 base::FilePath path = GetSwiftShaderBaseDirectory(); 211 if (!base::PathExists(path)) { 212 if (!base::CreateDirectory(path)) { 213 NOTREACHED() << "Could not create SwiftShader directory."; 214 return; 215 } 216 } 217 218 Version version(kNullVersion); 219 std::vector<base::FilePath> older_dirs; 220 if (GetLatestSwiftShaderDirectory(&path, &version, &older_dirs)) 221 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 222 base::Bind(&RegisterSwiftShaderWithChrome, path)); 223 224 UpdateChecker *update_checker = new UpdateChecker(cus); 225 GpuDataManager::GetInstance()->AddObserver(update_checker); 226 update_checker->OnGpuInfoUpdate(); 227 // We leak update_checker here, because it has to stick around for the life 228 // of the GpuDataManager. 229 230 // Remove older versions of SwiftShader. 231 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); 232 iter != older_dirs.end(); ++iter) { 233 base::DeleteFile(*iter, true); 234 } 235} 236 237void RegisterSwiftShaderComponent(ComponentUpdateService* cus) { 238#if defined(ENABLE_SWIFTSHADER) 239 base::CPU cpu; 240 241 if (!cpu.has_sse2()) 242 return; 243 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 244 base::Bind(&RegisterSwiftShaderPath, cus)); 245#endif 246} 247