| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 7 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 8 #include "base/macros.h" | 9 #include "base/macros.h" |
| 9 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| 10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/strings/string16.h" | 12 #include "base/strings/string16.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 13 #include "chrome/app/chrome_command_ids.h" | 14 #include "chrome/app/chrome_command_ids.h" |
| 14 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/chrome_notification_types.h" |
| 15 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" | 16 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" |
| 16 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert
est_util.h" | 17 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert
est_util.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 27 #include "content/public/browser/browser_message_filter.h" | 28 #include "content/public/browser/browser_message_filter.h" |
| 28 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/navigation_controller.h" | 30 #include "content/public/browser/navigation_controller.h" |
| 30 #include "content/public/browser/navigation_entry.h" | 31 #include "content/public/browser/navigation_entry.h" |
| 31 #include "content/public/browser/notification_service.h" | 32 #include "content/public/browser/notification_service.h" |
| 32 #include "content/public/browser/render_process_host.h" | 33 #include "content/public/browser/render_process_host.h" |
| 33 #include "content/public/browser/render_view_host.h" | 34 #include "content/public/browser/render_view_host.h" |
| 34 #include "content/public/browser/web_contents.h" | 35 #include "content/public/browser/web_contents.h" |
| 35 #include "content/public/test/browser_test_utils.h" | 36 #include "content/public/test/browser_test_utils.h" |
| 36 #include "content/public/test/test_utils.h" | 37 #include "content/public/test/test_utils.h" |
| 38 #include "net/base/load_flags.h" |
| 39 #include "net/url_request/url_request.h" |
| 40 #include "net/url_request/url_request_filter.h" |
| 41 #include "net/url_request/url_request_interceptor.h" |
| 37 #include "third_party/WebKit/public/web/WebContextMenuData.h" | 42 #include "third_party/WebKit/public/web/WebContextMenuData.h" |
| 38 #include "third_party/WebKit/public/web/WebInputEvent.h" | 43 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 39 | 44 |
| 40 using content::WebContents; | 45 using content::WebContents; |
| 41 | 46 |
| 42 namespace { | 47 namespace { |
| 43 | 48 |
| 44 class ContextMenuBrowserTest : public InProcessBrowserTest { | 49 class ContextMenuBrowserTest : public InProcessBrowserTest { |
| 45 public: | 50 public: |
| 46 ContextMenuBrowserTest() {} | 51 ContextMenuBrowserTest() {} |
| 47 | 52 |
| 48 TestRenderViewContextMenu* CreateContextMenu( | 53 content::ContextMenuParams CreateContextMenuParams( |
| 49 const GURL& unfiltered_url, | 54 const GURL& unfiltered_url, |
| 50 const GURL& url, | 55 const GURL& url, |
| 51 blink::WebContextMenuData::MediaType media_type) { | 56 blink::WebContextMenuData::MediaType media_type) { |
| 52 content::ContextMenuParams params; | 57 content::ContextMenuParams params; |
| 53 params.media_type = media_type; | 58 params.media_type = media_type; |
| 54 params.unfiltered_link_url = unfiltered_url; | 59 params.unfiltered_link_url = unfiltered_url; |
| 55 params.link_url = url; | 60 params.link_url = url; |
| 56 params.src_url = url; | 61 params.src_url = url; |
| 57 WebContents* web_contents = | 62 WebContents* web_contents = |
| 58 browser()->tab_strip_model()->GetActiveWebContents(); | 63 browser()->tab_strip_model()->GetActiveWebContents(); |
| 59 params.page_url = web_contents->GetController().GetActiveEntry()->GetURL(); | 64 params.page_url = web_contents->GetController().GetActiveEntry()->GetURL(); |
| 60 #if defined(OS_MACOSX) | 65 #if defined(OS_MACOSX) |
| 61 params.writing_direction_default = 0; | 66 params.writing_direction_default = 0; |
| 62 params.writing_direction_left_to_right = 0; | 67 params.writing_direction_left_to_right = 0; |
| 63 params.writing_direction_right_to_left = 0; | 68 params.writing_direction_right_to_left = 0; |
| 64 #endif // OS_MACOSX | 69 #endif // OS_MACOSX |
| 70 return params; |
| 71 } |
| 72 |
| 73 TestRenderViewContextMenu* CreateContextMenu( |
| 74 content::ContextMenuParams params) { |
| 65 TestRenderViewContextMenu* menu = new TestRenderViewContextMenu( | 75 TestRenderViewContextMenu* menu = new TestRenderViewContextMenu( |
| 66 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), | 76 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), |
| 67 params); | 77 params); |
| 68 menu->Init(); | 78 menu->Init(); |
| 69 return menu; | 79 return menu; |
| 70 } | 80 } |
| 71 | 81 |
| 72 TestRenderViewContextMenu* CreateContextMenuMediaTypeNone( | 82 TestRenderViewContextMenu* CreateContextMenuMediaTypeNone( |
| 73 const GURL& unfiltered_url, | 83 const GURL& unfiltered_url, |
| 74 const GURL& url) { | 84 const GURL& url) { |
| 75 return CreateContextMenu(unfiltered_url, url, | 85 return CreateContextMenu(CreateContextMenuParams( |
| 76 blink::WebContextMenuData::MediaTypeNone); | 86 unfiltered_url, url, blink::WebContextMenuData::MediaTypeNone)); |
| 77 } | 87 } |
| 78 }; | 88 }; |
| 79 | 89 |
| 80 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, | 90 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, |
| 81 OpenEntryPresentForNormalURLs) { | 91 OpenEntryPresentForNormalURLs) { |
| 82 scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenuMediaTypeNone( | 92 scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenuMediaTypeNone( |
| 83 GURL("http://www.google.com/"), GURL("http://www.google.com/"))); | 93 GURL("http://www.google.com/"), GURL("http://www.google.com/"))); |
| 84 | 94 |
| 85 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); | 95 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB)); |
| 86 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); | 96 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW)); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 TestRenderViewContextMenu menu(tab->GetMainFrame(), context_menu_params); | 311 TestRenderViewContextMenu menu(tab->GetMainFrame(), context_menu_params); |
| 302 menu.Init(); | 312 menu.Init(); |
| 303 | 313 |
| 304 // The item shouldn't be enabled in the menu. | 314 // The item shouldn't be enabled in the menu. |
| 305 EXPECT_FALSE(menu.IsCommandIdEnabled(IDC_CONTENT_CONTEXT_VIEWPAGEINFO)); | 315 EXPECT_FALSE(menu.IsCommandIdEnabled(IDC_CONTENT_CONTEXT_VIEWPAGEINFO)); |
| 306 | 316 |
| 307 // Ensure that viewing page info doesn't crash even if you can get to it. | 317 // Ensure that viewing page info doesn't crash even if you can get to it. |
| 308 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); | 318 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); |
| 309 } | 319 } |
| 310 | 320 |
| 321 // TODO(megjablon): Convert to a unit test once https://crbug.com/467163 is |
| 322 // fixed. |
| 323 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, DataSaverLoadImage) { |
| 324 content::ContextMenuParams params = CreateContextMenuParams( |
| 325 GURL(), GURL("http://url.com/image.png"), |
| 326 blink::WebContextMenuData::MediaTypeImage); |
| 327 params.image_was_fetched_lo_fi = true; |
| 328 |
| 329 scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenu(params)); |
| 330 |
| 331 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_RELOAD_ORIGINAL_IMAGE)); |
| 332 } |
| 333 |
| 311 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, DataSaverOpenOrigImageInNewTab) { | 334 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, DataSaverOpenOrigImageInNewTab) { |
| 312 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 335 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 313 command_line->AppendSwitch( | 336 command_line->AppendSwitch( |
| 314 data_reduction_proxy::switches::kEnableDataReductionProxy); | 337 data_reduction_proxy::switches::kEnableDataReductionProxy); |
| 315 | 338 |
| 316 scoped_ptr<TestRenderViewContextMenu> menu( | 339 scoped_ptr<TestRenderViewContextMenu> menu( |
| 317 CreateContextMenu(GURL(), GURL("http://url.com/image.png"), | 340 CreateContextMenu(CreateContextMenuParams( |
| 318 blink::WebContextMenuData::MediaTypeImage)); | 341 GURL(), GURL("http://url.com/image.png"), |
| 342 blink::WebContextMenuData::MediaTypeImage))); |
| 319 | 343 |
| 320 ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); | 344 ASSERT_FALSE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); |
| 321 ASSERT_TRUE(menu->IsItemPresent( | 345 ASSERT_TRUE(menu->IsItemPresent( |
| 322 IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB)); | 346 IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB)); |
| 323 } | 347 } |
| 324 | 348 |
| 325 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, | 349 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, |
| 326 DataSaverHttpsOpenImageInNewTab) { | 350 DataSaverHttpsOpenImageInNewTab) { |
| 327 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 351 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 328 command_line->AppendSwitch( | 352 command_line->AppendSwitch( |
| 329 data_reduction_proxy::switches::kEnableDataReductionProxy); | 353 data_reduction_proxy::switches::kEnableDataReductionProxy); |
| 330 | 354 |
| 331 scoped_ptr<TestRenderViewContextMenu> menu( | 355 scoped_ptr<TestRenderViewContextMenu> menu( |
| 332 CreateContextMenu(GURL(), GURL("https://url.com/image.png"), | 356 CreateContextMenu(CreateContextMenuParams( |
| 333 blink::WebContextMenuData::MediaTypeImage)); | 357 GURL(), GURL("https://url.com/image.png"), |
| 358 blink::WebContextMenuData::MediaTypeImage))); |
| 334 | 359 |
| 335 ASSERT_FALSE( | 360 ASSERT_FALSE( |
| 336 menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB)); | 361 menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB)); |
| 337 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); | 362 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); |
| 338 } | 363 } |
| 339 | 364 |
| 340 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenImageInNewTab) { | 365 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenImageInNewTab) { |
| 341 scoped_ptr<TestRenderViewContextMenu> menu( | 366 scoped_ptr<TestRenderViewContextMenu> menu( |
| 342 CreateContextMenu(GURL(), GURL("http://url.com/image.png"), | 367 CreateContextMenu(CreateContextMenuParams( |
| 343 blink::WebContextMenuData::MediaTypeImage)); | 368 GURL(), GURL("http://url.com/image.png"), |
| 369 blink::WebContextMenuData::MediaTypeImage))); |
| 344 ASSERT_FALSE( | 370 ASSERT_FALSE( |
| 345 menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB)); | 371 menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPEN_ORIGINAL_IMAGE_NEW_TAB)); |
| 346 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); | 372 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB)); |
| 347 } | 373 } |
| 348 | 374 |
| 349 class ThumbnailResponseWatcher : public content::NotificationObserver { | 375 class ThumbnailResponseWatcher : public content::NotificationObserver { |
| 350 public: | 376 public: |
| 351 enum QuitReason { | 377 enum QuitReason { |
| 352 STILL_RUNNING = 0, | 378 STILL_RUNNING = 0, |
| 353 THUMBNAIL_RECEIVED, | 379 THUMBNAIL_RECEIVED, |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 content::WebContents* tab = | 544 content::WebContents* tab = |
| 519 browser()->tab_strip_model()->GetActiveWebContents(); | 545 browser()->tab_strip_model()->GetActiveWebContents(); |
| 520 ThumbnailResponseWatcher watcher(tab->GetRenderProcessHost()); | 546 ThumbnailResponseWatcher watcher(tab->GetRenderProcessHost()); |
| 521 AttemptImageSearch(); | 547 AttemptImageSearch(); |
| 522 | 548 |
| 523 // The browser should receive a response from the renderer, because the | 549 // The browser should receive a response from the renderer, because the |
| 524 // renderer should not crash. | 550 // renderer should not crash. |
| 525 EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); | 551 EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); |
| 526 } | 552 } |
| 527 | 553 |
| 554 class LoadImageRequestInterceptor : public net::URLRequestInterceptor { |
| 555 public: |
| 556 LoadImageRequestInterceptor() : num_requests_(0), |
| 557 requests_to_wait_for_(-1), |
| 558 weak_factory_(this) { |
| 559 } |
| 560 |
| 561 ~LoadImageRequestInterceptor() override {} |
| 562 |
| 563 // net::URLRequestInterceptor implementation |
| 564 net::URLRequestJob* MaybeInterceptRequest( |
| 565 net::URLRequest* request, |
| 566 net::NetworkDelegate* network_delegate) const override { |
| 567 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 568 EXPECT_TRUE(request->load_flags() & net::LOAD_BYPASS_CACHE); |
| 569 content::BrowserThread::PostTask( |
| 570 content::BrowserThread::UI, FROM_HERE, |
| 571 base::Bind(&LoadImageRequestInterceptor::RequestCreated, |
| 572 weak_factory_.GetWeakPtr())); |
| 573 return nullptr; |
| 574 } |
| 575 |
| 576 void WaitForRequests(int requests_to_wait_for) { |
| 577 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 578 DCHECK_EQ(-1, requests_to_wait_for_); |
| 579 DCHECK(!run_loop_); |
| 580 |
| 581 if (num_requests_ >= requests_to_wait_for) |
| 582 return; |
| 583 |
| 584 requests_to_wait_for_ = requests_to_wait_for; |
| 585 run_loop_.reset(new base::RunLoop()); |
| 586 run_loop_->Run(); |
| 587 run_loop_.reset(); |
| 588 requests_to_wait_for_ = -1; |
| 589 EXPECT_EQ(num_requests_, requests_to_wait_for); |
| 590 } |
| 591 |
| 592 // It is up to the caller to wait until all relevant requests has been |
| 593 // created, either through calling WaitForRequests or some other manner, |
| 594 // before calling this method. |
| 595 int num_requests() const { |
| 596 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 597 return num_requests_; |
| 598 } |
| 599 |
| 600 private: |
| 601 void RequestCreated() { |
| 602 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 603 |
| 604 num_requests_++; |
| 605 if (num_requests_ == requests_to_wait_for_) |
| 606 run_loop_->Quit(); |
| 607 } |
| 608 |
| 609 // These are only used on the UI thread. |
| 610 int num_requests_; |
| 611 int requests_to_wait_for_; |
| 612 scoped_ptr<base::RunLoop> run_loop_; |
| 613 |
| 614 // This prevents any risk of flake if any test doesn't wait for a request |
| 615 // it sent. Mutable so it can be accessed from a const function. |
| 616 mutable base::WeakPtrFactory<LoadImageRequestInterceptor> weak_factory_; |
| 617 |
| 618 DISALLOW_COPY_AND_ASSIGN(LoadImageRequestInterceptor); |
| 619 }; |
| 620 |
| 621 class LoadImageBrowserTest : public InProcessBrowserTest { |
| 622 protected: |
| 623 void SetupAndLoadImagePage(const std::string& image_path) { |
| 624 // Go to a page with an image in it. The test server doesn't serve the image |
| 625 // with the right MIME type, so use a data URL to make a page containing it. |
| 626 GURL image_url(test_server()->GetURL(image_path)); |
| 627 GURL page("data:text/html,<img src='" + image_url.spec() + "'>"); |
| 628 ui_test_utils::NavigateToURL(browser(), page); |
| 629 } |
| 630 |
| 631 void AddLoadImageInterceptor(const std::string& image_path) { |
| 632 interceptor_ = new LoadImageRequestInterceptor(); |
| 633 scoped_ptr<net::URLRequestInterceptor> owned_interceptor(interceptor_); |
| 634 content::BrowserThread::PostTask( |
| 635 content::BrowserThread::IO, FROM_HERE, |
| 636 base::Bind(&LoadImageBrowserTest::AddInterceptorForURL, |
| 637 base::Unretained(this), |
| 638 GURL(test_server()->GetURL(image_path).spec()), |
| 639 base::Passed(&owned_interceptor))); |
| 640 } |
| 641 |
| 642 void AttemptImageLoad() { |
| 643 // Right-click where the image should be. |
| 644 // |menu_observer_| will cause the load-image menu item to be clicked. |
| 645 menu_observer_.reset(new ContextMenuNotificationObserver( |
| 646 IDC_CONTENT_CONTEXT_RELOAD_ORIGINAL_IMAGE)); |
| 647 content::WebContents* tab = |
| 648 browser()->tab_strip_model()->GetActiveWebContents(); |
| 649 content::SimulateMouseClickAt(tab, 0, blink::WebMouseEvent::ButtonRight, |
| 650 gfx::Point(15, 15)); |
| 651 } |
| 652 |
| 653 void AddInterceptorForURL( |
| 654 const GURL& url, scoped_ptr<net::URLRequestInterceptor> handler) { |
| 655 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 656 net::URLRequestFilter::GetInstance()->AddUrlInterceptor( |
| 657 url, handler.Pass()); |
| 658 } |
| 659 |
| 660 LoadImageRequestInterceptor* interceptor_; |
| 661 |
| 662 private: |
| 663 scoped_ptr<ContextMenuNotificationObserver> menu_observer_; |
| 664 }; |
| 665 |
| 666 IN_PROC_BROWSER_TEST_F(LoadImageBrowserTest, LoadImage) { |
| 667 static const char kValidImage[] = "files/load_image/image.png"; |
| 668 SetupAndLoadImagePage(kValidImage); |
| 669 AddLoadImageInterceptor(kValidImage); |
| 670 AttemptImageLoad(); |
| 671 interceptor_->WaitForRequests(1); |
| 672 EXPECT_EQ(1, interceptor_->num_requests()); |
| 673 } |
| 674 |
| 528 } // namespace | 675 } // namespace |
| OLD | NEW |