Chromium Code Reviews| 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 "content/browser/plugin_process_host.h" | |
|
sky
2014/05/23 20:44:03
Are these changes expected?
ananta
2014/05/23 21:16:29
No. Updated patch. PTAL
| |
| 6 | |
| 7 #if defined(OS_WIN) | |
| 8 #include <windows.h> | |
| 9 #elif defined(OS_POSIX) | |
| 10 #include <utility> // for pair<> | |
| 11 #endif | |
| 12 | |
| 13 #include <vector> | |
| 14 | |
| 15 #include "base/base_switches.h" | |
| 16 #include "base/bind.h" | |
| 5 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 6 #include "base/file_util.h" | 18 #include "base/files/file_path.h" |
| 19 #include "base/logging.h" | |
| 20 #include "base/metrics/histogram.h" | |
| 7 #include "base/path_service.h" | 21 #include "base/path_service.h" |
| 22 #include "base/strings/string_number_conversions.h" | |
| 8 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 24 #include "base/strings/utf_string_conversions.h" |
| 10 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 25 #include "content/browser/browser_child_process_host_impl.h" |
| 26 #include "content/browser/loader/resource_message_filter.h" | |
| 27 #include "content/browser/gpu/gpu_data_manager_impl.h" | |
| 28 #include "content/browser/plugin_service_impl.h" | |
| 29 #include "content/common/child_process_host_impl.h" | |
| 30 #include "content/common/plugin_process_messages.h" | |
| 31 #include "content/common/resource_messages.h" | |
| 11 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
| 12 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 33 #include "content/public/browser/content_browser_client.h" |
| 34 #include "content/public/browser/notification_types.h" | |
| 35 #include "content/public/browser/plugin_service.h" | |
| 36 #include "content/public/browser/resource_context.h" | |
| 13 #include "content/public/common/content_switches.h" | 37 #include "content/public/common/content_switches.h" |
| 14 #include "content/public/test/browser_test_utils.h" | 38 #include "content/public/common/process_type.h" |
| 15 #include "content/public/test/content_browser_test.h" | 39 #include "content/public/common/sandboxed_process_launcher_delegate.h" |
| 16 #include "content/public/test/content_browser_test_utils.h" | 40 #include "ipc/ipc_switches.h" |
| 17 #include "content/public/test/test_utils.h" | 41 #include "net/url_request/url_request_context_getter.h" |
| 18 #include "content/shell/browser/shell.h" | 42 #include "ui/base/ui_base_switches.h" |
| 19 #include "content/shell/common/shell_switches.h" | 43 #include "ui/gfx/native_widget_types.h" |
| 20 #include "content/test/net/url_request_mock_http_job.h" | 44 #include "ui/gl/gl_switches.h" |
| 21 #include "net/test/embedded_test_server/embedded_test_server.h" | 45 |
| 22 #include "net/url_request/url_request.h" | 46 #if defined(OS_MACOSX) |
| 47 #include "base/mac/mac_util.h" | |
| 48 #include "content/common/plugin_carbon_interpose_constants_mac.h" | |
| 23 #include "ui/gfx/rect.h" | 49 #include "ui/gfx/rect.h" |
| 24 | 50 #endif |
| 25 #if defined(OS_WIN) | 51 |
| 26 #include "base/win/registry.h" | 52 #if defined(OS_WIN) |
| 27 #endif | 53 #include "base/win/windows_version.h" |
| 28 | 54 #include "content/common/plugin_constants_win.h" |
| 29 // TODO(jschuh): Finish plugins on Win64. crbug.com/180861 | 55 #include "ui/gfx/switches.h" |
| 30 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64) | 56 #endif |
| 31 #define MAYBE(x) DISABLED_##x | 57 |
| 58 namespace content { | |
| 59 | |
| 60 #if defined(OS_WIN) | |
| 61 void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) { | |
| 62 // The window is destroyed at this point, we just care about its parent, which | |
| 63 // is the intermediate window we created. | |
| 64 std::set<HWND>::iterator window_index = | |
| 65 plugin_parent_windows_set_.find(parent); | |
| 66 if (window_index == plugin_parent_windows_set_.end()) | |
| 67 return; | |
| 68 | |
| 69 plugin_parent_windows_set_.erase(window_index); | |
| 70 PostMessage(parent, WM_CLOSE, 0, 0); | |
| 71 } | |
| 72 | |
| 73 void PluginProcessHost::AddWindow(HWND window) { | |
| 74 plugin_parent_windows_set_.insert(window); | |
| 75 } | |
| 76 #endif // defined(OS_WIN) | |
| 77 | |
| 78 // NOTE: changes to this class need to be reviewed by the security team. | |
| 79 class PluginSandboxedProcessLauncherDelegate | |
| 80 : public SandboxedProcessLauncherDelegate { | |
| 81 public: | |
| 82 explicit PluginSandboxedProcessLauncherDelegate(ChildProcessHost* host) | |
| 83 #if defined(OS_POSIX) | |
| 84 : ipc_fd_(host->TakeClientFileDescriptor()) | |
| 85 #endif // OS_POSIX | |
| 86 {} | |
| 87 | |
| 88 virtual ~PluginSandboxedProcessLauncherDelegate() {} | |
| 89 | |
| 90 #if defined(OS_WIN) | |
| 91 virtual bool ShouldSandbox() OVERRIDE { | |
| 92 return false; | |
| 93 } | |
| 94 | |
| 95 #elif defined(OS_POSIX) | |
| 96 virtual int GetIpcFd() OVERRIDE { | |
| 97 return ipc_fd_; | |
| 98 } | |
| 99 #endif // OS_WIN | |
| 100 | |
| 101 private: | |
| 102 #if defined(OS_POSIX) | |
| 103 int ipc_fd_; | |
| 104 #endif // OS_POSIX | |
| 105 | |
| 106 DISALLOW_COPY_AND_ASSIGN(PluginSandboxedProcessLauncherDelegate); | |
| 107 }; | |
| 108 | |
| 109 PluginProcessHost::PluginProcessHost() | |
| 110 #if defined(OS_MACOSX) | |
| 111 : plugin_cursor_visible_(true) | |
| 112 #endif | |
| 113 { | |
| 114 process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_PLUGIN, this)); | |
| 115 } | |
| 116 | |
| 117 PluginProcessHost::~PluginProcessHost() { | |
| 118 #if defined(OS_WIN) | |
| 119 // We erase HWNDs from the plugin_parent_windows_set_ when we receive a | |
| 120 // notification that the window is being destroyed. If we don't receive this | |
| 121 // notification and the PluginProcessHost instance is being destroyed, it | |
| 122 // means that the plugin process crashed. We paint a sad face in this case in | |
| 123 // the renderer process. To ensure that the sad face shows up, and we don't | |
| 124 // leak HWNDs, we should destroy existing plugin parent windows. | |
| 125 std::set<HWND>::iterator window_index; | |
| 126 for (window_index = plugin_parent_windows_set_.begin(); | |
| 127 window_index != plugin_parent_windows_set_.end(); | |
| 128 ++window_index) { | |
| 129 PostMessage(*window_index, WM_CLOSE, 0, 0); | |
| 130 } | |
| 131 #elif defined(OS_MACOSX) | |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 133 // If the plugin process crashed but had fullscreen windows open at the time, | |
| 134 // make sure that the menu bar is visible. | |
| 135 for (size_t i = 0; i < plugin_fullscreen_windows_set_.size(); ++i) { | |
| 136 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 137 base::Bind(base::mac::ReleaseFullScreen, | |
| 138 base::mac::kFullScreenModeHideAll)); | |
| 139 } | |
| 140 // If the plugin hid the cursor, reset that. | |
| 141 if (!plugin_cursor_visible_) { | |
| 142 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 143 base::Bind(base::mac::SetCursorVisibility, true)); | |
| 144 } | |
| 145 #endif | |
| 146 // Cancel all pending and sent requests. | |
| 147 CancelRequests(); | |
| 148 } | |
| 149 | |
| 150 bool PluginProcessHost::Send(IPC::Message* message) { | |
| 151 return process_->Send(message); | |
| 152 } | |
| 153 | |
| 154 bool PluginProcessHost::Init(const WebPluginInfo& info) { | |
| 155 info_ = info; | |
| 156 process_->SetName(info_.name); | |
| 157 | |
| 158 std::string channel_id = process_->GetHost()->CreateChannel(); | |
| 159 if (channel_id.empty()) | |
| 160 return false; | |
| 161 | |
| 162 // Build command line for plugin. When we have a plugin launcher, we can't | |
| 163 // allow "self" on linux and we need the real file path. | |
| 164 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); | |
| 165 CommandLine::StringType plugin_launcher = | |
| 166 browser_command_line.GetSwitchValueNative(switches::kPluginLauncher); | |
| 167 | |
| 168 #if defined(OS_MACOSX) | |
| 169 // Run the plug-in process in a mode tolerant of heap execution without | |
| 170 // explicit mprotect calls. Some plug-ins still rely on this quaint and | |
| 171 // archaic "feature." See http://crbug.com/93551. | |
| 172 int flags = ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION; | |
| 173 #elif defined(OS_LINUX) | |
| 174 int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : | |
| 175 ChildProcessHost::CHILD_NORMAL; | |
| 32 #else | 176 #else |
| 33 #define MAYBE(x) x | 177 int flags = ChildProcessHost::CHILD_NORMAL; |
| 34 #endif | 178 #endif |
| 35 | 179 |
| 36 using base::ASCIIToUTF16; | 180 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); |
| 37 | 181 if (exe_path.empty()) |
| 38 namespace content { | 182 return false; |
| 39 namespace { | 183 |
| 40 | 184 CommandLine* cmd_line = new CommandLine(exe_path); |
| 41 void SetUrlRequestMock(const base::FilePath& path) { | 185 // Put the process type and plugin path first so they're easier to see |
| 42 URLRequestMockHTTPJob::AddUrlHandler(path); | 186 // in process listings using native process management tools. |
| 43 } | 187 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kPluginProcess); |
| 44 | 188 cmd_line->AppendSwitchPath(switches::kPluginPath, info.path); |
| 45 } | 189 |
| 46 | 190 // Propagate the following switches to the plugin command line (along with |
| 47 class PluginTest : public ContentBrowserTest { | 191 // any associated values) if present in the browser command line |
| 48 protected: | 192 static const char* const kSwitchNames[] = { |
| 49 PluginTest() {} | 193 switches::kDisableBreakpad, |
| 50 | 194 switches::kDisableDirectNPAPIRequests, |
| 51 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 195 switches::kEnableStatsTable, |
| 52 // Some NPAPI tests schedule garbage collection to force object tear-down. | 196 switches::kFullMemoryCrashReport, |
| 53 command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose_gc"); | 197 switches::kLoggingLevel, |
| 54 | 198 switches::kLogPluginMessages, |
| 55 #if defined(OS_WIN) | 199 switches::kNoSandbox, |
| 56 const testing::TestInfo* const test_info = | 200 switches::kPluginStartupDialog, |
| 57 testing::UnitTest::GetInstance()->current_test_info(); | 201 switches::kTestSandbox, |
| 58 if (strcmp(test_info->name(), "MediaPlayerNew") == 0) { | 202 switches::kTraceStartup, |
| 59 // The installer adds our process names to the registry key below. Since | 203 switches::kUseGL, |
| 60 // the installer might not have run on this machine, add it manually. | 204 #if defined(OS_MACOSX) |
| 61 base::win::RegKey regkey; | 205 switches::kDisableCoreAnimationPlugins, |
| 62 if (regkey.Open(HKEY_LOCAL_MACHINE, | 206 switches::kEnableSandboxLogging, |
| 63 L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList", | 207 #endif |
| 64 KEY_WRITE) == ERROR_SUCCESS) { | 208 }; |
| 65 regkey.CreateKey(L"BROWSER_TESTS.EXE", KEY_READ); | 209 |
| 210 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, | |
| 211 arraysize(kSwitchNames)); | |
| 212 | |
| 213 GpuDataManagerImpl::GetInstance()->AppendPluginCommandLine(cmd_line); | |
| 214 | |
| 215 // If specified, prepend a launcher program to the command line. | |
| 216 if (!plugin_launcher.empty()) | |
| 217 cmd_line->PrependWrapper(plugin_launcher); | |
| 218 | |
| 219 std::string locale = GetContentClient()->browser()->GetApplicationLocale(); | |
| 220 if (!locale.empty()) { | |
| 221 // Pass on the locale so the null plugin will use the right language in the | |
| 222 // prompt to install the desired plugin. | |
| 223 cmd_line->AppendSwitchASCII(switches::kLang, locale); | |
| 224 } | |
| 225 | |
| 226 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); | |
| 227 | |
| 228 #if defined(OS_POSIX) | |
| 229 base::EnvironmentMap env; | |
| 230 #if defined(OS_MACOSX) && !defined(__LP64__) | |
| 231 if (browser_command_line.HasSwitch(switches::kEnableCarbonInterposing)) { | |
| 232 std::string interpose_list = GetContentClient()->GetCarbonInterposePath(); | |
| 233 if (!interpose_list.empty()) { | |
| 234 // Add our interposing library for Carbon. This is stripped back out in | |
| 235 // plugin_main.cc, so changes here should be reflected there. | |
| 236 const char* existing_list = getenv(kDYLDInsertLibrariesKey); | |
| 237 if (existing_list) { | |
| 238 interpose_list.insert(0, ":"); | |
| 239 interpose_list.insert(0, existing_list); | |
| 66 } | 240 } |
| 67 } else if (strcmp(test_info->name(), "FlashSecurity") == 0) { | |
| 68 command_line->AppendSwitchASCII(switches::kTestSandbox, | |
| 69 "security_tests.dll"); | |
| 70 } | 241 } |
| 71 #elif defined(OS_MACOSX) | 242 env[kDYLDInsertLibrariesKey] = interpose_list; |
| 72 base::FilePath plugin_dir; | 243 } |
| 73 PathService::Get(base::DIR_MODULE, &plugin_dir); | 244 #endif |
| 74 plugin_dir = plugin_dir.AppendASCII("plugins"); | 245 #endif |
| 75 // The plugins directory isn't read by default on the Mac, so it needs to be | 246 |
| 76 // explicitly registered. | 247 process_->Launch( |
| 77 command_line->AppendSwitchPath(switches::kExtraPluginDir, plugin_dir); | 248 new PluginSandboxedProcessLauncherDelegate(process_->GetHost()), |
| 78 #endif | 249 cmd_line); |
| 79 } | 250 |
| 80 | 251 // The plugin needs to be shutdown gracefully, i.e. NP_Shutdown needs to be |
| 81 virtual void SetUpOnMainThread() OVERRIDE { | 252 // called on the plugin. The plugin process exits when it receives the |
| 82 base::FilePath path = GetTestFilePath("", ""); | 253 // OnChannelError notification indicating that the browser plugin channel has |
| 83 BrowserThread::PostTask( | 254 // been destroyed. |
| 84 BrowserThread::IO, FROM_HERE, base::Bind(&SetUrlRequestMock, path)); | 255 process_->SetTerminateChildOnShutdown(false); |
| 85 } | 256 |
| 86 | 257 ResourceMessageFilter::GetContextsCallback get_contexts_callback( |
| 87 static void LoadAndWaitInWindow(Shell* window, const GURL& url) { | 258 base::Bind(&PluginProcessHost::GetContexts, |
| 88 base::string16 expected_title(ASCIIToUTF16("OK")); | 259 base::Unretained(this))); |
| 89 TitleWatcher title_watcher(window->web_contents(), expected_title); | 260 |
| 90 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); | 261 // TODO(jam): right now we're passing NULL for appcache, blob storage, and |
| 91 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found")); | 262 // file system. If NPAPI plugins actually use this, we'll have to plumb them. |
| 92 NavigateToURL(window, url); | 263 ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter( |
| 93 base::string16 title = title_watcher.WaitAndGetTitle(); | 264 process_->GetData().id, PROCESS_TYPE_PLUGIN, NULL, NULL, NULL, NULL, |
| 94 if (title == ASCIIToUTF16("plugin_not_found")) { | 265 get_contexts_callback); |
| 95 const testing::TestInfo* const test_info = | 266 process_->AddFilter(resource_message_filter); |
| 96 testing::UnitTest::GetInstance()->current_test_info(); | 267 return true; |
| 97 VLOG(0) << "PluginTest." << test_info->name() | 268 } |
| 98 << " not running because plugin not installed."; | 269 |
| 99 } else { | 270 void PluginProcessHost::ForceShutdown() { |
| 100 EXPECT_EQ(expected_title, title); | 271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 101 } | 272 Send(new PluginProcessMsg_NotifyRenderersOfPendingShutdown()); |
| 102 } | 273 process_->ForceShutdown(); |
| 103 | 274 } |
| 104 void LoadAndWait(const GURL& url) { | 275 |
| 105 LoadAndWaitInWindow(shell(), url); | 276 bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { |
| 106 } | 277 bool handled = true; |
| 107 | 278 IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg) |
| 108 GURL GetURL(const char* filename) { | 279 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated) |
| 109 return GetTestUrl("npapi", filename); | 280 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelDestroyed, |
| 110 } | 281 OnChannelDestroyed) |
| 111 | 282 #if defined(OS_WIN) |
| 112 void NavigateAway() { | 283 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed, |
| 113 GURL url = GetTestUrl("", "simple_page.html"); | 284 OnPluginWindowDestroyed) |
| 114 LoadAndWait(url); | 285 #endif |
| 115 } | 286 #if defined(OS_MACOSX) |
| 116 | 287 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSelectWindow, |
| 117 void TestPlugin(const char* filename) { | 288 OnPluginSelectWindow) |
| 118 base::FilePath path = GetTestFilePath("plugin", filename); | 289 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginShowWindow, |
| 119 if (!base::PathExists(path)) { | 290 OnPluginShowWindow) |
| 120 const testing::TestInfo* const test_info = | 291 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginHideWindow, |
| 121 testing::UnitTest::GetInstance()->current_test_info(); | 292 OnPluginHideWindow) |
| 122 VLOG(0) << "PluginTest." << test_info->name() | 293 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSetCursorVisibility, |
| 123 << " not running because test data wasn't found."; | 294 OnPluginSetCursorVisibility) |
| 295 #endif | |
| 296 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 297 IPC_END_MESSAGE_MAP() | |
| 298 | |
| 299 return handled; | |
| 300 } | |
| 301 | |
| 302 void PluginProcessHost::OnChannelConnected(int32 peer_pid) { | |
| 303 for (size_t i = 0; i < pending_requests_.size(); ++i) { | |
| 304 RequestPluginChannel(pending_requests_[i]); | |
| 305 } | |
| 306 | |
| 307 pending_requests_.clear(); | |
| 308 } | |
| 309 | |
| 310 void PluginProcessHost::OnChannelError() { | |
| 311 CancelRequests(); | |
| 312 } | |
| 313 | |
| 314 bool PluginProcessHost::CanShutdown() { | |
| 315 return sent_requests_.empty(); | |
| 316 } | |
| 317 | |
| 318 void PluginProcessHost::OnProcessCrashed(int exit_code) { | |
| 319 PluginServiceImpl::GetInstance()->RegisterPluginCrash(info_.path); | |
| 320 } | |
| 321 | |
| 322 void PluginProcessHost::CancelRequests() { | |
| 323 for (size_t i = 0; i < pending_requests_.size(); ++i) | |
| 324 pending_requests_[i]->OnError(); | |
| 325 pending_requests_.clear(); | |
| 326 | |
| 327 while (!sent_requests_.empty()) { | |
| 328 Client* client = sent_requests_.front(); | |
| 329 if (client) | |
| 330 client->OnError(); | |
| 331 sent_requests_.pop_front(); | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 void PluginProcessHost::OpenChannelToPlugin(Client* client) { | |
| 336 BrowserThread::PostTask( | |
| 337 BrowserThread::UI, FROM_HERE, | |
| 338 base::Bind(&BrowserChildProcessHostImpl::NotifyProcessInstanceCreated, | |
| 339 process_->GetData())); | |
| 340 client->SetPluginInfo(info_); | |
| 341 if (process_->GetHost()->IsChannelOpening()) { | |
| 342 // The channel is already in the process of being opened. Put | |
| 343 // this "open channel" request into a queue of requests that will | |
| 344 // be run once the channel is open. | |
| 345 pending_requests_.push_back(client); | |
| 346 return; | |
| 347 } | |
| 348 | |
| 349 // We already have an open channel, send a request right away to plugin. | |
| 350 RequestPluginChannel(client); | |
| 351 } | |
| 352 | |
| 353 void PluginProcessHost::CancelPendingRequest(Client* client) { | |
| 354 std::vector<Client*>::iterator it = pending_requests_.begin(); | |
| 355 while (it != pending_requests_.end()) { | |
| 356 if (client == *it) { | |
| 357 pending_requests_.erase(it); | |
| 124 return; | 358 return; |
| 125 } | 359 } |
| 126 | 360 ++it; |
| 127 GURL url = GetTestUrl("plugin", filename); | 361 } |
| 128 LoadAndWait(url); | 362 DCHECK(it != pending_requests_.end()); |
| 129 } | 363 } |
| 130 }; | 364 |
| 131 | 365 void PluginProcessHost::CancelSentRequest(Client* client) { |
| 132 // Make sure that navigating away from a plugin referenced by JS doesn't | 366 std::list<Client*>::iterator it = sent_requests_.begin(); |
| 133 // crash. | 367 while (it != sent_requests_.end()) { |
| 134 IN_PROC_BROWSER_TEST_F(PluginTest, UnloadNoCrash) { | 368 if (client == *it) { |
| 135 LoadAndWait(GetURL("layout_test_plugin.html")); | 369 *it = NULL; |
| 136 NavigateAway(); | |
| 137 } | |
| 138 | |
| 139 // Tests if a plugin executing a self deleting script using NPN_GetURL | |
| 140 // works without crashing or hanging | |
| 141 // Flaky: http://crbug.com/59327 | |
| 142 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginGetUrl)) { | |
| 143 LoadAndWait(GetURL("self_delete_plugin_geturl.html")); | |
| 144 } | |
| 145 | |
| 146 // Tests if a plugin executing a self deleting script using Invoke | |
| 147 // works without crashing or hanging | |
| 148 // Flaky. See http://crbug.com/30702 | |
| 149 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvoke)) { | |
| 150 LoadAndWait(GetURL("self_delete_plugin_invoke.html")); | |
| 151 } | |
| 152 | |
| 153 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectReleasedOnDestruction)) { | |
| 154 NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html")); | |
| 155 NavigateAway(); | |
| 156 } | |
| 157 | |
| 158 // Test that a dialog is properly created when a plugin throws an | |
| 159 // exception. Should be run for in and out of process plugins, but | |
| 160 // the more interesting case is out of process, where we must route | |
| 161 // the exception to the correct renderer. | |
| 162 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectSetException)) { | |
| 163 LoadAndWait(GetURL("npobject_set_exception.html")); | |
| 164 } | |
| 165 | |
| 166 #if defined(OS_WIN) | |
| 167 // Tests if a plugin executing a self deleting script in the context of | |
| 168 // a synchronous mouseup works correctly. | |
| 169 // This was never ported to Mac. The only thing remaining is to make | |
| 170 // SimulateMouseClick get to Mac plugins, currently it doesn't work. | |
| 171 IN_PROC_BROWSER_TEST_F(PluginTest, | |
| 172 MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp)) { | |
| 173 NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html")); | |
| 174 | |
| 175 base::string16 expected_title(ASCIIToUTF16("OK")); | |
| 176 TitleWatcher title_watcher(shell()->web_contents(), expected_title); | |
| 177 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); | |
| 178 SimulateMouseClick(shell()->web_contents(), 0, | |
| 179 blink::WebMouseEvent::ButtonLeft); | |
| 180 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); | |
| 181 } | |
| 182 #endif | |
| 183 | |
| 184 // Flaky, http://crbug.com/302274. | |
| 185 #if defined(OS_MACOSX) | |
| 186 #define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response | |
| 187 #else | |
| 188 #define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response) | |
| 189 #endif | |
| 190 | |
| 191 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_GetURLRequest404Response) { | |
| 192 GURL url(URLRequestMockHTTPJob::GetMockUrl( | |
| 193 base::FilePath().AppendASCII("npapi"). | |
| 194 AppendASCII("plugin_url_request_404.html"))); | |
| 195 LoadAndWait(url); | |
| 196 } | |
| 197 | |
| 198 // Tests if a plugin executing a self deleting script using Invoke with | |
| 199 // a modal dialog showing works without crashing or hanging | |
| 200 // Disabled, flakily exceeds timeout, http://crbug.com/46257. | |
| 201 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) { | |
| 202 // Navigate asynchronously because if we waitd until it completes, there's a | |
| 203 // race condition where the alert can come up before we start watching for it. | |
| 204 shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html")); | |
| 205 | |
| 206 base::string16 expected_title(ASCIIToUTF16("OK")); | |
| 207 TitleWatcher title_watcher(shell()->web_contents(), expected_title); | |
| 208 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); | |
| 209 | |
| 210 WaitForAppModalDialog(shell()); | |
| 211 | |
| 212 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); | |
| 213 } | |
| 214 | |
| 215 // Test passing arguments to a plugin. | |
| 216 // crbug.com/306318 | |
| 217 #if !defined(OS_LINUX) | |
| 218 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Arguments)) { | |
| 219 LoadAndWait(GetURL("arguments.html")); | |
| 220 } | |
| 221 #endif | |
| 222 | |
| 223 // Test invoking many plugins within a single page. | |
| 224 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ManyPlugins)) { | |
| 225 LoadAndWait(GetURL("many_plugins.html")); | |
| 226 } | |
| 227 | |
| 228 // Test various calls to GetURL from a plugin. | |
| 229 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURL)) { | |
| 230 LoadAndWait(GetURL("geturl.html")); | |
| 231 } | |
| 232 | |
| 233 // Test various calls to GetURL for javascript URLs with | |
| 234 // non NULL targets from a plugin. | |
| 235 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL)) { | |
| 236 LoadAndWait(GetURL("get_javascript_url.html")); | |
| 237 } | |
| 238 | |
| 239 // Test that calling GetURL with a javascript URL and target=_self | |
| 240 // works properly when the plugin is embedded in a subframe. | |
| 241 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL2)) { | |
| 242 LoadAndWait(GetURL("get_javascript_url2.html")); | |
| 243 } | |
| 244 | |
| 245 // Test is flaky on linux/cros/win builders. http://crbug.com/71904 | |
| 246 IN_PROC_BROWSER_TEST_F(PluginTest, GetURLRedirectNotification) { | |
| 247 LoadAndWait(GetURL("geturl_redirect_notify.html")); | |
| 248 } | |
| 249 | |
| 250 // Tests that identity is preserved for NPObjects passed from a plugin | |
| 251 // into JavaScript. | |
| 252 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectIdentity)) { | |
| 253 LoadAndWait(GetURL("npobject_identity.html")); | |
| 254 } | |
| 255 | |
| 256 // Tests that if an NPObject is proxies back to its original process, the | |
| 257 // original pointer is returned and not a proxy. If this fails the plugin | |
| 258 // will crash. | |
| 259 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectProxy)) { | |
| 260 LoadAndWait(GetURL("npobject_proxy.html")); | |
| 261 } | |
| 262 | |
| 263 #if defined(OS_WIN) || defined(OS_MACOSX) | |
| 264 // Tests if a plugin executing a self deleting script in the context of | |
| 265 // a synchronous paint event works correctly | |
| 266 // http://crbug.com/44960 | |
| 267 IN_PROC_BROWSER_TEST_F(PluginTest, | |
| 268 MAYBE(SelfDeletePluginInvokeInSynchronousPaint)) { | |
| 269 LoadAndWait(GetURL("execute_script_delete_in_paint.html")); | |
| 270 } | |
| 271 #endif | |
| 272 | |
| 273 // Tests that if a plugin executes a self resizing script in the context of a | |
| 274 // synchronous paint, the plugin doesn't use deallocated memory. | |
| 275 // http://crbug.com/139462 | |
| 276 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ResizeDuringPaint)) { | |
| 277 LoadAndWait(GetURL("resize_during_paint.html")); | |
| 278 } | |
| 279 | |
| 280 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNewStream)) { | |
| 281 LoadAndWait(GetURL("self_delete_plugin_stream.html")); | |
| 282 } | |
| 283 | |
| 284 // On Mac this test asserts in plugin_host: http://crbug.com/95558 | |
| 285 // On all platforms it flakes in ~URLRequestContext: http://crbug.com/310336 | |
| 286 #if !defined(NDEBUG) | |
| 287 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_DeletePluginInDeallocate) { | |
| 288 LoadAndWait(GetURL("plugin_delete_in_deallocate.html")); | |
| 289 } | |
| 290 #endif | |
| 291 | |
| 292 #if defined(OS_WIN) | |
| 293 | |
| 294 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyPluginWindowRect)) { | |
| 295 LoadAndWait(GetURL("verify_plugin_window_rect.html")); | |
| 296 } | |
| 297 | |
| 298 // Tests that creating a new instance of a plugin while another one is handling | |
| 299 // a paint message doesn't cause deadlock. | |
| 300 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(CreateInstanceInPaint)) { | |
| 301 LoadAndWait(GetURL("create_instance_in_paint.html")); | |
| 302 } | |
| 303 | |
| 304 // Tests that putting up an alert in response to a paint doesn't deadlock. | |
| 305 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_AlertInWindowMessage) { | |
| 306 NavigateToURL(shell(), GetURL("alert_in_window_message.html")); | |
| 307 | |
| 308 WaitForAppModalDialog(shell()); | |
| 309 WaitForAppModalDialog(shell()); | |
| 310 } | |
| 311 | |
| 312 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyNPObjectLifetimeTest)) { | |
| 313 LoadAndWait(GetURL("npobject_lifetime_test.html")); | |
| 314 } | |
| 315 | |
| 316 // Tests that we don't crash or assert if NPP_New fails | |
| 317 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NewFails)) { | |
| 318 LoadAndWait(GetURL("new_fails.html")); | |
| 319 } | |
| 320 | |
| 321 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNPNEvaluate)) { | |
| 322 LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html")); | |
| 323 } | |
| 324 | |
| 325 IN_PROC_BROWSER_TEST_F(PluginTest, | |
| 326 MAYBE(SelfDeleteCreatePluginInNPNEvaluate)) { | |
| 327 LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html")); | |
| 328 } | |
| 329 | |
| 330 #endif // OS_WIN | |
| 331 | |
| 332 // If this flakes, reopen http://crbug.com/17645 | |
| 333 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out). | |
| 334 #if !defined(OS_MACOSX) && !defined(OS_LINUX) | |
| 335 // Disabled on Mac because the plugin side isn't implemented yet, see | |
| 336 // "TODO(port)" in plugin_javascript_open_popup.cc. | |
| 337 // Disabled on Linux because we don't support NPAPI any more. | |
| 338 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(OpenPopupWindowWithPlugin)) { | |
| 339 LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html")); | |
| 340 } | |
| 341 #endif | |
| 342 | |
| 343 // Test checking the privacy mode is off. | |
| 344 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateDisabled)) { | |
| 345 LoadAndWait(GetURL("private.html")); | |
| 346 } | |
| 347 | |
| 348 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ScheduleTimer)) { | |
| 349 LoadAndWait(GetURL("schedule_timer.html")); | |
| 350 } | |
| 351 | |
| 352 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginThreadAsyncCall)) { | |
| 353 LoadAndWait(GetURL("plugin_thread_async_call.html")); | |
| 354 } | |
| 355 | |
| 356 IN_PROC_BROWSER_TEST_F(PluginTest, PluginSingleRangeRequest) { | |
| 357 LoadAndWait(GetURL("plugin_single_range_request.html")); | |
| 358 } | |
| 359 | |
| 360 // Test checking the privacy mode is on. | |
| 361 // If this flakes on Linux, use http://crbug.com/104380 | |
| 362 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateEnabled)) { | |
| 363 GURL url = GetURL("private.html"); | |
| 364 url = GURL(url.spec() + "?private"); | |
| 365 LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url); | |
| 366 } | |
| 367 | |
| 368 #if defined(OS_WIN) || defined(OS_MACOSX) | |
| 369 // Test a browser hang due to special case of multiple | |
| 370 // plugin instances indulged in sync calls across renderer. | |
| 371 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MultipleInstancesSyncCalls)) { | |
| 372 LoadAndWait(GetURL("multiple_instances_sync_calls.html")); | |
| 373 } | |
| 374 #endif | |
| 375 | |
| 376 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequestFailWrite)) { | |
| 377 GURL url(URLRequestMockHTTPJob::GetMockUrl( | |
| 378 base::FilePath().AppendASCII("npapi"). | |
| 379 AppendASCII("plugin_url_request_fail_write.html"))); | |
| 380 LoadAndWait(url); | |
| 381 } | |
| 382 | |
| 383 #if defined(OS_WIN) | |
| 384 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(EnsureScriptingWorksInDestroy)) { | |
| 385 LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html")); | |
| 386 } | |
| 387 | |
| 388 // This test uses a Windows Event to signal to the plugin that it should crash | |
| 389 // on NP_Initialize. | |
| 390 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NoHangIfInitCrashes)) { | |
| 391 HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit"); | |
| 392 SetEvent(crash_event); | |
| 393 LoadAndWait(GetURL("no_hang_if_init_crashes.html")); | |
| 394 CloseHandle(crash_event); | |
| 395 } | |
| 396 #endif | |
| 397 | |
| 398 // If this flakes on Mac, use http://crbug.com/111508 | |
| 399 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginReferrerTest)) { | |
| 400 GURL url(URLRequestMockHTTPJob::GetMockUrl( | |
| 401 base::FilePath().AppendASCII("npapi"). | |
| 402 AppendASCII("plugin_url_request_referrer_test.html"))); | |
| 403 LoadAndWait(url); | |
| 404 } | |
| 405 | |
| 406 #if defined(OS_MACOSX) | |
| 407 // Test is flaky, see http://crbug.com/134515. | |
| 408 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_PluginConvertPointTest) { | |
| 409 gfx::Rect bounds(50, 50, 400, 400); | |
| 410 SetWindowBounds(shell()->window(), bounds); | |
| 411 | |
| 412 NavigateToURL(shell(), GetURL("convert_point.html")); | |
| 413 | |
| 414 base::string16 expected_title(ASCIIToUTF16("OK")); | |
| 415 TitleWatcher title_watcher(shell()->web_contents(), expected_title); | |
| 416 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); | |
| 417 // TODO(stuartmorgan): When the automation system supports sending clicks, | |
| 418 // change the test to trigger on mouse-down rather than window focus. | |
| 419 | |
| 420 // TODO: is this code still needed? It was here when it used to run in | |
| 421 // browser_tests. | |
| 422 //static_cast<WebContentsDelegate*>(shell())-> | |
| 423 // ActivateContents(shell()->web_contents()); | |
| 424 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); | |
| 425 } | |
| 426 #endif | |
| 427 | |
| 428 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Flash)) { | |
| 429 TestPlugin("flash.html"); | |
| 430 } | |
| 431 | |
| 432 #if defined(OS_WIN) | |
| 433 // Windows only test | |
| 434 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashSecurity) { | |
| 435 TestPlugin("flash.html"); | |
| 436 } | |
| 437 #endif // defined(OS_WIN) | |
| 438 | |
| 439 #if defined(OS_WIN) | |
| 440 // TODO(port) Port the following tests to platforms that have the required | |
| 441 // plugins. | |
| 442 // Flaky: http://crbug.com/55915 | |
| 443 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Quicktime)) { | |
| 444 TestPlugin("quicktime.html"); | |
| 445 } | |
| 446 | |
| 447 // Disabled - http://crbug.com/44662 | |
| 448 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MediaPlayerNew)) { | |
| 449 TestPlugin("wmp_new.html"); | |
| 450 } | |
| 451 | |
| 452 // Disabled - http://crbug.com/44673 | |
| 453 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Real)) { | |
| 454 TestPlugin("real.html"); | |
| 455 } | |
| 456 | |
| 457 // http://crbug.com/320041 | |
| 458 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \ | |
| 459 (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN)) | |
| 460 #define MAYBE_FlashOctetStream DISABLED_FlashOctetStream | |
| 461 #else | |
| 462 #define MAYBE_FlashOctetStream FlashOctetStream | |
| 463 #endif | |
| 464 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_FlashOctetStream) { | |
| 465 TestPlugin("flash-octet-stream.html"); | |
| 466 } | |
| 467 | |
| 468 #if defined(OS_WIN) | |
| 469 // http://crbug.com/53926 | |
| 470 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashLayoutWhilePainting) { | |
| 471 #else | |
| 472 IN_PROC_BROWSER_TEST_F(PluginTest, FlashLayoutWhilePainting) { | |
| 473 #endif | |
| 474 TestPlugin("flash-layout-while-painting.html"); | |
| 475 } | |
| 476 | |
| 477 // http://crbug.com/8690 | |
| 478 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Java) { | |
| 479 TestPlugin("Java.html"); | |
| 480 } | |
| 481 | |
| 482 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Silverlight)) { | |
| 483 TestPlugin("silverlight.html"); | |
| 484 } | |
| 485 #endif // defined(OS_WIN) | |
| 486 | |
| 487 class TestResourceDispatcherHostDelegate | |
| 488 : public ResourceDispatcherHostDelegate { | |
| 489 public: | |
| 490 TestResourceDispatcherHostDelegate() : found_cookie_(false) {} | |
| 491 | |
| 492 bool found_cookie() { return found_cookie_; } | |
| 493 | |
| 494 void WaitForPluginRequest() { | |
| 495 if (found_cookie_) | |
| 496 return; | |
| 497 | |
| 498 runner_ = new MessageLoopRunner; | |
| 499 runner_->Run(); | |
| 500 } | |
| 501 | |
| 502 private: | |
| 503 // ResourceDispatcherHostDelegate implementation: | |
| 504 virtual void OnResponseStarted( | |
| 505 net::URLRequest* request, | |
| 506 ResourceContext* resource_context, | |
| 507 ResourceResponse* response, | |
| 508 IPC::Sender* sender) OVERRIDE { | |
| 509 // The URL below comes from plugin_geturl_test.cc. | |
| 510 if (!EndsWith(request->url().spec(), | |
| 511 "npapi/plugin_ref_target_page.html", | |
| 512 true)) { | |
| 513 return; | 370 return; |
| 514 } | 371 } |
| 515 net::HttpRequestHeaders headers; | 372 ++it; |
| 516 bool found_cookie = false; | 373 } |
| 517 if (request->GetFullRequestHeaders(&headers) && | 374 DCHECK(it != sent_requests_.end()); |
| 518 headers.ToString().find("Cookie: blah") != std::string::npos) { | 375 } |
| 519 found_cookie = true; | 376 |
| 377 void PluginProcessHost::RequestPluginChannel(Client* client) { | |
| 378 // We can't send any sync messages from the browser because it might lead to | |
| 379 // a hang. However this async messages must be answered right away by the | |
| 380 // plugin process (i.e. unblocks a Send() call like a sync message) otherwise | |
| 381 // a deadlock can occur if the plugin creation request from the renderer is | |
| 382 // a result of a sync message by the plugin process. | |
| 383 PluginProcessMsg_CreateChannel* msg = | |
| 384 new PluginProcessMsg_CreateChannel( | |
| 385 client->ID(), | |
| 386 client->OffTheRecord()); | |
| 387 msg->set_unblock(true); | |
| 388 if (Send(msg)) { | |
| 389 sent_requests_.push_back(client); | |
| 390 client->OnSentPluginChannelRequest(); | |
| 391 } else { | |
| 392 client->OnError(); | |
| 393 } | |
| 394 } | |
| 395 | |
| 396 void PluginProcessHost::OnChannelCreated( | |
| 397 const IPC::ChannelHandle& channel_handle) { | |
| 398 Client* client = sent_requests_.front(); | |
| 399 | |
| 400 if (client) { | |
| 401 if (!resource_context_map_.count(client->ID())) { | |
| 402 ResourceContextEntry entry; | |
| 403 entry.ref_count = 0; | |
| 404 entry.resource_context = client->GetResourceContext(); | |
| 405 resource_context_map_[client->ID()] = entry; | |
| 520 } | 406 } |
| 521 BrowserThread::PostTask( | 407 resource_context_map_[client->ID()].ref_count++; |
| 522 BrowserThread::UI, | 408 client->OnChannelOpened(channel_handle); |
| 523 FROM_HERE, | 409 } |
| 524 base::Bind(&TestResourceDispatcherHostDelegate::GotCookie, | 410 sent_requests_.pop_front(); |
| 525 base::Unretained(this), found_cookie)); | 411 } |
| 526 } | 412 |
| 527 | 413 void PluginProcessHost::OnChannelDestroyed(int renderer_id) { |
| 528 void GotCookie(bool found_cookie) { | 414 resource_context_map_[renderer_id].ref_count--; |
| 529 found_cookie_ = found_cookie; | 415 if (!resource_context_map_[renderer_id].ref_count) |
| 530 if (runner_) | 416 resource_context_map_.erase(renderer_id); |
| 531 runner_->QuitClosure().Run(); | 417 } |
| 532 } | 418 |
| 533 | 419 void PluginProcessHost::GetContexts(const ResourceHostMsg_Request& request, |
| 534 scoped_refptr<MessageLoopRunner> runner_; | 420 ResourceContext** resource_context, |
| 535 bool found_cookie_; | 421 net::URLRequestContext** request_context) { |
| 536 | 422 *resource_context = |
| 537 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate); | 423 resource_context_map_[request.origin_pid].resource_context; |
| 538 }; | 424 *request_context = (*resource_context)->GetRequestContext(); |
| 539 | |
| 540 // Ensure that cookies get sent with plugin requests. | |
| 541 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Cookies)) { | |
| 542 // Create a new browser just to ensure that the plugin process' child_id is | |
| 543 // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which | |
| 544 // caused this bug. | |
| 545 NavigateToURL(CreateBrowser(), GURL("about:blank")); | |
| 546 | |
| 547 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); | |
| 548 GURL url(embedded_test_server()->GetURL("/npapi/cookies.html")); | |
| 549 | |
| 550 TestResourceDispatcherHostDelegate test_delegate; | |
| 551 ResourceDispatcherHostDelegate* old_delegate = | |
| 552 ResourceDispatcherHostImpl::Get()->delegate(); | |
| 553 ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate); | |
| 554 LoadAndWait(url); | |
| 555 test_delegate.WaitForPluginRequest(); | |
| 556 ASSERT_TRUE(test_delegate.found_cookie()); | |
| 557 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate); | |
| 558 } | 425 } |
| 559 | 426 |
| 560 } // namespace content | 427 } // namespace content |
| OLD | NEW |