Chromium Code Reviews| Index: chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc |
| diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc |
| index 518ea4ba48e4a91090a43bac842b5d820cfc4052..3043de9e795dc96d59dbb37a9d97d19808e16774 100644 |
| --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc |
| +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc |
| @@ -12,16 +12,24 @@ |
| #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" |
| #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h" |
| #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" |
| +#include "chrome/browser/search_engines/template_url_service_factory.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "chrome/common/render_messages.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| +#include "components/search_engines/template_url_data.h" |
| +#include "components/search_engines/template_url_service.h" |
| +#include "content/public/browser/browser_message_filter.h" |
| +#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/navigation_controller.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| +#include "content/public/test/test_utils.h" |
| #include "third_party/WebKit/public/web/WebContextMenuData.h" |
| #include "third_party/WebKit/public/web/WebInputEvent.h" |
| @@ -288,4 +296,175 @@ IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ViewPageInfoWithNoEntry) { |
| menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); |
| } |
| +const char kImageSearchURL[] = "imagesearch"; |
| + |
| +void SetupImageSearchEngine(Profile* profile, |
| + net::SpawnedTestServer* test_server) { |
| + static const char kShortName[] = "test"; |
| + static const char kKeyword[] = "test"; |
|
Peter Kasting
2014/12/11 20:11:29
Nit: You could probably just pick one of these two
jbroman
2014/12/12 00:08:57
Done.
|
| + static const char kSearchURL[] = "search?q={searchTerms}"; |
| + static const char kImageSearchPostParams[] = "thumb={google:imageThumbnail}"; |
| + |
| + TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile); |
| + ASSERT_TRUE(model); |
| + ui_test_utils::WaitForTemplateURLServiceToLoad(model); |
| + ASSERT_TRUE(model->loaded()); |
| + |
| + TemplateURLData data; |
| + data.short_name = base::ASCIIToUTF16(kShortName); |
| + data.SetKeyword(base::ASCIIToUTF16(kKeyword)); |
| + data.SetURL(test_server->GetURL(kSearchURL).spec()); |
| + data.image_url = test_server->GetURL(kImageSearchURL).spec(); |
| + data.image_url_post_params = kImageSearchPostParams; |
| + |
| + // The model takes ownership of |template_url|. |
| + TemplateURL* template_url = new TemplateURL(data); |
| + ASSERT_TRUE(model->Add(template_url)); |
| + model->SetUserSelectedDefaultSearchProvider(template_url); |
| +} |
| + |
| +void DispatchRightClick(content::WebContents* tab, int x, int y) { |
|
Peter Kasting
2014/12/11 20:11:29
I feel like there has to be some kind of existing
jbroman
2014/12/12 00:08:57
Right you are. This file didn't previously use it,
|
| + gfx::Point offset = tab->GetContainerBounds().origin(); |
| + blink::WebMouseEvent mouse_event; |
| + mouse_event.type = blink::WebInputEvent::MouseDown; |
| + mouse_event.button = blink::WebMouseEvent::ButtonRight; |
| + mouse_event.x = x; |
| + mouse_event.y = y; |
| + mouse_event.globalX = mouse_event.x + offset.x(); |
| + mouse_event.globalY = mouse_event.y + offset.y(); |
| + tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| + mouse_event.type = blink::WebInputEvent::MouseUp; |
| + tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| +} |
| + |
| +class ThumbnailResponseWatcher : public content::NotificationObserver { |
| + public: |
| + enum QuitReason { |
| + STILL_RUNNING = 0, |
| + THUMBNAIL_RECEIVED, |
| + RENDER_PROCESS_GONE, |
| + }; |
| + |
| + class MessageFilter : public content::BrowserMessageFilter { |
| + public: |
| + explicit MessageFilter(ThumbnailResponseWatcher* owner) |
| + : content::BrowserMessageFilter(ChromeMsgStart), owner_(owner) {} |
| + |
| + bool OnMessageReceived(const IPC::Message& message) override { |
| + if (message.type() == |
| + ChromeViewHostMsg_RequestThumbnailForContextNode_ACK::ID) { |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&MessageFilter::OnRequestThumbnailForContextNodeACK, |
| + this)); |
| + } |
| + return false; |
| + } |
| + |
| + void OnRequestThumbnailForContextNodeACK() { |
| + if (owner_) { |
|
Peter Kasting
2014/12/11 20:11:29
Nit: {} unnecessary
jbroman
2014/12/12 00:08:57
Done.
|
| + owner_->OnRequestThumbnailForContextNodeACK(); |
| + } |
| + } |
| + |
| + void Disown() { owner_ = nullptr; } |
| + |
| + private: |
| + ~MessageFilter() override {} |
| + |
| + ThumbnailResponseWatcher* owner_; |
| + }; |
|
Peter Kasting
2014/12/11 20:11:29
Nit: DISALLOW_COPY_AND_ASSIGN (2 places)
jbroman
2014/12/12 00:08:57
Done.
|
| + |
| + explicit ThumbnailResponseWatcher(content::WebContents* web_contents) |
| + : message_loop_runner_(new content::MessageLoopRunner), |
| + filter_(new MessageFilter(this)), |
| + quit_reason_(STILL_RUNNING) { |
| + notification_registrar_.Add(this, |
| + content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| + content::NotificationService::AllSources()); |
| + notification_registrar_.Add( |
| + this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| + content::NotificationService::AllSources()); |
| + web_contents->GetRenderProcessHost()->AddFilter(filter_.get()); |
| + } |
| + |
| + ~ThumbnailResponseWatcher() override { filter_->Disown(); } |
| + |
| + QuitReason Wait() WARN_UNUSED_RESULT { |
| + message_loop_runner_->Run(); |
| + DCHECK(quit_reason_ != STILL_RUNNING); |
|
Peter Kasting
2014/12/11 20:11:29
Nit: DCHECK_NE
jbroman
2014/12/12 00:08:57
Done.
|
| + return quit_reason_; |
| + } |
| + |
| + void Observe(int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) override { |
| + DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || |
| + type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); |
| + quit_reason_ = RENDER_PROCESS_GONE; |
| + message_loop_runner_->Quit(); |
| + } |
| + |
| + void OnRequestThumbnailForContextNodeACK() { |
| + quit_reason_ = THUMBNAIL_RECEIVED; |
| + message_loop_runner_->Quit(); |
| + } |
| + |
| + private: |
| + scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| + scoped_refptr<MessageFilter> filter_; |
| + content::NotificationRegistrar notification_registrar_; |
| + QuitReason quit_reason_; |
| +}; |
| + |
| +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ImageSearchWithValidImage) { |
| + ContextMenuNotificationObserver menu_observer( |
| + IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE); |
| + ui_test_utils::WindowedTabAddedNotificationObserver tab_observer( |
| + content::NotificationService::AllSources()); |
| + ASSERT_TRUE(test_server()->Start()); |
| + SetupImageSearchEngine(browser()->profile(), test_server()); |
| + |
| + // Go to a page with an image in it. The test server doesn't serve the image |
| + // itself as image/png, so use a data URL to make a page containing it. |
| + static const char kValidImage[] = "files/image_search/valid.png"; |
| + GURL valid_image(test_server()->GetURL(kValidImage)); |
| + GURL page("data:text/html,<img src='" + valid_image.spec() + "'>"); |
| + ui_test_utils::NavigateToURL(browser(), page); |
| + |
| + // Open a context menu and click on the "search web for image" option. |
| + content::WebContents* tab = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + DispatchRightClick(tab, 15, 15); |
| + |
| + // The browser should open a new tab for an image search. |
| + tab_observer.Wait(); |
| + content::WebContents* new_tab = tab_observer.GetTab(); |
| + content::WaitForLoadStop(new_tab); |
| + EXPECT_EQ(test_server()->GetURL(kImageSearchURL), new_tab->GetURL()); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ImageSearchWithCorruptImage) { |
| + ContextMenuNotificationObserver menu_observer( |
| + IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE); |
| + ASSERT_TRUE(test_server()->Start()); |
| + SetupImageSearchEngine(browser()->profile(), test_server()); |
| + |
| + // Go to a page with an image in it. The test server doesn't serve the image |
| + // itself as image/png, so use a data URL to make a page containing it. |
| + static const char kCorruptImage[] = "files/image_search/corrupt.png"; |
| + GURL valid_image(test_server()->GetURL(kCorruptImage)); |
| + GURL page("data:text/html,<img src='" + valid_image.spec() + "'>"); |
| + ui_test_utils::NavigateToURL(browser(), page); |
| + |
| + // Open a context menu and click on the "search web for image" option. |
| + content::WebContents* tab = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + ThumbnailResponseWatcher watcher(tab); |
| + DispatchRightClick(tab, 15, 15); |
|
Peter Kasting
2014/12/11 20:11:29
Nit: Basically all the code above here is shared w
jbroman
2014/12/12 00:08:57
I've extracted the common logic into a helper clas
|
| + |
| + // This test passes if neither the renderer nor the browser crashes. |
| + EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); |
| +} |
| + |
| } // namespace |