| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // 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/plugin_service.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/path_service.h" | |
| 11 #include "base/string_util.h" | |
| 12 #include "base/threading/thread.h" | |
| 13 #include "base/utf_string_conversions.h" | |
| 14 #include "base/values.h" | |
| 15 #include "base/synchronization/waitable_event.h" | |
| 16 #include "chrome/browser/browser_process.h" | |
| 17 #include "chrome/browser/browser_thread.h" | |
| 18 #include "chrome/browser/chrome_plugin_host.h" | |
| 19 #include "chrome/browser/extensions/extension_service.h" | |
| 20 #include "chrome/browser/plugin_updater.h" | |
| 21 #include "chrome/browser/ppapi_plugin_process_host.h" | |
| 22 #include "chrome/browser/profiles/profile.h" | |
| 23 #include "chrome/browser/renderer_host/render_process_host.h" | |
| 24 #include "chrome/browser/renderer_host/render_view_host.h" | |
| 25 #include "chrome/common/chrome_plugin_lib.h" | |
| 26 #include "chrome/common/chrome_paths.h" | |
| 27 #include "chrome/common/chrome_switches.h" | |
| 28 #include "chrome/common/default_plugin.h" | |
| 29 #include "chrome/common/extensions/extension.h" | |
| 30 #include "chrome/common/gpu_plugin.h" | |
| 31 #include "chrome/common/logging_chrome.h" | |
| 32 #include "chrome/common/notification_type.h" | |
| 33 #include "chrome/common/notification_service.h" | |
| 34 #include "chrome/common/pepper_plugin_registry.h" | |
| 35 #include "chrome/common/plugin_messages.h" | |
| 36 #include "chrome/common/render_messages.h" | |
| 37 #include "webkit/plugins/npapi/plugin_constants_win.h" | |
| 38 #include "webkit/plugins/npapi/plugin_list.h" | |
| 39 #include "webkit/plugins/npapi/webplugininfo.h" | |
| 40 | |
| 41 #if defined(OS_CHROMEOS) | |
| 42 #include "chrome/browser/chromeos/plugin_selection_policy.h" | |
| 43 #endif | |
| 44 | |
| 45 #if defined(OS_MACOSX) | |
| 46 static void NotifyPluginsOfActivation() { | |
| 47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 48 | |
| 49 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); | |
| 50 !iter.Done(); ++iter) { | |
| 51 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); | |
| 52 plugin->OnAppActivation(); | |
| 53 } | |
| 54 } | |
| 55 #endif | |
| 56 | |
| 57 static void PurgePluginListCache(bool reload_pages) { | |
| 58 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); | |
| 59 !it.IsAtEnd(); it.Advance()) { | |
| 60 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages)); | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 #if defined(OS_LINUX) | |
| 65 // Delegate class for monitoring directories. | |
| 66 class PluginDirWatcherDelegate : public FilePathWatcher::Delegate { | |
| 67 virtual void OnFilePathChanged(const FilePath& path) { | |
| 68 VLOG(1) << "Watched path changed: " << path.value(); | |
| 69 // Make the plugin list update itself | |
| 70 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | |
| 71 } | |
| 72 virtual void OnError() { | |
| 73 // TODO(pastarmovj): Add some sensible error handling. Maybe silently | |
| 74 // stopping the watcher would be enough. Or possibly restart it. | |
| 75 NOTREACHED(); | |
| 76 } | |
| 77 }; | |
| 78 #endif | |
| 79 | |
| 80 // static | |
| 81 bool PluginService::enable_chrome_plugins_ = true; | |
| 82 | |
| 83 // static | |
| 84 void PluginService::InitGlobalInstance(Profile* profile) { | |
| 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 86 | |
| 87 // We first group the plugins and then figure out which groups to disable. | |
| 88 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile); | |
| 89 | |
| 90 // Have Chrome plugins write their data to the profile directory. | |
| 91 GetInstance()->SetChromePluginDataDir(profile->GetPath()); | |
| 92 } | |
| 93 | |
| 94 // static | |
| 95 PluginService* PluginService::GetInstance() { | |
| 96 return Singleton<PluginService>::get(); | |
| 97 } | |
| 98 | |
| 99 // static | |
| 100 void PluginService::EnableChromePlugins(bool enable) { | |
| 101 enable_chrome_plugins_ = enable; | |
| 102 } | |
| 103 | |
| 104 PluginService::PluginService() | |
| 105 : main_message_loop_(MessageLoop::current()), | |
| 106 resource_dispatcher_host_(NULL), | |
| 107 ui_locale_(g_browser_process->GetApplicationLocale()) { | |
| 108 RegisterPepperPlugins(); | |
| 109 | |
| 110 // Have the NPAPI plugin list search for Chrome plugins as well. | |
| 111 ChromePluginLib::RegisterPluginsWithNPAPI(); | |
| 112 | |
| 113 // Load any specified on the command line as well. | |
| 114 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 115 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin); | |
| 116 if (!path.empty()) | |
| 117 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); | |
| 118 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir); | |
| 119 if (!path.empty()) | |
| 120 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path); | |
| 121 | |
| 122 chrome::RegisterInternalDefaultPlugin(); | |
| 123 | |
| 124 // Register the internal Flash and PDF, if available. | |
| 125 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
| 126 switches::kDisableInternalFlash) && | |
| 127 PathService::Get(chrome::FILE_FLASH_PLUGIN, &path)) { | |
| 128 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); | |
| 129 } | |
| 130 | |
| 131 #if defined(OS_CHROMEOS) | |
| 132 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy; | |
| 133 plugin_selection_policy_->StartInit(); | |
| 134 #endif | |
| 135 | |
| 136 chrome::RegisterInternalGPUPlugin(); | |
| 137 | |
| 138 // Start watching for changes in the plugin list. This means watching | |
| 139 // for changes in the Windows registry keys and on both Windows and POSIX | |
| 140 // watch for changes in the paths that are expected to contain plugins. | |
| 141 #if defined(OS_WIN) | |
| 142 hkcu_key_.Create( | |
| 143 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); | |
| 144 hklm_key_.Create( | |
| 145 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); | |
| 146 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) { | |
| 147 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event())); | |
| 148 hkcu_watcher_.StartWatching(hkcu_event_.get(), this); | |
| 149 } | |
| 150 | |
| 151 if (hklm_key_.StartWatching() == ERROR_SUCCESS) { | |
| 152 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event())); | |
| 153 hklm_watcher_.StartWatching(hklm_event_.get(), this); | |
| 154 } | |
| 155 #elif defined(OS_POSIX) && !defined(OS_MACOSX) | |
| 156 // Also find plugins in a user-specific plugins dir, | |
| 157 // e.g. ~/.config/chromium/Plugins. | |
| 158 FilePath user_data_dir; | |
| 159 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { | |
| 160 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir( | |
| 161 user_data_dir.Append("Plugins")); | |
| 162 } | |
| 163 #endif | |
| 164 // The FilePathWatcher produces too many false positives on MacOS (access time | |
| 165 // updates?) which will lead to enforcing updates of the plugins way too often. | |
| 166 // On ChromeOS the user can't install plugins anyway and on Windows all | |
| 167 // important plugins register themselves in the registry so no need to do that. | |
| 168 #if defined(OS_LINUX) | |
| 169 file_watcher_delegate_ = new PluginDirWatcherDelegate(); | |
| 170 // Get the list of all paths for registering the FilePathWatchers | |
| 171 // that will track and if needed reload the list of plugins on runtime. | |
| 172 std::vector<FilePath> plugin_dirs; | |
| 173 webkit::npapi::PluginList::Singleton()->GetPluginDirectories( | |
| 174 &plugin_dirs); | |
| 175 | |
| 176 for (size_t i = 0; i < plugin_dirs.size(); ++i) { | |
| 177 FilePathWatcher* watcher = new FilePathWatcher(); | |
| 178 // FilePathWatcher can not handle non-absolute paths under windows. | |
| 179 // We don't watch for file changes in windows now but if this should ever | |
| 180 // be extended to Windows these lines might save some time of debugging. | |
| 181 #if defined(OS_WIN) | |
| 182 if (!plugin_dirs[i].IsAbsolute()) | |
| 183 continue; | |
| 184 #endif | |
| 185 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value(); | |
| 186 BrowserThread::PostTask( | |
| 187 BrowserThread::FILE, FROM_HERE, | |
| 188 NewRunnableFunction( | |
| 189 &PluginService::RegisterFilePathWatcher, | |
| 190 watcher, plugin_dirs[i], file_watcher_delegate_)); | |
| 191 file_watchers_.push_back(watcher); | |
| 192 } | |
| 193 #endif | |
| 194 registrar_.Add(this, NotificationType::EXTENSION_LOADED, | |
| 195 NotificationService::AllSources()); | |
| 196 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, | |
| 197 NotificationService::AllSources()); | |
| 198 #if defined(OS_MACOSX) | |
| 199 // We need to know when the browser comes forward so we can bring modal plugin | |
| 200 // windows forward too. | |
| 201 registrar_.Add(this, NotificationType::APP_ACTIVATED, | |
| 202 NotificationService::AllSources()); | |
| 203 #endif | |
| 204 registrar_.Add(this, NotificationType::PLUGIN_ENABLE_STATUS_CHANGED, | |
| 205 NotificationService::AllSources()); | |
| 206 registrar_.Add(this, | |
| 207 NotificationType::RENDERER_PROCESS_CLOSED, | |
| 208 NotificationService::AllSources()); | |
| 209 } | |
| 210 | |
| 211 PluginService::~PluginService() { | |
| 212 #if defined(OS_WIN) | |
| 213 // Release the events since they're owned by RegKey, not WaitableEvent. | |
| 214 hkcu_watcher_.StopWatching(); | |
| 215 hklm_watcher_.StopWatching(); | |
| 216 if (hkcu_event_.get()) | |
| 217 hkcu_event_->Release(); | |
| 218 if (hklm_event_.get()) | |
| 219 hklm_event_->Release(); | |
| 220 #endif | |
| 221 } | |
| 222 | |
| 223 void PluginService::LoadChromePlugins( | |
| 224 ResourceDispatcherHost* resource_dispatcher_host) { | |
| 225 if (!enable_chrome_plugins_) | |
| 226 return; | |
| 227 | |
| 228 resource_dispatcher_host_ = resource_dispatcher_host; | |
| 229 ChromePluginLib::LoadChromePlugins(GetCPBrowserFuncsForBrowser()); | |
| 230 } | |
| 231 | |
| 232 void PluginService::SetChromePluginDataDir(const FilePath& data_dir) { | |
| 233 chrome_plugin_data_dir_ = data_dir; | |
| 234 } | |
| 235 | |
| 236 const FilePath& PluginService::GetChromePluginDataDir() { | |
| 237 return chrome_plugin_data_dir_; | |
| 238 } | |
| 239 | |
| 240 const std::string& PluginService::GetUILocale() { | |
| 241 return ui_locale_; | |
| 242 } | |
| 243 | |
| 244 PluginProcessHost* PluginService::FindNpapiPluginProcess( | |
| 245 const FilePath& plugin_path) { | |
| 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 247 | |
| 248 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); | |
| 249 !iter.Done(); ++iter) { | |
| 250 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); | |
| 251 if (plugin->info().path == plugin_path) | |
| 252 return plugin; | |
| 253 } | |
| 254 | |
| 255 return NULL; | |
| 256 } | |
| 257 | |
| 258 PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess( | |
| 259 const FilePath& plugin_path) { | |
| 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 261 | |
| 262 for (BrowserChildProcessHost::Iterator iter( | |
| 263 ChildProcessInfo::PPAPI_PLUGIN_PROCESS); | |
| 264 !iter.Done(); ++iter) { | |
| 265 PpapiPluginProcessHost* plugin = | |
| 266 static_cast<PpapiPluginProcessHost*>(*iter); | |
| 267 if (plugin->plugin_path() == plugin_path) | |
| 268 return plugin; | |
| 269 } | |
| 270 | |
| 271 return NULL; | |
| 272 } | |
| 273 | |
| 274 PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess( | |
| 275 const FilePath& plugin_path) { | |
| 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 277 | |
| 278 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); | |
| 279 if (plugin_host) | |
| 280 return plugin_host; | |
| 281 | |
| 282 webkit::npapi::WebPluginInfo info; | |
| 283 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( | |
| 284 plugin_path, &info)) { | |
| 285 return NULL; | |
| 286 } | |
| 287 | |
| 288 // This plugin isn't loaded by any plugin process, so create a new process. | |
| 289 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); | |
| 290 if (!new_host->Init(info, ui_locale_)) { | |
| 291 NOTREACHED(); // Init is not expected to fail. | |
| 292 return NULL; | |
| 293 } | |
| 294 return new_host.release(); | |
| 295 } | |
| 296 | |
| 297 PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess( | |
| 298 const FilePath& plugin_path) { | |
| 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 300 | |
| 301 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path); | |
| 302 if (plugin_host) | |
| 303 return plugin_host; | |
| 304 | |
| 305 // Validate that the plugin is actually registered. There should generally | |
| 306 // be very few plugins so a brute-force search is fine. | |
| 307 PepperPluginInfo* info = NULL; | |
| 308 for (size_t i = 0; i < ppapi_plugins_.size(); i++) { | |
| 309 if (ppapi_plugins_[i].path == plugin_path) { | |
| 310 info = &ppapi_plugins_[i]; | |
| 311 break; | |
| 312 } | |
| 313 } | |
| 314 if (!info) | |
| 315 return NULL; | |
| 316 | |
| 317 // This plugin isn't loaded by any plugin process, so create a new process. | |
| 318 scoped_ptr<PpapiPluginProcessHost> new_host(new PpapiPluginProcessHost); | |
| 319 if (!new_host->Init(plugin_path)) { | |
| 320 NOTREACHED(); // Init is not expected to fail. | |
| 321 return NULL; | |
| 322 } | |
| 323 return new_host.release(); | |
| 324 } | |
| 325 | |
| 326 void PluginService::OpenChannelToNpapiPlugin( | |
| 327 int render_process_id, | |
| 328 int render_view_id, | |
| 329 const GURL& url, | |
| 330 const std::string& mime_type, | |
| 331 PluginProcessHost::Client* client) { | |
| 332 // The PluginList::GetFirstAllowedPluginInfo may need to load the | |
| 333 // plugins. Don't do it on the IO thread. | |
| 334 BrowserThread::PostTask( | |
| 335 BrowserThread::FILE, FROM_HERE, | |
| 336 NewRunnableMethod( | |
| 337 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, | |
| 338 render_process_id, render_view_id, url, mime_type, client)); | |
| 339 } | |
| 340 | |
| 341 void PluginService::OpenChannelToPpapiPlugin( | |
| 342 const FilePath& path, | |
| 343 PpapiPluginProcessHost::Client* client) { | |
| 344 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(path); | |
| 345 if (plugin_host) | |
| 346 plugin_host->OpenChannelToPlugin(client); | |
| 347 else // Send error. | |
| 348 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); | |
| 349 } | |
| 350 | |
| 351 void PluginService::GetAllowedPluginForOpenChannelToPlugin( | |
| 352 int render_process_id, | |
| 353 int render_view_id, | |
| 354 const GURL& url, | |
| 355 const std::string& mime_type, | |
| 356 PluginProcessHost::Client* client) { | |
| 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 358 webkit::npapi::WebPluginInfo info; | |
| 359 bool found = GetFirstAllowedPluginInfo( | |
| 360 render_process_id, render_view_id, url, mime_type, &info, NULL); | |
| 361 FilePath plugin_path; | |
| 362 if (found && webkit::npapi::IsPluginEnabled(info)) | |
| 363 plugin_path = FilePath(info.path); | |
| 364 | |
| 365 // Now we jump back to the IO thread to finish opening the channel. | |
| 366 BrowserThread::PostTask( | |
| 367 BrowserThread::IO, FROM_HERE, | |
| 368 NewRunnableMethod( | |
| 369 this, &PluginService::FinishOpenChannelToPlugin, | |
| 370 plugin_path, client)); | |
| 371 } | |
| 372 | |
| 373 void PluginService::FinishOpenChannelToPlugin( | |
| 374 const FilePath& plugin_path, | |
| 375 PluginProcessHost::Client* client) { | |
| 376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 377 | |
| 378 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path); | |
| 379 if (plugin_host) | |
| 380 plugin_host->OpenChannelToPlugin(client); | |
| 381 else | |
| 382 client->OnError(); | |
| 383 } | |
| 384 | |
| 385 bool PluginService::GetFirstAllowedPluginInfo( | |
| 386 int render_process_id, | |
| 387 int render_view_id, | |
| 388 const GURL& url, | |
| 389 const std::string& mime_type, | |
| 390 webkit::npapi::WebPluginInfo* info, | |
| 391 std::string* actual_mime_type) { | |
| 392 // GetPluginInfoArray may need to load the plugins, so we need to be | |
| 393 // on the FILE thread. | |
| 394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 395 bool allow_wildcard = true; | |
| 396 #if defined(OS_CHROMEOS) | |
| 397 std::vector<webkit::npapi::WebPluginInfo> info_array; | |
| 398 std::vector<std::string> actual_mime_types; | |
| 399 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( | |
| 400 url, mime_type, allow_wildcard, &info_array, &actual_mime_types); | |
| 401 | |
| 402 // Now we filter by the plugin selection policy. | |
| 403 int allowed_index = plugin_selection_policy_->FindFirstAllowed(url, | |
| 404 info_array); | |
| 405 if (!info_array.empty() && allowed_index >= 0) { | |
| 406 *info = info_array[allowed_index]; | |
| 407 if (actual_mime_type) | |
| 408 *actual_mime_type = actual_mime_types[allowed_index]; | |
| 409 return true; | |
| 410 } | |
| 411 return false; | |
| 412 #else | |
| 413 { | |
| 414 base::AutoLock auto_lock(overridden_plugins_lock_); | |
| 415 for (size_t i = 0; i < overridden_plugins_.size(); ++i) { | |
| 416 if (overridden_plugins_[i].render_process_id == render_process_id && | |
| 417 overridden_plugins_[i].render_view_id == render_view_id && | |
| 418 overridden_plugins_[i].url == url) { | |
| 419 if (actual_mime_type) | |
| 420 *actual_mime_type = mime_type; | |
| 421 *info = overridden_plugins_[i].plugin; | |
| 422 return true; | |
| 423 } | |
| 424 } | |
| 425 } | |
| 426 return webkit::npapi::PluginList::Singleton()->GetPluginInfo( | |
| 427 url, mime_type, allow_wildcard, info, actual_mime_type); | |
| 428 #endif | |
| 429 } | |
| 430 | |
| 431 void PluginService::OnWaitableEventSignaled( | |
| 432 base::WaitableEvent* waitable_event) { | |
| 433 #if defined(OS_WIN) | |
| 434 if (waitable_event == hkcu_event_.get()) { | |
| 435 hkcu_key_.StartWatching(); | |
| 436 } else { | |
| 437 hklm_key_.StartWatching(); | |
| 438 } | |
| 439 | |
| 440 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | |
| 441 PurgePluginListCache(true); | |
| 442 #else | |
| 443 // This event should only get signaled on a Windows machine. | |
| 444 NOTREACHED(); | |
| 445 #endif // defined(OS_WIN) | |
| 446 } | |
| 447 | |
| 448 static void ForceShutdownPlugin(const FilePath& plugin_path) { | |
| 449 PluginProcessHost* plugin = | |
| 450 PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path); | |
| 451 if (plugin) | |
| 452 plugin->ForceShutdown(); | |
| 453 } | |
| 454 | |
| 455 void PluginService::Observe(NotificationType type, | |
| 456 const NotificationSource& source, | |
| 457 const NotificationDetails& details) { | |
| 458 switch (type.value) { | |
| 459 case NotificationType::EXTENSION_LOADED: { | |
| 460 const Extension* extension = Details<const Extension>(details).ptr(); | |
| 461 bool plugins_changed = false; | |
| 462 for (size_t i = 0; i < extension->plugins().size(); ++i) { | |
| 463 const Extension::PluginInfo& plugin = extension->plugins()[i]; | |
| 464 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | |
| 465 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(plugin.path); | |
| 466 plugins_changed = true; | |
| 467 if (!plugin.is_public) | |
| 468 private_plugins_[plugin.path] = extension->url(); | |
| 469 } | |
| 470 if (plugins_changed) | |
| 471 PurgePluginListCache(false); | |
| 472 break; | |
| 473 } | |
| 474 | |
| 475 case NotificationType::EXTENSION_UNLOADED: { | |
| 476 const Extension* extension = | |
| 477 Details<UnloadedExtensionInfo>(details)->extension; | |
| 478 bool plugins_changed = false; | |
| 479 for (size_t i = 0; i < extension->plugins().size(); ++i) { | |
| 480 const Extension::PluginInfo& plugin = extension->plugins()[i]; | |
| 481 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 482 NewRunnableFunction(&ForceShutdownPlugin, | |
| 483 plugin.path)); | |
| 484 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | |
| 485 webkit::npapi::PluginList::Singleton()->RemoveExtraPluginPath( | |
| 486 plugin.path); | |
| 487 plugins_changed = true; | |
| 488 if (!plugin.is_public) | |
| 489 private_plugins_.erase(plugin.path); | |
| 490 } | |
| 491 if (plugins_changed) | |
| 492 PurgePluginListCache(false); | |
| 493 break; | |
| 494 } | |
| 495 | |
| 496 #if defined(OS_MACOSX) | |
| 497 case NotificationType::APP_ACTIVATED: { | |
| 498 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 499 NewRunnableFunction(&NotifyPluginsOfActivation)); | |
| 500 break; | |
| 501 } | |
| 502 #endif | |
| 503 | |
| 504 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: { | |
| 505 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | |
| 506 PurgePluginListCache(false); | |
| 507 break; | |
| 508 } | |
| 509 case NotificationType::RENDERER_PROCESS_CLOSED: { | |
| 510 int render_process_id = Source<RenderProcessHost>(source).ptr()->id(); | |
| 511 | |
| 512 base::AutoLock auto_lock(overridden_plugins_lock_); | |
| 513 for (size_t i = 0; i < overridden_plugins_.size(); ++i) { | |
| 514 if (overridden_plugins_[i].render_process_id == render_process_id) { | |
| 515 overridden_plugins_.erase(overridden_plugins_.begin() + i); | |
| 516 break; | |
| 517 } | |
| 518 } | |
| 519 break; | |
| 520 } | |
| 521 default: | |
| 522 NOTREACHED(); | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 bool PluginService::PrivatePluginAllowedForURL(const FilePath& plugin_path, | |
| 527 const GURL& url) { | |
| 528 if (url.is_empty()) | |
| 529 return true; // Caller wants all plugins. | |
| 530 | |
| 531 PrivatePluginMap::iterator it = private_plugins_.find(plugin_path); | |
| 532 if (it == private_plugins_.end()) | |
| 533 return true; // This plugin is not private, so it's allowed everywhere. | |
| 534 | |
| 535 // We do a dumb compare of scheme and host, rather than using the domain | |
| 536 // service, since we only care about this for extensions. | |
| 537 const GURL& required_url = it->second; | |
| 538 return (url.scheme() == required_url.scheme() && | |
| 539 url.host() == required_url.host()); | |
| 540 } | |
| 541 | |
| 542 void PluginService::OverridePluginForTab(OverriddenPlugin plugin) { | |
| 543 base::AutoLock auto_lock(overridden_plugins_lock_); | |
| 544 overridden_plugins_.push_back(plugin); | |
| 545 } | |
| 546 | |
| 547 void PluginService::RegisterPepperPlugins() { | |
| 548 PepperPluginRegistry::ComputeList(&ppapi_plugins_); | |
| 549 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { | |
| 550 webkit::npapi::WebPluginInfo info; | |
| 551 info.path = ppapi_plugins_[i].path; | |
| 552 info.name = ppapi_plugins_[i].name.empty() ? | |
| 553 ppapi_plugins_[i].path.BaseName().LossyDisplayName() : | |
| 554 ASCIIToUTF16(ppapi_plugins_[i].name); | |
| 555 info.desc = ASCIIToUTF16(ppapi_plugins_[i].description); | |
| 556 info.version = ASCIIToUTF16(ppapi_plugins_[i].version); | |
| 557 info.enabled = webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; | |
| 558 | |
| 559 // TODO(evan): Pepper shouldn't require us to parse strings to get | |
| 560 // the list of mime types out. | |
| 561 if (!webkit::npapi::PluginList::ParseMimeTypes( | |
| 562 JoinString(ppapi_plugins_[i].mime_types, '|'), | |
| 563 ppapi_plugins_[i].file_extensions, | |
| 564 ASCIIToUTF16(ppapi_plugins_[i].type_descriptions), | |
| 565 &info.mime_types)) { | |
| 566 LOG(ERROR) << "Error parsing mime types for " | |
| 567 << ppapi_plugins_[i].path.LossyDisplayName(); | |
| 568 return; | |
| 569 } | |
| 570 | |
| 571 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); | |
| 572 } | |
| 573 } | |
| 574 | |
| 575 #if defined(OS_LINUX) | |
| 576 // static | |
| 577 void PluginService::RegisterFilePathWatcher( | |
| 578 FilePathWatcher *watcher, | |
| 579 const FilePath& path, | |
| 580 FilePathWatcher::Delegate* delegate) { | |
| 581 bool result = watcher->Watch(path, delegate); | |
| 582 DCHECK(result); | |
| 583 } | |
| 584 #endif | |
| OLD | NEW |