editor/libeditor/base/IMETextTxn.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 "IMETextTxn.h"
     7 #include "mozilla/DebugOnly.h"          // for DebugOnly
     8 #include "mozilla/mozalloc.h"           // for operator new
     9 #include "mozilla/TextEvents.h"         // for TextRangeStyle
    10 #include "nsAString.h"                  // for nsAString_internal::Length, etc
    11 #include "nsAutoPtr.h"                  // for nsRefPtr
    12 #include "nsDebug.h"                    // for NS_ASSERTION, etc
    13 #include "nsError.h"                    // for NS_SUCCEEDED, NS_FAILED, etc
    14 #include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
    15 #include "nsIDOMRange.h"                // for nsRange::SetEnd, etc
    16 #include "nsIContent.h"                 // for nsIContent
    17 #include "nsIEditor.h"                  // for nsIEditor
    18 #include "nsIPresShell.h"               // for SelectionType
    19 #include "nsISelection.h"               // for nsISelection
    20 #include "nsISelectionController.h"     // for nsISelectionController, etc
    21 #include "nsISelectionPrivate.h"        // for nsISelectionPrivate
    22 #include "nsISupportsImpl.h"            // for nsRange::AddRef, etc
    23 #include "nsISupportsUtils.h"           // for NS_ADDREF_THIS, NS_RELEASE
    24 #include "nsITransaction.h"             // for nsITransaction
    25 #include "nsRange.h"                    // for nsRange
    26 #include "nsString.h"                   // for nsString
    28 using namespace mozilla;
    30 // #define DEBUG_IMETXN
    32 IMETextTxn::IMETextTxn()
    33   : EditTxn()
    34 {
    35 }
    37 NS_IMPL_CYCLE_COLLECTION_INHERITED(IMETextTxn, EditTxn,
    38                                    mElement)
    39 // mRangeList can't lead to cycles
    41 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IMETextTxn)
    42   if (aIID.Equals(IMETextTxn::GetCID())) {
    43     *aInstancePtr = (void*)(IMETextTxn*)this;
    44     NS_ADDREF_THIS();
    45     return NS_OK;
    46   } else
    47 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
    49 NS_IMETHODIMP IMETextTxn::Init(nsIDOMCharacterData     *aElement,
    50                                uint32_t                 aOffset,
    51                                uint32_t                 aReplaceLength,
    52                                TextRangeArray          *aTextRangeArray,
    53                                const nsAString         &aStringToInsert,
    54                                nsIEditor               *aEditor)
    55 {
    56   NS_ENSURE_ARG_POINTER(aElement);
    57   mElement = aElement;
    58   mOffset = aOffset;
    59   mReplaceLength = aReplaceLength;
    60   mStringToInsert = aStringToInsert;
    61   mEditor = aEditor;
    62   mRanges = aTextRangeArray;
    63   mFixed = false;
    64   return NS_OK;
    65 }
    67 NS_IMETHODIMP IMETextTxn::DoTransaction(void)
    68 {
    70 #ifdef DEBUG_IMETXN
    71   printf("Do IME Text element = %p replace = %d len = %d\n", mElement.get(), mReplaceLength, mStringToInsert.Length());
    72 #endif
    74   nsCOMPtr<nsISelectionController> selCon;
    75   mEditor->GetSelectionController(getter_AddRefs(selCon));
    76   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
    78   // advance caret: This requires the presentation shell to get the selection.
    79   nsresult result;
    80   if (mReplaceLength == 0) {
    81     result = mElement->InsertData(mOffset, mStringToInsert);
    82   } else {
    83     result = mElement->ReplaceData(mOffset, mReplaceLength, mStringToInsert);
    84   }
    85   if (NS_SUCCEEDED(result)) {
    86     result = SetSelectionForRanges();
    87   }
    89   return result;
    90 }
    92 NS_IMETHODIMP IMETextTxn::UndoTransaction(void)
    93 {
    94 #ifdef DEBUG_IMETXN
    95   printf("Undo IME Text element = %p\n", mElement.get());
    96 #endif
    98   nsCOMPtr<nsISelectionController> selCon;
    99   mEditor->GetSelectionController(getter_AddRefs(selCon));
   100   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
   102   nsresult result = mElement->DeleteData(mOffset, mStringToInsert.Length());
   103   if (NS_SUCCEEDED(result))
   104   { // set the selection to the insertion point where the string was removed
   105     nsCOMPtr<nsISelection> selection;
   106     result = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
   107     if (NS_SUCCEEDED(result) && selection) {
   108       result = selection->Collapse(mElement, mOffset);
   109       NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of IME insert.");
   110     }
   111   }
   112   return result;
   113 }
   115 NS_IMETHODIMP IMETextTxn::Merge(nsITransaction *aTransaction, bool *aDidMerge)
   116 {
   117   NS_ASSERTION(aDidMerge, "illegal vaule- null ptr- aDidMerge");
   118   NS_ASSERTION(aTransaction, "illegal vaule- null ptr- aTransaction");
   119   NS_ENSURE_TRUE(aDidMerge && aTransaction, NS_ERROR_NULL_POINTER);
   121 #ifdef DEBUG_IMETXN
   122   printf("Merge IME Text element = %p\n", mElement.get());
   123 #endif
   125   // 
   126   // check to make sure we aren't fixed, if we are then nothing get's absorbed
   127   //
   128   if (mFixed) {
   129     *aDidMerge = false;
   130     return NS_OK;
   131   }
   133   //
   134   // if aTransaction is another IMETextTxn then absorb it
   135   //
   136   IMETextTxn*  otherTxn = nullptr;
   137   nsresult result = aTransaction->QueryInterface(IMETextTxn::GetCID(),(void**)&otherTxn);
   138   if (otherTxn && NS_SUCCEEDED(result))
   139   {
   140     //
   141     //  we absorb the next IME transaction by adopting its insert string as our own
   142     //
   143     mStringToInsert = otherTxn->mStringToInsert;
   144     mRanges = otherTxn->mRanges;
   145     *aDidMerge = true;
   146 #ifdef DEBUG_IMETXN
   147     printf("IMETextTxn assimilated IMETextTxn:%p\n", aTransaction);
   148 #endif
   149     NS_RELEASE(otherTxn);
   150     return NS_OK;
   151   }
   153   *aDidMerge = false;
   154   return NS_OK;
   155 }
   157 NS_IMETHODIMP IMETextTxn::MarkFixed(void)
   158 {
   159   mFixed = true;
   160   return NS_OK;
   161 }
   163 NS_IMETHODIMP IMETextTxn::GetTxnDescription(nsAString& aString)
   164 {
   165   aString.AssignLiteral("IMETextTxn: ");
   166   aString += mStringToInsert;
   167   return NS_OK;
   168 }
   170 /* ============ protected methods ================== */
   171 static SelectionType
   172 ToSelectionType(uint32_t aTextRangeType)
   173 {
   174   switch(aTextRangeType) {
   175     case NS_TEXTRANGE_RAWINPUT:
   176       return nsISelectionController::SELECTION_IME_RAWINPUT;
   177     case NS_TEXTRANGE_SELECTEDRAWTEXT:
   178       return nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT;
   179     case NS_TEXTRANGE_CONVERTEDTEXT:
   180       return nsISelectionController::SELECTION_IME_CONVERTEDTEXT;
   181     case NS_TEXTRANGE_SELECTEDCONVERTEDTEXT:
   182       return nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT;
   183     default:
   184       MOZ_CRASH("Selection type is invalid");
   185       return nsISelectionController::SELECTION_NORMAL;
   186   }
   187 }
   189 nsresult
   190 IMETextTxn::SetSelectionForRanges()
   191 {
   192   nsCOMPtr<nsISelectionController> selCon;
   193   mEditor->GetSelectionController(getter_AddRefs(selCon));
   194   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
   196   nsCOMPtr<nsISelection> selection;
   197   nsresult rv =
   198     selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
   199                          getter_AddRefs(selection));
   200   NS_ENSURE_SUCCESS(rv, rv);
   202   nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
   203   rv = selPriv->StartBatchChanges();
   204   NS_ENSURE_SUCCESS(rv, rv);
   206   // First, remove all selections of IME composition.
   207   static const SelectionType kIMESelections[] = {
   208     nsISelectionController::SELECTION_IME_RAWINPUT,
   209     nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT,
   210     nsISelectionController::SELECTION_IME_CONVERTEDTEXT,
   211     nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT
   212   };
   213   for (uint32_t i = 0; i < ArrayLength(kIMESelections); ++i) {
   214     nsCOMPtr<nsISelection> selectionOfIME;
   215     if (NS_FAILED(selCon->GetSelection(kIMESelections[i],
   216                                        getter_AddRefs(selectionOfIME)))) {
   217       continue;
   218     }
   219     DebugOnly<nsresult> rv = selectionOfIME->RemoveAllRanges();
   220     NS_ASSERTION(NS_SUCCEEDED(rv),
   221                  "Failed to remove all ranges of IME selection");
   222   }
   224   // Set caret position and selection of IME composition with TextRangeArray.
   225   bool setCaret = false;
   226   uint32_t countOfRanges = mRanges ? mRanges->Length() : 0;
   227   for (uint32_t i = 0; i < countOfRanges; ++i) {
   228     const TextRange& textRange = mRanges->ElementAt(i);
   230     // Caret needs special handling since its length may be 0 and if it's not
   231     // specified explicitly, we need to handle it ourselves later.
   232     if (textRange.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
   233       NS_ASSERTION(!setCaret, "The ranges already has caret position");
   234       NS_ASSERTION(!textRange.Length(), "nsEditor doesn't support wide caret");
   235       // NOTE: If the caret position is larger than max length of the editor
   236       //       content, this may fail.
   237       rv = selection->Collapse(mElement, mOffset + textRange.mStartOffset);
   238       setCaret = setCaret || NS_SUCCEEDED(rv);
   239       NS_ASSERTION(setCaret, "Failed to collapse normal selection");
   240       continue;
   241     }
   243     // If the clause length is 0, it's should be a bug.
   244     if (!textRange.Length()) {
   245       NS_WARNING("Any clauses must not be empty");
   246       continue;
   247     }
   249     nsRefPtr<nsRange> clauseRange;
   250     rv = nsRange::CreateRange(mElement, mOffset + textRange.mStartOffset,
   251                               mElement, mOffset + textRange.mEndOffset,
   252                               getter_AddRefs(clauseRange));
   253     if (NS_FAILED(rv)) {
   254       NS_WARNING("Failed to create a DOM range for a clause of composition");
   255       break;
   256     }
   258     // Set the range of the clause to selection.
   259     nsCOMPtr<nsISelection> selectionOfIME;
   260     rv = selCon->GetSelection(ToSelectionType(textRange.mRangeType),
   261                               getter_AddRefs(selectionOfIME));
   262     if (NS_FAILED(rv)) {
   263       NS_WARNING("Failed to get IME selection");
   264       break;
   265     }
   267     rv = selectionOfIME->AddRange(clauseRange);
   268     if (NS_FAILED(rv)) {
   269       NS_WARNING("Failed to add selection range for a clause of composition");
   270       break;
   271     }
   273     // Set the style of the clause.
   274     nsCOMPtr<nsISelectionPrivate> selectionOfIMEPriv =
   275                                     do_QueryInterface(selectionOfIME);
   276     if (!selectionOfIMEPriv) {
   277       NS_WARNING("Failed to get nsISelectionPrivate interface from selection");
   278       continue; // Since this is additional feature, we can continue this job.
   279     }
   280     rv = selectionOfIMEPriv->SetTextRangeStyle(clauseRange,
   281                                                textRange.mRangeStyle);
   282     if (NS_FAILED(rv)) {
   283       NS_WARNING("Failed to set selection style");
   284       break; // but this is unexpected...
   285     }
   286   }
   288   // If the ranges doesn't include explicit caret position, let's set the
   289   // caret to the end of composition string.
   290   if (!setCaret) {
   291     rv = selection->Collapse(mElement, mOffset + mStringToInsert.Length());
   292     NS_ASSERTION(NS_SUCCEEDED(rv),
   293                  "Failed to set caret at the end of composition string");
   294   }
   296   rv = selPriv->EndBatchChanges();
   297   NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to end batch changes");
   299   return rv;
   300 }

mercurial