AccessibilityNotificationHandler.mm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Copyright (C) 2011 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following disclaimer
  12. * in the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #import "config.h"
  31. #import "DumpRenderTree.h"
  32. #import "AccessibilityNotificationHandler.h"
  33. #import "AccessibilityUIElement.h"
  34. #import <JavaScriptCore/JSRetainPtr.h>
  35. #import <JavaScriptCore/JSStringRef.h>
  36. #import <JavaScriptCore/JSStringRefCF.h>
  37. #import <WebKit/WebFrame.h>
  38. #import <WebKit/WebTypesInternal.h>
  39. #import <wtf/RetainPtr.h>
  40. @interface NSObject (WebAccessibilityObjectWrapperAdditions)
  41. + (void)accessibilitySetShouldRepostNotifications:(BOOL)repost;
  42. @end
  43. @interface NSString (JSStringRefAdditions)
  44. - (JSStringRef)createJSStringRef;
  45. @end
  46. @implementation NSString (JSStringRefAdditions)
  47. - (JSStringRef)createJSStringRef
  48. {
  49. return JSStringCreateWithCFString((CFStringRef)self);
  50. }
  51. @end
  52. @implementation AccessibilityNotificationHandler
  53. - (id)init
  54. {
  55. if (!(self = [super init]))
  56. return nil;
  57. m_platformElement = nil;
  58. return self;
  59. }
  60. - (void)setPlatformElement:(id)platformElement
  61. {
  62. m_platformElement = platformElement;
  63. }
  64. - (void)dealloc
  65. {
  66. [[NSNotificationCenter defaultCenter] removeObserver:self];
  67. JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback);
  68. m_notificationFunctionCallback = 0;
  69. [super dealloc];
  70. }
  71. - (void)setCallback:(JSObjectRef)callback
  72. {
  73. if (!callback)
  74. return;
  75. if (m_notificationFunctionCallback)
  76. JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback);
  77. m_notificationFunctionCallback = callback;
  78. JSValueProtect([mainFrame globalContext], m_notificationFunctionCallback);
  79. }
  80. - (void)startObserving
  81. {
  82. // Once we start requesting notifications, it's on for the duration of the program.
  83. // This is to avoid any race conditions between tests turning this flag on and off. Instead
  84. // AccessibilityNotificationHandler can ignore events it doesn't care about.
  85. id webAccessibilityObjectWrapperClass = NSClassFromString(@"WebAccessibilityObjectWrapper");
  86. ASSERT(webAccessibilityObjectWrapperClass);
  87. [webAccessibilityObjectWrapperClass accessibilitySetShouldRepostNotifications:YES];
  88. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_notificationReceived:) name:@"AXDRTNotification" object:nil];
  89. }
  90. - (void)_notificationReceived:(NSNotification *)notification
  91. {
  92. NSString *notificationName = [[notification userInfo] objectForKey:@"notificationName"];
  93. if (!notificationName)
  94. return;
  95. if (m_platformElement && m_platformElement != [notification object])
  96. return;
  97. JSRetainPtr<JSStringRef> jsNotification(Adopt, [notificationName createJSStringRef]);
  98. JSValueRef notificationNameArgument = JSValueMakeString([mainFrame globalContext], jsNotification.get());
  99. if (m_platformElement) {
  100. // Listener for one element just gets one argument, the notification name.
  101. JSObjectCallAsFunction([mainFrame globalContext], m_notificationFunctionCallback, 0, 1, &notificationNameArgument, 0);
  102. } else {
  103. // A global listener gets the element and the notification name as arguments.
  104. JSValueRef arguments[2];
  105. arguments[0] = AccessibilityUIElement::makeJSAccessibilityUIElement([mainFrame globalContext], AccessibilityUIElement([notification object]));
  106. arguments[1] = notificationNameArgument;
  107. JSObjectCallAsFunction([mainFrame globalContext], m_notificationFunctionCallback, 0, 2, arguments, 0);
  108. }
  109. }
  110. @end