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/macros.h" | |
8 #include "base/memory/ref_counted.h" | |
7 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
9 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/app/chrome_command_ids.h" | 12 #include "chrome/app/chrome_command_ids.h" |
11 #include "chrome/browser/chrome_notification_types.h" | 13 #include "chrome/browser/chrome_notification_types.h" |
12 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" | 14 #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" | 15 #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" | 16 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_uti l.h" |
17 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
15 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 19 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
20 #include "chrome/common/render_messages.h" | |
17 #include "chrome/test/base/in_process_browser_test.h" | 21 #include "chrome/test/base/in_process_browser_test.h" |
18 #include "chrome/test/base/ui_test_utils.h" | 22 #include "chrome/test/base/ui_test_utils.h" |
23 #include "components/search_engines/template_url_data.h" | |
24 #include "components/search_engines/template_url_service.h" | |
25 #include "content/public/browser/browser_message_filter.h" | |
26 #include "content/public/browser/browser_thread.h" | |
19 #include "content/public/browser/navigation_controller.h" | 27 #include "content/public/browser/navigation_controller.h" |
20 #include "content/public/browser/navigation_entry.h" | 28 #include "content/public/browser/navigation_entry.h" |
21 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
30 #include "content/public/browser/render_process_host.h" | |
22 #include "content/public/browser/render_view_host.h" | 31 #include "content/public/browser/render_view_host.h" |
23 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
24 #include "content/public/test/browser_test_utils.h" | 33 #include "content/public/test/browser_test_utils.h" |
34 #include "content/public/test/test_utils.h" | |
25 #include "third_party/WebKit/public/web/WebContextMenuData.h" | 35 #include "third_party/WebKit/public/web/WebContextMenuData.h" |
26 #include "third_party/WebKit/public/web/WebInputEvent.h" | 36 #include "third_party/WebKit/public/web/WebInputEvent.h" |
27 | 37 |
28 using content::WebContents; | 38 using content::WebContents; |
29 | 39 |
30 namespace { | 40 namespace { |
31 | 41 |
32 class ContextMenuBrowserTest : public InProcessBrowserTest { | 42 class ContextMenuBrowserTest : public InProcessBrowserTest { |
33 public: | 43 public: |
34 ContextMenuBrowserTest() { } | 44 ContextMenuBrowserTest() { } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 TestRenderViewContextMenu menu(tab->GetMainFrame(), context_menu_params); | 291 TestRenderViewContextMenu menu(tab->GetMainFrame(), context_menu_params); |
282 menu.Init(); | 292 menu.Init(); |
283 | 293 |
284 // The item shouldn't be enabled in the menu. | 294 // The item shouldn't be enabled in the menu. |
285 EXPECT_FALSE(menu.IsCommandIdEnabled(IDC_CONTENT_CONTEXT_VIEWPAGEINFO)); | 295 EXPECT_FALSE(menu.IsCommandIdEnabled(IDC_CONTENT_CONTEXT_VIEWPAGEINFO)); |
286 | 296 |
287 // Ensure that viewing page info doesn't crash even if you can get to it. | 297 // Ensure that viewing page info doesn't crash even if you can get to it. |
288 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); | 298 menu.ExecuteCommand(IDC_CONTENT_CONTEXT_VIEWPAGEINFO, 0); |
289 } | 299 } |
290 | 300 |
301 class ThumbnailResponseWatcher : public content::NotificationObserver { | |
302 public: | |
303 enum QuitReason { | |
304 STILL_RUNNING = 0, | |
305 THUMBNAIL_RECEIVED, | |
306 RENDER_PROCESS_GONE, | |
307 }; | |
308 | |
309 class MessageFilter : public content::BrowserMessageFilter { | |
310 public: | |
311 explicit MessageFilter(ThumbnailResponseWatcher* owner) | |
312 : content::BrowserMessageFilter(ChromeMsgStart), owner_(owner) {} | |
313 | |
314 bool OnMessageReceived(const IPC::Message& message) override { | |
315 if (message.type() == | |
316 ChromeViewHostMsg_RequestThumbnailForContextNode_ACK::ID) { | |
317 content::BrowserThread::PostTask( | |
318 content::BrowserThread::UI, FROM_HERE, | |
319 base::Bind(&MessageFilter::OnRequestThumbnailForContextNodeACK, | |
320 this)); | |
Nico
2014/12/12 18:43:32
Do you want to return true in this branch?
jbroman
2014/12/12 18:47:03
IIUC, this will block it from being received by Co
Nico
2014/12/12 18:49:06
Ok, sounds good. Maybe add an "// Not returning tr
| |
321 } | |
322 return false; | |
323 } | |
324 | |
325 void OnRequestThumbnailForContextNodeACK() { | |
326 if (owner_) | |
327 owner_->OnRequestThumbnailForContextNodeACK(); | |
328 } | |
329 | |
330 void Disown() { owner_ = nullptr; } | |
331 | |
332 private: | |
333 ~MessageFilter() override {} | |
334 | |
335 ThumbnailResponseWatcher* owner_; | |
336 | |
337 DISALLOW_COPY_AND_ASSIGN(MessageFilter); | |
338 }; | |
339 | |
340 explicit ThumbnailResponseWatcher( | |
341 content::RenderProcessHost* render_process_host) | |
342 : message_loop_runner_(new content::MessageLoopRunner), | |
343 filter_(new MessageFilter(this)), | |
344 quit_reason_(STILL_RUNNING) { | |
345 notification_registrar_.Add( | |
346 this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
347 content::Source<content::RenderProcessHost>(render_process_host)); | |
348 notification_registrar_.Add( | |
349 this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
350 content::Source<content::RenderProcessHost>(render_process_host)); | |
351 render_process_host->AddFilter(filter_.get()); | |
352 } | |
353 | |
354 ~ThumbnailResponseWatcher() override { filter_->Disown(); } | |
355 | |
356 QuitReason Wait() WARN_UNUSED_RESULT { | |
357 message_loop_runner_->Run(); | |
358 DCHECK_NE(STILL_RUNNING, quit_reason_); | |
359 return quit_reason_; | |
360 } | |
361 | |
362 void Observe(int type, | |
363 const content::NotificationSource& source, | |
364 const content::NotificationDetails& details) override { | |
365 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || | |
366 type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | |
367 quit_reason_ = RENDER_PROCESS_GONE; | |
368 message_loop_runner_->Quit(); | |
369 } | |
370 | |
371 void OnRequestThumbnailForContextNodeACK() { | |
372 quit_reason_ = THUMBNAIL_RECEIVED; | |
373 message_loop_runner_->Quit(); | |
374 } | |
375 | |
376 private: | |
377 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; | |
378 scoped_refptr<MessageFilter> filter_; | |
379 content::NotificationRegistrar notification_registrar_; | |
380 QuitReason quit_reason_; | |
381 | |
382 DISALLOW_COPY_AND_ASSIGN(ThumbnailResponseWatcher); | |
383 }; | |
384 | |
385 // Maintains image search test state. In particular, note that |menu_observer_| | |
386 // must live until the right-click completes asynchronously. | |
387 class SearchByImageBrowserTest : public InProcessBrowserTest { | |
388 protected: | |
389 void SetupAndLoadImagePage(const std::string& image_path) { | |
390 // The test server must start first, so that we know the port that the test | |
391 // server is using. | |
392 ASSERT_TRUE(test_server()->Start()); | |
393 SetupImageSearchEngine(); | |
394 | |
395 // Go to a page with an image in it. The test server doesn't serve the image | |
396 // with the right MIME type, so use a data URL to make a page containing it. | |
397 GURL image_url(test_server()->GetURL(image_path)); | |
398 GURL page("data:text/html,<img src='" + image_url.spec() + "'>"); | |
399 ui_test_utils::NavigateToURL(browser(), page); | |
400 } | |
401 | |
402 void AttemptImageSearch() { | |
403 // Right-click where the image should be. | |
404 // |menu_observer_| will cause the search-by-image menu item to be clicked. | |
405 menu_observer_.reset(new ContextMenuNotificationObserver( | |
406 IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE)); | |
407 content::WebContents* tab = | |
408 browser()->tab_strip_model()->GetActiveWebContents(); | |
409 content::SimulateMouseClickAt(tab, 0, blink::WebMouseEvent::ButtonRight, | |
410 gfx::Point(15, 15)); | |
411 } | |
412 | |
413 GURL GetImageSearchURL() { | |
414 static const char kImageSearchURL[] = "imagesearch"; | |
415 return test_server()->GetURL(kImageSearchURL); | |
416 } | |
417 | |
418 private: | |
419 void SetupImageSearchEngine() { | |
420 static const char kShortName[] = "test"; | |
Nico
2014/12/12 18:43:32
(note to future self: I was wondering if we usuall
| |
421 static const char kSearchURL[] = "search?q={searchTerms}"; | |
422 static const char kImageSearchPostParams[] = | |
423 "thumb={google:imageThumbnail}"; | |
424 | |
425 TemplateURLService* model = | |
426 TemplateURLServiceFactory::GetForProfile(browser()->profile()); | |
427 ASSERT_TRUE(model); | |
428 ui_test_utils::WaitForTemplateURLServiceToLoad(model); | |
429 ASSERT_TRUE(model->loaded()); | |
430 | |
431 TemplateURLData data; | |
432 data.short_name = base::ASCIIToUTF16(kShortName); | |
433 data.SetKeyword(data.short_name); | |
434 data.SetURL(test_server()->GetURL(kSearchURL).spec()); | |
435 data.image_url = GetImageSearchURL().spec(); | |
436 data.image_url_post_params = kImageSearchPostParams; | |
437 | |
438 // The model takes ownership of |template_url|. | |
439 TemplateURL* template_url = new TemplateURL(data); | |
440 ASSERT_TRUE(model->Add(template_url)); | |
441 model->SetUserSelectedDefaultSearchProvider(template_url); | |
442 } | |
443 | |
444 void TearDownInProcessBrowserTestFixture() override { | |
445 menu_observer_.reset(); | |
446 } | |
447 | |
448 scoped_ptr<ContextMenuNotificationObserver> menu_observer_; | |
449 }; | |
450 | |
451 IN_PROC_BROWSER_TEST_F(SearchByImageBrowserTest, ImageSearchWithValidImage) { | |
452 static const char kValidImage[] = "files/image_search/valid.png"; | |
453 SetupAndLoadImagePage(kValidImage); | |
454 | |
455 ui_test_utils::WindowedTabAddedNotificationObserver tab_observer( | |
456 content::NotificationService::AllSources()); | |
457 AttemptImageSearch(); | |
458 | |
459 // The browser should open a new tab for an image search. | |
460 tab_observer.Wait(); | |
461 content::WebContents* new_tab = tab_observer.GetTab(); | |
462 content::WaitForLoadStop(new_tab); | |
463 EXPECT_EQ(GetImageSearchURL(), new_tab->GetURL()); | |
464 } | |
465 | |
466 IN_PROC_BROWSER_TEST_F(SearchByImageBrowserTest, ImageSearchWithCorruptImage) { | |
467 static const char kCorruptImage[] = "files/image_search/corrupt.png"; | |
468 SetupAndLoadImagePage(kCorruptImage); | |
469 | |
470 content::WebContents* tab = | |
471 browser()->tab_strip_model()->GetActiveWebContents(); | |
472 ThumbnailResponseWatcher watcher(tab->GetRenderProcessHost()); | |
473 AttemptImageSearch(); | |
474 | |
475 // The browser should receive a response from the renderer, because the | |
476 // renderer should not crash. | |
477 EXPECT_EQ(ThumbnailResponseWatcher::THUMBNAIL_RECEIVED, watcher.Wait()); | |
478 } | |
479 | |
291 } // namespace | 480 } // namespace |
OLD | NEW |