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/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/string16.h" | 8 #include "base/strings/string16.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/app/chrome_command_ids.h" | 10 #include "chrome/app/chrome_command_ids.h" |
11 #include "chrome/browser/chrome_notification_types.h" | 11 #include "chrome/browser/chrome_notification_types.h" |
12 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" | 12 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" |
13 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert est_util.h" | 13 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsert est_util.h" |
14 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_uti l.h" | 14 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_uti l.h" |
15 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
15 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
18 #include "chrome/common/render_messages.h" | |
17 #include "chrome/test/base/in_process_browser_test.h" | 19 #include "chrome/test/base/in_process_browser_test.h" |
18 #include "chrome/test/base/ui_test_utils.h" | 20 #include "chrome/test/base/ui_test_utils.h" |
21 #include "components/search_engines/template_url_data.h" | |
22 #include "components/search_engines/template_url_service.h" | |
23 #include "content/public/browser/browser_message_filter.h" | |
24 #include "content/public/browser/browser_thread.h" | |
19 #include "content/public/browser/navigation_controller.h" | 25 #include "content/public/browser/navigation_controller.h" |
20 #include "content/public/browser/navigation_entry.h" | 26 #include "content/public/browser/navigation_entry.h" |
21 #include "content/public/browser/notification_service.h" | 27 #include "content/public/browser/notification_service.h" |
28 #include "content/public/browser/render_process_host.h" | |
22 #include "content/public/browser/render_view_host.h" | 29 #include "content/public/browser/render_view_host.h" |
23 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
24 #include "content/public/test/browser_test_utils.h" | 31 #include "content/public/test/browser_test_utils.h" |
32 #include "content/public/test/test_utils.h" | |
25 #include "third_party/WebKit/public/web/WebContextMenuData.h" | 33 #include "third_party/WebKit/public/web/WebContextMenuData.h" |
26 #include "third_party/WebKit/public/web/WebInputEvent.h" | 34 #include "third_party/WebKit/public/web/WebInputEvent.h" |
27 | 35 |
28 using content::WebContents; | 36 using content::WebContents; |
29 | 37 |
30 namespace { | 38 namespace { |
31 | 39 |
32 class ContextMenuBrowserTest : public InProcessBrowserTest { | 40 class ContextMenuBrowserTest : public InProcessBrowserTest { |
33 public: | 41 public: |
34 ContextMenuBrowserTest() { } | 42 ContextMenuBrowserTest() { } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 TestRenderViewContextMenu menu(tab->GetMainFrame(), context_menu_params); | 289 TestRenderViewContextMenu menu(tab->GetMainFrame(), context_menu_params); |
282 menu.Init(); | 290 menu.Init(); |
283 | 291 |
284 // The item shouldn't be enabled in the menu. | 292 // The item shouldn't be enabled in the menu. |
285 EXPECT_FALSE(menu.IsCommandIdEnabled(IDC_CONTENT_CONTEXT_VIEWPAGEINFO)); | 293 EXPECT_FALSE(menu.IsCommandIdEnabled(IDC_CONTENT_CONTEXT_VIEWPAGEINFO)); |
286 | 294 |
287 // Ensure that viewing page info doesn't crash even if you can get to it. | 295 // Ensure that viewing page info doesn't crash even if you can get to it. |
288 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); | 296 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); |
289 } | 297 } |
290 | 298 |
299 const char kImageSearchURL[] = "imagesearch"; | |
300 | |
301 void SetupImageSearchEngine(Profile* profile, | |
302 net::SpawnedTestServer* test_server) { | |
303 static const char kShortName[] = "test"; | |
304 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.
| |
305 static const char kSearchURL[] = "search?q={searchTerms}"; | |
306 static const char kImageSearchPostParams[] = "thumb={google:imageThumbnail}"; | |
307 | |
308 TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile); | |
309 ASSERT_TRUE(model); | |
310 ui_test_utils::WaitForTemplateURLServiceToLoad(model); | |
311 ASSERT_TRUE(model->loaded()); | |
312 | |
313 TemplateURLData data; | |
314 data.short_name = base::ASCIIToUTF16(kShortName); | |
315 data.SetKeyword(base::ASCIIToUTF16(kKeyword)); | |
316 data.SetURL(test_server->GetURL(kSearchURL).spec()); | |
317 data.image_url = test_server->GetURL(kImageSearchURL).spec(); | |
318 data.image_url_post_params = kImageSearchPostParams; | |
319 | |
320 // The model takes ownership of |template_url|. | |
321 TemplateURL* template_url = new TemplateURL(data); | |
322 ASSERT_TRUE(model->Add(template_url)); | |
323 model->SetUserSelectedDefaultSearchProvider(template_url); | |
324 } | |
325 | |
326 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,
| |
327 gfx::Point offset = tab->GetContainerBounds().origin(); | |
328 blink::WebMouseEvent mouse_event; | |
329 mouse_event.type = blink::WebInputEvent::MouseDown; | |
330 mouse_event.button = blink::WebMouseEvent::ButtonRight; | |
331 mouse_event.x = x; | |
332 mouse_event.y = y; | |
333 mouse_event.globalX = mouse_event.x + offset.x(); | |
334 mouse_event.globalY = mouse_event.y + offset.y(); | |
335 tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | |
336 mouse_event.type = blink::WebInputEvent::MouseUp; | |
337 tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | |
338 } | |
339 | |
340 class ThumbnailResponseWatcher : public content::NotificationObserver { | |
341 public: | |
342 enum QuitReason { | |
343 STILL_RUNNING = 0, | |
344 THUMBNAIL_RECEIVED, | |
345 RENDER_PROCESS_GONE, | |
346 }; | |
347 | |
348 class MessageFilter : public content::BrowserMessageFilter { | |
349 public: | |
350 explicit MessageFilter(ThumbnailResponseWatcher* owner) | |
351 : content::BrowserMessageFilter(ChromeMsgStart), owner_(owner) {} | |
352 | |
353 bool OnMessageReceived(const IPC::Message& message) override { | |
354 if (message.type() == | |
355 ChromeViewHostMsg_RequestThumbnailForContextNode_ACK::ID) { | |
356 content::BrowserThread::PostTask( | |
357 content::BrowserThread::UI, FROM_HERE, | |
358 base::Bind(&MessageFilter::OnRequestThumbnailForContextNodeACK, | |
359 this)); | |
360 } | |
361 return false; | |
362 } | |
363 | |
364 void OnRequestThumbnailForContextNodeACK() { | |
365 if (owner_) { | |
Peter Kasting
2014/12/11 20:11:29
Nit: {} unnecessary
jbroman
2014/12/12 00:08:57
Done.
| |
366 owner_->OnRequestThumbnailForContextNodeACK(); | |
367 } | |
368 } | |
369 | |
370 void Disown() { owner_ = nullptr; } | |
371 | |
372 private: | |
373 ~MessageFilter() override {} | |
374 | |
375 ThumbnailResponseWatcher* owner_; | |
376 }; | |
Peter Kasting
2014/12/11 20:11:29
Nit: DISALLOW_COPY_AND_ASSIGN (2 places)
jbroman
2014/12/12 00:08:57
Done.
| |
377 | |
378 explicit ThumbnailResponseWatcher(content::WebContents* web_contents) | |
379 : message_loop_runner_(new content::MessageLoopRunner), | |
380 filter_(new MessageFilter(this)), | |
381 quit_reason_(STILL_RUNNING) { | |
382 notification_registrar_.Add(this, | |
383 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
384 content::NotificationService::AllSources()); | |
385 notification_registrar_.Add( | |
386 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
387 content::NotificationService::AllSources()); | |
388 web_contents->GetRenderProcessHost()->AddFilter(filter_.get()); | |
389 } | |
390 | |
391 ~ThumbnailResponseWatcher() override { filter_->Disown(); } | |
392 | |
393 QuitReason Wait() WARN_UNUSED_RESULT { | |
394 message_loop_runner_->Run(); | |
395 DCHECK(quit_reason_ != STILL_RUNNING); | |
Peter Kasting
2014/12/11 20:11:29
Nit: DCHECK_NE
jbroman
2014/12/12 00:08:57
Done.
| |
396 return quit_reason_; | |
397 } | |
398 | |
399 void Observe(int type, | |
400 const content::NotificationSource& source, | |
401 const content::NotificationDetails& details) override { | |
402 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || | |
403 type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | |
404 quit_reason_ = RENDER_PROCESS_GONE; | |
405 message_loop_runner_->Quit(); | |
406 } | |
407 | |
408 void OnRequestThumbnailForContextNodeACK() { | |
409 quit_reason_ = THUMBNAIL_RECEIVED; | |
410 message_loop_runner_->Quit(); | |
411 } | |
412 | |
413 private: | |
414 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; | |
415 scoped_refptr<MessageFilter> filter_; | |
416 content::NotificationRegistrar notification_registrar_; | |
417 QuitReason quit_reason_; | |
418 }; | |
419 | |
420 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ImageSearchWithValidImage) { | |
421 ContextMenuNotificationObserver menu_observer( | |
422 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE); | |
423 ui_test_utils::WindowedTabAddedNotificationObserver tab_observer( | |
424 content::NotificationService::AllSources()); | |
425 ASSERT_TRUE(test_server()->Start()); | |
426 SetupImageSearchEngine(browser()->profile(), test_server()); | |
427 | |
428 // Go to a page with an image in it. The test server doesn't serve the image | |
429 // itself as image/png, so use a data URL to make a page containing it. | |
430 static const char kValidImage[] = "files/image_search/valid.png"; | |
431 GURL valid_image(test_server()->GetURL(kValidImage)); | |
432 GURL page("data:text/html,<img src='" + valid_image.spec() + "'>"); | |
433 ui_test_utils::NavigateToURL(browser(), page); | |
434 | |
435 // Open a context menu and click on the "search web for image" option. | |
436 content::WebContents* tab = | |
437 browser()->tab_strip_model()->GetActiveWebContents(); | |
438 DispatchRightClick(tab, 15, 15); | |
439 | |
440 // The browser should open a new tab for an image search. | |
441 tab_observer.Wait(); | |
442 content::WebContents* new_tab = tab_observer.GetTab(); | |
443 content::WaitForLoadStop(new_tab); | |
444 EXPECT_EQ(test_server()->GetURL(kImageSearchURL), new_tab->GetURL()); | |
445 } | |
446 | |
447 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, ImageSearchWithCorruptImage) { | |
448 ContextMenuNotificationObserver menu_observer( | |
449 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE); | |
450 ASSERT_TRUE(test_server()->Start()); | |
451 SetupImageSearchEngine(browser()->profile(), test_server()); | |
452 | |
453 // Go to a page with an image in it. The test server doesn't serve the image | |
454 // itself as image/png, so use a data URL to make a page containing it. | |
455 static const char kCorruptImage[] = "files/image_search/corrupt.png"; | |
456 GURL valid_image(test_server()->GetURL(kCorruptImage)); | |
457 GURL page("data:text/html,<img src='" + valid_image.spec() + "'>"); | |
458 ui_test_utils::NavigateToURL(browser(), page); | |
459 | |
460 // Open a context menu and click on the "search web for image" option. | |
461 content::WebContents* tab = | |
462 browser()->tab_strip_model()->GetActiveWebContents(); | |
463 ThumbnailResponseWatcher watcher(tab); | |
464 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
| |
465 | |
466 // This test passes if neither the renderer nor the browser crashes. | |
467 EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); | |
468 } | |
469 | |
291 } // namespace | 470 } // namespace |
OLD | NEW |