blob: 5df66baf4e59053a8f5557d6afaf0c6c4c1943ed [file] [log] [blame]
[email protected]4d3c27f32012-03-31 09:11:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]df353ab2011-12-16 23:57:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/component_updater/swiftshader_component_installer.h"
6
7#include "base/bind.h"
8#include "base/base_paths.h"
9#include "base/compiler_specific.h"
[email protected]4d3c27f32012-03-31 09:11:5910#include "base/cpu.h"
[email protected]df353ab2011-12-16 23:57:5711#include "base/file_path.h"
12#include "base/file_util.h"
13#include "base/logging.h"
14#include "base/path_service.h"
15#include "base/string_util.h"
16#include "base/values.h"
17#include "chrome/browser/component_updater/component_updater_service.h"
18#include "chrome/common/chrome_paths.h"
19#include "content/public/browser/browser_thread.h"
[email protected]79078df2012-02-16 01:22:3220#include "content/public/browser/gpu_data_manager.h"
21#include "content/public/browser/gpu_data_manager_observer.h"
[email protected]df353ab2011-12-16 23:57:5722
23using content::BrowserThread;
[email protected]79078df2012-02-16 01:22:3224using content::GpuDataManager;
[email protected]df353ab2011-12-16 23:57:5725
26namespace {
27
28// CRX hash. The extension id is: nhfgdggnnopgbfdlpeoalgcjdgfafocg.
29const uint8 sha2_hash[] = {0xd7, 0x56, 0x36, 0x6d, 0xde, 0xf6, 0x15, 0x3b,
30 0xf4, 0xe0, 0xb6, 0x29, 0x36, 0x50, 0x5e, 0x26,
31 0xbd, 0x77, 0x8b, 0x8e, 0x35, 0xc2, 0x7e, 0x43,
32 0x52, 0x47, 0x62, 0xed, 0x12, 0xca, 0xcc, 0x6a};
33
34// File name of the internal SwiftShader plugin on different platforms.
35const FilePath::CharType kSwiftShaderEglName[] =
36 FILE_PATH_LITERAL("libegl.dll");
37const FilePath::CharType kSwiftShaderGlesName[] =
38 FILE_PATH_LITERAL("libglesv2.dll");
39
40const char kSwiftShaderManifestName[] = "SwiftShader";
41
42const FilePath::CharType kSwiftShaderBaseDirectory[] =
43 FILE_PATH_LITERAL("SwiftShader");
44
45// If we don't have a SwiftShader component, this is the version we claim.
46const char kNullVersion[] = "0.0.0.0";
47
48// The base directory on windows looks like:
49// <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\.
50FilePath GetSwiftShaderBaseDirectory() {
51 FilePath result;
52 PathService::Get(chrome::DIR_USER_DATA, &result);
53 return result.Append(kSwiftShaderBaseDirectory);
54}
55
56// SwiftShader has version encoded in the path itself
57// so we need to enumerate the directories to find the full path.
58// On success it returns something like:
59// <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\10.3.44.555\.
60bool GetLatestSwiftShaderDirectory(FilePath* result, Version* latest) {
61 *result = GetSwiftShaderBaseDirectory();
62 bool found = false;
63 file_util::FileEnumerator
64 file_enumerator(*result, false, file_util::FileEnumerator::DIRECTORIES);
65 for (FilePath path = file_enumerator.Next(); !path.value().empty();
66 path = file_enumerator.Next()) {
67 Version version(path.BaseName().MaybeAsASCII());
68 if (!version.IsValid())
69 continue;
70 if (version.CompareTo(*latest) > 0 &&
71 file_util::PathExists(path.Append(kSwiftShaderEglName)) &&
72 file_util::PathExists(path.Append(kSwiftShaderGlesName))) {
73 *latest = version;
74 *result = path;
75 found = true;
76 }
77 }
78 return found;
79}
80
81void RegisterSwiftShaderWithChrome(const FilePath& path) {
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83 GpuDataManager::GetInstance()->RegisterSwiftShaderPath(path);
84}
85
86} // namespace
87
88class SwiftShaderComponentInstaller : public ComponentInstaller {
89 public:
90 explicit SwiftShaderComponentInstaller(const Version& version);
91
92 virtual ~SwiftShaderComponentInstaller() {}
93
94 virtual void OnUpdateError(int error) OVERRIDE;
95
96 virtual bool Install(base::DictionaryValue* manifest,
97 const FilePath& unpack_path) OVERRIDE;
98
99 private:
100 Version current_version_;
101};
102
103SwiftShaderComponentInstaller::SwiftShaderComponentInstaller(
104 const Version& version) : current_version_(version) {
105 DCHECK(version.IsValid());
106}
107
108void SwiftShaderComponentInstaller::OnUpdateError(int error) {
109 NOTREACHED() << "SwiftShader update error: " << error;
110}
111
112bool SwiftShaderComponentInstaller::Install(base::DictionaryValue* manifest,
113 const FilePath& unpack_path) {
114 std::string name;
115 manifest->GetStringASCII("name", &name);
116 if (name != kSwiftShaderManifestName)
117 return false;
118 std::string proposed_version;
119 manifest->GetStringASCII("version", &proposed_version);
120 Version version(proposed_version.c_str());
121 if (!version.IsValid())
122 return false;
123 if (current_version_.CompareTo(version) >= 0)
124 return false;
125 if (!file_util::PathExists(unpack_path.Append(kSwiftShaderEglName)) ||
126 !file_util::PathExists(unpack_path.Append(kSwiftShaderGlesName)))
127 return false;
128 // Passed the basic tests. Time to install it.
129 FilePath path =
130 GetSwiftShaderBaseDirectory().AppendASCII(version.GetString());
131 if (file_util::PathExists(path))
132 return false;
133 if (!file_util::Move(unpack_path, path))
134 return false;
135 // Installation is done. Now tell the rest of chrome.
136 current_version_ = version;
137 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
138 base::Bind(&RegisterSwiftShaderWithChrome, path));
139 return true;
140}
141
142void FinishSwiftShaderUpdateRegistration(ComponentUpdateService* cus,
143 const Version& version) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145
146 CrxComponent swiftshader;
147 swiftshader.name = "Swift Shader";
148 swiftshader.installer = new SwiftShaderComponentInstaller(version);
149 swiftshader.version = version;
150 swiftshader.pk_hash.assign(sha2_hash, &sha2_hash[sizeof(sha2_hash)]);
151 if (cus->RegisterComponent(swiftshader) != ComponentUpdateService::kOk) {
152 NOTREACHED() << "SwiftShader component registration fail";
153 }
154}
155
[email protected]79078df2012-02-16 01:22:32156class UpdateChecker : public content::GpuDataManagerObserver {
[email protected]df353ab2011-12-16 23:57:57157 public:
158 explicit UpdateChecker(ComponentUpdateService* cus);
159
160 virtual void OnGpuInfoUpdate() OVERRIDE;
161
162 private:
163 ComponentUpdateService* cus_;
164};
165
166UpdateChecker::UpdateChecker(ComponentUpdateService* cus)
167 : cus_(cus) {
168}
169
170void UpdateChecker::OnGpuInfoUpdate() {
171 GpuDataManager *gpu_data_manager = GpuDataManager::GetInstance();
172
173 if (!gpu_data_manager->GpuAccessAllowed() ||
[email protected]d56ecf922012-02-15 16:03:11174 (gpu_data_manager->GetGpuFeatureType() &
175 content::GPU_FEATURE_TYPE_WEBGL) ||
[email protected]79078df2012-02-16 01:22:32176 gpu_data_manager->ShouldUseSoftwareRendering()) {
[email protected]df353ab2011-12-16 23:57:57177 gpu_data_manager->RemoveObserver(this);
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
179 FilePath path = GetSwiftShaderBaseDirectory();
180
181 Version version(kNullVersion);
182 GetLatestSwiftShaderDirectory(&path, &version);
183
184 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
185 base::Bind(&FinishSwiftShaderUpdateRegistration, cus_, version));
186 }
187}
188
189// Check if there already is a version of swiftshader installed,
190// and if so register it.
191void RegisterSwiftShaderPath(ComponentUpdateService* cus) {
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
193 FilePath path = GetSwiftShaderBaseDirectory();
194 if (!file_util::PathExists(path)) {
195 if (!file_util::CreateDirectory(path)) {
196 NOTREACHED() << "Could not create SwiftShader directory.";
197 return;
198 }
199 }
200
201 Version version(kNullVersion);
202 if (GetLatestSwiftShaderDirectory(&path, &version))
203 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
204 base::Bind(&RegisterSwiftShaderWithChrome, path));
205
206 UpdateChecker *update_checker = new UpdateChecker(cus);
207 GpuDataManager::GetInstance()->AddObserver(update_checker);
208 update_checker->OnGpuInfoUpdate();
209 // We leak update_checker here, because it has to stick around for the life
210 // of the GpuDataManager.
211}
212
213void RegisterSwiftShaderComponent(ComponentUpdateService* cus) {
214#if defined(ENABLE_SWIFTSHADER)
[email protected]4d3c27f32012-03-31 09:11:59215 base::CPU cpu;
216
217 if (!cpu.has_sse2())
218 return;
[email protected]df353ab2011-12-16 23:57:57219 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
220 base::Bind(&RegisterSwiftShaderPath, cus));
221#endif
222}