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); |
| 85 } |
| 86 |
75 void SetUpOnMainThread() override { | 87 void SetUpOnMainThread() override { |
76 ExtensionApiTest::SetUpOnMainThread(); | 88 ExtensionApiTest::SetUpOnMainThread(); |
| 89 host_resolver()->AddRule("*", "127.0.0.1"); |
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 PDF accessibility |
| 610 // 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); |
| 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 |