| 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 "chrome/browser/renderer_context_menu/render_view_context_menu.h" | 5 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
| 17 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
| 18 #include "base/run_loop.h" |
| 18 #include "base/strings/string16.h" | 19 #include "base/strings/string16.h" |
| 19 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 21 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 22 #include "chrome/app/chrome_command_ids.h" | 23 #include "chrome/app/chrome_command_ids.h" |
| 23 #include "chrome/browser/browser_process.h" | 24 #include "chrome/browser/browser_process.h" |
| 24 #include "chrome/browser/chrome_notification_types.h" | 25 #include "chrome/browser/chrome_notification_types.h" |
| 25 #include "chrome/browser/profiles/profile_attributes_entry.h" | 26 #include "chrome/browser/profiles/profile_attributes_entry.h" |
| 26 #include "chrome/browser/profiles/profile_attributes_storage.h" | 27 #include "chrome/browser/profiles/profile_attributes_storage.h" |
| 27 #include "chrome/browser/profiles/profile_window.h" | 28 #include "chrome/browser/profiles/profile_window.h" |
| 28 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert
est_util.h" | 29 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert
est_util.h" |
| 29 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_uti
l.h" | 30 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_uti
l.h" |
| 30 #include "chrome/browser/search_engines/template_url_service_factory.h" | 31 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 31 #include "chrome/browser/ui/browser.h" | 32 #include "chrome/browser/ui/browser.h" |
| 32 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 33 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 33 #include "chrome/common/render_messages.h" | 34 #include "chrome/common/render_messages.h" |
| 35 #include "chrome/common/thumbnail_capturer.mojom.h" |
| 34 #include "chrome/test/base/in_process_browser_test.h" | 36 #include "chrome/test/base/in_process_browser_test.h" |
| 35 #include "chrome/test/base/search_test_utils.h" | 37 #include "chrome/test/base/search_test_utils.h" |
| 36 #include "chrome/test/base/ui_test_utils.h" | 38 #include "chrome/test/base/ui_test_utils.h" |
| 37 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switc
hes.h" | 39 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switc
hes.h" |
| 38 #include "components/search_engines/template_url_data.h" | 40 #include "components/search_engines/template_url_data.h" |
| 39 #include "components/search_engines/template_url_service.h" | 41 #include "components/search_engines/template_url_service.h" |
| 40 #include "content/public/browser/browser_message_filter.h" | 42 #include "content/public/browser/browser_message_filter.h" |
| 41 #include "content/public/browser/browser_thread.h" | 43 #include "content/public/browser/browser_thread.h" |
| 42 #include "content/public/browser/navigation_controller.h" | 44 #include "content/public/browser/navigation_controller.h" |
| 43 #include "content/public/browser/navigation_entry.h" | 45 #include "content/public/browser/navigation_entry.h" |
| 44 #include "content/public/browser/notification_service.h" | 46 #include "content/public/browser/notification_service.h" |
| 47 #include "content/public/browser/render_frame_host.h" |
| 45 #include "content/public/browser/render_process_host.h" | 48 #include "content/public/browser/render_process_host.h" |
| 46 #include "content/public/browser/render_view_host.h" | 49 #include "content/public/browser/render_view_host.h" |
| 47 #include "content/public/browser/render_widget_host.h" | 50 #include "content/public/browser/render_widget_host.h" |
| 48 #include "content/public/browser/web_contents.h" | 51 #include "content/public/browser/web_contents.h" |
| 49 #include "content/public/test/browser_test_utils.h" | 52 #include "content/public/test/browser_test_utils.h" |
| 50 #include "content/public/test/test_utils.h" | 53 #include "content/public/test/test_utils.h" |
| 51 #include "net/base/load_flags.h" | 54 #include "net/base/load_flags.h" |
| 52 #include "net/test/embedded_test_server/embedded_test_server.h" | 55 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 53 #include "net/url_request/url_request.h" | 56 #include "net/url_request/url_request.h" |
| 54 #include "net/url_request/url_request_filter.h" | 57 #include "net/url_request/url_request_filter.h" |
| 55 #include "net/url_request/url_request_interceptor.h" | 58 #include "net/url_request/url_request_interceptor.h" |
| 59 #include "services/service_manager/public/cpp/interface_provider.h" |
| 56 #include "third_party/WebKit/public/platform/WebInputEvent.h" | 60 #include "third_party/WebKit/public/platform/WebInputEvent.h" |
| 57 #include "third_party/WebKit/public/web/WebContextMenuData.h" | 61 #include "third_party/WebKit/public/web/WebContextMenuData.h" |
| 58 #include "ui/base/models/menu_model.h" | 62 #include "ui/base/models/menu_model.h" |
| 59 | 63 |
| 60 using content::WebContents; | 64 using content::WebContents; |
| 61 | 65 |
| 62 namespace { | 66 namespace { |
| 63 | 67 |
| 64 class ContextMenuBrowserTest : public InProcessBrowserTest { | 68 class ContextMenuBrowserTest : public InProcessBrowserTest { |
| 65 public: | 69 public: |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 #endif // !defined(OS_CHROMEOS) | 553 #endif // !defined(OS_CHROMEOS) |
| 550 | 554 |
| 551 class ThumbnailResponseWatcher : public content::NotificationObserver { | 555 class ThumbnailResponseWatcher : public content::NotificationObserver { |
| 552 public: | 556 public: |
| 553 enum QuitReason { | 557 enum QuitReason { |
| 554 STILL_RUNNING = 0, | 558 STILL_RUNNING = 0, |
| 555 THUMBNAIL_RECEIVED, | 559 THUMBNAIL_RECEIVED, |
| 556 RENDER_PROCESS_GONE, | 560 RENDER_PROCESS_GONE, |
| 557 }; | 561 }; |
| 558 | 562 |
| 559 class MessageFilter : public content::BrowserMessageFilter { | 563 explicit ThumbnailResponseWatcher(content::WebContents* tab) |
| 560 public: | 564 : tab_(tab), quit_reason_(STILL_RUNNING) { |
| 561 explicit MessageFilter(ThumbnailResponseWatcher* owner) | 565 content::RenderProcessHost* render_process_host = |
| 562 : content::BrowserMessageFilter(ChromeMsgStart), owner_(owner) {} | 566 tab->GetRenderProcessHost(); |
| 563 | |
| 564 bool OnMessageReceived(const IPC::Message& message) override { | |
| 565 if (message.type() == | |
| 566 ChromeViewHostMsg_RequestThumbnailForContextNode_ACK::ID) { | |
| 567 content::BrowserThread::PostTask( | |
| 568 content::BrowserThread::UI, FROM_HERE, | |
| 569 base::Bind(&MessageFilter::OnRequestThumbnailForContextNodeACK, | |
| 570 this)); | |
| 571 } | |
| 572 return false; | |
| 573 } | |
| 574 | |
| 575 void OnRequestThumbnailForContextNodeACK() { | |
| 576 if (owner_) | |
| 577 owner_->OnRequestThumbnailForContextNodeACK(); | |
| 578 } | |
| 579 | |
| 580 void Disown() { owner_ = nullptr; } | |
| 581 | |
| 582 private: | |
| 583 ~MessageFilter() override {} | |
| 584 | |
| 585 ThumbnailResponseWatcher* owner_; | |
| 586 | |
| 587 DISALLOW_COPY_AND_ASSIGN(MessageFilter); | |
| 588 }; | |
| 589 | |
| 590 explicit ThumbnailResponseWatcher( | |
| 591 content::RenderProcessHost* render_process_host) | |
| 592 : message_loop_runner_(new content::MessageLoopRunner), | |
| 593 filter_(new MessageFilter(this)), | |
| 594 quit_reason_(STILL_RUNNING) { | |
| 595 notification_registrar_.Add( | 567 notification_registrar_.Add( |
| 596 this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 568 this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 597 content::Source<content::RenderProcessHost>(render_process_host)); | 569 content::Source<content::RenderProcessHost>(render_process_host)); |
| 598 notification_registrar_.Add( | 570 notification_registrar_.Add( |
| 599 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 571 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 600 content::Source<content::RenderProcessHost>(render_process_host)); | 572 content::Source<content::RenderProcessHost>(render_process_host)); |
| 601 render_process_host->AddFilter(filter_.get()); | 573 notification_registrar_.Add( |
| 574 this, chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN, |
| 575 content::NotificationService::AllSources()); |
| 602 } | 576 } |
| 603 | 577 |
| 604 ~ThumbnailResponseWatcher() override { filter_->Disown(); } | |
| 605 | |
| 606 QuitReason Wait() WARN_UNUSED_RESULT { | 578 QuitReason Wait() WARN_UNUSED_RESULT { |
| 607 message_loop_runner_->Run(); | 579 run_loop_.Run(); |
| 608 DCHECK_NE(STILL_RUNNING, quit_reason_); | 580 DCHECK_NE(STILL_RUNNING, quit_reason_); |
| 609 return quit_reason_; | 581 return quit_reason_; |
| 610 } | 582 } |
| 611 | 583 |
| 612 void Observe(int type, | 584 void Observe(int type, |
| 613 const content::NotificationSource& source, | 585 const content::NotificationSource& source, |
| 614 const content::NotificationDetails& details) override { | 586 const content::NotificationDetails& details) override { |
| 615 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || | 587 if (type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || |
| 616 type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 588 type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED) { |
| 617 quit_reason_ = RENDER_PROCESS_GONE; | 589 quit_reason_ = RENDER_PROCESS_GONE; |
| 618 message_loop_runner_->Quit(); | 590 run_loop_.Quit(); |
| 591 } else { |
| 592 DCHECK_EQ(type, chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN); |
| 593 RequestThumbnail(); |
| 594 } |
| 619 } | 595 } |
| 620 | 596 |
| 621 void OnRequestThumbnailForContextNodeACK() { | 597 void RequestThumbnail() { |
| 598 tab_->GetMainFrame()->GetRemoteInterfaces()->GetInterface( |
| 599 &thumbnail_capturer_); |
| 600 thumbnail_capturer_->RequestThumbnailForContextNode( |
| 601 0, gfx::Size(2048, 2048), |
| 602 base::Bind(&ThumbnailResponseWatcher::OnRequestThumbnailResponse, |
| 603 base::Unretained(this))); |
| 604 } |
| 605 |
| 606 void OnRequestThumbnailResponse(const std::string& thumbnail_data, |
| 607 const gfx::Size& original_size) { |
| 622 quit_reason_ = THUMBNAIL_RECEIVED; | 608 quit_reason_ = THUMBNAIL_RECEIVED; |
| 623 message_loop_runner_->Quit(); | 609 run_loop_.Quit(); |
| 624 } | 610 } |
| 625 | 611 |
| 626 private: | 612 private: |
| 627 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; | 613 base::RunLoop run_loop_; |
| 628 scoped_refptr<MessageFilter> filter_; | |
| 629 content::NotificationRegistrar notification_registrar_; | 614 content::NotificationRegistrar notification_registrar_; |
| 615 content::WebContents* tab_; |
| 616 chrome::mojom::ThumbnailCapturerPtr thumbnail_capturer_; |
| 630 QuitReason quit_reason_; | 617 QuitReason quit_reason_; |
| 631 | 618 |
| 632 DISALLOW_COPY_AND_ASSIGN(ThumbnailResponseWatcher); | 619 DISALLOW_COPY_AND_ASSIGN(ThumbnailResponseWatcher); |
| 633 }; | 620 }; |
| 634 | 621 |
| 635 // Maintains image search test state. In particular, note that |menu_observer_| | 622 // Maintains image search test state. In particular, note that |menu_observer_| |
| 636 // must live until the right-click completes asynchronously. | 623 // must live until the right-click completes asynchronously. |
| 637 class SearchByImageBrowserTest : public InProcessBrowserTest { | 624 class SearchByImageBrowserTest : public InProcessBrowserTest { |
| 638 protected: | 625 protected: |
| 639 void SetupAndLoadImagePage(const std::string& image_path) { | 626 void SetupAndLoadImagePage(const std::string& image_path) { |
| 640 // The test server must start first, so that we know the port that the test | 627 // The test server must start first, so that we know the port that the test |
| 641 // server is using. | 628 // server is using. |
| 642 ASSERT_TRUE(embedded_test_server()->Start()); | 629 ASSERT_TRUE(embedded_test_server()->Start()); |
| 643 SetupImageSearchEngine(); | 630 SetupImageSearchEngine(); |
| 644 | 631 |
| 645 // Go to a page with an image in it. The test server doesn't serve the image | 632 // Go to a page with an image in it. The test server doesn't serve the image |
| 646 // with the right MIME type, so use a data URL to make a page containing it. | 633 // with the right MIME type, so use a data URL to make a page containing it. |
| 647 GURL image_url(embedded_test_server()->GetURL(image_path)); | 634 GURL image_url(embedded_test_server()->GetURL(image_path)); |
| 648 GURL page("data:text/html,<img src='" + image_url.spec() + "'>"); | 635 GURL page("data:text/html,<img src='" + image_url.spec() + "'>"); |
| 649 ui_test_utils::NavigateToURL(browser(), page); | 636 ui_test_utils::NavigateToURL(browser(), page); |
| 650 } | 637 } |
| 651 | 638 |
| 652 void AttemptImageSearch() { | 639 void AttemptImageSearch() { |
| 653 // Right-click where the image should be. | |
| 654 // |menu_observer_| will cause the search-by-image menu item to be clicked. | 640 // |menu_observer_| will cause the search-by-image menu item to be clicked. |
| 655 menu_observer_.reset(new ContextMenuNotificationObserver( | 641 menu_observer_.reset(new ContextMenuNotificationObserver( |
| 656 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE)); | 642 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE)); |
| 643 RightClickImage(); |
| 644 } |
| 645 |
| 646 // Right-click where the image should be. |
| 647 void RightClickImage() { |
| 657 content::WebContents* tab = | 648 content::WebContents* tab = |
| 658 browser()->tab_strip_model()->GetActiveWebContents(); | 649 browser()->tab_strip_model()->GetActiveWebContents(); |
| 659 content::SimulateMouseClickAt(tab, 0, blink::WebMouseEvent::Button::Right, | 650 content::SimulateMouseClickAt(tab, 0, blink::WebMouseEvent::Button::Right, |
| 660 gfx::Point(15, 15)); | 651 gfx::Point(15, 15)); |
| 661 } | 652 } |
| 662 | 653 |
| 663 GURL GetImageSearchURL() { | 654 GURL GetImageSearchURL() { |
| 664 static const char kImageSearchURL[] = "/imagesearch"; | 655 static const char kImageSearchURL[] = "/imagesearch"; |
| 665 return embedded_test_server()->GetURL(kImageSearchURL); | 656 return embedded_test_server()->GetURL(kImageSearchURL); |
| 666 } | 657 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 content::WaitForLoadStop(new_tab); | 702 content::WaitForLoadStop(new_tab); |
| 712 EXPECT_EQ(GetImageSearchURL(), new_tab->GetURL()); | 703 EXPECT_EQ(GetImageSearchURL(), new_tab->GetURL()); |
| 713 } | 704 } |
| 714 | 705 |
| 715 IN_PROC_BROWSER_TEST_F(SearchByImageBrowserTest, ImageSearchWithCorruptImage) { | 706 IN_PROC_BROWSER_TEST_F(SearchByImageBrowserTest, ImageSearchWithCorruptImage) { |
| 716 static const char kCorruptImage[] = "/image_search/corrupt.png"; | 707 static const char kCorruptImage[] = "/image_search/corrupt.png"; |
| 717 SetupAndLoadImagePage(kCorruptImage); | 708 SetupAndLoadImagePage(kCorruptImage); |
| 718 | 709 |
| 719 content::WebContents* tab = | 710 content::WebContents* tab = |
| 720 browser()->tab_strip_model()->GetActiveWebContents(); | 711 browser()->tab_strip_model()->GetActiveWebContents(); |
| 721 ThumbnailResponseWatcher watcher(tab->GetRenderProcessHost()); | 712 // Create the watcher first because it observes the context menu creation. |
| 722 AttemptImageSearch(); | 713 ThumbnailResponseWatcher watcher(tab); |
| 714 RightClickImage(); |
| 723 | 715 |
| 724 // The browser should receive a response from the renderer, because the | 716 // The browser should receive a response from the renderer, because the |
| 725 // renderer should not crash. | 717 // renderer should not crash. |
| 726 EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); | 718 EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); |
| 727 } | 719 } |
| 728 | 720 |
| 729 class LoadImageRequestInterceptor : public net::URLRequestInterceptor { | 721 class LoadImageRequestInterceptor : public net::URLRequestInterceptor { |
| 730 public: | 722 public: |
| 731 LoadImageRequestInterceptor() : num_requests_(0), | 723 LoadImageRequestInterceptor() : num_requests_(0), |
| 732 requests_to_wait_for_(-1), | 724 requests_to_wait_for_(-1), |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 IN_PROC_BROWSER_TEST_F(LoadImageBrowserTest, LoadImage) { | 835 IN_PROC_BROWSER_TEST_F(LoadImageBrowserTest, LoadImage) { |
| 844 static const char kValidImage[] = "/load_image/image.png"; | 836 static const char kValidImage[] = "/load_image/image.png"; |
| 845 SetupAndLoadImagePage(kValidImage); | 837 SetupAndLoadImagePage(kValidImage); |
| 846 AddLoadImageInterceptor(kValidImage); | 838 AddLoadImageInterceptor(kValidImage); |
| 847 AttemptLoadImage(); | 839 AttemptLoadImage(); |
| 848 interceptor_->WaitForRequests(1); | 840 interceptor_->WaitForRequests(1); |
| 849 EXPECT_EQ(1, interceptor_->num_requests()); | 841 EXPECT_EQ(1, interceptor_->num_requests()); |
| 850 } | 842 } |
| 851 | 843 |
| 852 } // namespace | 844 } // namespace |
| OLD | NEW |