OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/flash_component_installer.h" | 5 #include "chrome/browser/component_updater/flash_component_installer.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 | 84 |
85 // The base directory on Windows looks like: | 85 // The base directory on Windows looks like: |
86 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. | 86 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. |
87 base::FilePath GetPepperFlashBaseDirectory() { | 87 base::FilePath GetPepperFlashBaseDirectory() { |
88 base::FilePath result; | 88 base::FilePath result; |
89 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); | 89 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); |
90 return result; | 90 return result; |
91 } | 91 } |
92 | 92 |
93 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 93 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
| 94 // Install directory for pepper flash debugger dlls will be like |
| 95 // c:\windows\system32\macromed\flash\, or basically the Macromed\Flash |
| 96 // subdirectory of the Windows system directory. |
| 97 base::FilePath GetPepperFlashDebuggerDirectory() { |
| 98 base::FilePath result; |
| 99 PathService::Get(chrome::DIR_PEPPER_FLASH_DEBUGGER_PLUGIN, &result); |
| 100 return result; |
| 101 } |
| 102 |
94 // Pepper Flash plugins have the version encoded in the path itself | 103 // Pepper Flash plugins have the version encoded in the path itself |
95 // so we need to enumerate the directories to find the full path. | 104 // so we need to enumerate the directories to find the full path. |
96 // On success, |latest_dir| returns something like: | 105 // On success, |latest_dir| returns something like: |
97 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. | 106 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. |
98 // |latest_version| returns the corresponding version number. |older_dirs| | 107 // |latest_version| returns the corresponding version number. |older_dirs| |
99 // returns directories of all older versions. | 108 // returns directories of all older versions. |
100 bool GetPepperFlashDirectory(base::FilePath* latest_dir, | 109 bool GetPepperFlashDirectory(base::FilePath* latest_dir, |
101 Version* latest_version, | 110 Version* latest_version, |
102 std::vector<base::FilePath>* older_dirs) { | 111 std::vector<base::FilePath>* older_dirs) { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
103 base::FilePath base_dir = GetPepperFlashBaseDirectory(); | 113 base::FilePath base_dir = GetPepperFlashBaseDirectory(); |
104 bool found = false; | 114 bool found = false; |
105 base::FileEnumerator | 115 base::FileEnumerator |
106 file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); | 116 file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); |
107 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 117 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
108 path = file_enumerator.Next()) { | 118 path = file_enumerator.Next()) { |
109 Version version(path.BaseName().MaybeAsASCII()); | 119 Version version(path.BaseName().MaybeAsASCII()); |
110 if (!version.IsValid()) | 120 if (!version.IsValid()) |
111 continue; | 121 continue; |
112 if (found) { | 122 if (found) { |
113 if (version.CompareTo(*latest_version) > 0) { | 123 if (version.CompareTo(*latest_version) > 0) { |
114 older_dirs->push_back(*latest_dir); | 124 older_dirs->push_back(*latest_dir); |
115 *latest_dir = path; | 125 *latest_dir = path; |
116 *latest_version = version; | 126 *latest_version = version; |
117 } else { | 127 } else { |
118 older_dirs->push_back(path); | 128 older_dirs->push_back(path); |
119 } | 129 } |
120 } else { | 130 } else { |
121 *latest_dir = path; | 131 *latest_dir = path; |
122 *latest_version = version; | 132 *latest_version = version; |
123 found = true; | 133 found = true; |
124 } | 134 } |
125 } | 135 } |
126 return found; | 136 return found; |
127 } | 137 } |
| 138 |
| 139 #if defined(OS_WIN) |
| 140 const wchar_t kPepperFlashDebuggerDLLSearchString[] = |
| 141 #if defined(ARCH_CPU_X86) |
| 142 L"pepflashplayer32*.dll"; |
| 143 #elif defined(ARCH_CPU_X86_64) |
| 144 L"pepflashplayer64*.dll"; |
| 145 #else |
| 146 #error Unsupported Windows CPU architecture. |
| 147 #endif // defined(ARCH_CPU_X86) |
| 148 #endif // defined(OS_WIN) |
| 149 |
| 150 bool GetPepperFlashDebuggerPath(base::FilePath* dll_path, |
| 151 Version* dll_version) { |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 153 base::FilePath debugger_dir = GetPepperFlashDebuggerDirectory(); |
| 154 // If path doesn't exist they simply don't have the flash debugger installed. |
| 155 if (!base::PathExists(debugger_dir)) |
| 156 return false; |
| 157 |
| 158 bool found = false; |
| 159 #if defined(OS_WIN) |
| 160 // Enumerate any DLLs that match the appropriate pattern for this DLL, and |
| 161 // pick the highest version number we find. |
| 162 base::FileEnumerator file_enumerator(debugger_dir, |
| 163 false, |
| 164 base::FileEnumerator::FILES, |
| 165 kPepperFlashDebuggerDLLSearchString); |
| 166 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 167 path = file_enumerator.Next()) { |
| 168 // Version number is embedded in file name like basename_x_y_z.dll. Extract. |
| 169 std::string file_name(path.BaseName().RemoveExtension().MaybeAsASCII()); |
| 170 // file_name should now be basename_x_y_z. Split along '_' for version. |
| 171 std::vector<std::string> components; |
| 172 base::SplitString(file_name, '_', &components); |
| 173 // Should have at least one version number. |
| 174 if (components.size() <= 1) |
| 175 continue; |
| 176 // Meld version components back into a string, now separated by periods, so |
| 177 // Version can parse it. |
| 178 std::string version_string(components[1]); |
| 179 for (size_t i = 2; i < components.size(); ++i) { |
| 180 version_string += "." + components[i]; |
| 181 } |
| 182 Version version(version_string); |
| 183 if (!version.IsValid()) |
| 184 continue; |
| 185 if (found) { |
| 186 if (version.CompareTo(*dll_version) > 0) { |
| 187 *dll_path = path; |
| 188 *dll_version = version; |
| 189 } |
| 190 } else { |
| 191 *dll_path = path; |
| 192 *dll_version = version; |
| 193 found = true; |
| 194 } |
| 195 } |
128 #endif | 196 #endif |
| 197 return found; |
| 198 } |
| 199 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
129 | 200 |
130 // Returns true if the Pepper |interface_name| is implemented by this browser. | 201 // Returns true if the Pepper |interface_name| is implemented by this browser. |
131 // It does not check if the interface is proxied. | 202 // It does not check if the interface is proxied. |
132 bool SupportsPepperInterface(const char* interface_name) { | 203 bool SupportsPepperInterface(const char* interface_name) { |
133 if (IsSupportedPepperInterface(interface_name)) | 204 if (IsSupportedPepperInterface(interface_name)) |
134 return true; | 205 return true; |
135 // The PDF interface is invisible to SupportsInterface() on the browser | 206 // The PDF interface is invisible to SupportsInterface() on the browser |
136 // process because it is provided using PpapiInterfaceFactoryManager. We need | 207 // process because it is provided using PpapiInterfaceFactoryManager. We need |
137 // to check for that as well. | 208 // to check for that as well. |
138 // TODO(cpu): make this more sane. | 209 // TODO(cpu): make this more sane. |
139 return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0); | 210 return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0); |
140 } | 211 } |
141 | 212 |
142 bool MakePepperFlashPluginInfo(const base::FilePath& flash_path, | 213 bool MakePepperFlashPluginInfo(const base::FilePath& flash_path, |
143 const Version& flash_version, | 214 const Version& flash_version, |
144 bool out_of_process, | 215 bool out_of_process, |
| 216 bool is_debugger, |
145 content::PepperPluginInfo* plugin_info) { | 217 content::PepperPluginInfo* plugin_info) { |
146 if (!flash_version.IsValid()) | 218 if (!flash_version.IsValid()) |
147 return false; | 219 return false; |
148 const std::vector<uint16> ver_nums = flash_version.components(); | 220 const std::vector<uint16> ver_nums = flash_version.components(); |
149 if (ver_nums.size() < 3) | 221 if (ver_nums.size() < 3) |
150 return false; | 222 return false; |
151 | 223 |
152 plugin_info->is_internal = false; | 224 plugin_info->is_internal = false; |
153 plugin_info->is_out_of_process = out_of_process; | 225 plugin_info->is_out_of_process = out_of_process; |
154 plugin_info->path = flash_path; | 226 plugin_info->path = flash_path; |
155 plugin_info->name = content::kFlashPluginName; | 227 plugin_info->name = content::kFlashPluginName; |
156 plugin_info->permissions = kPepperFlashPermissions; | 228 plugin_info->permissions = kPepperFlashPermissions; |
157 | 229 |
158 // The description is like "Shockwave Flash 10.2 r154". | 230 // The description is like "Shockwave Flash 10.2 r154". |
159 plugin_info->description = base::StringPrintf("%s %d.%d r%d", | 231 plugin_info->description = base::StringPrintf("%s %d.%d r%d", |
160 content::kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]); | 232 content::kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]); |
| 233 if (is_debugger) { |
| 234 plugin_info->description += " Debug"; |
| 235 } |
161 | 236 |
162 plugin_info->version = flash_version.GetString(); | 237 plugin_info->version = flash_version.GetString(); |
163 | 238 |
164 content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, | 239 content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, |
165 content::kFlashPluginSwfExtension, | 240 content::kFlashPluginSwfExtension, |
166 content::kFlashPluginName); | 241 content::kFlashPluginName); |
167 plugin_info->mime_types.push_back(swf_mime_type); | 242 plugin_info->mime_types.push_back(swf_mime_type); |
168 content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType, | 243 content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType, |
169 content::kFlashPluginSplExtension, | 244 content::kFlashPluginSplExtension, |
170 content::kFlashPluginName); | 245 content::kFlashPluginName); |
171 plugin_info->mime_types.push_back(spl_mime_type); | 246 plugin_info->mime_types.push_back(spl_mime_type); |
172 return true; | 247 return true; |
173 } | 248 } |
174 | 249 |
175 bool IsPepperFlash(const content::WebPluginInfo& plugin) { | 250 bool IsPepperFlash(const content::WebPluginInfo& plugin) { |
176 // We try to recognize Pepper Flash by the following criteria: | 251 // We try to recognize Pepper Flash by the following criteria: |
177 // * It is a Pepper plug-in. | 252 // * It is a Pepper plug-in. |
178 // * It has the special Flash permissions. | 253 // * It has the special Flash permissions. |
179 return plugin.is_pepper_plugin() && | 254 return plugin.is_pepper_plugin() && |
180 (plugin.pepper_permissions & ppapi::PERMISSION_FLASH); | 255 (plugin.pepper_permissions & ppapi::PERMISSION_FLASH); |
181 } | 256 } |
182 | 257 |
183 void RegisterPepperFlashWithChrome(const base::FilePath& path, | 258 void RegisterPepperFlashWithChrome(const base::FilePath& path, |
184 const Version& version) { | 259 const Version& version, |
| 260 bool is_debugger) { |
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
186 content::PepperPluginInfo plugin_info; | 262 content::PepperPluginInfo plugin_info; |
187 if (!MakePepperFlashPluginInfo(path, version, true, &plugin_info)) | 263 if (!MakePepperFlashPluginInfo( |
| 264 path, version, true, is_debugger, &plugin_info)) |
188 return; | 265 return; |
189 | 266 |
190 std::vector<content::WebPluginInfo> plugins; | 267 // If this is the non-debugger version, we enumerate any installed versions of |
191 PluginService::GetInstance()->GetInternalPlugins(&plugins); | 268 // pepper flash to make sure we only replace the installed version with a |
192 for (std::vector<content::WebPluginInfo>::const_iterator it = plugins.begin(); | 269 // newer version. |
193 it != plugins.end(); ++it) { | 270 if (!is_debugger) { |
194 if (!IsPepperFlash(*it)) | 271 std::vector<content::WebPluginInfo> plugins; |
195 continue; | 272 PluginService::GetInstance()->GetInternalPlugins(&plugins); |
| 273 for (std::vector<content::WebPluginInfo>::const_iterator it = |
| 274 plugins.begin(); |
| 275 it != plugins.end(); |
| 276 ++it) { |
| 277 if (!IsPepperFlash(*it)) |
| 278 continue; |
196 | 279 |
197 // Do it only if the version we're trying to register is newer. | 280 // Do it only if the version we're trying to register is newer. |
198 Version registered_version(base::UTF16ToUTF8(it->version)); | 281 Version registered_version(base::UTF16ToUTF8(it->version)); |
199 if (registered_version.IsValid() && | 282 if (registered_version.IsValid() && |
200 version.CompareTo(registered_version) <= 0) { | 283 version.CompareTo(registered_version) <= 0) { |
201 return; | 284 return; |
| 285 } |
| 286 |
| 287 // If the version is newer, remove the old one first. |
| 288 PluginService::GetInstance()->UnregisterInternalPlugin(it->path); |
| 289 break; |
202 } | 290 } |
203 | |
204 // If the version is newer, remove the old one first. | |
205 PluginService::GetInstance()->UnregisterInternalPlugin(it->path); | |
206 break; | |
207 } | 291 } |
208 | 292 |
| 293 // We only ask for registration at the beginning for the non-debugger plugin, |
| 294 // that way the debugger plugin doesn't automatically clobber the built-in or |
| 295 // updated non-debugger version. |
209 PluginService::GetInstance()->RegisterInternalPlugin( | 296 PluginService::GetInstance()->RegisterInternalPlugin( |
210 plugin_info.ToWebPluginInfo(), true); | 297 plugin_info.ToWebPluginInfo(), !is_debugger); |
211 PluginService::GetInstance()->RefreshPlugins(); | 298 PluginService::GetInstance()->RefreshPlugins(); |
212 } | 299 } |
213 | 300 |
214 // Returns true if this browser implements one of the interfaces given in | 301 // Returns true if this browser implements one of the interfaces given in |
215 // |interface_string|, which is a '|'-separated string of interface names. | 302 // |interface_string|, which is a '|'-separated string of interface names. |
216 bool CheckPepperFlashInterfaceString(const std::string& interface_string) { | 303 bool CheckPepperFlashInterfaceString(const std::string& interface_string) { |
217 std::vector<std::string> interface_names; | 304 std::vector<std::string> interface_names; |
218 base::SplitString(interface_string, '|', &interface_names); | 305 base::SplitString(interface_string, '|', &interface_names); |
219 for (size_t i = 0; i < interface_names.size(); i++) { | 306 for (size_t i = 0; i < interface_names.size(); i++) { |
220 if (SupportsPepperInterface(interface_names[i].c_str())) | 307 if (SupportsPepperInterface(interface_names[i].c_str())) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 if (base::PathExists(path)) | 376 if (base::PathExists(path)) |
290 return false; | 377 return false; |
291 if (!base::Move(unpack_path, path)) | 378 if (!base::Move(unpack_path, path)) |
292 return false; | 379 return false; |
293 // Installation is done. Now tell the rest of chrome. Both the path service | 380 // Installation is done. Now tell the rest of chrome. Both the path service |
294 // and to the plugin service. | 381 // and to the plugin service. |
295 current_version_ = version; | 382 current_version_ = version; |
296 PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); | 383 PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); |
297 path = path.Append(chrome::kPepperFlashPluginFilename); | 384 path = path.Append(chrome::kPepperFlashPluginFilename); |
298 BrowserThread::PostTask( | 385 BrowserThread::PostTask( |
299 BrowserThread::UI, FROM_HERE, | 386 BrowserThread::UI, |
300 base::Bind(&RegisterPepperFlashWithChrome, path, version)); | 387 FROM_HERE, |
| 388 base::Bind(&RegisterPepperFlashWithChrome, path, version, false)); |
301 return true; | 389 return true; |
302 } | 390 } |
303 | 391 |
304 bool PepperFlashComponentInstaller::GetInstalledFile( | 392 bool PepperFlashComponentInstaller::GetInstalledFile( |
305 const std::string& file, base::FilePath* installed_file) { | 393 const std::string& file, base::FilePath* installed_file) { |
306 return false; | 394 return false; |
307 } | 395 } |
308 | 396 |
309 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, | 397 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, |
310 Version* version_out) { | 398 Version* version_out) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 return; | 458 return; |
371 } | 459 } |
372 } | 460 } |
373 | 461 |
374 Version version(kNullVersion); | 462 Version version(kNullVersion); |
375 std::vector<base::FilePath> older_dirs; | 463 std::vector<base::FilePath> older_dirs; |
376 if (GetPepperFlashDirectory(&path, &version, &older_dirs)) { | 464 if (GetPepperFlashDirectory(&path, &version, &older_dirs)) { |
377 path = path.Append(chrome::kPepperFlashPluginFilename); | 465 path = path.Append(chrome::kPepperFlashPluginFilename); |
378 if (base::PathExists(path)) { | 466 if (base::PathExists(path)) { |
379 BrowserThread::PostTask( | 467 BrowserThread::PostTask( |
380 BrowserThread::UI, FROM_HERE, | 468 BrowserThread::UI, |
381 base::Bind(&RegisterPepperFlashWithChrome, path, version)); | 469 FROM_HERE, |
| 470 base::Bind(&RegisterPepperFlashWithChrome, path, version, false)); |
382 } else { | 471 } else { |
383 version = Version(kNullVersion); | 472 version = Version(kNullVersion); |
384 } | 473 } |
385 } | 474 } |
386 | 475 |
387 BrowserThread::PostTask( | 476 BrowserThread::PostTask( |
388 BrowserThread::UI, FROM_HERE, | 477 BrowserThread::UI, FROM_HERE, |
389 base::Bind(&FinishPepperFlashUpdateRegistration, cus, version)); | 478 base::Bind(&FinishPepperFlashUpdateRegistration, cus, version)); |
390 | 479 |
391 // Remove older versions of Pepper Flash. | 480 // Remove older versions of Pepper Flash. |
392 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); | 481 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); |
393 iter != older_dirs.end(); ++iter) { | 482 iter != older_dirs.end(); ++iter) { |
394 base::DeleteFile(*iter, true); | 483 base::DeleteFile(*iter, true); |
395 } | 484 } |
| 485 |
| 486 // Check for Debugging version of Flash and register if present. |
| 487 base::FilePath debugger_path; |
| 488 Version debugger_version(kNullVersion); |
| 489 if (GetPepperFlashDebuggerPath(&debugger_path, &debugger_version)) { |
| 490 BrowserThread::PostTask(BrowserThread::UI, |
| 491 FROM_HERE, |
| 492 base::Bind(&RegisterPepperFlashWithChrome, |
| 493 debugger_path, |
| 494 debugger_version, |
| 495 true)); |
| 496 } |
396 } | 497 } |
397 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 498 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
398 | 499 |
399 } // namespace | 500 } // namespace |
400 | 501 |
401 void RegisterPepperFlashComponent(ComponentUpdateService* cus) { | 502 void RegisterPepperFlashComponent(ComponentUpdateService* cus) { |
402 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 503 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
403 // Component updated flash supersedes bundled flash therefore if that one | 504 // Component updated flash supersedes bundled flash therefore if that one |
404 // is disabled then this one should never install. | 505 // is disabled then this one should never install. |
405 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | 506 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
406 if (cmd_line->HasSwitch(switches::kDisableBundledPpapiFlash)) | 507 if (cmd_line->HasSwitch(switches::kDisableBundledPpapiFlash)) |
407 return; | 508 return; |
408 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 509 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
409 base::Bind(&StartPepperFlashUpdateRegistration, cus)); | 510 base::Bind(&StartPepperFlashUpdateRegistration, cus)); |
410 #endif | 511 #endif |
411 } | 512 } |
412 | 513 |
413 } // namespace component_updater | 514 } // namespace component_updater |
414 | 515 |
OLD | NEW |