Home | History | Annotate | Download | only in browser
      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
      3 // found in the LICENSE file.
      4 
      5 #include "base/command_line.h"
      6 #include "base/files/file_util.h"
      7 #include "base/path_service.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "content/browser/loader/resource_dispatcher_host_impl.h"
     11 #include "content/public/browser/browser_thread.h"
     12 #include "content/public/browser/resource_dispatcher_host_delegate.h"
     13 #include "content/public/common/content_switches.h"
     14 #include "content/public/test/browser_test_utils.h"
     15 #include "content/public/test/content_browser_test.h"
     16 #include "content/public/test/content_browser_test_utils.h"
     17 #include "content/public/test/test_utils.h"
     18 #include "content/shell/browser/shell.h"
     19 #include "content/shell/common/shell_switches.h"
     20 #include "net/test/embedded_test_server/embedded_test_server.h"
     21 #include "net/test/url_request/url_request_mock_http_job.h"
     22 #include "net/url_request/url_request.h"
     23 #include "ui/gfx/rect.h"
     24 
     25 #if defined(OS_WIN)
     26 #include "base/win/registry.h"
     27 #endif
     28 
     29 // TODO(jschuh): Finish plugins on Win64. crbug.com/180861
     30 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
     31 #define MAYBE(x) DISABLED_##x
     32 #else
     33 #define MAYBE(x) x
     34 #endif
     35 
     36 using base::ASCIIToUTF16;
     37 
     38 namespace content {
     39 namespace {
     40 
     41 void SetUrlRequestMock(const base::FilePath& path) {
     42   net::URLRequestMockHTTPJob::AddUrlHandler(
     43       path, content::BrowserThread::GetBlockingPool());
     44 }
     45 
     46 }
     47 
     48 class PluginTest : public ContentBrowserTest {
     49  protected:
     50   PluginTest() {}
     51 
     52   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     53     // Some NPAPI tests schedule garbage collection to force object tear-down.
     54     command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose_gc");
     55 
     56 #if defined(OS_WIN)
     57     const testing::TestInfo* const test_info =
     58         testing::UnitTest::GetInstance()->current_test_info();
     59     if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
     60       // The installer adds our process names to the registry key below.  Since
     61       // the installer might not have run on this machine, add it manually.
     62       base::win::RegKey regkey;
     63       if (regkey.Open(HKEY_LOCAL_MACHINE,
     64                       L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
     65                       KEY_WRITE) == ERROR_SUCCESS) {
     66         regkey.CreateKey(L"BROWSER_TESTS.EXE", KEY_READ);
     67       }
     68     }
     69 #elif defined(OS_MACOSX)
     70     base::FilePath plugin_dir;
     71     PathService::Get(base::DIR_MODULE, &plugin_dir);
     72     plugin_dir = plugin_dir.AppendASCII("plugins");
     73     // The plugins directory isn't read by default on the Mac, so it needs to be
     74     // explicitly registered.
     75     command_line->AppendSwitchPath(switches::kExtraPluginDir, plugin_dir);
     76 #endif
     77   }
     78 
     79   virtual void SetUpOnMainThread() OVERRIDE {
     80     base::FilePath path = GetTestFilePath("", "");
     81     BrowserThread::PostTask(
     82         BrowserThread::IO, FROM_HERE, base::Bind(&SetUrlRequestMock, path));
     83   }
     84 
     85   static void LoadAndWaitInWindow(Shell* window, const GURL& url) {
     86     base::string16 expected_title(ASCIIToUTF16("OK"));
     87     TitleWatcher title_watcher(window->web_contents(), expected_title);
     88     title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
     89     title_watcher.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found"));
     90     NavigateToURL(window, url);
     91     base::string16 title = title_watcher.WaitAndGetTitle();
     92     if (title == ASCIIToUTF16("plugin_not_found")) {
     93       const testing::TestInfo* const test_info =
     94           testing::UnitTest::GetInstance()->current_test_info();
     95       VLOG(0) << "PluginTest." << test_info->name()
     96               << " not running because plugin not installed.";
     97     } else {
     98       EXPECT_EQ(expected_title, title);
     99     }
    100   }
    101 
    102   void LoadAndWait(const GURL& url) {
    103     LoadAndWaitInWindow(shell(), url);
    104   }
    105 
    106   GURL GetURL(const char* filename) {
    107     return GetTestUrl("npapi", filename);
    108   }
    109 
    110   void NavigateAway() {
    111     GURL url = GetTestUrl("", "simple_page.html");
    112     LoadAndWait(url);
    113   }
    114 
    115   void TestPlugin(const char* filename) {
    116     base::FilePath path = GetTestFilePath("plugin", filename);
    117     if (!base::PathExists(path)) {
    118       const testing::TestInfo* const test_info =
    119           testing::UnitTest::GetInstance()->current_test_info();
    120       VLOG(0) << "PluginTest." << test_info->name()
    121               << " not running because test data wasn't found.";
    122       return;
    123     }
    124 
    125     GURL url = GetTestUrl("plugin", filename);
    126     LoadAndWait(url);
    127   }
    128 };
    129 
    130 // Make sure that navigating away from a plugin referenced by JS doesn't
    131 // crash.
    132 IN_PROC_BROWSER_TEST_F(PluginTest, UnloadNoCrash) {
    133   LoadAndWait(GetURL("layout_test_plugin.html"));
    134   NavigateAway();
    135 }
    136 
    137 // Tests if a plugin executing a self deleting script using NPN_GetURL
    138 // works without crashing or hanging
    139 // Flaky: http://crbug.com/59327
    140 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginGetUrl)) {
    141   LoadAndWait(GetURL("self_delete_plugin_geturl.html"));
    142 }
    143 
    144 // Tests if a plugin executing a self deleting script using Invoke
    145 // works without crashing or hanging
    146 // Flaky. See http://crbug.com/30702
    147 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvoke)) {
    148   LoadAndWait(GetURL("self_delete_plugin_invoke.html"));
    149 }
    150 
    151 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectReleasedOnDestruction)) {
    152   NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html"));
    153   NavigateAway();
    154 }
    155 
    156 // Test that a dialog is properly created when a plugin throws an
    157 // exception.  Should be run for in and out of process plugins, but
    158 // the more interesting case is out of process, where we must route
    159 // the exception to the correct renderer.
    160 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectSetException)) {
    161   LoadAndWait(GetURL("npobject_set_exception.html"));
    162 }
    163 
    164 #if defined(OS_WIN)
    165 // Tests if a plugin executing a self deleting script in the context of
    166 // a synchronous mouseup works correctly.
    167 // This was never ported to Mac. The only thing remaining is to make
    168 // SimulateMouseClick get to Mac plugins, currently it doesn't work.
    169 IN_PROC_BROWSER_TEST_F(PluginTest,
    170                        MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp)) {
    171   NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html"));
    172 
    173   base::string16 expected_title(ASCIIToUTF16("OK"));
    174   TitleWatcher title_watcher(shell()->web_contents(), expected_title);
    175   title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
    176   SimulateMouseClick(shell()->web_contents(), 0,
    177       blink::WebMouseEvent::ButtonLeft);
    178   EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
    179 }
    180 #endif
    181 
    182 // Flaky, http://crbug.com/302274.
    183 #if defined(OS_MACOSX)
    184 #define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response
    185 #else
    186 #define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response)
    187 #endif
    188 
    189 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_GetURLRequest404Response) {
    190   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
    191       base::FilePath().AppendASCII("npapi").AppendASCII(
    192           "plugin_url_request_404.html")));
    193   LoadAndWait(url);
    194 }
    195 
    196 // Tests if a plugin executing a self deleting script using Invoke with
    197 // a modal dialog showing works without crashing or hanging
    198 // Disabled, flakily exceeds timeout, http://crbug.com/46257.
    199 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) {
    200   // Navigate asynchronously because if we waitd until it completes, there's a
    201   // race condition where the alert can come up before we start watching for it.
    202   shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html"));
    203 
    204   base::string16 expected_title(ASCIIToUTF16("OK"));
    205   TitleWatcher title_watcher(shell()->web_contents(), expected_title);
    206   title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
    207 
    208   WaitForAppModalDialog(shell());
    209 
    210   EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
    211 }
    212 
    213 // Test passing arguments to a plugin.
    214 // crbug.com/306318
    215 #if !defined(OS_LINUX)
    216 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Arguments)) {
    217   LoadAndWait(GetURL("arguments.html"));
    218 }
    219 #endif
    220 
    221 // Test invoking many plugins within a single page.
    222 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ManyPlugins)) {
    223   LoadAndWait(GetURL("many_plugins.html"));
    224 }
    225 
    226 #if !defined(OS_MACOSX)  // http://crbug.com/402164
    227 // Test various calls to GetURL from a plugin.
    228 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURL)) {
    229   LoadAndWait(GetURL("geturl.html"));
    230 }
    231 #endif
    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 // http://crbug.com/406184
    301 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_CreateInstanceInPaint) {
    302   LoadAndWait(GetURL("create_instance_in_paint.html"));
    303 }
    304 
    305 // Tests that putting up an alert in response to a paint doesn't deadlock.
    306 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_AlertInWindowMessage) {
    307   NavigateToURL(shell(), GetURL("alert_in_window_message.html"));
    308 
    309   WaitForAppModalDialog(shell());
    310   WaitForAppModalDialog(shell());
    311 }
    312 
    313 // http://crbug.com/406184
    314 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_VerifyNPObjectLifetimeTest) {
    315   LoadAndWait(GetURL("npobject_lifetime_test.html"));
    316 }
    317 
    318 // Tests that we don't crash or assert if NPP_New fails
    319 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NewFails)) {
    320   LoadAndWait(GetURL("new_fails.html"));
    321 }
    322 
    323 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNPNEvaluate)) {
    324   LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html"));
    325 }
    326 
    327 IN_PROC_BROWSER_TEST_F(PluginTest,
    328                        MAYBE(SelfDeleteCreatePluginInNPNEvaluate)) {
    329   LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html"));
    330 }
    331 
    332 #endif  // OS_WIN
    333 
    334 // If this flakes, reopen http://crbug.com/17645
    335 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out).
    336 #if !defined(OS_MACOSX) && !defined(OS_LINUX)
    337 // Disabled on Mac because the plugin side isn't implemented yet, see
    338 // "TODO(port)" in plugin_javascript_open_popup.cc.
    339 // Disabled on Linux because we don't support NPAPI any more.
    340 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(OpenPopupWindowWithPlugin)) {
    341   LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html"));
    342 }
    343 #endif
    344 
    345 // Test checking the privacy mode is off.
    346 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateDisabled)) {
    347   LoadAndWait(GetURL("private.html"));
    348 }
    349 
    350 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ScheduleTimer)) {
    351   LoadAndWait(GetURL("schedule_timer.html"));
    352 }
    353 
    354 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginThreadAsyncCall)) {
    355   LoadAndWait(GetURL("plugin_thread_async_call.html"));
    356 }
    357 
    358 IN_PROC_BROWSER_TEST_F(PluginTest, PluginSingleRangeRequest) {
    359   LoadAndWait(GetURL("plugin_single_range_request.html"));
    360 }
    361 
    362 #if !defined(OS_WIN) // http://crbug.com/396373
    363 // Test checking the privacy mode is on.
    364 // If this flakes on Linux, use http://crbug.com/104380
    365 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateEnabled)) {
    366   GURL url = GetURL("private.html");
    367   url = GURL(url.spec() + "?private");
    368   LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url);
    369 }
    370 #endif
    371 
    372 // These used to run on Windows: http://crbug.com/396373
    373 #if defined(OS_MACOSX)
    374 // Test a browser hang due to special case of multiple
    375 // plugin instances indulged in sync calls across renderer.
    376 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MultipleInstancesSyncCalls)) {
    377   LoadAndWait(GetURL("multiple_instances_sync_calls.html"));
    378 }
    379 
    380 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequestFailWrite)) {
    381   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
    382       base::FilePath().AppendASCII("npapi").AppendASCII(
    383           "plugin_url_request_fail_write.html")));
    384   LoadAndWait(url);
    385 }
    386 #endif
    387 
    388 #if defined(OS_WIN)
    389 // Flaky on Windows x86.  http://crbug.com/388245
    390 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_EnsureScriptingWorksInDestroy) {
    391   LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html"));
    392 }
    393 
    394 // This test uses a Windows Event to signal to the plugin that it should crash
    395 // on NP_Initialize.
    396 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NoHangIfInitCrashes)) {
    397   HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit");
    398   SetEvent(crash_event);
    399   LoadAndWait(GetURL("no_hang_if_init_crashes.html"));
    400   CloseHandle(crash_event);
    401 }
    402 #endif
    403 
    404 // If this flakes on Mac, use http://crbug.com/111508
    405 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginReferrerTest)) {
    406   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
    407       base::FilePath().AppendASCII("npapi").AppendASCII(
    408           "plugin_url_request_referrer_test.html")));
    409   LoadAndWait(url);
    410 }
    411 
    412 #if defined(OS_MACOSX)
    413 // Test is flaky, see http://crbug.com/134515.
    414 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_PluginConvertPointTest) {
    415   gfx::Rect bounds(50, 50, 400, 400);
    416   SetWindowBounds(shell()->window(), bounds);
    417 
    418   NavigateToURL(shell(), GetURL("convert_point.html"));
    419 
    420   base::string16 expected_title(ASCIIToUTF16("OK"));
    421   TitleWatcher title_watcher(shell()->web_contents(), expected_title);
    422   title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
    423   // TODO(stuartmorgan): When the automation system supports sending clicks,
    424   // change the test to trigger on mouse-down rather than window focus.
    425 
    426   // TODO: is this code still needed? It was here when it used to run in
    427   // browser_tests.
    428   //static_cast<WebContentsDelegate*>(shell())->
    429   //    ActivateContents(shell()->web_contents());
    430   EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
    431 }
    432 #endif
    433 
    434 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Flash)) {
    435   TestPlugin("flash.html");
    436 }
    437 
    438 #if defined(OS_WIN)
    439 // Windows only test
    440 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashSecurity) {
    441   TestPlugin("flash.html");
    442 }
    443 #endif  // defined(OS_WIN)
    444 
    445 #if defined(OS_WIN)
    446 // TODO(port) Port the following tests to platforms that have the required
    447 // plugins.
    448 // Flaky: http://crbug.com/55915
    449 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Quicktime) {
    450   TestPlugin("quicktime.html");
    451 }
    452 
    453 // Disabled - http://crbug.com/44662
    454 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MediaPlayerNew)) {
    455   TestPlugin("wmp_new.html");
    456 }
    457 
    458 // Disabled - http://crbug.com/44673
    459 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Real)) {
    460   TestPlugin("real.html");
    461 }
    462 
    463 // http://crbug.com/320041
    464 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
    465     (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
    466 #define MAYBE_FlashOctetStream DISABLED_FlashOctetStream
    467 #else
    468 #define MAYBE_FlashOctetStream FlashOctetStream
    469 #endif
    470 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_FlashOctetStream) {
    471   TestPlugin("flash-octet-stream.html");
    472 }
    473 
    474 #if defined(OS_WIN)
    475 // http://crbug.com/53926
    476 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashLayoutWhilePainting) {
    477 #else
    478 IN_PROC_BROWSER_TEST_F(PluginTest, FlashLayoutWhilePainting) {
    479 #endif
    480   TestPlugin("flash-layout-while-painting.html");
    481 }
    482 
    483 // http://crbug.com/8690
    484 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Java) {
    485   TestPlugin("Java.html");
    486 }
    487 
    488 // Flaky: http://crbug.com/55915
    489 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Silverlight) {
    490   TestPlugin("silverlight.html");
    491 }
    492 #endif  // defined(OS_WIN)
    493 
    494 class TestResourceDispatcherHostDelegate
    495     : public ResourceDispatcherHostDelegate {
    496  public:
    497   TestResourceDispatcherHostDelegate() : found_cookie_(false) {}
    498 
    499   bool found_cookie() { return found_cookie_; }
    500 
    501   void WaitForPluginRequest() {
    502     if (found_cookie_)
    503       return;
    504 
    505     runner_ = new MessageLoopRunner;
    506     runner_->Run();
    507   }
    508 
    509  private:
    510   // ResourceDispatcherHostDelegate implementation:
    511   virtual void OnResponseStarted(
    512       net::URLRequest* request,
    513       ResourceContext* resource_context,
    514       ResourceResponse* response,
    515       IPC::Sender* sender) OVERRIDE {
    516     // The URL below comes from plugin_geturl_test.cc.
    517     if (!EndsWith(request->url().spec(),
    518                  "npapi/plugin_ref_target_page.html",
    519                  true)) {
    520       return;
    521     }
    522     net::HttpRequestHeaders headers;
    523     bool found_cookie = false;
    524     if (request->GetFullRequestHeaders(&headers) &&
    525         headers.ToString().find("Cookie: blah") != std::string::npos) {
    526       found_cookie = true;
    527     }
    528     BrowserThread::PostTask(
    529         BrowserThread::UI,
    530         FROM_HERE,
    531         base::Bind(&TestResourceDispatcherHostDelegate::GotCookie,
    532                    base::Unretained(this), found_cookie));
    533   }
    534 
    535   void GotCookie(bool found_cookie) {
    536     found_cookie_ = found_cookie;
    537     if (runner_.get())
    538       runner_->QuitClosure().Run();
    539   }
    540 
    541   scoped_refptr<MessageLoopRunner> runner_;
    542   bool found_cookie_;
    543 
    544   DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate);
    545 };
    546 
    547 // Ensure that cookies get sent with plugin requests.
    548 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Cookies)) {
    549   // Create a new browser just to ensure that the plugin process' child_id is
    550   // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which
    551   // caused this bug.
    552   NavigateToURL(CreateBrowser(), GURL("about:blank"));
    553 
    554   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
    555   GURL url(embedded_test_server()->GetURL("/npapi/cookies.html"));
    556 
    557   TestResourceDispatcherHostDelegate test_delegate;
    558   ResourceDispatcherHostDelegate* old_delegate =
    559       ResourceDispatcherHostImpl::Get()->delegate();
    560   ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate);
    561   LoadAndWait(url);
    562   test_delegate.WaitForPluginRequest();
    563   ASSERT_TRUE(test_delegate.found_cookie());
    564   ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate);
    565 }
    566 
    567 }  // namespace content
    568