editor/libeditor/base/SetDocTitleTxn.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 "SetDocTitleTxn.h"
     7 #include "mozilla/dom/Element.h"        // for Element
     8 #include "nsAString.h"
     9 #include "nsCOMPtr.h"                   // for nsCOMPtr, getter_AddRefs, etc
    10 #include "nsDebug.h"                    // for NS_ENSURE_SUCCESS, etc
    11 #include "nsError.h"                    // for NS_OK, NS_ERROR_FAILURE, etc
    12 #include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
    13 #include "nsIDOMDocument.h"             // for nsIDOMDocument
    14 #include "nsIDOMElement.h"              // for nsIDOMElement
    15 #include "nsIDOMNode.h"                 // for nsIDOMNode
    16 #include "nsIDOMNodeList.h"             // for nsIDOMNodeList
    17 #include "nsIDOMText.h"                 // for nsIDOMText
    18 #include "nsIDocument.h"                // for nsIDocument
    19 #include "nsIEditor.h"                  // for nsIEditor
    20 #include "nsIHTMLEditor.h"              // for nsIHTMLEditor
    21 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
    23 using namespace mozilla;
    25 // note that aEditor is not refcounted
    26 SetDocTitleTxn::SetDocTitleTxn()
    27   : EditTxn()
    28 , mIsTransient(false)
    29 {
    30 }
    32 NS_IMETHODIMP SetDocTitleTxn::Init(nsIHTMLEditor *aEditor,
    33                                    const nsAString *aValue)
    35 {
    36   NS_ASSERTION(aEditor && aValue, "null args");
    37   if (!aEditor || !aValue) { return NS_ERROR_NULL_POINTER; }
    39   mEditor = aEditor;
    40   mValue = *aValue;
    42   return NS_OK;
    43 }
    45 NS_IMETHODIMP SetDocTitleTxn::DoTransaction(void)
    46 {
    47   return SetDomTitle(mValue);
    48 }
    50 NS_IMETHODIMP SetDocTitleTxn::UndoTransaction(void)
    51 {
    52   // No extra work required; the DOM changes alone are enough
    53   return NS_OK;
    54 }
    56 NS_IMETHODIMP SetDocTitleTxn::RedoTransaction(void)
    57 {
    58   // No extra work required; the DOM changes alone are enough
    59   return NS_OK;
    60 }
    62 nsresult SetDocTitleTxn::SetDomTitle(const nsAString& aTitle)
    63 {
    64   nsCOMPtr<nsIEditor> editor = do_QueryInterface(mEditor);
    65   NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
    66   nsCOMPtr<nsIDOMDocument> domDoc;
    67   nsresult res = editor->GetDocument(getter_AddRefs(domDoc));
    68   NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
    70   nsCOMPtr<nsIDOMNodeList> titleList;
    71   res = domDoc->GetElementsByTagName(NS_LITERAL_STRING("title"), getter_AddRefs(titleList));
    72   NS_ENSURE_SUCCESS(res, res);
    74   // First assume we will NOT really do anything
    75   // (transaction will not be pushed on stack)
    76   mIsTransient = true;
    78   nsCOMPtr<nsIDOMNode>titleNode;
    79   if(titleList)
    80   {
    81     res = titleList->Item(0, getter_AddRefs(titleNode));
    82     NS_ENSURE_SUCCESS(res, res);
    83     if (titleNode)
    84     {
    85       // Delete existing child textnode of title node
    86       // (Note: all contents under a TITLE node are always in a single text node)
    87       nsCOMPtr<nsIDOMNode> child;
    88       res = titleNode->GetFirstChild(getter_AddRefs(child));
    89       if(NS_FAILED(res)) return res;
    90       if(child)
    91       {
    92         // Save current text as the undo value
    93         nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(child);
    94         if(textNode)
    95         {
    96           textNode->GetData(mUndoValue);
    98           // If title text is identical to what already exists,
    99           // quit now (mIsTransient is now TRUE)
   100           if (mUndoValue == aTitle)
   101             return NS_OK;
   102         }
   103         res = editor->DeleteNode(child);
   104         if(NS_FAILED(res)) return res;
   105       }
   106     }
   107   }
   109   // We didn't return above, thus we really will be changing the title
   110   mIsTransient = false;
   112   // Get the <HEAD> node, create a <TITLE> and insert it under the HEAD
   113   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDoc);
   114   NS_ENSURE_STATE(document);
   116   dom::Element* head = document->GetHeadElement();
   117   NS_ENSURE_STATE(head);
   119   bool     newTitleNode = false;
   120   uint32_t newTitleIndex = 0;
   122   if (!titleNode)
   123   {
   124     // Didn't find one above: Create a new one
   125     nsCOMPtr<nsIDOMElement>titleElement;
   126     res = domDoc->CreateElement(NS_LITERAL_STRING("title"), getter_AddRefs(titleElement));
   127     NS_ENSURE_SUCCESS(res, res);
   128     NS_ENSURE_TRUE(titleElement, NS_ERROR_FAILURE);
   130     titleNode = do_QueryInterface(titleElement);
   131     newTitleNode = true;
   133     // Get index so we append new title node after all existing HEAD children.
   134     newTitleIndex = head->GetChildCount();
   135   }
   137   // Append a text node under the TITLE
   138   //  only if the title text isn't empty
   139   if (titleNode && !aTitle.IsEmpty())
   140   {
   141     nsCOMPtr<nsIDOMText> textNode;
   142     res = domDoc->CreateTextNode(aTitle, getter_AddRefs(textNode));
   143     NS_ENSURE_SUCCESS(res, res);
   144     nsCOMPtr<nsIDOMNode> newNode = do_QueryInterface(textNode);
   145     NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
   147     if (newTitleNode)
   148     {
   149       // Not undoable: We will insert newTitleNode below
   150       nsCOMPtr<nsIDOMNode> resultNode;
   151       res = titleNode->AppendChild(newNode, getter_AddRefs(resultNode));
   152     } 
   153     else 
   154     {
   155       // This is an undoable transaction
   156       res = editor->InsertNode(newNode, titleNode, 0);
   157     }
   158     NS_ENSURE_SUCCESS(res, res);
   159   }
   161   if (newTitleNode)
   162   {
   163     // Undoable transaction to insert title+text together
   164     res = editor->InsertNode(titleNode, head->AsDOMNode(), newTitleIndex);
   165   }
   166   return res;
   167 }
   169 NS_IMETHODIMP SetDocTitleTxn::GetTxnDescription(nsAString& aString)
   170 {
   171   aString.AssignLiteral("SetDocTitleTxn: ");
   172   aString += mValue;
   173   return NS_OK;
   174 }
   176 NS_IMETHODIMP SetDocTitleTxn::GetIsTransient(bool *aIsTransient)
   177 {
   178   NS_ENSURE_TRUE(aIsTransient, NS_ERROR_NULL_POINTER);  
   179   *aIsTransient = mIsTransient;
   180   return NS_OK;
   181 }

mercurial