accessible/src/atk/nsMaiInterfaceText.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "InterfaceInitFuncs.h"
     9 #include "Accessible-inl.h"
    10 #include "HyperTextAccessible-inl.h"
    11 #include "nsMai.h"
    13 #include "nsIAccessibleTypes.h"
    14 #include "nsIPersistentProperties2.h"
    15 #include "nsISimpleEnumerator.h"
    17 #include "mozilla/Likely.h"
    19 using namespace mozilla;
    20 using namespace mozilla::a11y;
    22 static const char* sAtkTextAttrNames[ATK_TEXT_ATTR_LAST_DEFINED];
    24 static AtkAttributeSet*
    25 ConvertToAtkTextAttributeSet(nsIPersistentProperties* aAttributes)
    26 {
    27   if (!aAttributes)
    28     return nullptr;
    30   AtkAttributeSet* objAttributeSet = nullptr;
    31   nsCOMPtr<nsISimpleEnumerator> propEnum;
    32   nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
    33   NS_ENSURE_SUCCESS(rv, nullptr);
    35   bool hasMore = false;
    36   while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
    37     nsCOMPtr<nsISupports> sup;
    38     rv = propEnum->GetNext(getter_AddRefs(sup));
    39     NS_ENSURE_SUCCESS(rv, objAttributeSet);
    41     nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
    42     NS_ENSURE_TRUE(propElem, objAttributeSet);
    44     nsAutoCString name;
    45     rv = propElem->GetKey(name);
    46     NS_ENSURE_SUCCESS(rv, objAttributeSet);
    48     nsAutoString value;
    49     rv = propElem->GetValue(value);
    50     NS_ENSURE_SUCCESS(rv, objAttributeSet);
    52     AtkAttribute* objAttr = (AtkAttribute*)g_malloc(sizeof(AtkAttribute));
    53     objAttr->name = g_strdup(name.get());
    54     objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
    55     objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
    57     // Handle attributes where atk has its own name.
    58     const char* atkName = nullptr;
    59     nsAutoString atkValue;
    60     if (name.EqualsLiteral("color")) {
    61       // The format of the atk attribute is r,g,b and the gecko one is
    62       // rgb(r,g,b).
    63       atkValue = Substring(value, 5, value.Length() - 1);
    64       atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FG_COLOR];
    65     } else if (name.EqualsLiteral("background-color")) {
    66       // The format of the atk attribute is r,g,b and the gecko one is
    67       // rgb(r,g,b).
    68       atkValue = Substring(value, 5, value.Length() - 1);
    69       atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_BG_COLOR];
    70     } else if (name.EqualsLiteral("font-family")) {
    71       atkValue = value;
    72       atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_FAMILY_NAME];
    73     } else if (name.Equals("font-size")) {
    74       // ATK wants the number of pixels without px at the end.
    75       atkValue = StringHead(value, value.Length() - 2);
    76       atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_SIZE];
    77     } else if (name.EqualsLiteral("font-weight")) {
    78       atkValue = value;
    79       atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_WEIGHT];
    80     } else if (name.EqualsLiteral("invalid")) {
    81       atkValue = value;
    82       atkName = sAtkTextAttrNames[ATK_TEXT_ATTR_INVALID];
    83     }
    85     if (atkName) {
    86       objAttr = static_cast<AtkAttribute*>(g_malloc(sizeof(AtkAttribute)));
    87       objAttr->name = g_strdup(atkName);
    88       objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(atkValue).get());
    89       objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
    90     }
    91   }
    93   // libatk-adaptor will free it
    94   return objAttributeSet;
    95 }
    97 static void
    98 ConvertTexttoAsterisks(AccessibleWrap* accWrap, nsAString& aString)
    99 {
   100   // convert each char to "*" when it's "password text" 
   101   if (accWrap->NativeRole() == roles::PASSWORD_TEXT) {
   102     for (uint32_t i = 0; i < aString.Length(); i++)
   103       aString.Replace(i, 1, NS_LITERAL_STRING("*"));
   104   }
   105 }
   107 extern "C" {
   109 static gchar*
   110 getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
   111 {
   112   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   113   if (!accWrap)
   114     return nullptr;
   116   HyperTextAccessible* text = accWrap->AsHyperText();
   117   if (!text || !text->IsTextRole())
   118     return nullptr;
   120     nsAutoString autoStr;
   121     text->TextSubstring(aStartOffset, aEndOffset, autoStr);
   123     ConvertTexttoAsterisks(accWrap, autoStr);
   124     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
   126     //copy and return, libspi will free it.
   127     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
   128 }
   130 static gchar*
   131 getTextAfterOffsetCB(AtkText *aText, gint aOffset,
   132                      AtkTextBoundary aBoundaryType,
   133                      gint *aStartOffset, gint *aEndOffset)
   134 {
   135   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   136   if (!accWrap)
   137     return nullptr;
   139   HyperTextAccessible* text = accWrap->AsHyperText();
   140   if (!text || !text->IsTextRole())
   141     return nullptr;
   143   nsAutoString autoStr;
   144   int32_t startOffset = 0, endOffset = 0;
   145   text->TextAfterOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
   147   *aStartOffset = startOffset;
   148   *aEndOffset = endOffset;
   150   ConvertTexttoAsterisks(accWrap, autoStr);
   151   NS_ConvertUTF16toUTF8 cautoStr(autoStr);
   152   return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
   153 }
   155 static gchar*
   156 getTextAtOffsetCB(AtkText *aText, gint aOffset,
   157                   AtkTextBoundary aBoundaryType,
   158                   gint *aStartOffset, gint *aEndOffset)
   159 {
   160   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   161   if (!accWrap)
   162     return nullptr;
   164   HyperTextAccessible* text = accWrap->AsHyperText();
   165   if (!text || !text->IsTextRole())
   166     return nullptr;
   168     nsAutoString autoStr;
   169     int32_t startOffset = 0, endOffset = 0;
   170     text->TextAtOffset(aOffset, aBoundaryType, &startOffset, &endOffset, autoStr);
   171     *aStartOffset = startOffset;
   172     *aEndOffset = endOffset;
   174     ConvertTexttoAsterisks(accWrap, autoStr);
   175     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
   176     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
   177 }
   179 static gunichar
   180 getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
   181 {
   182   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   183   if (!accWrap)
   184     return 0;
   186   HyperTextAccessible* text = accWrap->AsHyperText();
   187   if (!text || !text->IsTextRole())
   188     return 0;
   190   // char16_t is unsigned short in Mozilla, gnuichar is guint32 in glib.
   191   return static_cast<gunichar>(text->CharAt(aOffset));
   192 }
   194 static gchar*
   195 getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
   196                       AtkTextBoundary aBoundaryType,
   197                       gint *aStartOffset, gint *aEndOffset)
   198 {
   199   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   200   if (!accWrap)
   201     return nullptr;
   203   HyperTextAccessible* text = accWrap->AsHyperText();
   204   if (!text || !text->IsTextRole())
   205     return nullptr;
   207   nsAutoString autoStr;
   208   int32_t startOffset = 0, endOffset = 0;
   209   text->TextBeforeOffset(aOffset, aBoundaryType,
   210                          &startOffset, &endOffset, autoStr);
   211   *aStartOffset = startOffset;
   212   *aEndOffset = endOffset;
   214   ConvertTexttoAsterisks(accWrap, autoStr);
   215   NS_ConvertUTF16toUTF8 cautoStr(autoStr);
   216   return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
   217 }
   219 static gint
   220 getCaretOffsetCB(AtkText *aText)
   221 {
   222   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   223   if (!accWrap)
   224     return 0;
   226   HyperTextAccessible* text = accWrap->AsHyperText();
   227   if (!text || !text->IsTextRole())
   228     return 0;
   230   return static_cast<gint>(text->CaretOffset());
   231 }
   233 static AtkAttributeSet*
   234 getRunAttributesCB(AtkText *aText, gint aOffset,
   235                    gint *aStartOffset,
   236                    gint *aEndOffset)
   237 {
   238   *aStartOffset = -1;
   239   *aEndOffset = -1;
   241   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   242   if (!accWrap)
   243     return nullptr;
   245   HyperTextAccessible* text = accWrap->AsHyperText();
   246   if (!text || !text->IsTextRole())
   247     return nullptr;
   249   int32_t startOffset = 0, endOffset = 0;
   250   nsCOMPtr<nsIPersistentProperties> attributes =
   251     text->TextAttributes(false, aOffset, &startOffset, &endOffset);
   253   *aStartOffset = startOffset;
   254   *aEndOffset = endOffset;
   256   return ConvertToAtkTextAttributeSet(attributes);
   257 }
   259 static AtkAttributeSet*
   260 getDefaultAttributesCB(AtkText *aText)
   261 {
   262   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   263   if (!accWrap)
   264     return nullptr;
   266   HyperTextAccessible* text = accWrap->AsHyperText();
   267   if (!text || !text->IsTextRole())
   268     return nullptr;
   270   nsCOMPtr<nsIPersistentProperties> attributes = text->DefaultTextAttributes();
   271   return ConvertToAtkTextAttributeSet(attributes);
   272 }
   274 static void
   275 getCharacterExtentsCB(AtkText *aText, gint aOffset,
   276                       gint *aX, gint *aY,
   277                       gint *aWidth, gint *aHeight,
   278                       AtkCoordType aCoords)
   279 {
   280   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   281   if(!accWrap || !aX || !aY || !aWidth || !aHeight)
   282     return;
   284   HyperTextAccessible* text = accWrap->AsHyperText();
   285   if (!text || !text->IsTextRole())
   286     return;
   288     uint32_t geckoCoordType;
   289     if (aCoords == ATK_XY_SCREEN)
   290         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
   291     else
   292         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
   294   nsIntRect rect = text->CharBounds(aOffset, geckoCoordType);
   295   *aX = rect.x;
   296   *aY = rect.y;
   297   *aWidth = rect.width;
   298   *aHeight = rect.height;
   299 }
   301 static void
   302 getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
   303                   AtkCoordType aCoords, AtkTextRectangle *aRect)
   304 {
   305   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   306   if(!accWrap || !aRect)
   307     return;
   309   HyperTextAccessible* text = accWrap->AsHyperText();
   310   if (!text || !text->IsTextRole())
   311     return;
   313     uint32_t geckoCoordType;
   314     if (aCoords == ATK_XY_SCREEN)
   315         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
   316     else
   317         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
   319   nsIntRect rect = text->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
   320   aRect->x = rect.x;
   321   aRect->y = rect.y;
   322   aRect->width = rect.width;
   323   aRect->height = rect.height;
   324 }
   326 static gint
   327 getCharacterCountCB(AtkText *aText)
   328 {
   329   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   330   if (!accWrap)
   331     return 0;
   333   HyperTextAccessible* textAcc = accWrap->AsHyperText();
   334   return textAcc->IsDefunct() ?
   335     0 : static_cast<gint>(textAcc->CharacterCount());
   336 }
   338 static gint
   339 getOffsetAtPointCB(AtkText *aText,
   340                    gint aX, gint aY,
   341                    AtkCoordType aCoords)
   342 {
   343   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   344   if (!accWrap)
   345     return -1;
   347   HyperTextAccessible* text = accWrap->AsHyperText();
   348   if (!text || !text->IsTextRole())
   349     return -1;
   351   return static_cast<gint>(
   352     text->OffsetAtPoint(aX, aY,
   353                         (aCoords == ATK_XY_SCREEN ?
   354                          nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
   355                          nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
   356 }
   358 static gint
   359 getTextSelectionCountCB(AtkText *aText)
   360 {
   361   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   362   if (!accWrap)
   363     return 0;
   365   HyperTextAccessible* text = accWrap->AsHyperText();
   366   if (!text || !text->IsTextRole())
   367     return 0;
   369   return text->SelectionCount();
   370 }
   372 static gchar*
   373 getTextSelectionCB(AtkText *aText, gint aSelectionNum,
   374                    gint *aStartOffset, gint *aEndOffset)
   375 {
   376   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   377   if (!accWrap)
   378     return nullptr;
   380   HyperTextAccessible* text = accWrap->AsHyperText();
   381   if (!text || !text->IsTextRole())
   382     return nullptr;
   384   int32_t startOffset = 0, endOffset = 0;
   385   text->SelectionBoundsAt(aSelectionNum, &startOffset, &endOffset);
   387     *aStartOffset = startOffset;
   388     *aEndOffset = endOffset;
   390     return getTextCB(aText, *aStartOffset, *aEndOffset);
   391 }
   393 // set methods
   394 static gboolean
   395 addTextSelectionCB(AtkText *aText,
   396                    gint aStartOffset,
   397                    gint aEndOffset)
   398 {
   399   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   400   if (!accWrap)
   401     return FALSE;
   403   HyperTextAccessible* text = accWrap->AsHyperText();
   404   if (!text || !text->IsTextRole())
   405     return FALSE;
   407   return text->AddToSelection(aStartOffset, aEndOffset);
   408 }
   410 static gboolean
   411 removeTextSelectionCB(AtkText *aText,
   412                       gint aSelectionNum)
   413 {
   414   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   415   if (!accWrap)
   416     return FALSE;
   418   HyperTextAccessible* text = accWrap->AsHyperText();
   419   if (!text || !text->IsTextRole())
   420     return FALSE;
   422   return text->RemoveFromSelection(aSelectionNum);
   423 }
   425 static gboolean
   426 setTextSelectionCB(AtkText *aText, gint aSelectionNum,
   427                    gint aStartOffset, gint aEndOffset)
   428 {
   429   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   430   if (!accWrap)
   431     return FALSE;
   433   HyperTextAccessible* text = accWrap->AsHyperText();
   434   if (!text || !text->IsTextRole())
   435     return FALSE;
   437   return text->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
   438 }
   440 static gboolean
   441 setCaretOffsetCB(AtkText *aText, gint aOffset)
   442 {
   443   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   444   if (!accWrap)
   445     return FALSE;
   447   HyperTextAccessible* text = accWrap->AsHyperText();
   448   if (!text || !text->IsTextRole() || !text->IsValidOffset(aOffset))
   449     return FALSE;
   451   text->SetCaretOffset(aOffset);
   452   return TRUE;
   453 }
   454 }
   456 void
   457 textInterfaceInitCB(AtkTextIface* aIface)
   458 {
   459   NS_ASSERTION(aIface, "Invalid aIface");
   460   if (MOZ_UNLIKELY(!aIface))
   461     return;
   463   aIface->get_text = getTextCB;
   464   aIface->get_text_after_offset = getTextAfterOffsetCB;
   465   aIface->get_text_at_offset = getTextAtOffsetCB;
   466   aIface->get_character_at_offset = getCharacterAtOffsetCB;
   467   aIface->get_text_before_offset = getTextBeforeOffsetCB;
   468   aIface->get_caret_offset = getCaretOffsetCB;
   469   aIface->get_run_attributes = getRunAttributesCB;
   470   aIface->get_default_attributes = getDefaultAttributesCB;
   471   aIface->get_character_extents = getCharacterExtentsCB;
   472   aIface->get_range_extents = getRangeExtentsCB;
   473   aIface->get_character_count = getCharacterCountCB;
   474   aIface->get_offset_at_point = getOffsetAtPointCB;
   475   aIface->get_n_selections = getTextSelectionCountCB;
   476   aIface->get_selection = getTextSelectionCB;
   478     // set methods
   479   aIface->add_selection = addTextSelectionCB;
   480   aIface->remove_selection = removeTextSelectionCB;
   481   aIface->set_selection = setTextSelectionCB;
   482   aIface->set_caret_offset = setCaretOffsetCB;
   484   // Cache the string values of the atk text attribute names.
   485   for (uint32_t i = 0; i < ArrayLength(sAtkTextAttrNames); i++)
   486     sAtkTextAttrNames[i] =
   487       atk_text_attribute_get_name(static_cast<AtkTextAttribute>(i));
   488 }

mercurial