Home | History | Annotate | Download | only in accessibility
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/strings/utf_string_conversions.h"
      6 #include "content/common/frame_messages.h"
      7 #include "content/common/view_message_enums.h"
      8 #include "content/public/test/render_view_test.h"
      9 #include "content/renderer/accessibility/renderer_accessibility_complete.h"
     10 #include "content/renderer/render_view_impl.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "third_party/WebKit/public/platform/WebSize.h"
     13 #include "third_party/WebKit/public/web/WebAXObject.h"
     14 #include "third_party/WebKit/public/web/WebDocument.h"
     15 #include "third_party/WebKit/public/web/WebView.h"
     16 #include "ui/accessibility/ax_node_data.h"
     17 
     18 using blink::WebAXObject;
     19 using blink::WebDocument;
     20 
     21 namespace content {
     22 
     23 class TestRendererAccessibilityComplete : public RendererAccessibilityComplete {
     24  public:
     25   explicit TestRendererAccessibilityComplete(RenderViewImpl* render_view)
     26     : RendererAccessibilityComplete(render_view) {
     27   }
     28 
     29   void SendPendingAccessibilityEvents() {
     30     RendererAccessibilityComplete::SendPendingAccessibilityEvents();
     31   }
     32 };
     33 
     34 class RendererAccessibilityTest : public RenderViewTest {
     35  public:
     36   RendererAccessibilityTest() {}
     37 
     38   RenderViewImpl* view() {
     39     return static_cast<RenderViewImpl*>(view_);
     40   }
     41 
     42   RenderFrameImpl* frame() {
     43     return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame());
     44   }
     45 
     46   virtual void SetUp() {
     47     RenderViewTest::SetUp();
     48     sink_ = &render_thread_->sink();
     49   }
     50 
     51   void SetMode(AccessibilityMode mode) {
     52     view()->OnSetAccessibilityMode(mode);
     53   }
     54 
     55   void GetLastAccEvent(
     56       AccessibilityHostMsg_EventParams* params) {
     57     const IPC::Message* message =
     58         sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID);
     59     ASSERT_TRUE(message);
     60     Tuple1<std::vector<AccessibilityHostMsg_EventParams> > param;
     61     AccessibilityHostMsg_Events::Read(message, &param);
     62     ASSERT_GE(param.a.size(), 1U);
     63     *params = param.a[0];
     64   }
     65 
     66   int CountAccessibilityNodesSentToBrowser() {
     67     AccessibilityHostMsg_EventParams event;
     68     GetLastAccEvent(&event);
     69     return event.update.nodes.size();
     70   }
     71 
     72  protected:
     73   IPC::TestSink* sink_;
     74 
     75   DISALLOW_COPY_AND_ASSIGN(RendererAccessibilityTest);
     76 
     77 };
     78 
     79 TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
     80   // This is not a test of true web accessibility, it's a test of
     81   // a mode used on Windows 8 in Metro mode where an extremely simplified
     82   // accessibility tree containing only the current focused node is
     83   // generated.
     84   SetMode(AccessibilityModeEditableTextOnly);
     85 
     86   // Set a minimum size and give focus so simulated events work.
     87   view()->webwidget()->resize(blink::WebSize(500, 500));
     88   view()->webwidget()->setFocus(true);
     89 
     90   std::string html =
     91       "<body>"
     92       "  <input>"
     93       "  <textarea></textarea>"
     94       "  <p contentEditable>Editable</p>"
     95       "  <div tabindex=0 role=textbox>Textbox</div>"
     96       "  <button>Button</button>"
     97       "  <a href=#>Link</a>"
     98       "</body>";
     99 
    100   // Load the test page.
    101   LoadHTML(html.c_str());
    102 
    103   // We should have sent a message to the browser with the initial focus
    104   // on the document.
    105   {
    106     SCOPED_TRACE("Initial focus on document");
    107     AccessibilityHostMsg_EventParams event;
    108     GetLastAccEvent(&event);
    109     EXPECT_EQ(event.event_type,
    110               ui::AX_EVENT_LAYOUT_COMPLETE);
    111     EXPECT_EQ(event.id, 1);
    112     EXPECT_EQ(event.update.nodes.size(), 2U);
    113     EXPECT_EQ(event.update.nodes[0].id, 1);
    114     EXPECT_EQ(event.update.nodes[0].role,
    115               ui::AX_ROLE_ROOT_WEB_AREA);
    116     EXPECT_EQ(event.update.nodes[0].state,
    117               (1U << ui::AX_STATE_READ_ONLY) |
    118               (1U << ui::AX_STATE_FOCUSABLE) |
    119               (1U << ui::AX_STATE_FOCUSED));
    120     EXPECT_EQ(event.update.nodes[0].child_ids.size(), 1U);
    121   }
    122 
    123   // Now focus the input element, and check everything again.
    124   {
    125     SCOPED_TRACE("input");
    126     sink_->ClearMessages();
    127     ExecuteJavaScript("document.querySelector('input').focus();");
    128     AccessibilityHostMsg_EventParams event;
    129     GetLastAccEvent(&event);
    130     EXPECT_EQ(event.event_type,
    131               ui::AX_EVENT_FOCUS);
    132     EXPECT_EQ(event.id, 3);
    133     EXPECT_EQ(event.update.nodes[0].id, 1);
    134     EXPECT_EQ(event.update.nodes[0].role,
    135               ui::AX_ROLE_ROOT_WEB_AREA);
    136     EXPECT_EQ(event.update.nodes[0].state,
    137               (1U << ui::AX_STATE_READ_ONLY) |
    138               (1U << ui::AX_STATE_FOCUSABLE));
    139     EXPECT_EQ(event.update.nodes[0].child_ids.size(), 1U);
    140     EXPECT_EQ(event.update.nodes[1].id, 3);
    141     EXPECT_EQ(event.update.nodes[1].role,
    142               ui::AX_ROLE_GROUP);
    143     EXPECT_EQ(event.update.nodes[1].state,
    144               (1U << ui::AX_STATE_FOCUSABLE) |
    145               (1U << ui::AX_STATE_FOCUSED));
    146   }
    147 
    148   // Check other editable text nodes.
    149   {
    150     SCOPED_TRACE("textarea");
    151     sink_->ClearMessages();
    152     ExecuteJavaScript("document.querySelector('textarea').focus();");
    153     AccessibilityHostMsg_EventParams event;
    154     GetLastAccEvent(&event);
    155     EXPECT_EQ(event.id, 4);
    156     EXPECT_EQ(event.update.nodes[1].state,
    157               (1U << ui::AX_STATE_FOCUSABLE) |
    158               (1U << ui::AX_STATE_FOCUSED));
    159   }
    160 
    161   {
    162     SCOPED_TRACE("contentEditable");
    163     sink_->ClearMessages();
    164     ExecuteJavaScript("document.querySelector('p').focus();");
    165     AccessibilityHostMsg_EventParams event;
    166     GetLastAccEvent(&event);
    167     EXPECT_EQ(event.id, 5);
    168     EXPECT_EQ(event.update.nodes[1].state,
    169               (1U << ui::AX_STATE_FOCUSABLE) |
    170               (1U << ui::AX_STATE_FOCUSED));
    171   }
    172 
    173   {
    174     SCOPED_TRACE("role=textarea");
    175     sink_->ClearMessages();
    176     ExecuteJavaScript("document.querySelector('div').focus();");
    177     AccessibilityHostMsg_EventParams event;
    178     GetLastAccEvent(&event);
    179     EXPECT_EQ(event.id, 6);
    180     EXPECT_EQ(event.update.nodes[1].state,
    181               (1U << ui::AX_STATE_FOCUSABLE) |
    182               (1U << ui::AX_STATE_FOCUSED));
    183   }
    184 
    185   // Try focusing things that aren't editable text.
    186   {
    187     SCOPED_TRACE("button");
    188     sink_->ClearMessages();
    189     ExecuteJavaScript("document.querySelector('button').focus();");
    190     AccessibilityHostMsg_EventParams event;
    191     GetLastAccEvent(&event);
    192     EXPECT_EQ(event.id, 7);
    193     EXPECT_EQ(event.update.nodes[1].state,
    194               (1U << ui::AX_STATE_FOCUSABLE) |
    195               (1U << ui::AX_STATE_FOCUSED) |
    196               (1U << ui::AX_STATE_READ_ONLY));
    197   }
    198 
    199   {
    200     SCOPED_TRACE("link");
    201     sink_->ClearMessages();
    202     ExecuteJavaScript("document.querySelector('a').focus();");
    203     AccessibilityHostMsg_EventParams event;
    204     GetLastAccEvent(&event);
    205     EXPECT_EQ(event.id, 8);
    206     EXPECT_EQ(event.update.nodes[1].state,
    207               (1U << ui::AX_STATE_FOCUSABLE) |
    208               (1U << ui::AX_STATE_FOCUSED) |
    209               (1U << ui::AX_STATE_READ_ONLY));
    210   }
    211 
    212   // Clear focus.
    213   {
    214     SCOPED_TRACE("Back to document.");
    215     sink_->ClearMessages();
    216     ExecuteJavaScript("document.activeElement.blur()");
    217     AccessibilityHostMsg_EventParams event;
    218     GetLastAccEvent(&event);
    219     EXPECT_EQ(event.id, 1);
    220   }
    221 }
    222 
    223 TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
    224   // The job of RendererAccessibilityComplete is to serialize the
    225   // accessibility tree built by WebKit and send it to the browser.
    226   // When the accessibility tree changes, it tries to send only
    227   // the nodes that actually changed or were reparented. This test
    228   // ensures that the messages sent are correct in cases when a page
    229   // reloads, and that internal state is properly garbage-collected.
    230   std::string html =
    231       "<body>"
    232       "  <div role='group' id='A'>"
    233       "    <div role='group' id='A1'></div>"
    234       "    <div role='group' id='A2'></div>"
    235       "  </div>"
    236       "</body>";
    237   LoadHTML(html.c_str());
    238 
    239   // Creating a RendererAccessibilityComplete should sent the tree
    240   // to the browser.
    241   scoped_ptr<TestRendererAccessibilityComplete> accessibility(
    242       new TestRendererAccessibilityComplete(view()));
    243   accessibility->SendPendingAccessibilityEvents();
    244   EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
    245 
    246   // If we post another event but the tree doesn't change,
    247   // we should only send 1 node to the browser.
    248   sink_->ClearMessages();
    249   WebDocument document = view()->GetWebView()->mainFrame()->document();
    250   WebAXObject root_obj = document.accessibilityObject();
    251   accessibility->HandleAXEvent(
    252       root_obj,
    253       ui::AX_EVENT_LAYOUT_COMPLETE);
    254   accessibility->SendPendingAccessibilityEvents();
    255   EXPECT_EQ(1, CountAccessibilityNodesSentToBrowser());
    256   {
    257     // Make sure it's the root object that was updated.
    258     AccessibilityHostMsg_EventParams event;
    259     GetLastAccEvent(&event);
    260     EXPECT_EQ(root_obj.axID(), event.update.nodes[0].id);
    261   }
    262 
    263   // If we reload the page and send a event, we should send
    264   // all 4 nodes to the browser. Also double-check that we didn't
    265   // leak any of the old BrowserTreeNodes.
    266   LoadHTML(html.c_str());
    267   document = view()->GetWebView()->mainFrame()->document();
    268   root_obj = document.accessibilityObject();
    269   sink_->ClearMessages();
    270   accessibility->HandleAXEvent(
    271       root_obj,
    272       ui::AX_EVENT_LAYOUT_COMPLETE);
    273   accessibility->SendPendingAccessibilityEvents();
    274   EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
    275 
    276   // Even if the first event is sent on an element other than
    277   // the root, the whole tree should be updated because we know
    278   // the browser doesn't have the root element.
    279   LoadHTML(html.c_str());
    280   document = view()->GetWebView()->mainFrame()->document();
    281   root_obj = document.accessibilityObject();
    282   sink_->ClearMessages();
    283   const WebAXObject& first_child = root_obj.childAt(0);
    284   accessibility->HandleAXEvent(
    285       first_child,
    286       ui::AX_EVENT_LIVE_REGION_CHANGED);
    287   accessibility->SendPendingAccessibilityEvents();
    288   EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
    289 }
    290 
    291 // http://crbug.com/253537
    292 #if defined(OS_ANDROID)
    293 #define MAYBE_AccessibilityMessagesQueueWhileSwappedOut \
    294         DISABLED_AccessibilityMessagesQueueWhileSwappedOut
    295 #else
    296 #define MAYBE_AccessibilityMessagesQueueWhileSwappedOut \
    297         AccessibilityMessagesQueueWhileSwappedOut
    298 #endif
    299 
    300 TEST_F(RendererAccessibilityTest,
    301        MAYBE_AccessibilityMessagesQueueWhileSwappedOut) {
    302   std::string html =
    303       "<body>"
    304       "  <p>Hello, world.</p>"
    305       "</body>";
    306   LoadHTML(html.c_str());
    307   static const int kProxyRoutingId = 13;
    308 
    309   // Creating a RendererAccessibilityComplete should send the tree
    310   // to the browser.
    311   scoped_ptr<TestRendererAccessibilityComplete> accessibility(
    312       new TestRendererAccessibilityComplete(view()));
    313   accessibility->SendPendingAccessibilityEvents();
    314   EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser());
    315 
    316   // Post a "value changed" event, but then swap out
    317   // before sending it. It shouldn't send the event while
    318   // swapped out.
    319   sink_->ClearMessages();
    320   WebDocument document = view()->GetWebView()->mainFrame()->document();
    321   WebAXObject root_obj = document.accessibilityObject();
    322   accessibility->HandleAXEvent(
    323       root_obj,
    324       ui::AX_EVENT_VALUE_CHANGED);
    325   view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
    326   accessibility->SendPendingAccessibilityEvents();
    327   EXPECT_FALSE(sink_->GetUniqueMessageMatching(
    328       AccessibilityHostMsg_Events::ID));
    329 
    330   // Navigate, so we're not swapped out anymore. Now we should
    331   // send accessibility events again. Note that the
    332   // message that was queued up before will be quickly discarded
    333   // because the element it was referring to no longer exists,
    334   // so the event here is from loading this new page.
    335   FrameMsg_Navigate_Params nav_params;
    336   nav_params.url = GURL("data:text/html,<p>Hello, again.</p>");
    337   nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
    338   nav_params.transition = PAGE_TRANSITION_TYPED;
    339   nav_params.current_history_list_length = 1;
    340   nav_params.current_history_list_offset = 0;
    341   nav_params.pending_history_list_offset = 1;
    342   nav_params.page_id = -1;
    343   frame()->OnNavigate(nav_params);
    344   accessibility->SendPendingAccessibilityEvents();
    345   EXPECT_TRUE(sink_->GetUniqueMessageMatching(
    346       AccessibilityHostMsg_Events::ID));
    347 }
    348 
    349 TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
    350   // Test RendererAccessibilityComplete and make sure it sends the
    351   // proper event to the browser when an object in the tree
    352   // is hidden, but its children are not.
    353   std::string html =
    354       "<body>"
    355       "  <div role='group' id='A'>"
    356       "    <div role='group' id='B'>"
    357       "      <div role='group' id='C' style='visibility:visible'>"
    358       "      </div>"
    359       "    </div>"
    360       "  </div>"
    361       "</body>";
    362   LoadHTML(html.c_str());
    363 
    364   scoped_ptr<TestRendererAccessibilityComplete> accessibility(
    365       new TestRendererAccessibilityComplete(view()));
    366   accessibility->SendPendingAccessibilityEvents();
    367   EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
    368 
    369   WebDocument document = view()->GetWebView()->mainFrame()->document();
    370   WebAXObject root_obj = document.accessibilityObject();
    371   WebAXObject node_a = root_obj.childAt(0);
    372   WebAXObject node_b = node_a.childAt(0);
    373   WebAXObject node_c = node_b.childAt(0);
    374 
    375   // Hide node 'B' ('C' stays visible).
    376   ExecuteJavaScript(
    377       "document.getElementById('B').style.visibility = 'hidden';");
    378   // Force layout now.
    379   ExecuteJavaScript("document.getElementById('B').offsetLeft;");
    380 
    381   // Send a childrenChanged on 'A'.
    382   sink_->ClearMessages();
    383   accessibility->HandleAXEvent(
    384       node_a,
    385       ui::AX_EVENT_CHILDREN_CHANGED);
    386 
    387   accessibility->SendPendingAccessibilityEvents();
    388   AccessibilityHostMsg_EventParams event;
    389   GetLastAccEvent(&event);
    390   ASSERT_EQ(2U, event.update.nodes.size());
    391 
    392   // RendererAccessibilityComplete notices that 'C' is being reparented,
    393   // so it clears the subtree rooted at 'A', then updates 'A' and then 'C'.
    394   EXPECT_EQ(node_a.axID(), event.update.node_id_to_clear);
    395   EXPECT_EQ(node_a.axID(), event.update.nodes[0].id);
    396   EXPECT_EQ(node_c.axID(), event.update.nodes[1].id);
    397   EXPECT_EQ(2, CountAccessibilityNodesSentToBrowser());
    398 }
    399 
    400 TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
    401   // Test RendererAccessibilityComplete and make sure it sends the
    402   // proper event to the browser when an object in the tree
    403   // is shown, causing its own already-visible children to be
    404   // reparented to it.
    405   std::string html =
    406       "<body>"
    407       "  <div role='group' id='A'>"
    408       "    <div role='group' id='B' style='visibility:hidden'>"
    409       "      <div role='group' id='C' style='visibility:visible'>"
    410       "      </div>"
    411       "    </div>"
    412       "  </div>"
    413       "</body>";
    414   LoadHTML(html.c_str());
    415 
    416   scoped_ptr<TestRendererAccessibilityComplete> accessibility(
    417       new TestRendererAccessibilityComplete(view()));
    418   accessibility->SendPendingAccessibilityEvents();
    419   EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
    420 
    421   // Show node 'B', then send a childrenChanged on 'A'.
    422   ExecuteJavaScript(
    423       "document.getElementById('B').style.visibility = 'visible';");
    424   ExecuteJavaScript("document.getElementById('B').offsetLeft;");
    425 
    426   sink_->ClearMessages();
    427   WebDocument document = view()->GetWebView()->mainFrame()->document();
    428   WebAXObject root_obj = document.accessibilityObject();
    429   WebAXObject node_a = root_obj.childAt(0);
    430   WebAXObject node_b = node_a.childAt(0);
    431   WebAXObject node_c = node_b.childAt(0);
    432 
    433   accessibility->HandleAXEvent(
    434       node_a,
    435       ui::AX_EVENT_CHILDREN_CHANGED);
    436 
    437   accessibility->SendPendingAccessibilityEvents();
    438   AccessibilityHostMsg_EventParams event;
    439   GetLastAccEvent(&event);
    440 
    441   ASSERT_EQ(3U, event.update.nodes.size());
    442   EXPECT_EQ(node_a.axID(), event.update.node_id_to_clear);
    443   EXPECT_EQ(node_a.axID(), event.update.nodes[0].id);
    444   EXPECT_EQ(node_b.axID(), event.update.nodes[1].id);
    445   EXPECT_EQ(node_c.axID(), event.update.nodes[2].id);
    446   EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
    447 }
    448 
    449 TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
    450   // Test RendererAccessibilityComplete and make sure it sends the
    451   // proper event to the browser when an object in the tree
    452   // is detached, but its children are not. This can happen when
    453   // a layout occurs and an anonymous render block is no longer needed.
    454   std::string html =
    455       "<body aria-label='Body'>"
    456       "<span>1</span><span style='display:block'>2</span>"
    457       "</body>";
    458   LoadHTML(html.c_str());
    459 
    460   scoped_ptr<TestRendererAccessibilityComplete> accessibility(
    461       new TestRendererAccessibilityComplete(view()));
    462   accessibility->SendPendingAccessibilityEvents();
    463   EXPECT_EQ(7, CountAccessibilityNodesSentToBrowser());
    464 
    465   // Initially, the accessibility tree looks like this:
    466   //
    467   //   Document
    468   //   +--Body
    469   //      +--Anonymous Block
    470   //         +--Static Text "1"
    471   //            +--Inline Text Box "1"
    472   //      +--Static Text "2"
    473   //         +--Inline Text Box "2"
    474   WebDocument document = view()->GetWebView()->mainFrame()->document();
    475   WebAXObject root_obj = document.accessibilityObject();
    476   WebAXObject body = root_obj.childAt(0);
    477   WebAXObject anonymous_block = body.childAt(0);
    478   WebAXObject text_1 = anonymous_block.childAt(0);
    479   WebAXObject text_2 = body.childAt(1);
    480 
    481   // Change the display of the second 'span' back to inline, which causes the
    482   // anonymous block to be destroyed.
    483   ExecuteJavaScript(
    484       "document.querySelectorAll('span')[1].style.display = 'inline';");
    485   // Force layout now.
    486   ExecuteJavaScript("document.body.offsetLeft;");
    487 
    488   // Send a childrenChanged on the body.
    489   sink_->ClearMessages();
    490   accessibility->HandleAXEvent(
    491       body,
    492       ui::AX_EVENT_CHILDREN_CHANGED);
    493 
    494   accessibility->SendPendingAccessibilityEvents();
    495 
    496   // Afterwards, the accessibility tree looks like this:
    497   //
    498   //   Document
    499   //   +--Body
    500   //      +--Static Text "1"
    501   //         +--Inline Text Box "1"
    502   //      +--Static Text "2"
    503   //         +--Inline Text Box "2"
    504   //
    505   // We just assert that there are now four nodes in the
    506   // accessibility tree and that only three nodes needed
    507   // to be updated (the body, the static text 1, and
    508   // the static text 2).
    509 
    510   AccessibilityHostMsg_EventParams event;
    511   GetLastAccEvent(&event);
    512   ASSERT_EQ(5U, event.update.nodes.size());
    513 
    514   EXPECT_EQ(body.axID(), event.update.nodes[0].id);
    515   EXPECT_EQ(text_1.axID(), event.update.nodes[1].id);
    516   // The third event is to update text_2, but its id changes
    517   // so we don't have a test expectation for it.
    518 }
    519 
    520 TEST_F(RendererAccessibilityTest, EventOnObjectNotInTree) {
    521   // Test RendererAccessibilityComplete and make sure it doesn't send anything
    522   // if we get a notification from Blink for an object that isn't in the
    523   // tree, like the scroll area that's the parent of the main document,
    524   // which we don't expose.
    525   std::string html = "<body><input></body>";
    526   LoadHTML(html.c_str());
    527 
    528   scoped_ptr<TestRendererAccessibilityComplete> accessibility(
    529       new TestRendererAccessibilityComplete(view()));
    530   accessibility->SendPendingAccessibilityEvents();
    531   EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
    532 
    533   WebDocument document = view()->GetWebView()->mainFrame()->document();
    534   WebAXObject root_obj = document.accessibilityObject();
    535   WebAXObject scroll_area = root_obj.parentObject();
    536   EXPECT_EQ(blink::WebAXRoleScrollArea, scroll_area.role());
    537 
    538   // Try to fire a message on the scroll area, and assert that we just
    539   // ignore it.
    540   sink_->ClearMessages();
    541   accessibility->HandleAXEvent(scroll_area,
    542                                ui::AX_EVENT_VALUE_CHANGED);
    543 
    544   accessibility->SendPendingAccessibilityEvents();
    545 
    546   const IPC::Message* message =
    547       sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID);
    548   ASSERT_TRUE(message);
    549   Tuple1<std::vector<AccessibilityHostMsg_EventParams> > param;
    550   AccessibilityHostMsg_Events::Read(message, &param);
    551   ASSERT_EQ(0U, param.a.size());
    552 }
    553 
    554 }  // namespace content
    555