diff --git a/DEPS b/DEPS index 3365dfd1..67e7306 100644 --- a/DEPS +++ b/DEPS
@@ -43,7 +43,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '75076c2a96bc67b1c44cc283f85bac40ef456de3', + 'v8_revision': '6b270a44e31ea4b473d6806039ee71b262ead725', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other.
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 57cccab..98aff681 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -725,7 +725,10 @@ void BrowserAccessibility::Destroy() { // Allow the object to fire a TextRemoved notification. - manager_->NotifyAccessibilityEvent(ui::AX_EVENT_HIDE, this); + manager()->NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_HIDE, + this); node_ = NULL; manager_ = NULL;
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 55982e9c..dd96eaa9b 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -65,7 +65,10 @@ } void BrowserAccessibilityAndroid::OnLocationChanged() { - manager()->NotifyAccessibilityEvent(ui::AX_EVENT_LOCATION_CHANGED, this); + manager()->NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_LOCATION_CHANGED, + this); } base::string16 BrowserAccessibilityAndroid::GetValue() const { @@ -1373,8 +1376,12 @@ } } - if (GetRole() == ui::AX_ROLE_ALERT && first_time_) - manager()->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); + if (GetRole() == ui::AX_ROLE_ALERT && first_time_) { + manager()->NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_ALERT, + this); + } base::string16 live; if (GetString16Attribute( @@ -1394,8 +1401,10 @@ base::string16 text = GetText(); if (cached_text_ != text) { if (!text.empty()) { - manager()->NotifyAccessibilityEvent(ui::AX_EVENT_SHOW, - this); + manager()->NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_SHOW, + this); } cached_text_ = text; }
diff --git a/content/browser/accessibility/browser_accessibility_event.cc b/content/browser/accessibility/browser_accessibility_event.cc new file mode 100644 index 0000000..778c25a --- /dev/null +++ b/content/browser/accessibility/browser_accessibility_event.cc
@@ -0,0 +1,146 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/accessibility/browser_accessibility_event.h" + +#include <string> + +#include "base/strings/string_util.h" +#include "content/browser/accessibility/browser_accessibility.h" +#include "content/browser/accessibility/browser_accessibility_manager.h" + +namespace content { + +namespace { +std::string ReplaceNewlines(std::string str) { + std::string result; + base::ReplaceChars(str, "\n", "\\n", &result); + return result; +} +} // namespace + +// static +bool BrowserAccessibilityEvent::FailedToSend(Result result) { + switch (result) { + case Sent: + case NotNeededOnThisPlatform: + case DiscardedBecauseUserNavigatingAway: + case DiscardedBecauseLiveRegionBusy: + return false; + case FailedBecauseNoWindow: + case FailedBecauseNoFocus: + case FailedBecauseFrameIsDetached: + return true; + } + + NOTREACHED(); + return true; +} + +#if !defined(OS_WIN) +// static +BrowserAccessibilityEvent* BrowserAccessibilityEvent::Create( + Source source, + ui::AXEvent event_type, + const BrowserAccessibility* target) { + return new BrowserAccessibilityEvent(source, event_type, target); +} +#endif // !defined(OS_WIN) + +BrowserAccessibilityEvent::BrowserAccessibilityEvent( + Source source, + ui::AXEvent event_type, + const BrowserAccessibility* target) + : source_(source), + event_type_(event_type), + target_(target), + original_target_(target) { + DCHECK(target_); +} + +BrowserAccessibilityEvent::~BrowserAccessibilityEvent() { +} + +BrowserAccessibilityEvent::Result BrowserAccessibilityEvent::Fire() { + delete this; + return NotNeededOnThisPlatform; +} + +std::string BrowserAccessibilityEvent::GetEventNameStr() { + return ui::ToString(event_type_); +} + +void BrowserAccessibilityEvent::VerboseLog(Result result) { + std::string event_name = GetEventNameStr(); + + const char* result_str = nullptr; + switch (result) { + case Sent: + result_str = "Sent"; + break; + case NotNeededOnThisPlatform: + result_str = "NotNeededOnThisPlatform"; + break; + case DiscardedBecauseUserNavigatingAway: + result_str = "DiscardedBecauseUserNavigatingAway"; + break; + case DiscardedBecauseLiveRegionBusy: + result_str = "DiscardedBecauseLiveRegionBusy"; + break; + case FailedBecauseNoWindow: + result_str = "FailedBecauseNoWindow"; + break; + case FailedBecauseNoFocus: + result_str = "FailedBecauseNoFocus"; + break; + case FailedBecauseFrameIsDetached: + result_str = "FailedBecauseFrameIsDetached"; + break; + } + + const char* success_str = (result == Sent ? "+" : "-"); + + const char* source_str = nullptr; + switch (source_) { + case FromBlink: + source_str = "FromBlink"; + break; + case FromChildFrameLoading: + source_str = "FromChildFrameLoading"; + break; + case FromFindInPageResult: + source_str = "FromFindInPageResult"; + break; + case FromRenderFrameHost: + source_str = "FromRenderFrameHost"; + break; + case FromScroll: + source_str = "FromScroll"; + break; + case FromTreeChange: + source_str = "FromTreeChange"; + break; + case FromWindowFocusChange: + source_str = "FromWindowFocusChange"; + break; + } + + std::string original_target_str; + if (original_target_ != target_) { + original_target_str = " originalTarget=[[" + + ReplaceNewlines(original_target_->GetData().ToString()) + "]]"; + } + + VLOG(1) << "Accessibility event" + << " " << success_str + << " " << event_name + << " result=" << result_str + << " source=" << source_str + << " unique_id=" << target_->unique_id() + << " target=[[" + << ReplaceNewlines(target_->GetData().ToString()) << "]]" + << original_target_str; +} + +} // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_event.h b/content/browser/accessibility/browser_accessibility_event.h new file mode 100644 index 0000000..470d8b2f --- /dev/null +++ b/content/browser/accessibility/browser_accessibility_event.h
@@ -0,0 +1,84 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_EVENT_H_ +#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_EVENT_H_ + +#include <string> + +#include "content/browser/accessibility/browser_accessibility.h" +#include "content/common/content_export.h" +#include "ui/accessibility/ax_enums.h" + +namespace content { + +class BrowserAccessibility; + +class CONTENT_EXPORT BrowserAccessibilityEvent { + public: + enum Source { + FromBlink, + FromChildFrameLoading, + FromFindInPageResult, + FromRenderFrameHost, + FromScroll, + FromTreeChange, + FromWindowFocusChange, + }; + + enum Result { + Sent, + NotNeededOnThisPlatform, + DiscardedBecauseUserNavigatingAway, + DiscardedBecauseLiveRegionBusy, + FailedBecauseNoWindow, + FailedBecauseNoFocus, + FailedBecauseFrameIsDetached, + }; + + // Returns true if the given result indicates that sending the event failed. + // Returns false if the event was sent, or if it was not needed (which is + // not considered failure). + static bool FailedToSend(Result result); + + static BrowserAccessibilityEvent* Create(Source source, + ui::AXEvent event_type, + const BrowserAccessibility* target); + + // Construct a new accessibility event that should be sent via a + // platform-specific notification. + BrowserAccessibilityEvent(Source source, + ui::AXEvent event_type, + const BrowserAccessibility* target); + virtual ~BrowserAccessibilityEvent(); + + // Synchronously try to send the native accessibility event notification + // and return a result indicating the outcome. This deletes the event. + virtual Result Fire(); + + Source source() { return source_; } + ui::AXEvent event_type() { return event_type_; } + const BrowserAccessibility* target() { return target_; } + void set_target(const BrowserAccessibility* target) { target_ = target; } + void set_original_target(BrowserAccessibility* target) { + original_target_ = target; + } + + protected: + virtual std::string GetEventNameStr(); + void VerboseLog(Result result); + + private: + Source source_; + ui::AXEvent event_type_; + const BrowserAccessibility* target_; + const BrowserAccessibility* original_target_; + + private: + DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityEvent); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_EVENT_H_
diff --git a/content/browser/accessibility/browser_accessibility_event_win.cc b/content/browser/accessibility/browser_accessibility_event_win.cc new file mode 100644 index 0000000..effc4151 --- /dev/null +++ b/content/browser/accessibility/browser_accessibility_event_win.cc
@@ -0,0 +1,100 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/accessibility/browser_accessibility_event_win.h" + +#include "base/strings/utf_string_conversions.h" +#include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h" +#include "content/browser/accessibility/browser_accessibility.h" +#include "content/browser/accessibility/browser_accessibility_manager_win.h" + +namespace content { + +// static +BrowserAccessibilityEvent* BrowserAccessibilityEvent::Create( + Source source, + ui::AXEvent event_type, + const BrowserAccessibility* target) { + LONG win_event_type = EVENT_MIN; + switch (event_type) { + case ui::AX_EVENT_ACTIVEDESCENDANTCHANGED: + win_event_type = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED; + break; + case ui::AX_EVENT_ALERT: + win_event_type = EVENT_SYSTEM_ALERT; + break; + case ui::AX_EVENT_AUTOCORRECTION_OCCURED: + win_event_type = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED; + break; + case ui::AX_EVENT_CHILDREN_CHANGED: + win_event_type = EVENT_OBJECT_REORDER; + break; + case ui::AX_EVENT_FOCUS: + win_event_type = EVENT_OBJECT_FOCUS; + break; + case ui::AX_EVENT_LIVE_REGION_CHANGED: + win_event_type = EVENT_OBJECT_LIVEREGIONCHANGED; + break; + case ui::AX_EVENT_LOAD_COMPLETE: + win_event_type = IA2_EVENT_DOCUMENT_LOAD_COMPLETE; + break; + case ui::AX_EVENT_SCROLL_POSITION_CHANGED: + win_event_type = EVENT_SYSTEM_SCROLLINGEND; + break; + case ui::AX_EVENT_SCROLLED_TO_ANCHOR: + win_event_type = EVENT_SYSTEM_SCROLLINGSTART; + break; + case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED: + win_event_type = EVENT_OBJECT_SELECTIONWITHIN; + break; + default: + break; + } + + return new BrowserAccessibilityEventWin( + source, + event_type, + win_event_type, + target); +} + +BrowserAccessibilityEventWin::BrowserAccessibilityEventWin( + Source source, + ui::AXEvent event_type, + LONG win_event_type, + const BrowserAccessibility* target) + : BrowserAccessibilityEvent(source, event_type, target), + win_event_type_(win_event_type) { +} + +BrowserAccessibilityEventWin::~BrowserAccessibilityEventWin() { +} + +BrowserAccessibilityEvent::Result BrowserAccessibilityEventWin::Fire() { + DCHECK(target()->manager()); + + if (win_event_type_ == EVENT_MIN) { + delete this; + return NotNeededOnThisPlatform; + } + + Result result = target()->manager()->ToBrowserAccessibilityManagerWin() + ->FireWinAccessibilityEvent(this); + + if (VLOG_IS_ON(1)) + VerboseLog(result); + + delete this; + return result; +} + +std::string BrowserAccessibilityEventWin::GetEventNameStr() { + std::string result = base::UTF16ToUTF8(AccessibilityEventToString( + win_event_type_)); + if (event_type() != ui::AX_EVENT_NONE) + result += "/" + ui::ToString(event_type()); + return result; +} + +} // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_event_win.h b/content/browser/accessibility/browser_accessibility_event_win.h new file mode 100644 index 0000000..1d1ac4e --- /dev/null +++ b/content/browser/accessibility/browser_accessibility_event_win.h
@@ -0,0 +1,38 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_EVENT_WIN_H_ +#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_EVENT_WIN_H_ + +#include <oleacc.h> + +#include "content/browser/accessibility/browser_accessibility_event.h" + +namespace content { + +class CONTENT_EXPORT BrowserAccessibilityEventWin + : public BrowserAccessibilityEvent { + public: + BrowserAccessibilityEventWin(Source source, + ui::AXEvent event_type, + LONG win_event_type, + const BrowserAccessibility* target); + ~BrowserAccessibilityEventWin() override; + + LONG win_event_type() { return win_event_type_; } + + Result Fire() override; + + protected: + std::string GetEventNameStr() override; + + LONG win_event_type_; + + private: + DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityEventWin); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_EVENT_WIN_H_
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index df9c931..84c2ec0e 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -183,7 +183,15 @@ return update; } -void BrowserAccessibilityManager::FireFocusEventsIfNeeded() { +void BrowserAccessibilityManager::NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, + ui::AXEvent event_type, + BrowserAccessibility* node) { + BrowserAccessibilityEvent::Create(source, event_type, node)->Fire(); +} + +void BrowserAccessibilityManager::FireFocusEventsIfNeeded( + BrowserAccessibilityEvent::Source source) { BrowserAccessibility* focus = GetFocus(); // Don't fire focus events if the window itself doesn't have focus. @@ -209,7 +217,7 @@ } if (focus && focus != last_focused_node_) - FireFocusEvent(focus); + FireFocusEvent(source, focus); last_focused_node_ = focus; last_focused_manager_ = focus ? focus->manager() : nullptr; @@ -219,8 +227,10 @@ return true; } -void BrowserAccessibilityManager::FireFocusEvent(BrowserAccessibility* node) { - NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node); +void BrowserAccessibilityManager::FireFocusEvent( + BrowserAccessibilityEvent::Source source, + BrowserAccessibility* node) { + NotifyAccessibilityEvent(source, ui::AX_EVENT_FOCUS, node); if (!g_focus_change_callback_for_testing.Get().is_null()) g_focus_change_callback_for_testing.Get().Run(); @@ -292,7 +302,7 @@ void BrowserAccessibilityManager::OnWindowFocused() { if (this == GetRootManager()) - FireFocusEventsIfNeeded(); + FireFocusEventsIfNeeded(BrowserAccessibilityEvent::FromWindowFocusChange); } void BrowserAccessibilityManager::OnWindowBlurred() { @@ -318,15 +328,6 @@ user_is_navigating_away_ = false; } -void BrowserAccessibilityManager::GotMouseDown() { - BrowserAccessibility* focus = GetFocus(); - if (!focus) - return; - - osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT; - NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus); -} - bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() { return true; } @@ -354,8 +355,10 @@ if (!connected_to_parent_tree_node_) { parent->OnDataChanged(); parent->UpdatePlatformAttributes(); - parent->manager()->NotifyAccessibilityEvent( - ui::AX_EVENT_CHILDREN_CHANGED, parent); + NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromChildFrameLoading, + ui::AX_EVENT_CHILDREN_CHANGED, + parent); connected_to_parent_tree_node_ = true; } } else { @@ -366,7 +369,8 @@ // Screen readers might not do the right thing if they're not aware of what // has focus, so always try that first. Nothing will be fired if the window // itself isn't focused or if focus hasn't changed. - GetRootManager()->FireFocusEventsIfNeeded(); + GetRootManager()->FireFocusEventsIfNeeded( + BrowserAccessibilityEvent::FromBlink); // Now iterate over the events again and fire the events other than focus // events. @@ -398,7 +402,13 @@ } // Fire the native event. - NotifyAccessibilityEvent(event_type, GetFromAXNode(node)); + BrowserAccessibility* event_target = GetFromAXNode(node); + if (event_target) { + NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromBlink, + event_type, + event_target); + } } } @@ -473,7 +483,10 @@ // The "scrolled to anchor" notification is a great way to get a // screen reader to jump directly to a specific location in a document. - NotifyAccessibilityEvent(ui::AX_EVENT_SCROLLED_TO_ANCHOR, node); + NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromFindInPageResult, + ui::AX_EVENT_SCROLLED_TO_ANCHOR, + node); } BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus(
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index ad073bf..d875e8ae 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "build/build_config.h" #include "content/browser/accessibility/ax_tree_id_registry.h" +#include "content/browser/accessibility/browser_accessibility_event.h" #include "content/common/content_export.h" #include "content/public/browser/ax_event_notification_details.h" #include "third_party/WebKit/public/web/WebAXEnums.h" @@ -142,19 +143,22 @@ static ui::AXTreeUpdate GetEmptyDocument(); virtual void NotifyAccessibilityEvent( - ui::AXEvent event_type, BrowserAccessibility* node) { } + BrowserAccessibilityEvent::Source source, + ui::AXEvent event_type, + BrowserAccessibility* node); // Checks whether focus has changed since the last time it was checked, // taking into account whether the window has focus and which frame within // the frame tree has focus. If focus has changed, calls FireFocusEvent. - void FireFocusEventsIfNeeded(); + void FireFocusEventsIfNeeded(BrowserAccessibilityEvent::Source source); // Return whether or not we are currently able to fire events. virtual bool CanFireEvents(); // Fire a focus event. Virtual so that some platforms can customize it, // like firing a focus event on the root first, on Windows. - virtual void FireFocusEvent(BrowserAccessibility* node); + virtual void FireFocusEvent(BrowserAccessibilityEvent::Source source, + BrowserAccessibility* node); // Return a pointer to the root of the tree, does not make a new reference. BrowserAccessibility* GetRoot(); @@ -186,10 +190,6 @@ void NavigationSucceeded(); void NavigationFailed(); - // Called to notify the accessibility manager that a mouse down event - // occurred in the tab. - void GotMouseDown(); - // Send a message to the renderer to set focus to this node. void SetFocus(const BrowserAccessibility& node);
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 1522967..0575e94d 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -193,6 +193,7 @@ } void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, ui::AXEvent event_type, BrowserAccessibility* node) { JNIEnv* env = AttachCurrentThread();
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h index 981af00..90d0064f 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.h +++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -77,8 +77,10 @@ bool ShouldExposePasswordText(); // BrowserAccessibilityManager overrides. - void NotifyAccessibilityEvent(ui::AXEvent event_type, - BrowserAccessibility* node) override; + void NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, + ui::AXEvent event_type, + BrowserAccessibility* node) override; void SendLocationChangeEvents( const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) override;
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc index 72dbdfd..bb67bc9 100644 --- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc +++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -50,6 +50,7 @@ } void BrowserAccessibilityManagerAuraLinux::NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, ui::AXEvent event_type, BrowserAccessibility* node) { // TODO(shreeram.k) : Implement.
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/content/browser/accessibility/browser_accessibility_manager_auralinux.h index 4ccd31f..36c983e 100644 --- a/content/browser/accessibility/browser_accessibility_manager_auralinux.h +++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -28,8 +28,10 @@ static ui::AXTreeUpdate GetEmptyDocument(); // Implementation BrowserAccessibilityManager methods - void NotifyAccessibilityEvent(ui::AXEvent event_type, - BrowserAccessibility* node) override; + void NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, + ui::AXEvent event_type, + BrowserAccessibility* node) override; AtkObject* parent_object() { return parent_object_; }
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h index 715081920..74063b7 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.h +++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -35,8 +35,10 @@ BrowserAccessibility* GetFocus() override; // Implementation of BrowserAccessibilityManager. - void NotifyAccessibilityEvent(ui::AXEvent event_type, - BrowserAccessibility* node) override; + void NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, + ui::AXEvent event_type, + BrowserAccessibility* node) override; void OnAccessibilityEvents( const std::vector<AXEventNotificationDetails>& details) override;
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index 097eb44..d45e0c28e 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -141,6 +141,7 @@ } void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, ui::AXEvent event_type, BrowserAccessibility* node) { if (!node->IsNative()) @@ -393,7 +394,10 @@ static_cast<BrowserAccessibilityMac*>(GetRoot()); if (root) { root->RecreateNativeObject(); - NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, root); + NotifyAccessibilityEvent( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_CHILDREN_CHANGED, + root); } }
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index b3e6613e..281d74d 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/win/scoped_comptr.h" #include "base/win/windows_version.h" +#include "content/browser/accessibility/browser_accessibility_event_win.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" #include "content/browser/accessibility/browser_accessibility_win.h" #include "content/browser/renderer_host/legacy_render_widget_host_win.h" @@ -88,144 +89,112 @@ return delegate->AccessibilityGetNativeViewAccessible(); } -void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent( - DWORD event, BrowserAccessibility* node) { - BrowserAccessibilityDelegate* delegate = - node->manager()->GetDelegateFromRootManager(); - if (!delegate) { - // This line and other LOG(WARNING) lines are temporary, to debug - // flaky failures in DumpAccessibilityEvent* tests. - // http://crbug.com/440579 - DLOG(WARNING) << "Not firing AX event because of no delegate"; - return; - } - - if (!node->IsNative()) - return; - - HWND hwnd = delegate->AccessibilityGetAcceleratedWidget(); - if (!hwnd) { - DLOG(WARNING) << "Not firing AX event because of no hwnd"; - return; - } - - // Inline text boxes are an internal implementation detail, we don't - // expose them to Windows. - if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) - return; - - // It doesn't make sense to fire a REORDER event on a leaf node; that - // happens when the node has internal children line inline text boxes. - if (event == EVENT_OBJECT_REORDER && node->PlatformChildCount() == 0) - return; - - // Pass the negation of this node's unique id in the |child_id| - // argument to NotifyWinEvent; the AT client will then call get_accChild - // on the HWND's accessibility object and pass it that same id, which - // we can use to retrieve the IAccessible for this node. - LONG child_id = -node->unique_id(); - ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id); -} - void BrowserAccessibilityManagerWin::OnIAccessible2Used() { BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected(); } void BrowserAccessibilityManagerWin::UserIsReloading() { - if (GetRoot()) - MaybeCallNotifyWinEvent(IA2_EVENT_DOCUMENT_RELOAD, GetRoot()); + if (GetRoot()) { + (new BrowserAccessibilityEventWin( + BrowserAccessibilityEvent::FromRenderFrameHost, + ui::AX_EVENT_NONE, + IA2_EVENT_DOCUMENT_RELOAD, + GetRoot()))->Fire(); + } } void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent( + BrowserAccessibilityEvent::Source source, ui::AXEvent event_type, BrowserAccessibility* node) { - BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager(); - if (!root_delegate || !root_delegate->AccessibilityGetAcceleratedWidget()) { - DLOG(WARNING) << "Not firing AX event because of no root_delegate or hwnd"; - return; + if (event_type == ui::AX_EVENT_BLUR) { + // Equivalent to focus on the root. + event_type = ui::AX_EVENT_FOCUS; + node = GetRoot(); } + if (event_type == ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED) { + // Fire the event on the object where the focus of the selection is. + int32_t focus_id = GetTreeData().sel_focus_object_id; + BrowserAccessibility* focus_object = GetFromID(focus_id); + if (focus_object) { + (new BrowserAccessibilityEventWin( + source, + ui::AX_EVENT_NONE, + IA2_EVENT_TEXT_CARET_MOVED, + focus_object))->Fire(); + return; + } + } + + BrowserAccessibilityManager::NotifyAccessibilityEvent( + source, event_type, node); +} + +BrowserAccessibilityEvent::Result + BrowserAccessibilityManagerWin::FireWinAccessibilityEvent( + BrowserAccessibilityEventWin* event) { + const BrowserAccessibility* target = event->target(); + ui::AXEvent event_type = event->event_type(); + LONG win_event_type = event->win_event_type(); + + BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager(); + if (!root_delegate) + return BrowserAccessibilityEvent::FailedBecauseFrameIsDetached; + + HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget(); + if (!hwnd) + return BrowserAccessibilityEvent::FailedBecauseNoWindow; + // Don't fire events when this document might be stale as the user has // started navigating to a new document. if (user_is_navigating_away_) - return; + return BrowserAccessibilityEvent::DiscardedBecauseUserNavigatingAway; // Inline text boxes are an internal implementation detail, we don't // expose them to Windows. - if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) - return; + if (target->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) + return BrowserAccessibilityEvent::NotNeededOnThisPlatform; - LONG event_id = EVENT_MIN; - switch (event_type) { - case ui::AX_EVENT_ACTIVEDESCENDANTCHANGED: - event_id = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED; - break; - case ui::AX_EVENT_ALERT: - event_id = EVENT_SYSTEM_ALERT; - break; - case ui::AX_EVENT_AUTOCORRECTION_OCCURED: - event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED; - break; - case ui::AX_EVENT_BLUR: - // Equivalent to focus on the root. - event_id = EVENT_OBJECT_FOCUS; - node = GetRoot(); - break; - case ui::AX_EVENT_CHILDREN_CHANGED: - event_id = EVENT_OBJECT_REORDER; - break; - case ui::AX_EVENT_FOCUS: - event_id = EVENT_OBJECT_FOCUS; - break; - case ui::AX_EVENT_LIVE_REGION_CHANGED: - if (node->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY)) - return; - event_id = EVENT_OBJECT_LIVEREGIONCHANGED; - break; - case ui::AX_EVENT_LOAD_COMPLETE: - event_id = IA2_EVENT_DOCUMENT_LOAD_COMPLETE; - break; - case ui::AX_EVENT_SCROLL_POSITION_CHANGED: - event_id = EVENT_SYSTEM_SCROLLINGEND; - break; - case ui::AX_EVENT_SCROLLED_TO_ANCHOR: - event_id = EVENT_SYSTEM_SCROLLINGSTART; - break; - case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED: - event_id = EVENT_OBJECT_SELECTIONWITHIN; - break; - case ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED: { - // Fire the event on the object where the focus of the selection is. - int32_t focus_id = GetTreeData().sel_focus_object_id; - BrowserAccessibility* focus_object = GetFromID(focus_id); - if (focus_object) - node = focus_object; - event_id = IA2_EVENT_TEXT_CARET_MOVED; - break; - } - default: - // Not all WebKit accessibility events result in a Windows - // accessibility notification. - break; + if (event_type == ui::AX_EVENT_LIVE_REGION_CHANGED && + target->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY)) + return BrowserAccessibilityEvent::DiscardedBecauseLiveRegionBusy; + + if (!target) + return BrowserAccessibilityEvent::FailedBecauseNoFocus; + + event->set_target(target); + + // It doesn't make sense to fire a REORDER event on a leaf node; that + // happens when the target has internal children inline text boxes. + if (win_event_type == EVENT_OBJECT_REORDER && + target->PlatformChildCount() == 0) { + return BrowserAccessibilityEvent::NotNeededOnThisPlatform; } - if (!node) - return; - - if (event_id != EVENT_MIN) - MaybeCallNotifyWinEvent(event_id, node); + // Pass the negation of this node's unique id in the |child_id| + // argument to NotifyWinEvent; the AT client will then call get_accChild + // on the HWND's accessibility object and pass it that same id, which + // we can use to retrieve the IAccessible for this node. + LONG child_id = -target->unique_id(); + ::NotifyWinEvent(win_event_type, hwnd, OBJID_CLIENT, child_id); // If this is a layout complete notification (sent when a container scrolls) // and there is a descendant tracked object, send a notification on it. // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed. if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE && tracked_scroll_object_ && - tracked_scroll_object_->IsDescendantOf(node)) { - MaybeCallNotifyWinEvent( - IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_); + tracked_scroll_object_->IsDescendantOf(target)) { + (new BrowserAccessibilityEventWin( + BrowserAccessibilityEvent::FromScroll, + ui::AX_EVENT_NONE, + IA2_EVENT_VISIBLE_DATA_CHANGED, + tracked_scroll_object_))->Fire(); tracked_scroll_object_->Release(); tracked_scroll_object_ = NULL; } + + return BrowserAccessibilityEvent::Sent; } bool BrowserAccessibilityManagerWin::CanFireEvents() { @@ -237,15 +206,18 @@ } void BrowserAccessibilityManagerWin::FireFocusEvent( + BrowserAccessibilityEvent::Source source, BrowserAccessibility* node) { // On Windows, we always fire a FOCUS event on the root of a frame before // firing a focus event within that frame. if (node->manager() != last_focused_manager_ && node != node->manager()->GetRoot()) { - NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node->manager()->GetRoot()); + BrowserAccessibilityEvent::Create(source, + ui::AX_EVENT_FOCUS, + node->manager()->GetRoot())->Fire(); } - BrowserAccessibilityManager::FireFocusEvent(node); + BrowserAccessibilityManager::FireFocusEvent(source, node); } void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h index 669db87..701526a8 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.h +++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -15,6 +15,7 @@ #include "ui/accessibility/platform/ax_platform_node_win.h" namespace content { +class BrowserAccessibilityEventWin; class BrowserAccessibilityWin; // Manages a tree of BrowserAccessibilityWin objects. @@ -37,18 +38,21 @@ // The IAccessible for the parent window. IAccessible* GetParentIAccessible(); - // Calls NotifyWinEvent if the parent window's IAccessible pointer is known. - void MaybeCallNotifyWinEvent(DWORD event, BrowserAccessibility* node); - // IAccessible2UsageObserver void OnIAccessible2Used() override; // BrowserAccessibilityManager methods void UserIsReloading() override; void NotifyAccessibilityEvent( - ui::AXEvent event_type, BrowserAccessibility* node) override; + BrowserAccessibilityEvent::Source source, + ui::AXEvent event_type, + BrowserAccessibility* node) override; + BrowserAccessibilityEvent::Result + FireWinAccessibilityEvent(BrowserAccessibilityEventWin* event); bool CanFireEvents() override; - void FireFocusEvent(BrowserAccessibility* node) override; + void FireFocusEvent( + BrowserAccessibilityEvent::Source source, + BrowserAccessibility* node) override; // Track this object and post a VISIBLE_DATA_CHANGED notification when // its container scrolls.
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index 2ee1691b8..73f13ec 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -16,6 +16,7 @@ #include "base/win/enum_variant.h" #include "base/win/scoped_comptr.h" #include "base/win/windows_version.h" +#include "content/browser/accessibility/browser_accessibility_event_win.h" #include "content/browser/accessibility/browser_accessibility_manager_win.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" #include "content/common/accessibility_messages.h" @@ -3493,31 +3494,31 @@ } void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) { - BrowserAccessibilityManagerWin* manager = - this->manager()->ToBrowserAccessibilityManagerWin(); - // Fire an event when an alert first appears. if (ia_role() == ROLE_SYSTEM_ALERT && old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { - manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); + BrowserAccessibilityEvent::Create( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_ALERT, + this)->Fire(); } // Fire an event when a new subtree is created. if (is_subtree_creation) - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SHOW, this); + FireNativeEvent(EVENT_OBJECT_SHOW); // The rest of the events only fire on changes, not on new objects. if (old_win_attributes_->ia_role != 0 || !old_win_attributes_->role_name.empty()) { // Fire an event if the name, description, help, or value changes. if (name() != old_win_attributes_->name) - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); + FireNativeEvent(EVENT_OBJECT_NAMECHANGE); if (description() != old_win_attributes_->description) - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); + FireNativeEvent(EVENT_OBJECT_DESCRIPTIONCHANGE); if (value() != old_win_attributes_->value) - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); + FireNativeEvent(EVENT_OBJECT_VALUECHANGE); if (ia_state() != old_win_attributes_->ia_state) - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); + FireNativeEvent(EVENT_OBJECT_STATECHANGE); // Normally focus events are handled elsewhere, however // focus for managed descendants is platform-specific. @@ -3528,7 +3529,7 @@ (ia_state() & STATE_SYSTEM_SELECTABLE) && (ia_state() & STATE_SYSTEM_FOCUSED) && !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this); + FireNativeEvent(EVENT_OBJECT_FOCUS); } // Handle selection being added or removed. @@ -3543,13 +3544,13 @@ if (multiselect) { // In a multi-select box, fire SELECTIONADD and SELECTIONREMOVE events. if (is_selected_now && !was_selected_before) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); + FireNativeEvent(EVENT_OBJECT_SELECTIONADD); } else if (!is_selected_now && was_selected_before) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); + FireNativeEvent(EVENT_OBJECT_SELECTIONREMOVE); } } else if (is_selected_now && !was_selected_before) { // In a single-select box, only fire SELECTION events. - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTION, this); + FireNativeEvent(EVENT_OBJECT_SELECTION); } } @@ -3559,7 +3560,7 @@ if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { if (sx != previous_scroll_x_ || sy != previous_scroll_y_) - manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); + FireNativeEvent(EVENT_SYSTEM_SCROLLINGEND); previous_scroll_x_ = sx; previous_scroll_y_ = sy; } @@ -3570,12 +3571,12 @@ if (old_len > 0) { // In-process screen readers may call IAccessibleText::get_oldText // in reaction to this event to retrieve the text that was removed. - manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); + FireNativeEvent(IA2_EVENT_TEXT_REMOVED); } if (new_len > 0) { // In-process screen readers may call IAccessibleText::get_newText // in reaction to this event to retrieve the text that was inserted. - manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); + FireNativeEvent(IA2_EVENT_TEXT_INSERTED); } // Changing a static text node can affect the IAccessibleText hypertext @@ -3597,8 +3598,7 @@ } void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { - manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( - EVENT_OBJECT_HIDE, this); + FireNativeEvent(EVENT_OBJECT_HIDE); } void BrowserAccessibilityWin::NativeAddReference() { @@ -3614,8 +3614,7 @@ } void BrowserAccessibilityWin::OnLocationChanged() { - manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( - EVENT_OBJECT_LOCATIONCHANGE, this); + FireNativeEvent(EVENT_OBJECT_LOCATIONCHANGE); } std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes() @@ -4394,6 +4393,14 @@ } } +void BrowserAccessibilityWin::FireNativeEvent(LONG win_event_type) const { + (new BrowserAccessibilityEventWin( + BrowserAccessibilityEvent::FromTreeChange, + ui::AX_EVENT_NONE, + win_event_type, + this))->Fire(); +} + void BrowserAccessibilityWin::InitRoleAndState() { int32_t ia_role = 0; int32_t ia_state = 0;
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h index 2092a9ca..9d7dd515 100644 --- a/content/browser/accessibility/browser_accessibility_win.h +++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -888,8 +888,8 @@ // Updates object attributes of IA2 with html attributes. void UpdateRequiredAttributes(); - // Updates the IA2 text style attributes. - void UpdateTextAttributes(); + // Fire a Windows-specific accessibility event notification on this node. + void FireNativeEvent(LONG win_event_type) const; struct WinAttributes { WinAttributes();
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h index 1fe50c0..254ebb5 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
@@ -88,6 +88,7 @@ IOHIDElementRef axis_elements[blink::WebGamepad::axesLengthCap]; CFIndex axis_minimums[blink::WebGamepad::axesLengthCap]; CFIndex axis_maximums[blink::WebGamepad::axesLengthCap]; + CFIndex axis_report_sizes[blink::WebGamepad::axesLengthCap]; } hid; struct { XboxController* device;
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm index fe77f536..38e69b6 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm
@@ -45,6 +45,18 @@ return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; } +float NormalizeUInt8Axis(uint8_t value, uint8_t min, uint8_t max) { + return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; +} + +float NormalizeUInt16Axis(uint16_t value, uint16_t min, uint16_t max) { + return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; +} + +float NormalizeUInt32Axis(uint32_t value, uint32_t min, uint32_t max) { + return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f; +} + // http://www.usb.org/developers/hidpage const uint32_t kGenericDesktopUsagePage = 0x01; const uint32_t kGameControlsUsagePage = 0x05; @@ -205,10 +217,6 @@ else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) { uint32_t axis_index = usage - kAxisMinimumUsageNumber; if (axis_index < WebGamepad::axesLengthCap) { - associated.hid.axis_minimums[axis_index] = - IOHIDElementGetLogicalMin(element); - associated.hid.axis_maximums[axis_index] = - IOHIDElementGetLogicalMax(element); associated.hid.axis_elements[axis_index] = element; pad.axesLength = std::max(pad.axesLength, axis_index + 1); } else { @@ -235,10 +243,6 @@ break; } if (next_index < WebGamepad::axesLengthCap) { - associated.hid.axis_minimums[next_index] = - IOHIDElementGetLogicalMin(element); - associated.hid.axis_maximums[next_index] = - IOHIDElementGetLogicalMax(element); associated.hid.axis_elements[next_index] = element; pad.axesLength = std::max(pad.axesLength, next_index + 1); } @@ -249,6 +253,26 @@ } } + for (uint32_t axis_index = 0; axis_index < pad.axesLength; ++axis_index) { + IOHIDElementRef element = associated.hid.axis_elements[axis_index]; + if (element != NULL) { + CFIndex axis_min = IOHIDElementGetLogicalMin(element); + CFIndex axis_max = IOHIDElementGetLogicalMax(element); + + // Some HID axes report a logical range of -1 to 0 signed, which must be + // interpreted as 0 to -1 unsigned for correct normalization behavior. + if (axis_min == -1 && axis_max == 0) { + axis_max = -1; + axis_min = 0; + } + + associated.hid.axis_minimums[axis_index] = axis_min; + associated.hid.axis_maximums[axis_index] = axis_max; + associated.hid.axis_report_sizes[axis_index] = + IOHIDElementGetReportSize(element); + } + } + return (pad.axesLength > 0 || pad.buttonsLength > 0); } @@ -416,9 +440,27 @@ // Find and fill in the associated axis event, if any. for (size_t i = 0; i < pad.axesLength; ++i) { if (associated.hid.axis_elements[i] == element) { - pad.axes[i] = NormalizeAxis(IOHIDValueGetIntegerValue(value), - associated.hid.axis_minimums[i], - associated.hid.axis_maximums[i]); + CFIndex axis_min = associated.hid.axis_minimums[i]; + CFIndex axis_max = associated.hid.axis_maximums[i]; + CFIndex axis_value = IOHIDValueGetIntegerValue(value); + + if (axis_min > axis_max) { + // We'll need to interpret this axis as unsigned during normalization. + switch (associated.hid.axis_report_sizes[i]) { + case 8: + pad.axes[i] = NormalizeUInt8Axis(axis_value, axis_min, axis_max); + break; + case 16: + pad.axes[i] = NormalizeUInt16Axis(axis_value, axis_min, axis_max); + break; + case 32: + pad.axes[i] = NormalizeUInt32Axis(axis_value, axis_min, axis_max); + break; + } + } else { + pad.axes[i] = NormalizeAxis(axis_value, axis_min, axis_max); + } + pad.timestamp = std::max(pad.timestamp, IOHIDValueGetTimeStamp(value)); return; }
diff --git a/content/common/page_messages.h b/content/common/page_messages.h index a7f56bb8..afe62b8a 100644 --- a/content/common/page_messages.h +++ b/content/common/page_messages.h
@@ -16,7 +16,7 @@ IPC_ENUM_TRAITS_MAX_VALUE( PageMsg_SetZoomLevel_Command, - PageMsg_SetZoomLevel_Command::LAST); + PageMsg_SetZoomLevel_Command::LAST) // Messages sent from the browser to the renderer.
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 87693f25..9d475eb 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -374,6 +374,10 @@ 'browser/accessibility/browser_accessibility.h', 'browser/accessibility/browser_accessibility_cocoa.h', 'browser/accessibility/browser_accessibility_cocoa.mm', + 'browser/accessibility/browser_accessibility_event.h', + 'browser/accessibility/browser_accessibility_event.cc', + 'browser/accessibility/browser_accessibility_event_win.h', + 'browser/accessibility/browser_accessibility_event_win.cc', 'browser/accessibility/browser_accessibility_mac.h', 'browser/accessibility/browser_accessibility_mac.mm', 'browser/accessibility/browser_accessibility_manager.cc',
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index e66c4c30..1e4fba8 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/location.h" #include "base/macros.h" #include "base/single_thread_task_runner.h" @@ -407,6 +408,7 @@ void OnDevToolsMessage( int, int, const std::string& message, const std::string&) { + last_received_message_ = message; std::unique_ptr<base::DictionaryValue> root( static_cast<base::DictionaryValue*>( base::JSONReader::Read(message).release())); @@ -427,12 +429,15 @@ return result; } + std::string LastReceivedMessage() const { return last_received_message_; } + private: DevToolsAgent* agent() { return frame()->devtools_agent(); } std::vector<std::string> notifications_; + std::string last_received_message_; }; class RenderViewImplBlinkSettingsTest : public RenderViewImplTest { @@ -2404,4 +2409,56 @@ EXPECT_EQ(2, CountNotifications("Runtime.executionContextCreated")); } +TEST_F(DevToolsAgentTest, RuntimeEvaluateRunMicrotasks) { + LoadHTML("<body>page</body>"); + Attach(); + DispatchDevToolsMessage("Console.enable", + "{\"id\":1,\"method\":\"Console.enable\"}"); + DispatchDevToolsMessage("Runtime.evaluate", + "{\"id\":2," + "\"method\":\"Runtime.evaluate\"," + "\"params\":{" + "\"expression\":\"Promise.resolve().then(" + "() => console.log(42));\"" + "}" + "}"); + EXPECT_EQ(1, CountNotifications("Console.messageAdded")); +} + +TEST_F(DevToolsAgentTest, RuntimeCallFunctionOnRunMicrotasks) { + LoadHTML("<body>page</body>"); + Attach(); + DispatchDevToolsMessage("Console.enable", + "{\"id\":1,\"method\":\"Console.enable\"}"); + DispatchDevToolsMessage("Runtime.evaluate", + "{\"id\":2," + "\"method\":\"Runtime.evaluate\"," + "\"params\":{" + "\"expression\":\"window\"" + "}" + "}"); + + std::unique_ptr<base::DictionaryValue> root( + static_cast<base::DictionaryValue*>( + base::JSONReader::Read(LastReceivedMessage()).release())); + const base::Value* object_id; + ASSERT_TRUE(root->Get("result.result.objectId", &object_id)); + std::string object_id_str; + EXPECT_TRUE(base::JSONWriter::Write(*object_id, &object_id_str)); + + DispatchDevToolsMessage("Runtime.callFunctionOn", + "{\"id\":3," + "\"method\":\"Runtime.callFunctionOn\"," + "\"params\":{" + "\"objectId\":" + + object_id_str + + "," + "\"functionDeclaration\":\"function foo(){ " + "Promise.resolve().then(() => " + "console.log(239))}\"" + "}" + "}"); + EXPECT_EQ(1, CountNotifications("Console.messageAdded")); +} + } // namespace content
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 44dc0f0..c4b99f6 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -705,7 +705,7 @@ request->OnRequestCompleteSuccess(CreateOutgoingReliableStreamImpl()); } - if (GetNumOpenOutgoingStreams() == 0) { + if (GetNumOpenOutgoingStreams() == 0 && stream_factory_) { stream_factory_->OnIdleSession(this); } } @@ -909,7 +909,9 @@ } void QuicChromiumClientSession::OnPathDegrading() { - stream_factory_->MaybeMigrateSessionEarly(this); + if (stream_factory_) { + stream_factory_->MaybeMigrateSessionEarly(this); + } } void QuicChromiumClientSession::OnProofValid(
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 8b20266..5c6fb46 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -8623,6 +8623,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "ppapi_unittests" }, {
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index bd8816bd..d33534e 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -286,6 +286,7 @@ crbug.com/498539 [ Win ] inspector/tracing/timeline-event-dispatch.html [ Failure Pass ] crbug.com/498539 inspector/console/console-log-syntax-error.html [ Pass Timeout ] crbug.com/498539 inspector/tracing/timeline-bound-function.html [ Pass Failure ] +crbug.com/498539 virtual/threaded/inspector/tracing/timeline-bound-function.html [ Pass Failure ] crbug.com/498539 inspector/tracing/timeline-injected-script-eval.html [ Pass Failure ] crbug.com/498539 inspector/tracing/timeline-time.html [ Pass Failure Timeout ] crbug.com/498539 inspector/tracing/timeline-timer.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt new file mode 100644 index 0000000..eab57bfa --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt
@@ -0,0 +1,19 @@ +Check that stepInto at then end of the script go to next user script instead InjectedScriptSource.js. +Stack trace: +boo:0:38 +:0:50 + +Perform stepInto +Stack trace: +boo:0:48 +:0:50 + +Perform stepInto +Stack trace: +:0:51 + +Perform stepInto +Stack trace: +foo:5:12 + +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html new file mode 100644 index 0000000..fb092b0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html
@@ -0,0 +1,39 @@ +<html> +<head> +<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> +<script> + +function foo() +{ + return 239; +} + +function test() +{ + InspectorTest.sendCommandOrDie("Debugger.enable", {}); + InspectorTest.eventHandler["Debugger.paused"] = debuggerPaused; + InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "(function boo() { setTimeout(foo, 0); debugger; })()" }); + + var actions = [ "stepInto", "stepInto", "stepInto" ]; + function debuggerPaused(result) + { + InspectorTest.log("Stack trace:"); + for (var callFrame of result.params.callFrames) + InspectorTest.log(callFrame.functionName + ':' + callFrame.location.lineNumber + ":" + callFrame.location.columnNumber); + InspectorTest.log(""); + + var action = actions.shift(); + if (!action) { + InspectorTest.sendCommandOrDie("Debugger.resume", {}, () => InspectorTest.completeTest()); + return; + } + InspectorTest.log("Perform " + action); + InspectorTest.sendCommandOrDie("Debugger." + action, {}); + } +} +</script> +</head> +<body onLoad="runTest();"> +Check that stepInto at then end of the script go to next user script instead InjectedScriptSource.js. +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt new file mode 100644 index 0000000..c8cb3dcb --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt
@@ -0,0 +1,25 @@ +CONSOLE MESSAGE: line 9: 42 +CONSOLE MESSAGE: line 10: 43 +CONSOLE MESSAGE: line 8: 239 +CONSOLE MESSAGE: line 1: finished +Check that console.log doesn't run microtasks. +{ + description : 42 + type : number + value : 42 +} +{ + description : 43 + type : number + value : 43 +} +{ + description : 239 + type : number + value : 239 +} +{ + type : string + value : finished +} +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks.html b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks.html new file mode 100644 index 0000000..73aa542e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks.html
@@ -0,0 +1,32 @@ +<html> +<head> +<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> +<script> + +function testFunction() +{ + Promise.resolve().then(function(){ console.log(239); }); + console.log(42); + console.log(43); +} + +function test() +{ + InspectorTest.sendCommandOrDie("Console.enable", {}); + InspectorTest.eventHandler["Console.messageAdded"] = messageAdded; + InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "testFunction()" }); + InspectorTest.sendCommandOrDie("Runtime.evaluate", { "expression": "setTimeout(() => console.log(\"finished\"), 0)" }); + + function messageAdded(result) + { + InspectorTest.logObject(result.params.message.parameters[0]); + if (result.params.message.parameters[0].value === "finished") + InspectorTest.completeTest(); + } +} +</script> +</head> +<body onLoad="runTest();"> +Check that console.log doesn't run microtasks. +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-custom-formatters-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-custom-formatters-expected.txt index dc1bd2b..77b99b856 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-custom-formatters-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-custom-formatters-expected.txt
@@ -2,8 +2,8 @@ CONSOLE MESSAGE: line 124: [object Object] CONSOLE MESSAGE: line 125: [object Object] CONSOLE MESSAGE: line 126: [object Object] -CONSOLE ERROR: line 127: Custom Formatter Failed: Too deep hierarchy of inlined custom previews CONSOLE MESSAGE: line 127: [object Object] +CONSOLE ERROR: Custom Formatter Failed: Too deep hierarchy of inlined custom previews Tests that console logging dumps properly when there are multiple custom formatters on the page console-custom-formatters.html:123 Header formatted by 1 aBody formatted by 1 a @@ -11,5 +11,5 @@ console-custom-formatters.html:125 Header formatted by 1 cBody formatted by 1 c console-custom-formatters.html:126 Formatter with config Header info: additional infobodyinfo: additional info console-custom-formatters.html:127 Formatter with config Formatter with config Formatter with config Formatter with config Formatter with config Formatter with config Formatter with config Formatter with config Formatter with config Object -console-custom-formatters.html:127 Custom Formatter Failed: Too deep hierarchy of inlined custom previews undefinedlogVars @ console-custom-formatters.html:127(anonymous function) @ VM:1 +Custom Formatter Failed: Too deep hierarchy of inlined custom previews undefined
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md b/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md index e946a05..21a150b 100644 --- a/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md +++ b/third_party/WebKit/Source/platform/heap/BlinkGCAPIReference.md
@@ -335,8 +335,10 @@ The function implementation must contain: * For each on-heap object `m_object` in your class, a tracing call: "```visitor->trace(m_object);```". +* If your class has one or more weak references (`WeakMember<T>`), you have the option of + registering a *weak callback* for the object. See details below for how. * For each base class of your class `BaseClass` that is a descendant of `GarbageCollected<T>` or - `GarbageCollectedMixin`, delegation call to base class: "```BaseClass::trace(visitor);```" + `GarbageCollectedMixin`, a delegation call to base class: "```BaseClass::trace(visitor);```" It is recommended that the delegation call, if any, is put at the end of a tracing method. @@ -382,4 +384,43 @@ } ``` +Given that the class `C` above contained a `WeakMember<Y>` field, you could alternatively +register a *weak callback* in the trace method, and have it be invoked after the marking +phase: + +```c++ + +void C::clearWeakMembers(Visitor* visitor) +{ + if (ThreadHeap::isHeapObjectAlive(m_y)) + return; + + // |m_y| is not referred to by anyone else, clear the weak + // reference along with updating state / clearing any other + // resources at the same time. None of those operations are + // allowed to perform heap allocations: + m_y->detach(); + + // Note: if the weak callback merely clears the weak reference, + // it is much simpler to just |trace| the field rather than + // install a custom weak callback. + m_y = nullptr; +} + +DEFINE_TRACE(C) +{ + visitor->template registerWeakMembers<C, &C::clearWeakMembers>(this); + visitor->trace(m_x); + visitor->trace(m_z); // Heap collection does, too. + B::trace(visitor); // Delegate to the parent. In this case it's empty, but this is required. +} +``` + +Please notice that if the object (of type `C`) is also not reachable, its `trace` method +will not be invoked and any follow-on weak processing will not be done. Hence, if the +object must always perform some operation when the weak reference is cleared, that +needs to (also) happen during finalization. + +Weak callbacks have so far seen little use in Blink, but a mechanism that's available. + ## Heap collections
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8FunctionCall.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8FunctionCall.cpp index 590bb2d2..12927b4 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8FunctionCall.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8FunctionCall.cpp
@@ -84,6 +84,10 @@ v8::Local<v8::Value> V8FunctionCall::callWithoutExceptionHandling() { + // TODO(dgozman): get rid of this check. + if (!m_debugger->client()->isExecutionAllowed()) + return v8::Local<v8::Value>(); + v8::Local<v8::Object> thisObject = v8::Local<v8::Object>::Cast(m_value); v8::Local<v8::Value> value; if (!thisObject->Get(m_context, m_name).ToLocal(&value)) @@ -98,8 +102,9 @@ ASSERT(!info[i].IsEmpty()); } + v8::MicrotasksScope microtasksScope(m_context->GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> result; - if (!m_debugger->callFunction(function, m_context, thisObject, m_arguments.size(), info.get()).ToLocal(&result)) + if (!function->Call(m_context, thisObject, m_arguments.size(), info.get()).ToLocal(&result)) return v8::Local<v8::Value>(); return result; }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp index 6822775..dac95be1 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp
@@ -107,7 +107,12 @@ // Temporarily enable allow evals for inspector. if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(true); - v8::MaybeLocal<v8::Value> maybeResultValue = m_debugger->compileAndRunInternalScript(scope.context(), toV8String(m_debugger->isolate(), expression)); + + v8::MaybeLocal<v8::Value> maybeResultValue; + v8::Local<v8::Script> script = m_debugger->compileInternalScript(scope.context(), toV8String(m_debugger->isolate(), expression), String16()); + if (!script.IsEmpty()) + maybeResultValue = m_debugger->runCompiledScript(scope.context(), script); + if (evalIsDisabled) scope.context()->AllowCodeGenerationFromStrings(false);
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index dbce5b0..fb8766c 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -4275,8 +4275,13 @@ devTools->layerTreeViewChanged(m_layerTreeView); m_page->settings().setAcceleratedCompositingEnabled(m_layerTreeView); - if (m_layerTreeView) + if (m_layerTreeView) { m_page->layerTreeViewInitialized(*m_layerTreeView); + // We don't yet have a page loaded at this point of the initialization of WebViewImpl. + // Suppress commits until Blink generates invalidations so we don't + // attempt to paint too early in the next page load. + m_layerTreeView->setDeferCommits(true); + } // FIXME: only unittests, click to play, Android printing, and printing (for headers and footers) // make this assert necessary. We should make them not hit this code and then delete allowsBrokenNullLayerTreeView.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py index b2fa663..f282e81 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -500,6 +500,9 @@ # from a file url for results.html and Chromium doesn't allow that. json_results_generator.write_json(self._filesystem, summarized_failing_results, full_results_path, callback="ADD_RESULTS") + if self._options.json_test_results: + json_results_generator.write_json(self._filesystem, summarized_failing_results, self._options.json_test_results) + _log.debug("Finished writing JSON files.") def _upload_json_files(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py index 8af17125..3e78d65 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -164,6 +164,10 @@ default=False, help="Show all failures in results.html, rather than only regressions"), optparse.make_option( + "--json-test-results", + action="store", + help="Path to write the JSON test results to."), + optparse.make_option( "--new-baseline", action="store_true", default=False,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py index fd1d7c4a..e5be517 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
@@ -196,7 +196,9 @@ self.should_test_processes = not self._platform.is_win() def test_basic(self): - options, args = parse_args(tests_included=True) + options, args = parse_args( + extra_args=['--json-test-results', '/tmp/json_test_results.json'], + tests_included=True) logging_stream = StringIO.StringIO() stdout = StringIO.StringIO() host = MockHost() @@ -231,6 +233,9 @@ json_to_eval = failing_results_text.replace("ADD_RESULTS(", "").replace(");", "") self.assertEqual(json.loads(json_to_eval), details.summarized_failing_results) + json_test_results = host.filesystem.read_text_file('/tmp/json_test_results.json') + self.assertEqual(json.loads(json_test_results), details.summarized_failing_results) + full_results_text = host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json') self.assertEqual(json.loads(full_results_text), details.summarized_full_results)