OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/component_updater/swiftshader_component_installer.h" | 5 #include "chrome/browser/component_updater/swiftshader_component_installer.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/base_paths.h" | 10 #include "base/base_paths.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/cpu.h" | 13 #include "base/cpu.h" |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/files/file_enumerator.h" | 15 #include "base/files/file_enumerator.h" |
16 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/path_service.h" | 18 #include "base/path_service.h" |
19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
20 #include "base/values.h" | 20 #include "base/values.h" |
21 #include "chrome/browser/component_updater/component_updater_service.h" | 21 #include "chrome/browser/component_updater/component_updater_service.h" |
22 #include "chrome/common/chrome_paths.h" | |
23 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
24 #include "content/public/browser/gpu_data_manager.h" | 23 #include "content/public/browser/gpu_data_manager.h" |
25 #include "content/public/browser/gpu_data_manager_observer.h" | 24 #include "content/public/browser/gpu_data_manager_observer.h" |
26 #include "gpu/config/gpu_feature_type.h" | 25 #include "gpu/config/gpu_feature_type.h" |
27 | 26 |
28 using content::BrowserThread; | 27 using content::BrowserThread; |
29 using content::GpuDataManager; | 28 using content::GpuDataManager; |
30 | 29 |
31 namespace component_updater { | 30 namespace component_updater { |
32 | 31 |
33 namespace { | 32 namespace { |
34 | 33 |
35 // CRX hash. The extension id is: nhfgdggnnopgbfdlpeoalgcjdgfafocg. | 34 // CRX hash. The extension id is: nhfgdggnnopgbfdlpeoalgcjdgfafocg. |
36 const uint8 kSha2Hash[] = {0xd7, 0x56, 0x36, 0x6d, 0xde, 0xf6, 0x15, 0x3b, | 35 const uint8 kSha2Hash[] = {0xd7, 0x56, 0x36, 0x6d, 0xde, 0xf6, 0x15, 0x3b, |
37 0xf4, 0xe0, 0xb6, 0x29, 0x36, 0x50, 0x5e, 0x26, | 36 0xf4, 0xe0, 0xb6, 0x29, 0x36, 0x50, 0x5e, 0x26, |
38 0xbd, 0x77, 0x8b, 0x8e, 0x35, 0xc2, 0x7e, 0x43, | 37 0xbd, 0x77, 0x8b, 0x8e, 0x35, 0xc2, 0x7e, 0x43, |
39 0x52, 0x47, 0x62, 0xed, 0x12, 0xca, 0xcc, 0x6a}; | 38 0x52, 0x47, 0x62, 0xed, 0x12, 0xca, 0xcc, 0x6a}; |
40 | 39 |
41 // File name of the internal SwiftShader plugin on different platforms. | 40 // File name of the internal SwiftShader plugin on different platforms. |
42 const base::FilePath::CharType kSwiftShaderEglName[] = | 41 const base::FilePath::CharType kSwiftShaderEglName[] = |
43 FILE_PATH_LITERAL("libegl.dll"); | 42 FILE_PATH_LITERAL("libegl.dll"); |
44 const base::FilePath::CharType kSwiftShaderGlesName[] = | 43 const base::FilePath::CharType kSwiftShaderGlesName[] = |
45 FILE_PATH_LITERAL("libglesv2.dll"); | 44 FILE_PATH_LITERAL("libglesv2.dll"); |
46 | 45 |
47 const char kSwiftShaderManifestName[] = "SwiftShader"; | 46 const char kSwiftShaderManifestName[] = "SwiftShader"; |
48 | 47 |
| 48 #if defined(ENABLE_SWIFTSHADER) |
49 const base::FilePath::CharType kSwiftShaderBaseDirectory[] = | 49 const base::FilePath::CharType kSwiftShaderBaseDirectory[] = |
50 FILE_PATH_LITERAL("SwiftShader"); | 50 FILE_PATH_LITERAL("SwiftShader"); |
| 51 #endif // ENABLE_SWIFTSHADER |
51 | 52 |
52 // If we don't have a SwiftShader component, this is the version we claim. | 53 // If we don't have a SwiftShader component, this is the version we claim. |
53 const char kNullVersion[] = "0.0.0.0"; | 54 const char kNullVersion[] = "0.0.0.0"; |
54 | 55 |
55 // The base directory on windows looks like: | |
56 // <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\. | |
57 base::FilePath GetSwiftShaderBaseDirectory() { | |
58 base::FilePath result; | |
59 PathService::Get(chrome::DIR_USER_DATA, &result); | |
60 return result.Append(kSwiftShaderBaseDirectory); | |
61 } | |
62 | |
63 // SwiftShader has version encoded in the path itself | 56 // SwiftShader has version encoded in the path itself |
64 // so we need to enumerate the directories to find the full path. | 57 // so we need to enumerate the directories to find the full path. |
65 // On success it returns something like: | 58 // On success it returns something like: |
66 // <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\10.3.44.555\. | 59 // <profile>\AppData\Local\Google\Chrome\User Data\SwiftShader\10.3.44.555\. |
67 bool GetLatestSwiftShaderDirectory(base::FilePath* result, | 60 // Return true if a SwiftShader directory newer than |latest| was found. |
| 61 // |result| must be initially an empty directory. |
| 62 bool GetLatestSwiftShaderDirectory(const base::FilePath& base_dir, |
| 63 base::FilePath* result, |
68 Version* latest, | 64 Version* latest, |
69 std::vector<base::FilePath>* older_dirs) { | 65 std::vector<base::FilePath>* older_dirs) { |
70 base::FilePath base_dir = GetSwiftShaderBaseDirectory(); | 66 DCHECK(result->empty()); |
71 bool found = false; | 67 bool found = false; |
72 base::FileEnumerator file_enumerator( | 68 base::FileEnumerator file_enumerator( |
73 base_dir, false, base::FileEnumerator::DIRECTORIES); | 69 base_dir, false, base::FileEnumerator::DIRECTORIES); |
74 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 70 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
75 path = file_enumerator.Next()) { | 71 path = file_enumerator.Next()) { |
76 Version version(path.BaseName().MaybeAsASCII()); | 72 Version version(path.BaseName().MaybeAsASCII()); |
77 if (!version.IsValid()) | 73 if (!version.IsValid()) |
78 continue; | 74 continue; |
79 if (version.CompareTo(*latest) > 0 && | 75 if (version.CompareTo(*latest) > 0 && |
80 base::PathExists(path.Append(kSwiftShaderEglName)) && | 76 base::PathExists(path.Append(kSwiftShaderEglName)) && |
81 base::PathExists(path.Append(kSwiftShaderGlesName))) { | 77 base::PathExists(path.Append(kSwiftShaderGlesName))) { |
82 if (found && older_dirs) | 78 if (found && older_dirs && !result->empty()) |
83 older_dirs->push_back(*result); | 79 older_dirs->push_back(*result); |
84 *latest = version; | 80 *latest = version; |
85 *result = path; | 81 *result = path; |
86 found = true; | 82 found = true; |
87 } else { | 83 } else { |
88 if (older_dirs) | 84 if (older_dirs) |
89 older_dirs->push_back(path); | 85 older_dirs->push_back(path); |
90 } | 86 } |
91 } | 87 } |
92 return found; | 88 return found; |
93 } | 89 } |
94 | 90 |
95 void RegisterSwiftShaderWithChrome(const base::FilePath& path) { | 91 void RegisterSwiftShaderWithChrome(const base::FilePath& path) { |
96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
97 GpuDataManager::GetInstance()->RegisterSwiftShaderPath(path); | 93 GpuDataManager::GetInstance()->RegisterSwiftShaderPath(path); |
98 } | 94 } |
99 | 95 |
100 class SwiftShaderComponentInstaller : public ComponentInstaller { | 96 class SwiftShaderComponentInstaller : public ComponentInstaller { |
101 public: | 97 public: |
102 explicit SwiftShaderComponentInstaller(const Version& version); | 98 explicit SwiftShaderComponentInstaller(const base::FilePath& base_dir, |
| 99 const Version& version); |
103 | 100 |
104 virtual ~SwiftShaderComponentInstaller() {} | 101 virtual ~SwiftShaderComponentInstaller() {} |
105 | 102 |
106 virtual void OnUpdateError(int error) OVERRIDE; | 103 virtual void OnUpdateError(int error) OVERRIDE; |
107 | 104 |
108 virtual bool Install(const base::DictionaryValue& manifest, | 105 virtual bool Install(const base::DictionaryValue& manifest, |
109 const base::FilePath& unpack_path) OVERRIDE; | 106 const base::FilePath& unpack_path) OVERRIDE; |
110 | 107 |
111 virtual bool GetInstalledFile(const std::string& file, | 108 virtual bool GetInstalledFile(const std::string& file, |
112 base::FilePath* installed_file) OVERRIDE; | 109 base::FilePath* installed_file) OVERRIDE; |
113 | 110 |
114 private: | 111 private: |
| 112 const base::FilePath base_dir_; |
115 Version current_version_; | 113 Version current_version_; |
116 }; | 114 }; |
117 | 115 |
118 SwiftShaderComponentInstaller::SwiftShaderComponentInstaller( | 116 SwiftShaderComponentInstaller::SwiftShaderComponentInstaller( |
| 117 const base::FilePath& base_dir, |
119 const Version& version) | 118 const Version& version) |
120 : current_version_(version) { | 119 : base_dir_(base_dir), current_version_(version) { |
121 DCHECK(version.IsValid()); | 120 DCHECK(version.IsValid()); |
122 } | 121 } |
123 | 122 |
124 void SwiftShaderComponentInstaller::OnUpdateError(int error) { | 123 void SwiftShaderComponentInstaller::OnUpdateError(int error) { |
125 NOTREACHED() << "SwiftShader update error: " << error; | 124 NOTREACHED() << "SwiftShader update error: " << error; |
126 } | 125 } |
127 | 126 |
128 bool SwiftShaderComponentInstaller::Install( | 127 bool SwiftShaderComponentInstaller::Install( |
129 const base::DictionaryValue& manifest, | 128 const base::DictionaryValue& manifest, |
130 const base::FilePath& unpack_path) { | 129 const base::FilePath& unpack_path) { |
131 std::string name; | 130 std::string name; |
132 manifest.GetStringASCII("name", &name); | 131 manifest.GetStringASCII("name", &name); |
133 if (name != kSwiftShaderManifestName) | 132 if (name != kSwiftShaderManifestName) |
134 return false; | 133 return false; |
135 std::string proposed_version; | 134 std::string proposed_version; |
136 manifest.GetStringASCII("version", &proposed_version); | 135 manifest.GetStringASCII("version", &proposed_version); |
137 Version version(proposed_version.c_str()); | 136 Version version(proposed_version.c_str()); |
138 if (!version.IsValid()) | 137 if (!version.IsValid()) |
139 return false; | 138 return false; |
140 if (current_version_.CompareTo(version) >= 0) | 139 if (current_version_.CompareTo(version) >= 0) |
141 return false; | 140 return false; |
142 if (!base::PathExists(unpack_path.Append(kSwiftShaderEglName)) || | 141 if (!base::PathExists(unpack_path.Append(kSwiftShaderEglName)) || |
143 !base::PathExists(unpack_path.Append(kSwiftShaderGlesName))) | 142 !base::PathExists(unpack_path.Append(kSwiftShaderGlesName))) |
144 return false; | 143 return false; |
145 // Passed the basic tests. Time to install it. | 144 // Passed the basic tests. Time to install it. |
146 base::FilePath path = | 145 base::FilePath path = base_dir_.AppendASCII(version.GetString()); |
147 GetSwiftShaderBaseDirectory().AppendASCII(version.GetString()); | |
148 if (base::PathExists(path)) | 146 if (base::PathExists(path)) |
149 return false; | 147 return false; |
150 if (!base::Move(unpack_path, path)) | 148 if (!base::Move(unpack_path, path)) |
151 return false; | 149 return false; |
152 // Installation is done. Now tell the rest of chrome. | 150 // Installation is done. Now tell the rest of chrome. |
153 current_version_ = version; | 151 current_version_ = version; |
154 BrowserThread::PostTask(BrowserThread::UI, | 152 BrowserThread::PostTask(BrowserThread::UI, |
155 FROM_HERE, | 153 FROM_HERE, |
156 base::Bind(&RegisterSwiftShaderWithChrome, path)); | 154 base::Bind(&RegisterSwiftShaderWithChrome, path)); |
157 return true; | 155 return true; |
158 } | 156 } |
159 | 157 |
160 bool SwiftShaderComponentInstaller::GetInstalledFile( | 158 bool SwiftShaderComponentInstaller::GetInstalledFile( |
161 const std::string& file, | 159 const std::string& file, |
162 base::FilePath* installed_file) { | 160 base::FilePath* installed_file) { |
163 return false; | 161 return false; |
164 } | 162 } |
165 | 163 |
166 void FinishSwiftShaderUpdateRegistration(ComponentUpdateService* cus, | 164 void FinishSwiftShaderUpdateRegistration(const base::FilePath& base_dir, |
| 165 ComponentUpdateService* cus, |
167 const Version& version) { | 166 const Version& version) { |
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
169 | 168 |
170 CrxComponent swiftshader; | 169 CrxComponent swiftshader; |
171 swiftshader.name = "Swift Shader"; | 170 swiftshader.name = "Swift Shader"; |
172 swiftshader.installer = new SwiftShaderComponentInstaller(version); | 171 swiftshader.installer = new SwiftShaderComponentInstaller(base_dir, version); |
173 swiftshader.version = version; | 172 swiftshader.version = version; |
174 swiftshader.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); | 173 swiftshader.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); |
175 if (cus->RegisterComponent(swiftshader) != ComponentUpdateService::kOk) { | 174 if (cus->RegisterComponent(swiftshader) != ComponentUpdateService::kOk) { |
176 NOTREACHED() << "SwiftShader component registration fail"; | 175 NOTREACHED() << "SwiftShader component registration fail"; |
177 } | 176 } |
178 } | 177 } |
179 | 178 |
180 class UpdateChecker : public content::GpuDataManagerObserver { | 179 class UpdateChecker : public content::GpuDataManagerObserver { |
181 public: | 180 public: |
182 explicit UpdateChecker(ComponentUpdateService* cus); | 181 explicit UpdateChecker(ComponentUpdateService* cus, |
| 182 const base::FilePath& base_dir); |
183 | 183 |
184 virtual void OnGpuInfoUpdate() OVERRIDE; | 184 virtual void OnGpuInfoUpdate() OVERRIDE; |
185 | 185 |
186 private: | 186 private: |
187 ComponentUpdateService* cus_; | 187 ComponentUpdateService* cus_; |
| 188 const base::FilePath base_dir_; |
188 }; | 189 }; |
189 | 190 |
190 UpdateChecker::UpdateChecker(ComponentUpdateService* cus) : cus_(cus) { | 191 UpdateChecker::UpdateChecker(ComponentUpdateService* cus, |
| 192 const base::FilePath& base_dir) |
| 193 : cus_(cus), base_dir_(base_dir) { |
191 } | 194 } |
192 | 195 |
193 void UpdateChecker::OnGpuInfoUpdate() { | 196 void UpdateChecker::OnGpuInfoUpdate() { |
194 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); | 197 GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); |
195 | 198 |
196 if (!gpu_data_manager->GpuAccessAllowed(NULL) || | 199 if (!gpu_data_manager->GpuAccessAllowed(NULL) || |
197 gpu_data_manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) || | 200 gpu_data_manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) || |
198 gpu_data_manager->ShouldUseSwiftShader()) { | 201 gpu_data_manager->ShouldUseSwiftShader()) { |
199 gpu_data_manager->RemoveObserver(this); | 202 gpu_data_manager->RemoveObserver(this); |
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
201 base::FilePath path = GetSwiftShaderBaseDirectory(); | |
202 | 204 |
| 205 base::FilePath latest_dir; |
203 Version version(kNullVersion); | 206 Version version(kNullVersion); |
204 GetLatestSwiftShaderDirectory(&path, &version, NULL); | 207 GetLatestSwiftShaderDirectory(base_dir_, &latest_dir, &version, NULL); |
205 | 208 |
206 BrowserThread::PostTask( | 209 BrowserThread::PostTask( |
207 BrowserThread::UI, | 210 BrowserThread::UI, |
208 FROM_HERE, | 211 FROM_HERE, |
209 base::Bind(&FinishSwiftShaderUpdateRegistration, cus_, version)); | 212 base::Bind( |
| 213 &FinishSwiftShaderUpdateRegistration, base_dir_, cus_, version)); |
210 } | 214 } |
211 } | 215 } |
212 | 216 |
213 #if defined(ENABLE_SWIFTSHADER) | 217 #if defined(ENABLE_SWIFTSHADER) |
214 | 218 |
215 // Check if there already is a version of swiftshader installed, | 219 // Check if there already is a version of swiftshader installed, |
216 // and if so register it. | 220 // and if so register it. |
217 void RegisterSwiftShaderPath(ComponentUpdateService* cus) { | 221 void RegisterSwiftShaderPath(ComponentUpdateService* cus, |
| 222 const base::FilePath& user_data_dir) { |
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
219 base::FilePath path = GetSwiftShaderBaseDirectory(); | 224 base::FilePath base_dir = user_data_dir.Append(kSwiftShaderBaseDirectory); |
220 if (!base::PathExists(path)) { | 225 if (!base::PathExists(base_dir)) { |
221 if (!base::CreateDirectory(path)) { | 226 if (!base::CreateDirectory(base_dir)) { |
222 NOTREACHED() << "Could not create SwiftShader directory."; | 227 NOTREACHED() << "Could not create SwiftShader directory."; |
223 return; | 228 return; |
224 } | 229 } |
225 } | 230 } |
226 | 231 |
| 232 base::FilePath latest_dir; |
227 Version version(kNullVersion); | 233 Version version(kNullVersion); |
228 std::vector<base::FilePath> older_dirs; | 234 std::vector<base::FilePath> older_dirs; |
229 if (GetLatestSwiftShaderDirectory(&path, &version, &older_dirs)) | 235 if (GetLatestSwiftShaderDirectory(&latest_dir, &version, &older_dirs)) |
230 BrowserThread::PostTask(BrowserThread::UI, | 236 BrowserThread::PostTask( |
231 FROM_HERE, | 237 BrowserThread::UI, |
232 base::Bind(&RegisterSwiftShaderWithChrome, path)); | 238 FROM_HERE, |
| 239 base::Bind(&RegisterSwiftShaderWithChrome, latest_dir)); |
233 | 240 |
234 UpdateChecker* update_checker = new UpdateChecker(cus); | 241 UpdateChecker* update_checker = new UpdateChecker(cus, base_dir); |
235 GpuDataManager::GetInstance()->AddObserver(update_checker); | 242 GpuDataManager::GetInstance()->AddObserver(update_checker); |
236 update_checker->OnGpuInfoUpdate(); | 243 update_checker->OnGpuInfoUpdate(); |
237 // We leak update_checker here, because it has to stick around for the life | 244 // We leak update_checker here, because it has to stick around for the life |
238 // of the GpuDataManager. | 245 // of the GpuDataManager. |
239 | 246 |
240 // Remove older versions of SwiftShader. | 247 // Remove older versions of SwiftShader. |
241 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); | 248 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); |
242 iter != older_dirs.end(); | 249 iter != older_dirs.end(); |
243 ++iter) { | 250 ++iter) { |
244 base::DeleteFile(*iter, true); | 251 base::DeleteFile(*iter, true); |
245 } | 252 } |
246 } | 253 } |
247 | 254 |
248 #endif // ENABLE_SWIFTSHADER | 255 #endif // ENABLE_SWIFTSHADER |
249 | 256 |
250 } // namespace | 257 } // namespace |
251 | 258 |
252 void RegisterSwiftShaderComponent(ComponentUpdateService* cus) { | 259 void RegisterSwiftShaderComponent(ComponentUpdateService* cus, |
| 260 const base::FilePath& user_data_dir) { |
253 #if defined(ENABLE_SWIFTSHADER) | 261 #if defined(ENABLE_SWIFTSHADER) |
254 base::CPU cpu; | 262 base::CPU cpu; |
255 | 263 |
256 if (!cpu.has_sse2()) | 264 if (!cpu.has_sse2()) |
257 return; | 265 return; |
258 BrowserThread::PostTask(BrowserThread::FILE, | 266 BrowserThread::PostTask(BrowserThread::FILE, |
259 FROM_HERE, | 267 FROM_HERE, |
260 base::Bind(&RegisterSwiftShaderPath, cus)); | 268 base::Bind(&RegisterSwiftShaderPath, cus)); |
261 #endif | 269 #endif |
262 } | 270 } |
263 | 271 |
264 } // namespace component_updater | 272 } // namespace component_updater |
OLD | NEW |