editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "ChangeCSSInlineStyleTxn.h"
     7 #include "nsAString.h"                  // for nsAString_internal::Append, etc
     8 #include "nsCRT.h"                      // for nsCRT
     9 #include "nsDebug.h"                    // for NS_ENSURE_SUCCESS, etc
    10 #include "nsError.h"                    // for NS_ERROR_NULL_POINTER, etc
    11 #include "nsGkAtoms.h"                  // for nsGkAtoms, etc
    12 #include "nsIAtom.h"                    // for nsIAtom
    13 #include "nsIDOMCSSStyleDeclaration.h"  // for nsIDOMCSSStyleDeclaration
    14 #include "nsIDOMElement.h"              // for nsIDOMElement
    15 #include "nsIDOMElementCSSInlineStyle.h"
    16 #include "nsISupportsImpl.h"            // for EditTxn::QueryInterface, etc
    17 #include "nsISupportsUtils.h"           // for NS_ADDREF
    18 #include "nsLiteralString.h"            // for NS_LITERAL_STRING, etc
    19 #include "nsReadableUtils.h"            // for ToNewUnicode
    20 #include "nsString.h"                   // for nsAutoString, nsString, etc
    21 #include "nsUnicharUtils.h"
    22 #include "nsXPCOM.h"                    // for NS_Free
    24 class nsIEditor;
    26 #define kNullCh (char16_t('\0'))
    28 NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeCSSInlineStyleTxn, EditTxn,
    29                                    mElement)
    31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeCSSInlineStyleTxn)
    32 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
    34 // answers true if aValue is in the string list of white-space separated values aValueList
    35 // a case-sensitive search is performed if aCaseSensitive is true
    36 bool
    37 ChangeCSSInlineStyleTxn::ValueIncludes(const nsAString &aValueList, const nsAString &aValue, bool aCaseSensitive)
    38 {
    39   nsAutoString  valueList(aValueList);
    40   bool result = false;
    42   valueList.Append(kNullCh);  // put an extra null at the end
    44   char16_t *value = ToNewUnicode(aValue);
    45   char16_t *start = valueList.BeginWriting();
    46   char16_t *end   = start;
    48   while (kNullCh != *start) {
    49     while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) {  // skip leading space
    50       start++;
    51     }
    52     end = start;
    54     while ((kNullCh != *end) && (false == nsCRT::IsAsciiSpace(*end))) { // look for space or end
    55       end++;
    56     }
    57     *end = kNullCh; // end string here
    59     if (start < end) {
    60       if (aCaseSensitive) {
    61         if (!nsCRT::strcmp(value, start)) {
    62           result = true;
    63           break;
    64         }
    65       }
    66       else {
    67         if (nsDependentString(value).Equals(nsDependentString(start),
    68                                             nsCaseInsensitiveStringComparator())) {
    69           result = true;
    70           break;
    71         }
    72       }
    73     }
    74     start = ++end;
    75   }
    76   NS_Free(value);
    77   return result;
    78 }
    80 // removes the value aRemoveValue from the string list of white-space separated values aValueList
    81 void
    82 ChangeCSSInlineStyleTxn::RemoveValueFromListOfValues(nsAString & aValues, const nsAString  & aRemoveValue)
    83 {
    84   nsAutoString  classStr(aValues);  // copy to work buffer   nsAutoString  rv(aRemoveValue);
    85   nsAutoString  outString;
    86   classStr.Append(kNullCh);  // put an extra null at the end
    88   char16_t *start = classStr.BeginWriting();
    89   char16_t *end   = start;
    91   while (kNullCh != *start) {
    92     while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) {  // skip leading space
    93       start++;
    94     }
    95     end = start;
    97     while ((kNullCh != *end) && (false == nsCRT::IsAsciiSpace(*end))) { // look for space or end
    98       end++;
    99     }
   100     *end = kNullCh; // end string here
   102     if (start < end) {
   103       if (!aRemoveValue.Equals(start)) {
   104         outString.Append(start);
   105         outString.Append(char16_t(' '));
   106       }
   107     }
   109     start = ++end;
   110   }
   111   aValues.Assign(outString);
   112 }
   114 ChangeCSSInlineStyleTxn::ChangeCSSInlineStyleTxn()
   115   : EditTxn()
   116 {
   117 }
   119 NS_IMETHODIMP ChangeCSSInlineStyleTxn::Init(nsIEditor      *aEditor,
   120                                             nsIDOMElement  *aElement,
   121                                             nsIAtom        *aProperty,
   122                                             const nsAString& aValue,
   123                                             bool aRemoveProperty)
   124 {
   125   NS_ASSERTION(aEditor && aElement, "bad arg");
   126   if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
   128   mEditor = aEditor;
   129   mElement = do_QueryInterface(aElement);
   130   mProperty = aProperty;
   131   NS_ADDREF(mProperty);
   132   mValue.Assign(aValue);
   133   mRemoveProperty = aRemoveProperty;
   134   mUndoAttributeWasSet = false;
   135   mRedoAttributeWasSet = false;
   136   mUndoValue.Truncate();
   137   mRedoValue.Truncate();
   138   return NS_OK;
   139 }
   141 NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
   142 {
   143   NS_ASSERTION(mEditor && mElement, "bad state");
   144   if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
   146   nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
   147   NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
   149   nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
   150   nsresult result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
   151   NS_ENSURE_SUCCESS(result, result);
   152   NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
   154   nsAutoString propertyNameString;
   155   mProperty->ToString(propertyNameString);
   157   NS_NAMED_LITERAL_STRING(styleAttr, "style");
   158   result = mElement->HasAttribute(styleAttr, &mUndoAttributeWasSet);
   159   NS_ENSURE_SUCCESS(result, result);
   161   nsAutoString values;
   162   result = cssDecl->GetPropertyValue(propertyNameString, values);
   163   NS_ENSURE_SUCCESS(result, result);     
   164   mUndoValue.Assign(values);
   166   // does this property accept more than 1 value ?
   167   // we need to know that because of bug 62682
   168   bool multiple = AcceptsMoreThanOneValue(mProperty);
   170   if (mRemoveProperty) {
   171     nsAutoString returnString;
   172     if (multiple) {
   173       // the property can have more than one value, let's remove only
   174       // the value we have to remove and not the others
   176       // the 2 lines below are a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
   177       // is not yet implemented (bug 62682)
   178       RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
   179       RemoveValueFromListOfValues(values, mValue);
   180       if (values.IsEmpty()) {
   181         result = cssDecl->RemoveProperty(propertyNameString, returnString);
   182         NS_ENSURE_SUCCESS(result, result);     
   183       }
   184       else {
   185         nsAutoString priority;
   186         result = cssDecl->GetPropertyPriority(propertyNameString, priority);
   187         NS_ENSURE_SUCCESS(result, result);     
   188         result = cssDecl->SetProperty(propertyNameString, values,
   189                                       priority);
   190         NS_ENSURE_SUCCESS(result, result);     
   191       }
   192     }
   193     else {
   194       result = cssDecl->RemoveProperty(propertyNameString, returnString);
   195       NS_ENSURE_SUCCESS(result, result);     
   196     }
   197   }
   198   else {
   199     nsAutoString priority;
   200     result = cssDecl->GetPropertyPriority(propertyNameString, priority);
   201     NS_ENSURE_SUCCESS(result, result);
   202     if (multiple) {
   203       // the property can have more than one value, let's add
   204       // the value we have to add to the others
   206       // the line below is a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
   207       // is not yet implemented (bug 62682)
   208       AddValueToMultivalueProperty(values, mValue);
   209     }
   210     else
   211       values.Assign(mValue);
   212     result = cssDecl->SetProperty(propertyNameString, values,
   213                                   priority);
   214     NS_ENSURE_SUCCESS(result, result);     
   215   }
   217   // let's be sure we don't keep an empty style attribute
   218   uint32_t length;
   219   result = cssDecl->GetLength(&length);
   220   NS_ENSURE_SUCCESS(result, result);     
   221   if (!length) {
   222     result = mElement->RemoveAttribute(styleAttr);
   223     NS_ENSURE_SUCCESS(result, result);     
   224   }
   225   else
   226     mRedoAttributeWasSet = true;
   228   return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
   229 }
   231 nsresult ChangeCSSInlineStyleTxn::SetStyle(bool aAttributeWasSet,
   232                                            nsAString & aValue)
   233 {
   234   NS_ASSERTION(mEditor && mElement, "bad state");
   235   if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
   237   nsresult result = NS_OK;
   238   if (aAttributeWasSet) {
   239     // the style attribute was set and not empty, let's recreate the declaration
   240     nsAutoString propertyNameString;
   241     mProperty->ToString(propertyNameString);
   243     nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
   244     NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
   245     nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
   246     result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
   247     NS_ENSURE_SUCCESS(result, result);
   248     NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
   250     if (aValue.IsEmpty()) {
   251       // an empty value means we have to remove the property
   252       nsAutoString returnString;
   253       result = cssDecl->RemoveProperty(propertyNameString, returnString);
   254     }
   255     else {
   256       // let's recreate the declaration as it was
   257       nsAutoString priority;
   258       result = cssDecl->GetPropertyPriority(propertyNameString, priority);
   259       NS_ENSURE_SUCCESS(result, result);
   260       result = cssDecl->SetProperty(propertyNameString, aValue, priority);
   261     }
   262   }
   263   else
   264     result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
   266   return result;
   267 }
   269 NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
   270 {
   271   return SetStyle(mUndoAttributeWasSet, mUndoValue);
   272 }
   274 NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
   275 {
   276   return SetStyle(mRedoAttributeWasSet, mRedoValue);
   277 }
   279 NS_IMETHODIMP ChangeCSSInlineStyleTxn::GetTxnDescription(nsAString& aString)
   280 {
   281   aString.AssignLiteral("ChangeCSSInlineStyleTxn: [mRemoveProperty == ");
   283   if (!mRemoveProperty)
   284     aString.AppendLiteral("false] ");
   285   else
   286     aString.AppendLiteral("true] ");
   287   nsAutoString tempString;
   288   mProperty->ToString(tempString);
   289   aString += tempString;
   290   return NS_OK;
   291 }
   293 // answers true if the CSS property accepts more than one value
   294 bool
   295 ChangeCSSInlineStyleTxn::AcceptsMoreThanOneValue(nsIAtom *aCSSProperty)
   296 {
   297   return aCSSProperty == nsGkAtoms::text_decoration;
   298 }
   300 // adds the value aNewValue to the list of white-space separated values aValues
   301 NS_IMETHODIMP
   302 ChangeCSSInlineStyleTxn::AddValueToMultivalueProperty(nsAString & aValues, const nsAString & aNewValue)
   303 {
   304   if (aValues.IsEmpty()
   305       || aValues.LowerCaseEqualsLiteral("none")) {
   306     // the list of values is empty of the value is 'none'
   307     aValues.Assign(aNewValue);
   308   }
   309   else if (!ValueIncludes(aValues, aNewValue, false)) {
   310     // we already have another value but not this one; add it
   311     aValues.Append(char16_t(' '));
   312     aValues.Append(aNewValue);
   313   }
   314   return NS_OK;
   315 }

mercurial