widget/windows/winrt/UIABridge.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "UIABridge.h"
michael@0 7 #include "MetroUtils.h"
michael@0 8 #include "UIABridgePrivate.h"
michael@0 9 #include "MetroWidget.h"
michael@0 10 #include "WinUtils.h"
michael@0 11
michael@0 12 #include <wrl.h>
michael@0 13 #include <OAIdl.h>
michael@0 14 #include <windows.graphics.display.h>
michael@0 15
michael@0 16 #ifdef ACCESSIBILITY
michael@0 17 using namespace mozilla::a11y;
michael@0 18 #endif
michael@0 19 using namespace mozilla::widget;
michael@0 20 using namespace Microsoft::WRL;
michael@0 21 using namespace Microsoft::WRL::Wrappers;
michael@0 22 using namespace ABI::Windows::UI;
michael@0 23 using namespace ABI::Windows::UI::Core;
michael@0 24 using namespace ABI::Windows::Foundation;
michael@0 25 using namespace ABI::Windows::System;
michael@0 26
michael@0 27 //#define DEBUG_BRIDGE
michael@0 28 #if !defined(DEBUG_BRIDGE)
michael@0 29 #undef LogThread
michael@0 30 #undef LogFunction
michael@0 31 #define LogThread()
michael@0 32 #define LogFunction()
michael@0 33 #define BridgeLog(...)
michael@0 34 #else
michael@0 35 #define BridgeLog(...) WinUtils::Log(__VA_ARGS__)
michael@0 36 #endif
michael@0 37
michael@0 38 #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
michael@0 39 const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
michael@0 40 MIDL_DEFINE_GUID(IID, IID_IUIABridge, 0xc78b35b5, 0x5db, 0x43aa, 0xae, 0x73, 0x94, 0xc2, 0x33, 0xa9, 0x3c, 0x98);
michael@0 41
michael@0 42 namespace mozilla {
michael@0 43 namespace widget {
michael@0 44 namespace winrt {
michael@0 45
michael@0 46 #define ProviderOptions_UseClientCoordinates (ProviderOptions)0x100
michael@0 47
michael@0 48 static int gIDIndex = 2;
michael@0 49 ComPtr<IUIABridge> gProviderRoot = nullptr;
michael@0 50 static ComPtr<IUIAElement> gElement = nullptr;
michael@0 51
michael@0 52 HRESULT
michael@0 53 UIABridge_CreateInstance(IInspectable **retVal)
michael@0 54 {
michael@0 55 HRESULT hr = E_OUTOFMEMORY;
michael@0 56 *retVal = nullptr;
michael@0 57 ComPtr<UIABridge> spProvider = Make<UIABridge>();
michael@0 58 if (spProvider != nullptr &&
michael@0 59 SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(retVal))) &&
michael@0 60 SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gProviderRoot)))) {
michael@0 61 return S_OK;
michael@0 62 }
michael@0 63 return hr;
michael@0 64 }
michael@0 65
michael@0 66 HRESULT
michael@0 67 UIATextElement_CreateInstance(IRawElementProviderFragmentRoot* aRoot)
michael@0 68 {
michael@0 69 LogFunction();
michael@0 70 HRESULT hr = E_OUTOFMEMORY;
michael@0 71 ComPtr<UIATextElement> spProvider = Make<UIATextElement>();
michael@0 72 if (spProvider != nullptr &&
michael@0 73 SUCCEEDED(hr = spProvider.Get()->QueryInterface(IID_PPV_ARGS(&gElement)))) {
michael@0 74 spProvider->SetIndexID(gIDIndex++);
michael@0 75 return S_OK;
michael@0 76 }
michael@0 77 return hr;
michael@0 78 }
michael@0 79
michael@0 80 // IUIABridge
michael@0 81
michael@0 82 HRESULT
michael@0 83 UIABridge::Init(IInspectable* aView, IInspectable* aWindow, LONG_PTR aInnerPtr)
michael@0 84 {
michael@0 85 LogFunction();
michael@0 86 NS_ASSERTION(aView, "invalid framework view pointer");
michael@0 87 NS_ASSERTION(aWindow, "invalid window pointer");
michael@0 88 NS_ASSERTION(aInnerPtr, "invalid Accessible pointer");
michael@0 89
michael@0 90 #if defined(ACCESSIBILITY)
michael@0 91 // init AccessibilityBridge and connect to accessibility
michael@0 92 mAccBridge = new AccessibilityBridge();
michael@0 93 if (!mAccBridge->Init(CastToUnknown(), (Accessible*)aInnerPtr)) {
michael@0 94 return E_FAIL;
michael@0 95 }
michael@0 96
michael@0 97 aWindow->QueryInterface(IID_PPV_ARGS(&mWindow));
michael@0 98
michael@0 99 if (FAILED(UIATextElement_CreateInstance(this)))
michael@0 100 return E_FAIL;
michael@0 101
michael@0 102 mAccessible = (Accessible*)aInnerPtr;
michael@0 103
michael@0 104 return S_OK;
michael@0 105 #endif
michael@0 106 return E_FAIL;
michael@0 107 }
michael@0 108
michael@0 109 HRESULT
michael@0 110 UIABridge::Disconnect()
michael@0 111 {
michael@0 112 LogFunction();
michael@0 113 #if defined(ACCESSIBILITY)
michael@0 114 mAccBridge->Disconnect();
michael@0 115 mAccessible = nullptr;
michael@0 116 #endif
michael@0 117 mWindow = nullptr;
michael@0 118 gElement = nullptr;
michael@0 119 gProviderRoot = nullptr;
michael@0 120 return S_OK;
michael@0 121 }
michael@0 122
michael@0 123 bool
michael@0 124 UIABridge::Connected()
michael@0 125 {
michael@0 126 return !!mAccessible;
michael@0 127 }
michael@0 128
michael@0 129 // IUIAElement
michael@0 130
michael@0 131 HRESULT
michael@0 132 UIABridge::SetFocusInternal(LONG_PTR aAccessible)
michael@0 133 {
michael@0 134 LogFunction();
michael@0 135 return S_OK;
michael@0 136 }
michael@0 137
michael@0 138 HRESULT
michael@0 139 UIABridge::ClearFocus()
michael@0 140 {
michael@0 141 LogFunction();
michael@0 142 return S_OK;
michael@0 143 }
michael@0 144
michael@0 145 static void
michael@0 146 DumpChildInfo(nsCOMPtr<nsIAccessible>& aChild)
michael@0 147 {
michael@0 148 #ifdef DEBUG
michael@0 149 if (!aChild) {
michael@0 150 return;
michael@0 151 }
michael@0 152 nsString str;
michael@0 153 aChild->GetName(str);
michael@0 154 BridgeLog("name: %ls", str.BeginReading());
michael@0 155 aChild->GetDescription(str);
michael@0 156 BridgeLog("description: %ls", str.BeginReading());
michael@0 157 #endif
michael@0 158 }
michael@0 159
michael@0 160 static bool
michael@0 161 ChildHasFocus(nsCOMPtr<nsIAccessible>& aChild)
michael@0 162 {
michael@0 163 Accessible* access = (Accessible*)aChild.get();
michael@0 164 BridgeLog("Focus element flags: editable:%d focusable:%d readonly:%d",
michael@0 165 ((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0),
michael@0 166 ((access->NativeState() & mozilla::a11y::states::FOCUSABLE) > 0),
michael@0 167 ((access->NativeState() & mozilla::a11y::states::READONLY) > 0));
michael@0 168 return (((access->NativeState() & mozilla::a11y::states::EDITABLE) > 0) &&
michael@0 169 ((access->NativeState() & mozilla::a11y::states::READONLY) == 0));
michael@0 170 }
michael@0 171
michael@0 172 HRESULT
michael@0 173 UIABridge::FocusChangeEvent()
michael@0 174 {
michael@0 175 LogFunction();
michael@0 176 if (!Connected()) {
michael@0 177 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 178 }
michael@0 179
michael@0 180 nsCOMPtr<nsIAccessible> child;
michael@0 181 mAccessible->GetFocusedChild(getter_AddRefs(child));
michael@0 182 if (!child) {
michael@0 183 return S_OK;
michael@0 184 }
michael@0 185
michael@0 186 if (!ChildHasFocus(child)) {
michael@0 187 ComPtr<IUIAElement> element;
michael@0 188 gElement.As(&element);
michael@0 189 if (!element) {
michael@0 190 return S_OK;
michael@0 191 }
michael@0 192 element->ClearFocus();
michael@0 193 UiaRaiseAutomationEvent(this, UIA_AutomationFocusChangedEventId);
michael@0 194 }
michael@0 195
michael@0 196 return S_OK;
michael@0 197 }
michael@0 198
michael@0 199 // IRawElementProviderFragmentRoot
michael@0 200
michael@0 201 HRESULT
michael@0 202 UIABridge::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment ** retVal)
michael@0 203 {
michael@0 204 LogFunction();
michael@0 205 *retVal = nullptr;
michael@0 206 if (!Connected()) {
michael@0 207 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 208 }
michael@0 209 gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
michael@0 210 return S_OK;
michael@0 211 }
michael@0 212
michael@0 213 // Windows calls this looking for the current focus element. Windows
michael@0 214 // will call here before accessible sends us any observer events through
michael@0 215 // the accessibility bridge, so update child focus information.
michael@0 216 HRESULT
michael@0 217 UIABridge::GetFocus(IRawElementProviderFragment ** retVal)
michael@0 218 {
michael@0 219 LogFunction();
michael@0 220 if (!Connected()) {
michael@0 221 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 222 }
michael@0 223
michael@0 224 nsCOMPtr<nsIAccessible> child;
michael@0 225 nsresult rv = mAccessible->GetFocusedChild(getter_AddRefs(child));
michael@0 226 if (!child) {
michael@0 227 BridgeLog("mAccessible->GetFocusedChild failed.");
michael@0 228 return S_OK;
michael@0 229 }
michael@0 230
michael@0 231 DumpChildInfo(child);
michael@0 232
michael@0 233 ComPtr<IUIAElement> element;
michael@0 234 gElement.As(&element);
michael@0 235 if (!element) {
michael@0 236 BridgeLog("gElement as IUIAElement failed.");
michael@0 237 return S_OK;
michael@0 238 }
michael@0 239
michael@0 240 if (!ChildHasFocus(child)) {
michael@0 241 element->ClearFocus();
michael@0 242 } else {
michael@0 243 element->SetFocusInternal((LONG_PTR)child.get());
michael@0 244 element.Get()->QueryInterface(IID_PPV_ARGS(retVal));
michael@0 245 }
michael@0 246
michael@0 247 return S_OK;
michael@0 248 }
michael@0 249
michael@0 250 // IRawElementProviderFragment
michael@0 251
michael@0 252 HRESULT
michael@0 253 UIABridge::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal)
michael@0 254 {
michael@0 255 LogFunction();
michael@0 256 if (!Connected()) {
michael@0 257 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 258 }
michael@0 259 *retVal = nullptr;
michael@0 260
michael@0 261 switch(direction) {
michael@0 262 case NavigateDirection_Parent:
michael@0 263 BridgeLog("UIABridge::Navigate NavigateDirection_Parent");
michael@0 264 break;
michael@0 265 case NavigateDirection_NextSibling:
michael@0 266 BridgeLog("UIABridge::Navigate NavigateDirection_NextSibling");
michael@0 267 break;
michael@0 268 case NavigateDirection_PreviousSibling:
michael@0 269 BridgeLog("UIABridge::Navigate NavigateDirection_PreviousSibling");
michael@0 270 break;
michael@0 271 case NavigateDirection_FirstChild:
michael@0 272 BridgeLog("UIABridge::Navigate NavigateDirection_FirstChild");
michael@0 273 gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
michael@0 274 break;
michael@0 275 case NavigateDirection_LastChild:
michael@0 276 BridgeLog("UIABridge::Navigate NavigateDirection_LastChild");
michael@0 277 gElement.Get()->QueryInterface(IID_PPV_ARGS(retVal));
michael@0 278 break;
michael@0 279 }
michael@0 280
michael@0 281 // For the other directions (parent, next, previous) the default of nullptr is correct
michael@0 282 return S_OK;
michael@0 283 }
michael@0 284
michael@0 285 HRESULT
michael@0 286 UIABridge::GetRuntimeId(SAFEARRAY ** retVal)
michael@0 287 {
michael@0 288 LogFunction();
michael@0 289 if (!Connected()) {
michael@0 290 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 291 }
michael@0 292
michael@0 293 int runtimeId[2] = { UiaAppendRuntimeId, 1 }; // always 1
michael@0 294 *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId));
michael@0 295 if (*retVal != nullptr) {
michael@0 296 for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) {
michael@0 297 SafeArrayPutElement(*retVal, &index, &runtimeId[index]);
michael@0 298 }
michael@0 299 } else {
michael@0 300 return E_OUTOFMEMORY;
michael@0 301 }
michael@0 302 return S_OK;
michael@0 303 }
michael@0 304
michael@0 305 HRESULT
michael@0 306 UIABridge::get_BoundingRectangle(UiaRect * retVal)
michael@0 307 {
michael@0 308 LogFunction();
michael@0 309 if (!Connected() || !mWindow) {
michael@0 310 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 311 }
michael@0 312
michael@0 313 // returns logical pixels
michael@0 314 Rect bounds;
michael@0 315 mWindow->get_Bounds(&bounds);
michael@0 316
michael@0 317 // we need to return physical pixels
michael@0 318 retVal->left = WinUtils::LogToPhys(bounds.X);
michael@0 319 retVal->top = WinUtils::LogToPhys(bounds.Y);
michael@0 320 retVal->width = WinUtils::LogToPhys(bounds.Width);
michael@0 321 retVal->height = WinUtils::LogToPhys(bounds.Height);
michael@0 322
michael@0 323 return S_OK;
michael@0 324 }
michael@0 325
michael@0 326 HRESULT
michael@0 327 UIABridge::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal)
michael@0 328 {
michael@0 329 if (!Connected()) {
michael@0 330 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 331 }
michael@0 332 // doesn't apply according to msdn.
michael@0 333 *retVal = nullptr;
michael@0 334 return S_OK;
michael@0 335 }
michael@0 336
michael@0 337 HRESULT
michael@0 338 UIABridge::SetFocus()
michael@0 339 {
michael@0 340 LogFunction();
michael@0 341 if (!Connected()) {
michael@0 342 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 343 }
michael@0 344 return S_OK;
michael@0 345 }
michael@0 346
michael@0 347 HRESULT
michael@0 348 UIABridge::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal)
michael@0 349 {
michael@0 350 // we are the fragment root. Our children return us for this call.
michael@0 351 return QueryInterface(IID_PPV_ARGS(retVal));
michael@0 352 }
michael@0 353
michael@0 354 // IRawElementProviderSimple
michael@0 355
michael@0 356 HRESULT
michael@0 357 UIABridge::get_ProviderOptions(ProviderOptions * pRetVal)
michael@0 358 {
michael@0 359 LogFunction();
michael@0 360 if (!Connected()) {
michael@0 361 return E_FAIL;
michael@0 362 }
michael@0 363 *pRetVal = ProviderOptions_ServerSideProvider |
michael@0 364 ProviderOptions_UseComThreading |
michael@0 365 ProviderOptions_UseClientCoordinates;
michael@0 366 return S_OK;
michael@0 367 }
michael@0 368
michael@0 369 HRESULT
michael@0 370 UIABridge::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
michael@0 371 {
michael@0 372 LogFunction();
michael@0 373 BridgeLog("UIABridge::GetPatternProvider=%d", patternId);
michael@0 374
michael@0 375 // The root window doesn't support any specific pattern
michael@0 376 *ppRetVal = nullptr;
michael@0 377
michael@0 378 return S_OK;
michael@0 379 }
michael@0 380
michael@0 381 HRESULT
michael@0 382 UIABridge::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
michael@0 383 {
michael@0 384 pRetVal->vt = VT_EMPTY;
michael@0 385
michael@0 386 switch (idProp) {
michael@0 387 case UIA_AutomationIdPropertyId:
michael@0 388 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_AutomationIdPropertyId");
michael@0 389 break;
michael@0 390 case UIA_ControlTypePropertyId:
michael@0 391 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_ControlTypePropertyId");
michael@0 392 break;
michael@0 393 case UIA_IsKeyboardFocusablePropertyId:
michael@0 394 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId");
michael@0 395 break;
michael@0 396 case UIA_IsContentElementPropertyId:
michael@0 397 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsContentElementPropertyId");
michael@0 398 break;
michael@0 399 case UIA_IsControlElementPropertyId:
michael@0 400 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsControlElementPropertyId");
michael@0 401 break;
michael@0 402 case UIA_IsEnabledPropertyId:
michael@0 403 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsEnabledPropertyId");
michael@0 404 break;
michael@0 405 case UIA_HasKeyboardFocusPropertyId:
michael@0 406 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId");
michael@0 407 break;
michael@0 408 case UIA_NamePropertyId:
michael@0 409 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NamePropertyId");
michael@0 410 break;
michael@0 411 case UIA_IsPasswordPropertyId:
michael@0 412 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_IsPasswordPropertyId");
michael@0 413 break;
michael@0 414 case UIA_NativeWindowHandlePropertyId:
michael@0 415 BridgeLog("UIABridge::GetPropertyValue: idProp=UIA_NativeWindowHandlePropertyId");
michael@0 416 break;
michael@0 417 default:
michael@0 418 BridgeLog("UIABridge::GetPropertyValue: idProp=%d", idProp);
michael@0 419 break;
michael@0 420 }
michael@0 421
michael@0 422 if (!Connected()) {
michael@0 423 return E_FAIL;
michael@0 424 }
michael@0 425
michael@0 426 switch (idProp) {
michael@0 427 case UIA_AutomationIdPropertyId:
michael@0 428 pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge0001");
michael@0 429 pRetVal->vt = VT_BSTR;
michael@0 430 break;
michael@0 431
michael@0 432 case UIA_ControlTypePropertyId:
michael@0 433 pRetVal->vt = VT_I4;
michael@0 434 pRetVal->lVal = UIA_WindowControlTypeId;
michael@0 435 break;
michael@0 436
michael@0 437 case UIA_IsKeyboardFocusablePropertyId:
michael@0 438 case UIA_IsContentElementPropertyId:
michael@0 439 case UIA_IsControlElementPropertyId:
michael@0 440 case UIA_IsEnabledPropertyId:
michael@0 441 pRetVal->boolVal = VARIANT_TRUE;
michael@0 442 pRetVal->vt = VT_BOOL;
michael@0 443 break;
michael@0 444
michael@0 445 case UIA_HasKeyboardFocusPropertyId:
michael@0 446 pRetVal->vt = VT_BOOL;
michael@0 447 pRetVal->boolVal = VARIANT_FALSE;
michael@0 448 break;
michael@0 449
michael@0 450 case UIA_NamePropertyId:
michael@0 451 pRetVal->bstrVal = SysAllocString(L"MozillaAccessibilityBridge");
michael@0 452 pRetVal->vt = VT_BSTR;
michael@0 453 break;
michael@0 454
michael@0 455 case UIA_IsPasswordPropertyId:
michael@0 456 pRetVal->vt = VT_BOOL;
michael@0 457 pRetVal->boolVal = VARIANT_FALSE;
michael@0 458 break;
michael@0 459
michael@0 460 case UIA_NativeWindowHandlePropertyId:
michael@0 461 pRetVal->vt = VT_I4;
michael@0 462 pRetVal->lVal = (LONG)MetroWidget::GetICoreWindowHWND();
michael@0 463 break;
michael@0 464
michael@0 465 default:
michael@0 466 BridgeLog("UIABridge: Unhandled property");
michael@0 467 break;
michael@0 468 }
michael@0 469 return S_OK;
michael@0 470 }
michael@0 471
michael@0 472 HRESULT
michael@0 473 UIABridge::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal)
michael@0 474 {
michael@0 475 // We only have this in the root bridge - this is our parent ICoreWindow.
michael@0 476 *ppRetVal = nullptr;
michael@0 477 if (mWindow != nullptr) {
michael@0 478 IInspectable *pHostAsInspectable = nullptr;
michael@0 479 if (SUCCEEDED(mWindow->get_AutomationHostProvider(&pHostAsInspectable))) {
michael@0 480 pHostAsInspectable->QueryInterface(ppRetVal);
michael@0 481 pHostAsInspectable->Release();
michael@0 482 }
michael@0 483 }
michael@0 484 return S_OK;
michael@0 485 }
michael@0 486
michael@0 487 ///////////////////////////////////////////////////////////////////////////////
michael@0 488 // Element
michael@0 489
michael@0 490 HRESULT
michael@0 491 UIATextElement::SetFocusInternal(LONG_PTR aAccessible)
michael@0 492 {
michael@0 493 LogFunction();
michael@0 494 #if defined(ACCESSIBILITY)
michael@0 495 NS_ASSERTION(mAccessItem, "Bad accessible pointer");
michael@0 496 if (mAccessItem == (nsIAccessible*)aAccessible) {
michael@0 497 return E_UNEXPECTED;
michael@0 498 }
michael@0 499 mAccessItem = (nsIAccessible*)aAccessible;
michael@0 500 return S_OK;
michael@0 501 #endif
michael@0 502 return E_FAIL;
michael@0 503 }
michael@0 504
michael@0 505 HRESULT
michael@0 506 UIATextElement::ClearFocus()
michael@0 507 {
michael@0 508 LogFunction();
michael@0 509 mAccessItem = nullptr;
michael@0 510 return S_OK;
michael@0 511 }
michael@0 512
michael@0 513 // IRawElementProviderFragment
michael@0 514
michael@0 515 HRESULT
michael@0 516 UIATextElement::Navigate(NavigateDirection direction, IRawElementProviderFragment ** retVal)
michael@0 517 {
michael@0 518 LogFunction();
michael@0 519
michael@0 520 *retVal = nullptr;
michael@0 521 switch(direction) {
michael@0 522 case NavigateDirection_Parent:
michael@0 523 gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal));
michael@0 524 break;
michael@0 525 case NavigateDirection_NextSibling:
michael@0 526 break;
michael@0 527 case NavigateDirection_PreviousSibling:
michael@0 528 break;
michael@0 529 case NavigateDirection_FirstChild:
michael@0 530 break;
michael@0 531 case NavigateDirection_LastChild:
michael@0 532 break;
michael@0 533 }
michael@0 534 return S_OK;
michael@0 535 }
michael@0 536
michael@0 537 HRESULT
michael@0 538 UIATextElement::GetRuntimeId(SAFEARRAY ** retVal)
michael@0 539 {
michael@0 540 LogFunction();
michael@0 541 int runtimeId[2] = { UiaAppendRuntimeId, mIndexID };
michael@0 542 *retVal = SafeArrayCreateVector(VT_I4, 0, ARRAYSIZE(runtimeId));
michael@0 543 if (*retVal != nullptr) {
michael@0 544 for (long index = 0; index < ARRAYSIZE(runtimeId); ++index) {
michael@0 545 SafeArrayPutElement(*retVal, &index, &runtimeId[index]);
michael@0 546 }
michael@0 547 } else {
michael@0 548 return E_OUTOFMEMORY;
michael@0 549 }
michael@0 550 return S_OK;
michael@0 551 }
michael@0 552
michael@0 553 HRESULT
michael@0 554 UIATextElement::get_BoundingRectangle(UiaRect * retVal)
michael@0 555 {
michael@0 556 LogFunction();
michael@0 557
michael@0 558 if (!mAccessItem) {
michael@0 559 return UIA_E_ELEMENTNOTAVAILABLE;
michael@0 560 }
michael@0 561
michael@0 562 // bounds are in physical pixels
michael@0 563 int32_t docX = 0, docY = 0, docWidth = 0, docHeight = 0;
michael@0 564 mAccessItem->GetBounds(&docX, &docY, &docWidth, &docHeight);
michael@0 565
michael@0 566 retVal->left = (float)docX;
michael@0 567 retVal->top = (float)docY;
michael@0 568 retVal->width = (float)docWidth;
michael@0 569 retVal->height = (float)docHeight;
michael@0 570
michael@0 571 BridgeLog("get_BoundingRectangle: left=%d top=%d right=%d bottom=%d", docX, docY, docX + docWidth, docY + docHeight);
michael@0 572 return S_OK;
michael@0 573 }
michael@0 574
michael@0 575 HRESULT
michael@0 576 UIATextElement::GetEmbeddedFragmentRoots(SAFEARRAY ** retVal)
michael@0 577 {
michael@0 578 *retVal = nullptr;
michael@0 579 return S_OK;
michael@0 580 }
michael@0 581
michael@0 582 HRESULT
michael@0 583 UIATextElement::SetFocus()
michael@0 584 {
michael@0 585 LogFunction();
michael@0 586 return S_OK;
michael@0 587 }
michael@0 588
michael@0 589 HRESULT
michael@0 590 UIATextElement::get_FragmentRoot(IRawElementProviderFragmentRoot ** retVal)
michael@0 591 {
michael@0 592 return gProviderRoot.Get()->QueryInterface(IID_PPV_ARGS(retVal));
michael@0 593 }
michael@0 594
michael@0 595 // IRawElementProviderSimple
michael@0 596
michael@0 597 HRESULT
michael@0 598 UIATextElement::get_ProviderOptions(ProviderOptions * pRetVal)
michael@0 599 {
michael@0 600 *pRetVal = ProviderOptions_ServerSideProvider |
michael@0 601 ProviderOptions_UseComThreading |
michael@0 602 ProviderOptions_UseClientCoordinates;
michael@0 603 return S_OK;
michael@0 604 }
michael@0 605
michael@0 606 HRESULT
michael@0 607 UIATextElement::GetPatternProvider(PATTERNID patternId, IUnknown **ppRetVal)
michael@0 608 {
michael@0 609 LogFunction();
michael@0 610 BridgeLog("UIATextElement::GetPatternProvider=%d", patternId);
michael@0 611
michael@0 612 // UIA_ValuePatternId - 10002
michael@0 613 // UIA_TextPatternId - 10014
michael@0 614 // UIA_TextChildPatternId - 10029
michael@0 615
michael@0 616 *ppRetVal = nullptr;
michael@0 617 if (patternId == UIA_TextPatternId) {
michael@0 618 BridgeLog("** TextPattern requested from element.");
michael@0 619 *ppRetVal = static_cast<ITextProvider*>(this);
michael@0 620 AddRef();
michael@0 621 return S_OK;
michael@0 622 } else if (patternId == UIA_ValuePatternId) {
michael@0 623 BridgeLog("** ValuePattern requested from element.");
michael@0 624 *ppRetVal = static_cast<IValueProvider*>(this);
michael@0 625 AddRef();
michael@0 626 return S_OK;
michael@0 627 }
michael@0 628
michael@0 629 return S_OK;
michael@0 630 }
michael@0 631
michael@0 632 HRESULT
michael@0 633 UIATextElement::GetPropertyValue(PROPERTYID idProp, VARIANT * pRetVal)
michael@0 634 {
michael@0 635 pRetVal->vt = VT_EMPTY;
michael@0 636
michael@0 637 // native hwnd, we don't have one for elements
michael@0 638 if (idProp == 30020) {
michael@0 639 return S_OK;
michael@0 640 }
michael@0 641
michael@0 642 switch (idProp) {
michael@0 643 case UIA_AutomationIdPropertyId:
michael@0 644 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_AutomationIdPropertyId");
michael@0 645 break;
michael@0 646 case UIA_ControlTypePropertyId:
michael@0 647 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_ControlTypePropertyId");
michael@0 648 break;
michael@0 649 case UIA_IsKeyboardFocusablePropertyId:
michael@0 650 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsKeyboardFocusablePropertyId");
michael@0 651 break;
michael@0 652 case UIA_IsContentElementPropertyId:
michael@0 653 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsContentElementPropertyId");
michael@0 654 break;
michael@0 655 case UIA_IsControlElementPropertyId:
michael@0 656 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsControlElementPropertyId");
michael@0 657 break;
michael@0 658 case UIA_IsEnabledPropertyId:
michael@0 659 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsEnabledPropertyId");
michael@0 660 break;
michael@0 661 case UIA_HasKeyboardFocusPropertyId:
michael@0 662 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_HasKeyboardFocusPropertyId");
michael@0 663 break;
michael@0 664 case UIA_NamePropertyId:
michael@0 665 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_NamePropertyId");
michael@0 666 break;
michael@0 667 case UIA_IsPasswordPropertyId:
michael@0 668 BridgeLog("UIATextElement::GetPropertyValue: idProp=UIA_IsPasswordPropertyId");
michael@0 669 break;
michael@0 670 default:
michael@0 671 BridgeLog("UIATextElement::GetPropertyValue: idProp=%d", idProp);
michael@0 672 break;
michael@0 673 }
michael@0 674
michael@0 675 switch (idProp) {
michael@0 676 case UIA_AutomationIdPropertyId:
michael@0 677 pRetVal->bstrVal = SysAllocString(L"MozillaDocument0001");
michael@0 678 pRetVal->vt = VT_BSTR;
michael@0 679 break;
michael@0 680
michael@0 681 case UIA_ControlTypePropertyId:
michael@0 682 pRetVal->vt = VT_I4;
michael@0 683 pRetVal->lVal = UIA_EditControlTypeId;
michael@0 684 break;
michael@0 685
michael@0 686 case UIA_IsTextPatternAvailablePropertyId:
michael@0 687 case UIA_IsKeyboardFocusablePropertyId:
michael@0 688 case UIA_IsContentElementPropertyId:
michael@0 689 case UIA_IsControlElementPropertyId:
michael@0 690 case UIA_IsEnabledPropertyId:
michael@0 691 pRetVal->boolVal = VARIANT_TRUE;
michael@0 692 pRetVal->vt = VT_BOOL;
michael@0 693 break;
michael@0 694
michael@0 695 case UIA_LocalizedControlTypePropertyId:
michael@0 696 case UIA_LabeledByPropertyId:
michael@0 697 break;
michael@0 698
michael@0 699 case UIA_HasKeyboardFocusPropertyId:
michael@0 700 {
michael@0 701 if (mAccessItem) {
michael@0 702 uint32_t state, extraState;
michael@0 703 if (NS_SUCCEEDED(mAccessItem->GetState(&state, &extraState)) &&
michael@0 704 (state & nsIAccessibleStates::STATE_FOCUSED)) {
michael@0 705 pRetVal->vt = VT_BOOL;
michael@0 706 pRetVal->boolVal = VARIANT_TRUE;
michael@0 707 return S_OK;
michael@0 708 }
michael@0 709 }
michael@0 710 pRetVal->vt = VT_BOOL;
michael@0 711 pRetVal->boolVal = VARIANT_FALSE;
michael@0 712 break;
michael@0 713 }
michael@0 714
michael@0 715 case UIA_NamePropertyId:
michael@0 716 pRetVal->bstrVal = SysAllocString(L"MozillaDocument");
michael@0 717 pRetVal->vt = VT_BSTR;
michael@0 718 break;
michael@0 719
michael@0 720 case UIA_IsPasswordPropertyId:
michael@0 721 pRetVal->vt = VT_BOOL;
michael@0 722 pRetVal->boolVal = VARIANT_FALSE;
michael@0 723 break;
michael@0 724
michael@0 725 default:
michael@0 726 BridgeLog("UIATextElement: Unhandled property");
michael@0 727 break;
michael@0 728 }
michael@0 729 return S_OK;
michael@0 730 }
michael@0 731
michael@0 732 HRESULT
michael@0 733 UIATextElement::get_HostRawElementProvider(IRawElementProviderSimple **ppRetVal)
michael@0 734 {
michael@0 735 *ppRetVal = nullptr;
michael@0 736 return S_OK;
michael@0 737 }
michael@0 738
michael@0 739 // ITextProvider
michael@0 740
michael@0 741 HRESULT
michael@0 742 UIATextElement::GetSelection(SAFEARRAY * *pRetVal)
michael@0 743 {
michael@0 744 LogFunction();
michael@0 745 return E_NOTIMPL;
michael@0 746 }
michael@0 747
michael@0 748 HRESULT
michael@0 749 UIATextElement::GetVisibleRanges(SAFEARRAY * *pRetVal)
michael@0 750 {
michael@0 751 LogFunction();
michael@0 752 return E_NOTIMPL;
michael@0 753 }
michael@0 754
michael@0 755 HRESULT
michael@0 756 UIATextElement::RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal)
michael@0 757 {
michael@0 758 LogFunction();
michael@0 759 return E_NOTIMPL;
michael@0 760 }
michael@0 761
michael@0 762 HRESULT
michael@0 763 UIATextElement::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal)
michael@0 764 {
michael@0 765 LogFunction();
michael@0 766 return E_NOTIMPL;
michael@0 767 }
michael@0 768
michael@0 769 HRESULT
michael@0 770 UIATextElement::get_DocumentRange(ITextRangeProvider **pRetVal)
michael@0 771 {
michael@0 772 LogFunction();
michael@0 773 return E_NOTIMPL;
michael@0 774 }
michael@0 775
michael@0 776 HRESULT
michael@0 777 UIATextElement::get_SupportedTextSelection(SupportedTextSelection *pRetVal)
michael@0 778 {
michael@0 779 LogFunction();
michael@0 780 return E_NOTIMPL;
michael@0 781 }
michael@0 782
michael@0 783 // IValueProvider
michael@0 784
michael@0 785 IFACEMETHODIMP
michael@0 786 UIATextElement::SetValue(LPCWSTR val)
michael@0 787 {
michael@0 788 LogFunction();
michael@0 789 return E_NOTIMPL;
michael@0 790 }
michael@0 791
michael@0 792 IFACEMETHODIMP
michael@0 793 UIATextElement::get_Value(BSTR *pRetVal)
michael@0 794 {
michael@0 795 LogFunction();
michael@0 796 return E_NOTIMPL;
michael@0 797 }
michael@0 798
michael@0 799 IFACEMETHODIMP
michael@0 800 UIATextElement::get_IsReadOnly(BOOL *pRetVal)
michael@0 801 {
michael@0 802 LogFunction();
michael@0 803 *pRetVal = FALSE;
michael@0 804 return S_OK;
michael@0 805 }
michael@0 806
michael@0 807 } } }

mercurial