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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
(...skipping 30 matching lines...) Expand all Loading... | |
41 #include "content/public/browser/notification_registrar.h" | 41 #include "content/public/browser/notification_registrar.h" |
42 #include "content/public/browser/plugin_service.h" | 42 #include "content/public/browser/plugin_service.h" |
43 #include "content/public/browser/render_process_host.h" | 43 #include "content/public/browser/render_process_host.h" |
44 #include "content/public/browser/render_view_host.h" | 44 #include "content/public/browser/render_view_host.h" |
45 #include "content/public/browser/render_widget_host.h" | 45 #include "content/public/browser/render_widget_host.h" |
46 #include "content/public/browser/web_contents.h" | 46 #include "content/public/browser/web_contents.h" |
47 #include "content/public/test/browser_test_utils.h" | 47 #include "content/public/test/browser_test_utils.h" |
48 #include "extensions/browser/extension_registry.h" | 48 #include "extensions/browser/extension_registry.h" |
49 #include "extensions/common/manifest_handlers/mime_types_handler.h" | 49 #include "extensions/common/manifest_handlers/mime_types_handler.h" |
50 #include "extensions/test/result_catcher.h" | 50 #include "extensions/test/result_catcher.h" |
51 #include "net/dns/mock_host_resolver.h" | |
51 #include "net/test/embedded_test_server/embedded_test_server.h" | 52 #include "net/test/embedded_test_server/embedded_test_server.h" |
52 #include "ui/base/resource/resource_bundle.h" | 53 #include "ui/base/resource/resource_bundle.h" |
53 #include "url/gurl.h" | 54 #include "url/gurl.h" |
54 | 55 |
55 #if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX) | 56 #if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX) |
56 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" | 57 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" |
57 #endif | 58 #endif |
58 | 59 |
59 const int kNumberLoadTestParts = 10; | 60 const int kNumberLoadTestParts = 10; |
60 | 61 |
62 // Using ASSERT_TRUE deliberately instead of ASSERT_EQ or ASSERT_STREQ | |
63 // in order to print a more readable message if the strings differ. | |
64 #define ASSERT_MULTILINE_STREQ(expected, actual) \ | |
65 ASSERT_TRUE(expected == actual) \ | |
66 << "Expected:\n" << expected \ | |
67 << "\n\nActual:\n" << actual | |
68 | |
61 bool GetGuestCallback(content::WebContents** guest_out, | 69 bool GetGuestCallback(content::WebContents** guest_out, |
62 content::WebContents* guest) { | 70 content::WebContents* guest) { |
63 EXPECT_FALSE(*guest_out); | 71 EXPECT_FALSE(*guest_out); |
64 *guest_out = guest; | 72 *guest_out = guest; |
65 // Return false so that we iterate through all the guests and verify there is | 73 // Return false so that we iterate through all the guests and verify there is |
66 // only one. | 74 // only one. |
67 return false; | 75 return false; |
68 } | 76 } |
69 | 77 |
70 class PDFExtensionTest : public ExtensionApiTest, | 78 class PDFExtensionTest : public ExtensionApiTest, |
71 public testing::WithParamInterface<int> { | 79 public testing::WithParamInterface<int> { |
72 public: | 80 public: |
73 ~PDFExtensionTest() override {} | 81 ~PDFExtensionTest() override {} |
74 | 82 |
83 void SetUpCommandLine(base::CommandLine* command_line) override { | |
84 content::IsolateAllSitesForTesting(command_line); | |
raymes
2016/07/12 01:36:23
Don't we have site isolation bots that will run al
dmazzoni
2016/07/13 23:17:53
My understanding is that when the test is agnostic
raymes
2016/07/14 03:15:54
Should we only enable it in PdfAccessibilityInOOPI
nasko
2016/07/14 18:21:44
Long term the goal is to eliminate the FYI bots th
| |
85 } | |
86 | |
75 void SetUpOnMainThread() override { | 87 void SetUpOnMainThread() override { |
76 ExtensionApiTest::SetUpOnMainThread(); | 88 ExtensionApiTest::SetUpOnMainThread(); |
89 host_resolver()->AddRule("*", "127.0.0.1"); | |
raymes
2016/07/12 01:36:23
How come this is needed?
dmazzoni
2016/07/13 23:17:53
This allows us to use a url of "/cross-site/1.com/
raymes
2016/07/14 03:15:54
Thanks. This might conflict with https://coderevie
nasko
2016/07/14 18:21:44
We have the * rule all over the place. What is a g
| |
77 ASSERT_TRUE(embedded_test_server()->Start()); | 90 ASSERT_TRUE(embedded_test_server()->Start()); |
91 content::SetupCrossSiteRedirector(embedded_test_server()); | |
78 } | 92 } |
79 | 93 |
80 void TearDownOnMainThread() override { | 94 void TearDownOnMainThread() override { |
81 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); | 95 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); |
82 ExtensionApiTest::TearDownOnMainThread(); | 96 ExtensionApiTest::TearDownOnMainThread(); |
83 } | 97 } |
84 | 98 |
85 bool PdfIsExpectedToFailLoad(const std::string& pdf_file) { | 99 bool PdfIsExpectedToFailLoad(const std::string& pdf_file) { |
86 const char* const kFailingPdfs[] = { | 100 const char* const kFailingPdfs[] = { |
87 // TODO(thestig): Investigate why this file doesn't fail when served by | 101 // TODO(thestig): Investigate why this file doesn't fail when served by |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 #endif | 520 #endif |
507 ASSERT_TRUE( | 521 ASSERT_TRUE( |
508 content::ExecuteScript(guest_contents, "viewer.viewport.zoomIn();")); | 522 content::ExecuteScript(guest_contents, "viewer.viewport.zoomIn();")); |
509 | 523 |
510 watcher.Wait(); | 524 watcher.Wait(); |
511 #if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX) | 525 #if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX) |
512 EXPECT_EQ(nullptr, ZoomBubbleView::GetZoomBubble()); | 526 EXPECT_EQ(nullptr, ZoomBubbleView::GetZoomBubble()); |
513 #endif | 527 #endif |
514 } | 528 } |
515 | 529 |
516 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibility) { | 530 static std::string DumpPdfAccessibilityTree(const ui::AXTreeUpdate& ax_tree) { |
517 content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); | |
518 | |
519 GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-bookmarks.pdf")); | |
520 content::WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); | |
521 ASSERT_TRUE(guest_contents); | |
522 | |
523 WaitForAccessibilityTreeToContainNodeWithName(guest_contents, | |
524 "1 First Section\r\n"); | |
525 ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents); | |
526 | |
527 // Create a string representation of the tree starting with the embedded | 531 // Create a string representation of the tree starting with the embedded |
528 // object. | 532 // object. |
529 std::string ax_tree_dump; | 533 std::string ax_tree_dump; |
530 base::hash_map<int32_t, int> id_to_indentation; | 534 base::hash_map<int32_t, int> id_to_indentation; |
531 bool found_embedded_object = false; | 535 bool found_embedded_object = false; |
532 for (auto& node : ax_tree.nodes) { | 536 for (auto& node : ax_tree.nodes) { |
533 if (node.role == ui::AX_ROLE_EMBEDDED_OBJECT) | 537 if (node.role == ui::AX_ROLE_EMBEDDED_OBJECT) |
534 found_embedded_object = true; | 538 found_embedded_object = true; |
535 if (!found_embedded_object) | 539 if (!found_embedded_object) |
536 continue; | 540 continue; |
537 | 541 |
538 int indent = id_to_indentation[node.id]; | 542 int indent = id_to_indentation[node.id]; |
539 ax_tree_dump += std::string(2 * indent, ' '); | 543 ax_tree_dump += std::string(2 * indent, ' '); |
540 ax_tree_dump += ui::ToString(node.role); | 544 ax_tree_dump += ui::ToString(node.role); |
541 | 545 |
542 std::string name = node.GetStringAttribute(ui::AX_ATTR_NAME); | 546 std::string name = node.GetStringAttribute(ui::AX_ATTR_NAME); |
543 base::ReplaceChars(name, "\r", "\\r", &name); | 547 base::ReplaceChars(name, "\r", "\\r", &name); |
544 base::ReplaceChars(name, "\n", "\\n", &name); | 548 base::ReplaceChars(name, "\n", "\\n", &name); |
545 if (!name.empty()) | 549 if (!name.empty()) |
546 ax_tree_dump += " '" + name + "'"; | 550 ax_tree_dump += " '" + name + "'"; |
547 ax_tree_dump += "\n"; | 551 ax_tree_dump += "\n"; |
548 for (size_t j = 0; j < node.child_ids.size(); ++j) | 552 for (size_t j = 0; j < node.child_ids.size(); ++j) |
549 id_to_indentation[node.child_ids[j]] = indent + 1; | 553 id_to_indentation[node.child_ids[j]] = indent + 1; |
550 } | 554 } |
551 | 555 |
552 const char* expected_ax_tree = | 556 return ax_tree_dump; |
553 "embeddedObject\n" | 557 } |
554 " group\n" | |
555 " region 'Page 1'\n" | |
556 " paragraph\n" | |
557 " staticText '1 First Section\\r\\n'\n" | |
558 " inlineTextBox '1 '\n" | |
559 " inlineTextBox 'First Section\\r\\n'\n" | |
560 " paragraph\n" | |
561 " staticText 'This is the first section.\\r\\n1'\n" | |
562 " inlineTextBox 'This is the first section.\\r\\n'\n" | |
563 " inlineTextBox '1'\n" | |
564 " region 'Page 2'\n" | |
565 " paragraph\n" | |
566 " staticText '1.1 First Subsection\\r\\n'\n" | |
567 " inlineTextBox '1.1 '\n" | |
568 " inlineTextBox 'First Subsection\\r\\n'\n" | |
569 " paragraph\n" | |
570 " staticText 'This is the first subsection.\\r\\n2'\n" | |
571 " inlineTextBox 'This is the first subsection.\\r\\n'\n" | |
572 " inlineTextBox '2'\n" | |
573 " region 'Page 3'\n" | |
574 " paragraph\n" | |
575 " staticText '2 Second Section\\r\\n'\n" | |
576 " inlineTextBox '2 '\n" | |
577 " inlineTextBox 'Second Section\\r\\n'\n" | |
578 " paragraph\n" | |
579 " staticText '3'\n" | |
580 " inlineTextBox '3'\n"; | |
581 | 558 |
582 // Using ASSERT_TRUE deliberately instead of ASSERT_EQ or ASSERT_STREQ | 559 static const char* kExpectedPDFAXTree = |
583 // in order to print a more readable message if the strings differ. | 560 "embeddedObject\n" |
584 ASSERT_TRUE(expected_ax_tree == ax_tree_dump) | 561 " group\n" |
585 << "Expected:\n" << expected_ax_tree | 562 " region 'Page 1'\n" |
586 << "\n\nActual:\n" << ax_tree_dump; | 563 " paragraph\n" |
564 " staticText '1 First Section\\r\\n'\n" | |
565 " inlineTextBox '1 '\n" | |
566 " inlineTextBox 'First Section\\r\\n'\n" | |
567 " paragraph\n" | |
568 " staticText 'This is the first section.\\r\\n1'\n" | |
569 " inlineTextBox 'This is the first section.\\r\\n'\n" | |
570 " inlineTextBox '1'\n" | |
571 " region 'Page 2'\n" | |
572 " paragraph\n" | |
573 " staticText '1.1 First Subsection\\r\\n'\n" | |
574 " inlineTextBox '1.1 '\n" | |
575 " inlineTextBox 'First Subsection\\r\\n'\n" | |
576 " paragraph\n" | |
577 " staticText 'This is the first subsection.\\r\\n2'\n" | |
578 " inlineTextBox 'This is the first subsection.\\r\\n'\n" | |
579 " inlineTextBox '2'\n" | |
580 " region 'Page 3'\n" | |
581 " paragraph\n" | |
582 " staticText '2 Second Section\\r\\n'\n" | |
583 " inlineTextBox '2 '\n" | |
584 " inlineTextBox 'Second Section\\r\\n'\n" | |
585 " paragraph\n" | |
586 " staticText '3'\n" | |
587 " inlineTextBox '3'\n"; | |
588 | |
589 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibility) { | |
590 content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); | |
591 | |
592 GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-bookmarks.pdf")); | |
593 content::WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); | |
594 ASSERT_TRUE(guest_contents); | |
595 | |
596 WaitForAccessibilityTreeToContainNodeWithName(guest_contents, | |
597 "1 First Section\r\n"); | |
598 ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents); | |
599 std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree); | |
600 ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump); | |
587 } | 601 } |
602 | |
603 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityEnableLater) { | |
604 // In this test, load the PDF file first, with accessibility off. | |
605 GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-bookmarks.pdf")); | |
606 content::WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); | |
607 ASSERT_TRUE(guest_contents); | |
608 | |
609 // Now enable accessibility globally, and assert that the | |
raymes
2016/07/12 01:36:23
nit: fill 80 chars
dmazzoni
2016/07/13 23:17:53
Done
| |
610 // PDF accessibility tree loads. | |
611 EnableAccessibilityForWebContents(guest_contents); | |
612 WaitForAccessibilityTreeToContainNodeWithName(guest_contents, | |
613 "1 First Section\r\n"); | |
614 ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents); | |
615 std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree); | |
616 ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump); | |
617 } | |
618 | |
619 bool RetrieveGuestContents( | |
620 content::WebContents** out_guest_contents, | |
621 content::WebContents* in_guest_contents) { | |
622 *out_guest_contents = in_guest_contents; | |
623 return true; | |
624 } | |
625 | |
626 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityInIframe) { | |
627 content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); | |
628 GURL test_iframe_url(embedded_test_server()->GetURL("/pdf/test-iframe.html")); | |
629 ui_test_utils::NavigateToURL(browser(), test_iframe_url); | |
630 content::WebContents* contents = | |
631 browser()->tab_strip_model()->GetActiveWebContents(); | |
632 WaitForAccessibilityTreeToContainNodeWithName(contents, | |
633 "1 First Section\r\n"); | |
634 | |
635 content::WebContents* guest_contents = nullptr; | |
636 content::BrowserPluginGuestManager* guest_manager = | |
637 contents->GetBrowserContext()->GetGuestManager(); | |
638 guest_manager->ForEachGuest(contents, | |
639 base::Bind(&RetrieveGuestContents, | |
640 &guest_contents)); | |
641 ASSERT_TRUE(guest_contents); | |
642 | |
643 ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents); | |
raymes
2016/07/12 01:36:23
Hmm, why can't we get the accessibility tree from
dmazzoni
2016/07/13 23:17:53
It's easy to get a single frame's accessibility tr
raymes
2016/07/14 03:15:54
I still don't fully understand. Does WaitForAccess
dmazzoni
2016/07/14 21:04:40
WaitForAccessibilityTreeToContainNodeWithName is i
| |
644 std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree); | |
645 ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump); | |
646 } | |
647 | |
648 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, PdfAccessibilityInOOPIF) { | |
649 content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); | |
650 GURL test_iframe_url(embedded_test_server()->GetURL( | |
651 "/pdf/test-cross-site-iframe.html")); | |
652 ui_test_utils::NavigateToURL(browser(), test_iframe_url); | |
653 content::WebContents* contents = | |
654 browser()->tab_strip_model()->GetActiveWebContents(); | |
655 WaitForAccessibilityTreeToContainNodeWithName(contents, | |
656 "1 First Section\r\n"); | |
657 | |
658 content::WebContents* guest_contents = nullptr; | |
659 content::BrowserPluginGuestManager* guest_manager = | |
660 contents->GetBrowserContext()->GetGuestManager(); | |
661 guest_manager->ForEachGuest(contents, | |
662 base::Bind(&RetrieveGuestContents, | |
663 &guest_contents)); | |
664 ASSERT_TRUE(guest_contents); | |
665 | |
666 ui::AXTreeUpdate ax_tree = GetAccessibilityTreeSnapshot(guest_contents); | |
667 std::string ax_tree_dump = DumpPdfAccessibilityTree(ax_tree); | |
668 ASSERT_MULTILINE_STREQ(kExpectedPDFAXTree, ax_tree_dump); | |
669 } | |
OLD | NEW |