1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/generic/OuterDocAccessible.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,218 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "OuterDocAccessible.h" 1.10 + 1.11 +#include "Accessible-inl.h" 1.12 +#include "nsAccUtils.h" 1.13 +#include "DocAccessible-inl.h" 1.14 +#include "Role.h" 1.15 +#include "States.h" 1.16 + 1.17 +#ifdef A11Y_LOG 1.18 +#include "Logging.h" 1.19 +#endif 1.20 + 1.21 +using namespace mozilla; 1.22 +using namespace mozilla::a11y; 1.23 + 1.24 +//////////////////////////////////////////////////////////////////////////////// 1.25 +// OuterDocAccessible 1.26 +//////////////////////////////////////////////////////////////////////////////// 1.27 + 1.28 +OuterDocAccessible:: 1.29 + OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.30 + AccessibleWrap(aContent, aDoc) 1.31 +{ 1.32 +} 1.33 + 1.34 +OuterDocAccessible::~OuterDocAccessible() 1.35 +{ 1.36 +} 1.37 + 1.38 +//////////////////////////////////////////////////////////////////////////////// 1.39 +// nsISupports 1.40 + 1.41 +NS_IMPL_ISUPPORTS_INHERITED0(OuterDocAccessible, 1.42 + Accessible) 1.43 + 1.44 +//////////////////////////////////////////////////////////////////////////////// 1.45 +// Accessible public (DON'T add methods here) 1.46 + 1.47 +role 1.48 +OuterDocAccessible::NativeRole() 1.49 +{ 1.50 + return roles::INTERNAL_FRAME; 1.51 +} 1.52 + 1.53 +Accessible* 1.54 +OuterDocAccessible::ChildAtPoint(int32_t aX, int32_t aY, 1.55 + EWhichChildAtPoint aWhichChild) 1.56 +{ 1.57 + int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0; 1.58 + nsresult rv = GetBounds(&docX, &docY, &docWidth, &docHeight); 1.59 + NS_ENSURE_SUCCESS(rv, nullptr); 1.60 + 1.61 + if (aX < docX || aX >= docX + docWidth || aY < docY || aY >= docY + docHeight) 1.62 + return nullptr; 1.63 + 1.64 + // Always return the inner doc as direct child accessible unless bounds 1.65 + // outside of it. 1.66 + Accessible* child = GetChildAt(0); 1.67 + NS_ENSURE_TRUE(child, nullptr); 1.68 + 1.69 + if (aWhichChild == eDeepestChild) 1.70 + return child->ChildAtPoint(aX, aY, eDeepestChild); 1.71 + return child; 1.72 +} 1.73 + 1.74 +//////////////////////////////////////////////////////////////////////////////// 1.75 +// nsIAccessible 1.76 + 1.77 +uint8_t 1.78 +OuterDocAccessible::ActionCount() 1.79 +{ 1.80 + // Internal frame, which is the doc's parent, should not have a click action. 1.81 + return 0; 1.82 +} 1.83 + 1.84 +NS_IMETHODIMP 1.85 +OuterDocAccessible::GetActionName(uint8_t aIndex, nsAString& aName) 1.86 +{ 1.87 + aName.Truncate(); 1.88 + 1.89 + return NS_ERROR_INVALID_ARG; 1.90 +} 1.91 + 1.92 +NS_IMETHODIMP 1.93 +OuterDocAccessible::GetActionDescription(uint8_t aIndex, 1.94 + nsAString& aDescription) 1.95 +{ 1.96 + aDescription.Truncate(); 1.97 + 1.98 + return NS_ERROR_INVALID_ARG; 1.99 +} 1.100 + 1.101 +NS_IMETHODIMP 1.102 +OuterDocAccessible::DoAction(uint8_t aIndex) 1.103 +{ 1.104 + return NS_ERROR_INVALID_ARG; 1.105 +} 1.106 + 1.107 +//////////////////////////////////////////////////////////////////////////////// 1.108 +// Accessible public 1.109 + 1.110 +void 1.111 +OuterDocAccessible::Shutdown() 1.112 +{ 1.113 + // XXX: sometimes outerdoc accessible is shutdown because of layout style 1.114 + // change however the presshell of underlying document isn't destroyed and 1.115 + // the document doesn't get pagehide events. Schedule a document rebind 1.116 + // to its parent document. Otherwise a document accessible may be lost if its 1.117 + // outerdoc has being recreated (see bug 862863 for details). 1.118 + 1.119 +#ifdef A11Y_LOG 1.120 + if (logging::IsEnabled(logging::eDocDestroy)) 1.121 + logging::OuterDocDestroy(this); 1.122 +#endif 1.123 + 1.124 + Accessible* child = mChildren.SafeElementAt(0, nullptr); 1.125 + if (child) { 1.126 +#ifdef A11Y_LOG 1.127 + if (logging::IsEnabled(logging::eDocDestroy)) { 1.128 + logging::DocDestroy("outerdoc's child document rebind is scheduled", 1.129 + child->AsDoc()->DocumentNode()); 1.130 + } 1.131 +#endif 1.132 + RemoveChild(child); 1.133 + mDoc->BindChildDocument(child->AsDoc()); 1.134 + } 1.135 + 1.136 + AccessibleWrap::Shutdown(); 1.137 +} 1.138 + 1.139 +void 1.140 +OuterDocAccessible::InvalidateChildren() 1.141 +{ 1.142 + // Do not invalidate children because DocManager is responsible for 1.143 + // document accessible lifetime when DOM document is created or destroyed. If 1.144 + // DOM document isn't destroyed but its presshell is destroyed (for example, 1.145 + // when DOM node of outerdoc accessible is hidden), then outerdoc accessible 1.146 + // notifies DocManager about this. If presshell is created for existing 1.147 + // DOM document (for example when DOM node of outerdoc accessible is shown) 1.148 + // then allow DocManager to handle this case since the document 1.149 + // accessible is created and appended as a child when it's requested. 1.150 + 1.151 + SetChildrenFlag(eChildrenUninitialized); 1.152 +} 1.153 + 1.154 +bool 1.155 +OuterDocAccessible::InsertChildAt(uint32_t aIdx, Accessible* aAccessible) 1.156 +{ 1.157 + NS_ASSERTION(aAccessible->IsDoc(), 1.158 + "OuterDocAccessible should only have document child!"); 1.159 + // We keep showing the old document for a bit after creating the new one, 1.160 + // and while building the new DOM and frame tree. That's done on purpose 1.161 + // to avoid weird flashes of default background color. 1.162 + // The old viewer will be destroyed after the new one is created. 1.163 + // For a11y, it should be safe to shut down the old document now. 1.164 + if (mChildren.Length()) 1.165 + mChildren[0]->Shutdown(); 1.166 + 1.167 + if (!AccessibleWrap::InsertChildAt(0, aAccessible)) 1.168 + return false; 1.169 + 1.170 +#ifdef A11Y_LOG 1.171 + if (logging::IsEnabled(logging::eDocCreate)) { 1.172 + logging::DocCreate("append document to outerdoc", 1.173 + aAccessible->AsDoc()->DocumentNode()); 1.174 + logging::Address("outerdoc", this); 1.175 + } 1.176 +#endif 1.177 + 1.178 + return true; 1.179 +} 1.180 + 1.181 +bool 1.182 +OuterDocAccessible::RemoveChild(Accessible* aAccessible) 1.183 +{ 1.184 + Accessible* child = mChildren.SafeElementAt(0, nullptr); 1.185 + if (child != aAccessible) { 1.186 + NS_ERROR("Wrong child to remove!"); 1.187 + return false; 1.188 + } 1.189 + 1.190 +#ifdef A11Y_LOG 1.191 + if (logging::IsEnabled(logging::eDocDestroy)) { 1.192 + logging::DocDestroy("remove document from outerdoc", 1.193 + child->AsDoc()->DocumentNode(), child->AsDoc()); 1.194 + logging::Address("outerdoc", this); 1.195 + } 1.196 +#endif 1.197 + 1.198 + bool wasRemoved = AccessibleWrap::RemoveChild(child); 1.199 + 1.200 + NS_ASSERTION(!mChildren.Length(), 1.201 + "This child document of outerdoc accessible wasn't removed!"); 1.202 + 1.203 + return wasRemoved; 1.204 +} 1.205 + 1.206 + 1.207 +//////////////////////////////////////////////////////////////////////////////// 1.208 +// Accessible protected 1.209 + 1.210 +void 1.211 +OuterDocAccessible::CacheChildren() 1.212 +{ 1.213 + // Request document accessible for the content document to make sure it's 1.214 + // created. It will appended to outerdoc accessible children asynchronously. 1.215 + nsIDocument* outerDoc = mContent->GetCurrentDoc(); 1.216 + if (outerDoc) { 1.217 + nsIDocument* innerDoc = outerDoc->GetSubDocumentFor(mContent); 1.218 + if (innerDoc) 1.219 + GetAccService()->GetDocAccessible(innerDoc); 1.220 + } 1.221 +}