| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 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 "build/build_config.h" | |
| 6 | |
| 7 #include "chrome/browser/plugin_process_host.h" | |
| 8 | |
| 9 #if defined(OS_WIN) | |
| 10 #include <windows.h> | |
| 11 #endif | |
| 12 | |
| 13 #include <vector> | |
| 14 | |
| 15 #include "app/app_switches.h" | |
| 16 #include "base/command_line.h" | |
| 17 #if defined(OS_POSIX) | |
| 18 #include "base/global_descriptors_posix.h" | |
| 19 #endif | |
| 20 #include "base/file_path.h" | |
| 21 #include "base/file_util.h" | |
| 22 #include "base/file_version_info.h" | |
| 23 #include "base/gfx/native_widget_types.h" | |
| 24 #include "base/logging.h" | |
| 25 #include "base/path_service.h" | |
| 26 #include "base/process_util.h" | |
| 27 #include "base/scoped_ptr.h" | |
| 28 #include "base/thread.h" | |
| 29 #include "chrome/browser/browser_process.h" | |
| 30 #include "chrome/browser/child_process_security_policy.h" | |
| 31 #include "chrome/browser/chrome_plugin_browsing_context.h" | |
| 32 #include "chrome/browser/chrome_thread.h" | |
| 33 #include "chrome/browser/plugin_service.h" | |
| 34 #include "chrome/browser/profile.h" | |
| 35 #include "chrome/browser/renderer_host/browser_render_process_host.h" | |
| 36 #include "chrome/browser/renderer_host/render_process_host.h" | |
| 37 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | |
| 38 #include "chrome/common/chrome_paths.h" | |
| 39 #include "chrome/common/chrome_plugin_lib.h" | |
| 40 #include "chrome/common/chrome_switches.h" | |
| 41 #include "chrome/common/logging_chrome.h" | |
| 42 #include "chrome/common/plugin_messages.h" | |
| 43 #include "chrome/common/render_messages.h" | |
| 44 #include "ipc/ipc_channel_handle.h" | |
| 45 #include "ipc/ipc_descriptors.h" | |
| 46 #include "ipc/ipc_switches.h" | |
| 47 #include "net/base/file_stream.h" | |
| 48 #include "net/base/io_buffer.h" | |
| 49 #include "net/url_request/url_request.h" | |
| 50 #include "net/url_request/url_request_context.h" | |
| 51 #include "webkit/glue/plugins/plugin_constants_win.h" | |
| 52 | |
| 53 #if defined(OS_WIN) | |
| 54 #include "app/win_util.h" | |
| 55 #include "chrome/browser/sandbox_policy.h" | |
| 56 #include "sandbox/src/sandbox.h" | |
| 57 #endif | |
| 58 | |
| 59 #if defined(OS_POSIX) | |
| 60 #include "ipc/ipc_channel_posix.h" | |
| 61 #endif | |
| 62 | |
| 63 #if defined(OS_LINUX) | |
| 64 #include "base/gfx/gtk_native_view_id_manager.h" | |
| 65 #endif | |
| 66 | |
| 67 static const char kDefaultPluginFinderURL[] = | |
| 68 "http://dl.google.com/chrome/plugins/plugins2.xml"; | |
| 69 | |
| 70 #if defined(OS_WIN) | |
| 71 | |
| 72 // The PluginDownloadUrlHelper is used to handle one download URL request | |
| 73 // from the plugin. Each download request is handled by a new instance | |
| 74 // of this class. | |
| 75 class PluginDownloadUrlHelper : public URLRequest::Delegate { | |
| 76 static const int kDownloadFileBufferSize = 32768; | |
| 77 public: | |
| 78 PluginDownloadUrlHelper(const std::string& download_url, | |
| 79 int source_pid, gfx::NativeWindow caller_window); | |
| 80 ~PluginDownloadUrlHelper(); | |
| 81 | |
| 82 void InitiateDownload(); | |
| 83 | |
| 84 // URLRequest::Delegate | |
| 85 virtual void OnAuthRequired(URLRequest* request, | |
| 86 net::AuthChallengeInfo* auth_info); | |
| 87 virtual void OnSSLCertificateError(URLRequest* request, | |
| 88 int cert_error, | |
| 89 net::X509Certificate* cert); | |
| 90 virtual void OnResponseStarted(URLRequest* request); | |
| 91 virtual void OnReadCompleted(URLRequest* request, int bytes_read); | |
| 92 | |
| 93 void OnDownloadCompleted(URLRequest* request); | |
| 94 | |
| 95 protected: | |
| 96 void DownloadCompletedHelper(bool success); | |
| 97 | |
| 98 // The download file request initiated by the plugin. | |
| 99 URLRequest* download_file_request_; | |
| 100 // Handle to the downloaded file. | |
| 101 scoped_ptr<net::FileStream> download_file_; | |
| 102 // The full path of the downloaded file. | |
| 103 FilePath download_file_path_; | |
| 104 // The buffer passed off to URLRequest::Read. | |
| 105 scoped_refptr<net::IOBuffer> download_file_buffer_; | |
| 106 // TODO(port): this comment doesn't describe the situation on Posix. | |
| 107 // The window handle for sending the WM_COPYDATA notification, | |
| 108 // indicating that the download completed. | |
| 109 gfx::NativeWindow download_file_caller_window_; | |
| 110 | |
| 111 std::string download_url_; | |
| 112 int download_source_pid_; | |
| 113 | |
| 114 DISALLOW_EVIL_CONSTRUCTORS(PluginDownloadUrlHelper); | |
| 115 }; | |
| 116 | |
| 117 PluginDownloadUrlHelper::PluginDownloadUrlHelper( | |
| 118 const std::string& download_url, | |
| 119 int source_pid, gfx::NativeWindow caller_window) | |
| 120 : download_file_request_(NULL), | |
| 121 download_file_buffer_(new net::IOBuffer(kDownloadFileBufferSize)), | |
| 122 download_file_caller_window_(caller_window), | |
| 123 download_url_(download_url), | |
| 124 download_source_pid_(source_pid) { | |
| 125 DCHECK(::IsWindow(caller_window)); | |
| 126 memset(download_file_buffer_->data(), 0, kDownloadFileBufferSize); | |
| 127 download_file_.reset(new net::FileStream()); | |
| 128 } | |
| 129 | |
| 130 PluginDownloadUrlHelper::~PluginDownloadUrlHelper() { | |
| 131 if (download_file_request_) { | |
| 132 delete download_file_request_; | |
| 133 download_file_request_ = NULL; | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 void PluginDownloadUrlHelper::InitiateDownload() { | |
| 138 download_file_request_= new URLRequest(GURL(download_url_), this); | |
| 139 download_file_request_->set_origin_pid(download_source_pid_); | |
| 140 download_file_request_->set_context(Profile::GetDefaultRequestContext()); | |
| 141 download_file_request_->Start(); | |
| 142 } | |
| 143 | |
| 144 void PluginDownloadUrlHelper::OnAuthRequired( | |
| 145 URLRequest* request, | |
| 146 net::AuthChallengeInfo* auth_info) { | |
| 147 URLRequest::Delegate::OnAuthRequired(request, auth_info); | |
| 148 DownloadCompletedHelper(false); | |
| 149 } | |
| 150 | |
| 151 void PluginDownloadUrlHelper::OnSSLCertificateError( | |
| 152 URLRequest* request, | |
| 153 int cert_error, | |
| 154 net::X509Certificate* cert) { | |
| 155 URLRequest::Delegate::OnSSLCertificateError(request, cert_error, cert); | |
| 156 DownloadCompletedHelper(false); | |
| 157 } | |
| 158 | |
| 159 void PluginDownloadUrlHelper::OnResponseStarted(URLRequest* request) { | |
| 160 if (!download_file_->IsOpen()) { | |
| 161 file_util::GetTempDir(&download_file_path_); | |
| 162 | |
| 163 GURL request_url = request->url(); | |
| 164 download_file_path_ = download_file_path_.Append( | |
| 165 UTF8ToWide(request_url.ExtractFileName())); | |
| 166 download_file_->Open(download_file_path_, | |
| 167 base::PLATFORM_FILE_CREATE_ALWAYS | | |
| 168 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_WRITE); | |
| 169 if (!download_file_->IsOpen()) { | |
| 170 NOTREACHED(); | |
| 171 OnDownloadCompleted(request); | |
| 172 return; | |
| 173 } | |
| 174 } | |
| 175 if (!request->status().is_success()) { | |
| 176 OnDownloadCompleted(request); | |
| 177 } else { | |
| 178 // Initiate a read. | |
| 179 int bytes_read = 0; | |
| 180 if (!request->Read(download_file_buffer_, kDownloadFileBufferSize, | |
| 181 &bytes_read)) { | |
| 182 // If the error is not an IO pending, then we're done | |
| 183 // reading. | |
| 184 if (!request->status().is_io_pending()) { | |
| 185 OnDownloadCompleted(request); | |
| 186 } | |
| 187 } else if (bytes_read == 0) { | |
| 188 OnDownloadCompleted(request); | |
| 189 } else { | |
| 190 OnReadCompleted(request, bytes_read); | |
| 191 } | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 void PluginDownloadUrlHelper::OnReadCompleted(URLRequest* request, | |
| 196 int bytes_read) { | |
| 197 DCHECK(download_file_->IsOpen()); | |
| 198 | |
| 199 if (bytes_read == 0) { | |
| 200 OnDownloadCompleted(request); | |
| 201 return; | |
| 202 } | |
| 203 | |
| 204 int request_bytes_read = bytes_read; | |
| 205 | |
| 206 while (request->status().is_success()) { | |
| 207 int bytes_written = download_file_->Write(download_file_buffer_->data(), | |
| 208 request_bytes_read, NULL); | |
| 209 DCHECK((bytes_written < 0) || (bytes_written == request_bytes_read)); | |
| 210 | |
| 211 if ((bytes_written < 0) || (bytes_written != request_bytes_read)) { | |
| 212 DownloadCompletedHelper(false); | |
| 213 break; | |
| 214 } | |
| 215 | |
| 216 // Start reading | |
| 217 request_bytes_read = 0; | |
| 218 if (!request->Read(download_file_buffer_, kDownloadFileBufferSize, | |
| 219 &request_bytes_read)) { | |
| 220 if (!request->status().is_io_pending()) { | |
| 221 // If the error is not an IO pending, then we're done | |
| 222 // reading. | |
| 223 OnDownloadCompleted(request); | |
| 224 } | |
| 225 break; | |
| 226 } else if (request_bytes_read == 0) { | |
| 227 OnDownloadCompleted(request); | |
| 228 break; | |
| 229 } | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 void PluginDownloadUrlHelper::OnDownloadCompleted(URLRequest* request) { | |
| 234 bool success = true; | |
| 235 if (!request->status().is_success()) { | |
| 236 success = false; | |
| 237 } else if (!download_file_->IsOpen()) { | |
| 238 success = false; | |
| 239 } | |
| 240 | |
| 241 DownloadCompletedHelper(success); | |
| 242 } | |
| 243 | |
| 244 void PluginDownloadUrlHelper::DownloadCompletedHelper(bool success) { | |
| 245 if (download_file_->IsOpen()) { | |
| 246 download_file_.reset(); | |
| 247 } | |
| 248 | |
| 249 std::wstring path = download_file_path_.value(); | |
| 250 COPYDATASTRUCT download_file_data = {0}; | |
| 251 download_file_data.cbData = | |
| 252 static_cast<unsigned long>((path.length() + 1) * sizeof(wchar_t)); | |
| 253 download_file_data.lpData = const_cast<wchar_t *>(path.c_str()); | |
| 254 download_file_data.dwData = success; | |
| 255 | |
| 256 if (::IsWindow(download_file_caller_window_)) { | |
| 257 ::SendMessage(download_file_caller_window_, WM_COPYDATA, NULL, | |
| 258 reinterpret_cast<LPARAM>(&download_file_data)); | |
| 259 } | |
| 260 | |
| 261 // Don't access any members after this. | |
| 262 delete this; | |
| 263 } | |
| 264 | |
| 265 void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) { | |
| 266 // The window is destroyed at this point, we just care about its parent, which | |
| 267 // is the intermediate window we created. | |
| 268 std::set<HWND>::iterator window_index = | |
| 269 plugin_parent_windows_set_.find(parent); | |
| 270 if (window_index == plugin_parent_windows_set_.end()) | |
| 271 return; | |
| 272 | |
| 273 plugin_parent_windows_set_.erase(window_index); | |
| 274 PostMessage(parent, WM_CLOSE, 0, 0); | |
| 275 } | |
| 276 | |
| 277 void PluginProcessHost::OnDownloadUrl(const std::string& url, | |
| 278 int source_pid, | |
| 279 gfx::NativeWindow caller_window) { | |
| 280 PluginDownloadUrlHelper* download_url_helper = | |
| 281 new PluginDownloadUrlHelper(url, source_pid, caller_window); | |
| 282 download_url_helper->InitiateDownload(); | |
| 283 } | |
| 284 | |
| 285 void PluginProcessHost::AddWindow(HWND window) { | |
| 286 plugin_parent_windows_set_.insert(window); | |
| 287 } | |
| 288 | |
| 289 #endif // defined(OS_WIN) | |
| 290 | |
| 291 #if defined(OS_LINUX) | |
| 292 void PluginProcessHost::OnMapNativeViewId(gfx::NativeViewId id, | |
| 293 gfx::PluginWindowHandle* output) { | |
| 294 *output = 0; | |
| 295 Singleton<GtkNativeViewManager>()->GetXIDForId(output, id); | |
| 296 } | |
| 297 #endif // defined(OS_LINUX) | |
| 298 | |
| 299 PluginProcessHost::PluginProcessHost() | |
| 300 : ChildProcessHost( | |
| 301 PLUGIN_PROCESS, | |
| 302 PluginService::GetInstance()->resource_dispatcher_host()), | |
| 303 ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)) { | |
| 304 } | |
| 305 | |
| 306 PluginProcessHost::~PluginProcessHost() { | |
| 307 #if defined(OS_WIN) | |
| 308 // We erase HWNDs from the plugin_parent_windows_set_ when we receive a | |
| 309 // notification that the window is being destroyed. If we don't receive this | |
| 310 // notification and the PluginProcessHost instance is being destroyed, it | |
| 311 // means that the plugin process crashed. We paint a sad face in this case in | |
| 312 // the renderer process. To ensure that the sad face shows up, and we don't | |
| 313 // leak HWNDs, we should destroy existing plugin parent windows. | |
| 314 std::set<HWND>::iterator window_index; | |
| 315 for (window_index = plugin_parent_windows_set_.begin(); | |
| 316 window_index != plugin_parent_windows_set_.end(); | |
| 317 window_index++) { | |
| 318 PostMessage(*window_index, WM_CLOSE, 0, 0); | |
| 319 } | |
| 320 #endif | |
| 321 } | |
| 322 | |
| 323 bool PluginProcessHost::Init(const WebPluginInfo& info, | |
| 324 const std::string& activex_clsid, | |
| 325 const std::wstring& locale) { | |
| 326 info_ = info; | |
| 327 set_name(info_.name); | |
| 328 | |
| 329 if (!CreateChannel()) | |
| 330 return false; | |
| 331 | |
| 332 // build command line for plugin, we have to quote the plugin's path to deal | |
| 333 // with spaces. | |
| 334 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | |
| 335 std::wstring exe_path = | |
| 336 browser_command_line.GetSwitchValue(switches::kBrowserSubprocessPath); | |
| 337 if (exe_path.empty() && !PathService::Get(base::FILE_EXE, &exe_path)) | |
| 338 return false; | |
| 339 | |
| 340 CommandLine cmd_line(exe_path); | |
| 341 if (logging::DialogsAreSuppressed()) | |
| 342 cmd_line.AppendSwitch(switches::kNoErrorDialogs); | |
| 343 | |
| 344 // propagate the following switches to the plugin command line (along with | |
| 345 // any associated values) if present in the browser command line | |
| 346 static const wchar_t* const switch_names[] = { | |
| 347 switches::kPluginStartupDialog, | |
| 348 switches::kNoSandbox, | |
| 349 switches::kSafePlugins, | |
| 350 switches::kTestSandbox, | |
| 351 switches::kUserAgent, | |
| 352 switches::kDisableBreakpad, | |
| 353 switches::kFullMemoryCrashReport, | |
| 354 switches::kEnableLogging, | |
| 355 switches::kDisableLogging, | |
| 356 switches::kLoggingLevel, | |
| 357 switches::kLogPluginMessages, | |
| 358 switches::kUserDataDir, | |
| 359 switches::kAllowAllActiveX, | |
| 360 switches::kEnableDCHECK, | |
| 361 switches::kSilentDumpOnDCHECK, | |
| 362 switches::kMemoryProfiling, | |
| 363 switches::kUseLowFragHeapCrt, | |
| 364 switches::kEnableStatsTable, | |
| 365 }; | |
| 366 | |
| 367 for (size_t i = 0; i < arraysize(switch_names); ++i) { | |
| 368 if (browser_command_line.HasSwitch(switch_names[i])) { | |
| 369 cmd_line.AppendSwitchWithValue( | |
| 370 switch_names[i], | |
| 371 browser_command_line.GetSwitchValue(switch_names[i])); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 // If specified, prepend a launcher program to the command line. | |
| 376 std::wstring plugin_launcher = | |
| 377 browser_command_line.GetSwitchValue(switches::kPluginLauncher); | |
| 378 if (!plugin_launcher.empty()) | |
| 379 cmd_line.PrependWrapper(plugin_launcher); | |
| 380 | |
| 381 if (!locale.empty()) { | |
| 382 // Pass on the locale so the null plugin will use the right language in the | |
| 383 // prompt to install the desired plugin. | |
| 384 cmd_line.AppendSwitchWithValue(switches::kLang, locale); | |
| 385 } | |
| 386 | |
| 387 // Gears requires the data dir to be available on startup. | |
| 388 std::wstring data_dir = | |
| 389 PluginService::GetInstance()->GetChromePluginDataDir().ToWStringHack(); | |
| 390 DCHECK(!data_dir.empty()); | |
| 391 cmd_line.AppendSwitchWithValue(switches::kPluginDataDir, data_dir); | |
| 392 | |
| 393 cmd_line.AppendSwitchWithValue(switches::kProcessType, | |
| 394 switches::kPluginProcess); | |
| 395 | |
| 396 cmd_line.AppendSwitchWithValue(switches::kProcessChannelID, | |
| 397 ASCIIToWide(channel_id())); | |
| 398 | |
| 399 cmd_line.AppendSwitchWithValue(switches::kPluginPath, | |
| 400 info.path.ToWStringHack()); | |
| 401 | |
| 402 base::ProcessHandle process = 0; | |
| 403 #if defined(OS_WIN) | |
| 404 process = sandbox::StartProcess(&cmd_line); | |
| 405 #else | |
| 406 // This code is duplicated with browser_render_process_host.cc, but | |
| 407 // there's not a good place to de-duplicate it. | |
| 408 base::file_handle_mapping_vector fds_to_map; | |
| 409 const int ipcfd = channel().GetClientFileDescriptor(); | |
| 410 if (ipcfd > -1) | |
| 411 fds_to_map.push_back(std::pair<int, int>( | |
| 412 ipcfd, kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor)); | |
| 413 base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process); | |
| 414 #endif | |
| 415 | |
| 416 if (!process) | |
| 417 return false; | |
| 418 SetHandle(process); | |
| 419 | |
| 420 FilePath gears_path; | |
| 421 if (PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_path)) { | |
| 422 FilePath::StringType gears_path_lc = StringToLowerASCII(gears_path.value()); | |
| 423 FilePath::StringType plugin_path_lc = | |
| 424 StringToLowerASCII(info.path.value()); | |
| 425 if (plugin_path_lc == gears_path_lc) { | |
| 426 // Give Gears plugins "background" priority. See | |
| 427 // http://b/issue?id=1280317. | |
| 428 SetProcessBackgrounded(); | |
| 429 } | |
| 430 } | |
| 431 | |
| 432 return true; | |
| 433 } | |
| 434 | |
| 435 void PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { | |
| 436 IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg) | |
| 437 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated) | |
| 438 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_GetPluginFinderUrl, | |
| 439 OnGetPluginFinderUrl) | |
| 440 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginMessage, OnPluginMessage) | |
| 441 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_GetCookies, OnGetCookies) | |
| 442 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_AccessFiles, OnAccessFiles) | |
| 443 IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginProcessHostMsg_ResolveProxy, | |
| 444 OnResolveProxy) | |
| 445 #if defined(OS_WIN) | |
| 446 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed, | |
| 447 OnPluginWindowDestroyed) | |
| 448 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_DownloadUrl, OnDownloadUrl) | |
| 449 #endif | |
| 450 #if defined(OS_LINUX) | |
| 451 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId, | |
| 452 OnMapNativeViewId) | |
| 453 #endif | |
| 454 IPC_MESSAGE_UNHANDLED_ERROR() | |
| 455 IPC_END_MESSAGE_MAP() | |
| 456 } | |
| 457 | |
| 458 void PluginProcessHost::OnChannelConnected(int32 peer_pid) { | |
| 459 for (size_t i = 0; i < pending_requests_.size(); ++i) { | |
| 460 RequestPluginChannel(pending_requests_[i].renderer_message_filter_.get(), | |
| 461 pending_requests_[i].mime_type, | |
| 462 pending_requests_[i].reply_msg); | |
| 463 } | |
| 464 | |
| 465 pending_requests_.clear(); | |
| 466 } | |
| 467 | |
| 468 void PluginProcessHost::OnChannelError() { | |
| 469 for (size_t i = 0; i < pending_requests_.size(); ++i) { | |
| 470 ReplyToRenderer(pending_requests_[i].renderer_message_filter_.get(), | |
| 471 IPC::ChannelHandle(), | |
| 472 FilePath(), | |
| 473 pending_requests_[i].reply_msg); | |
| 474 } | |
| 475 | |
| 476 pending_requests_.clear(); | |
| 477 } | |
| 478 | |
| 479 void PluginProcessHost::OpenChannelToPlugin( | |
| 480 ResourceMessageFilter* renderer_message_filter, | |
| 481 const std::string& mime_type, | |
| 482 IPC::Message* reply_msg) { | |
| 483 InstanceCreated(); | |
| 484 if (opening_channel()) { | |
| 485 // The channel is already in the process of being opened. Put | |
| 486 // this "open channel" request into a queue of requests that will | |
| 487 // be run once the channel is open. | |
| 488 pending_requests_.push_back( | |
| 489 ChannelRequest(renderer_message_filter, mime_type, reply_msg)); | |
| 490 return; | |
| 491 } | |
| 492 | |
| 493 // We already have an open channel, send a request right away to plugin. | |
| 494 RequestPluginChannel(renderer_message_filter, mime_type, reply_msg); | |
| 495 } | |
| 496 | |
| 497 void PluginProcessHost::OnGetCookies(uint32 request_context, | |
| 498 const GURL& url, | |
| 499 std::string* cookies) { | |
| 500 URLRequestContext* context = CPBrowsingContextManager::Instance()-> | |
| 501 ToURLRequestContext(request_context); | |
| 502 // TODO(mpcomplete): remove fallback case when Gears support is prevalent. | |
| 503 if (!context) | |
| 504 context = Profile::GetDefaultRequestContext(); | |
| 505 | |
| 506 // Note: We don't have a first_party_for_cookies check because plugins bypass | |
| 507 // third-party cookie blocking. | |
| 508 *cookies = context->cookie_store()->GetCookies(url); | |
| 509 } | |
| 510 | |
| 511 void PluginProcessHost::OnAccessFiles(int process_id, | |
| 512 const std::vector<std::string>& files, | |
| 513 bool* allowed) { | |
| 514 ChildProcessSecurityPolicy* policy = | |
| 515 ChildProcessSecurityPolicy::GetInstance(); | |
| 516 | |
| 517 for (size_t i = 0; i < files.size(); ++i) { | |
| 518 const FilePath path = FilePath::FromWStringHack(UTF8ToWide(files[i])); | |
| 519 if (!policy->CanUploadFile(process_id, path)) { | |
| 520 LOG(INFO) << "Denied unauthorized request for file " << files[i]; | |
| 521 *allowed = false; | |
| 522 return; | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 *allowed = true; | |
| 527 } | |
| 528 | |
| 529 void PluginProcessHost::OnResolveProxy(const GURL& url, | |
| 530 IPC::Message* reply_msg) { | |
| 531 resolve_proxy_msg_helper_.Start(url, reply_msg); | |
| 532 } | |
| 533 | |
| 534 void PluginProcessHost::OnResolveProxyCompleted(IPC::Message* reply_msg, | |
| 535 int result, | |
| 536 const std::string& proxy_list) { | |
| 537 PluginProcessHostMsg_ResolveProxy::WriteReplyParams( | |
| 538 reply_msg, result, proxy_list); | |
| 539 Send(reply_msg); | |
| 540 } | |
| 541 | |
| 542 void PluginProcessHost::ReplyToRenderer( | |
| 543 ResourceMessageFilter* renderer_message_filter, | |
| 544 const IPC::ChannelHandle& channel, | |
| 545 const FilePath& plugin_path, | |
| 546 IPC::Message* reply_msg) { | |
| 547 ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg, channel, | |
| 548 plugin_path); | |
| 549 renderer_message_filter->Send(reply_msg); | |
| 550 } | |
| 551 | |
| 552 URLRequestContext* PluginProcessHost::GetRequestContext( | |
| 553 uint32 request_id, | |
| 554 const ViewHostMsg_Resource_Request& request_data) { | |
| 555 return CPBrowsingContextManager::Instance()->ToURLRequestContext(request_id); | |
| 556 } | |
| 557 | |
| 558 void PluginProcessHost::RequestPluginChannel( | |
| 559 ResourceMessageFilter* renderer_message_filter, | |
| 560 const std::string& mime_type, IPC::Message* reply_msg) { | |
| 561 // We can't send any sync messages from the browser because it might lead to | |
| 562 // a hang. However this async messages must be answered right away by the | |
| 563 // plugin process (i.e. unblocks a Send() call like a sync message) otherwise | |
| 564 // a deadlock can occur if the plugin creation request from the renderer is | |
| 565 // a result of a sync message by the plugin process. | |
| 566 PluginProcessMsg_CreateChannel* msg = new PluginProcessMsg_CreateChannel( | |
| 567 renderer_message_filter->GetProcessId(), | |
| 568 renderer_message_filter->off_the_record()); | |
| 569 msg->set_unblock(true); | |
| 570 if (Send(msg)) { | |
| 571 sent_requests_.push(ChannelRequest( | |
| 572 renderer_message_filter, mime_type, reply_msg)); | |
| 573 } else { | |
| 574 ReplyToRenderer(renderer_message_filter, IPC::ChannelHandle(), FilePath(), | |
| 575 reply_msg); | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 void PluginProcessHost::OnChannelCreated( | |
| 580 const IPC::ChannelHandle& channel_handle) { | |
| 581 const ChannelRequest& request = sent_requests_.front(); | |
| 582 | |
| 583 ReplyToRenderer(request.renderer_message_filter_.get(), | |
| 584 channel_handle, | |
| 585 info_.path, | |
| 586 request.reply_msg); | |
| 587 sent_requests_.pop(); | |
| 588 } | |
| 589 | |
| 590 void PluginProcessHost::OnGetPluginFinderUrl(std::string* plugin_finder_url) { | |
| 591 if (!plugin_finder_url) { | |
| 592 NOTREACHED(); | |
| 593 return; | |
| 594 } | |
| 595 | |
| 596 // TODO(iyengar) Add the plumbing to retrieve the default | |
| 597 // plugin finder URL. | |
| 598 *plugin_finder_url = kDefaultPluginFinderURL; | |
| 599 } | |
| 600 | |
| 601 void PluginProcessHost::OnPluginMessage( | |
| 602 const std::vector<uint8>& data) { | |
| 603 DCHECK(MessageLoop::current() == | |
| 604 ChromeThread::GetMessageLoop(ChromeThread::IO)); | |
| 605 | |
| 606 ChromePluginLib *chrome_plugin = ChromePluginLib::Find(info_.path); | |
| 607 if (chrome_plugin) { | |
| 608 void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0])); | |
| 609 uint32 data_len = static_cast<uint32>(data.size()); | |
| 610 chrome_plugin->functions().on_message(data_ptr, data_len); | |
| 611 } | |
| 612 } | |
| OLD | NEW |