LCOV - code coverage report
Current view: directory - content/base/src - nsContentAreaDragDrop.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 415 0 0.0 %
Date: 2012-06-02 Functions: 17 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2002
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Mike Pinkerton <pinkerton@netscape.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsReadableUtils.h"
      40                 : 
      41                 : // Local Includes
      42                 : #include "nsContentAreaDragDrop.h"
      43                 : 
      44                 : // Helper Classes
      45                 : #include "nsString.h"
      46                 : 
      47                 : // Interfaces needed to be included
      48                 : #include "nsCopySupport.h"
      49                 : #include "nsIDOMUIEvent.h"
      50                 : #include "nsISelection.h"
      51                 : #include "nsISelectionController.h"
      52                 : #include "nsIDOMNode.h"
      53                 : #include "nsIDOMNodeList.h"
      54                 : #include "nsIDOMEvent.h"
      55                 : #include "nsIDOMNSEvent.h"
      56                 : #include "nsIDOMDragEvent.h"
      57                 : #include "nsPIDOMWindow.h"
      58                 : #include "nsIDOMDocument.h"
      59                 : #include "nsIDOMRange.h"
      60                 : #include "nsIFormControl.h"
      61                 : #include "nsIDOMHTMLAreaElement.h"
      62                 : #include "nsIDOMHTMLAnchorElement.h"
      63                 : #include "nsITransferable.h"
      64                 : #include "nsComponentManagerUtils.h"
      65                 : #include "nsXPCOM.h"
      66                 : #include "nsISupportsPrimitives.h"
      67                 : #include "nsServiceManagerUtils.h"
      68                 : #include "nsNetUtil.h"
      69                 : #include "nsIFile.h"
      70                 : #include "nsIWebNavigation.h"
      71                 : #include "nsIDocShell.h"
      72                 : #include "nsIContent.h"
      73                 : #include "nsIImageLoadingContent.h"
      74                 : #include "nsITextControlElement.h"
      75                 : #include "nsUnicharUtils.h"
      76                 : #include "nsIURL.h"
      77                 : #include "nsIDocument.h"
      78                 : #include "nsIScriptSecurityManager.h"
      79                 : #include "nsIPrincipal.h"
      80                 : #include "nsIDocShellTreeItem.h"
      81                 : #include "nsIWebBrowserPersist.h"
      82                 : #include "nsEscape.h"
      83                 : #include "nsContentUtils.h"
      84                 : #include "nsIMIMEService.h"
      85                 : #include "imgIContainer.h"
      86                 : #include "imgIRequest.h"
      87                 : #include "nsDOMDataTransfer.h"
      88                 : 
      89                 : class NS_STACK_CLASS DragDataProducer
      90               0 : {
      91                 : public:
      92                 :   DragDataProducer(nsIDOMWindow* aWindow,
      93                 :                    nsIContent* aTarget,
      94                 :                    nsIContent* aSelectionTargetNode,
      95                 :                    bool aIsAltKeyPressed);
      96                 :   nsresult Produce(nsDOMDataTransfer* aDataTransfer,
      97                 :                    bool* aCanDrag,
      98                 :                    nsISelection** aSelection,
      99                 :                    nsIContent** aDragNode);
     100                 : 
     101                 : private:
     102                 :   void AddString(nsDOMDataTransfer* aDataTransfer,
     103                 :                  const nsAString& aFlavor,
     104                 :                  const nsAString& aData,
     105                 :                  nsIPrincipal* aPrincipal);
     106                 :   nsresult AddStringsToDataTransfer(nsIContent* aDragNode,
     107                 :                                     nsDOMDataTransfer* aDataTransfer);
     108                 :   static nsresult GetDraggableSelectionData(nsISelection* inSelection,
     109                 :                                             nsIContent* inRealTargetNode,
     110                 :                                             nsIContent **outImageOrLinkNode,
     111                 :                                             bool* outDragSelectedText);
     112                 :   static already_AddRefed<nsIContent> FindParentLinkNode(nsIContent* inNode);
     113                 :   static void GetAnchorURL(nsIContent* inNode, nsAString& outURL);
     114                 :   static void GetNodeString(nsIContent* inNode, nsAString & outNodeString);
     115                 :   static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
     116                 :                               nsAString& outLinkText);
     117                 :   static void GetSelectedLink(nsISelection* inSelection,
     118                 :                               nsIContent **outLinkNode);
     119                 : 
     120                 :   nsCOMPtr<nsIDOMWindow> mWindow;
     121                 :   nsCOMPtr<nsIContent> mTarget;
     122                 :   nsCOMPtr<nsIContent> mSelectionTargetNode;
     123                 :   bool mIsAltKeyPressed;
     124                 : 
     125                 :   nsString mUrlString;
     126                 :   nsString mImageSourceString;
     127                 :   nsString mImageDestFileName;
     128                 :   nsString mTitleString;
     129                 :   // will be filled automatically if you fill urlstring
     130                 :   nsString mHtmlString;
     131                 :   nsString mContextString;
     132                 :   nsString mInfoString;
     133                 : 
     134                 :   bool mIsAnchor;
     135                 :   nsCOMPtr<imgIContainer> mImage;
     136                 : };
     137                 : 
     138                 : 
     139                 : nsresult
     140               0 : nsContentAreaDragDrop::GetDragData(nsIDOMWindow* aWindow,
     141                 :                                    nsIContent* aTarget,
     142                 :                                    nsIContent* aSelectionTargetNode,
     143                 :                                    bool aIsAltKeyPressed,
     144                 :                                    nsDOMDataTransfer* aDataTransfer,
     145                 :                                    bool* aCanDrag,
     146                 :                                    nsISelection** aSelection,
     147                 :                                    nsIContent** aDragNode)
     148                 : {
     149               0 :   NS_ENSURE_TRUE(aSelectionTargetNode, NS_ERROR_INVALID_ARG);
     150                 : 
     151               0 :   *aCanDrag = true;
     152                 : 
     153                 :   DragDataProducer
     154               0 :     provider(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
     155               0 :   return provider.Produce(aDataTransfer, aCanDrag, aSelection, aDragNode);
     156                 : }
     157                 : 
     158                 : 
     159               0 : NS_IMPL_ISUPPORTS1(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
     160                 : 
     161                 : // SaveURIToFile
     162                 : // used on platforms where it's possible to drag items (e.g. images)
     163                 : // into the file system
     164                 : nsresult
     165               0 : nsContentAreaDragDropDataProvider::SaveURIToFile(nsAString& inSourceURIString,
     166                 :                                                  nsIFile* inDestFile)
     167                 : {
     168               0 :   nsCOMPtr<nsIURI> sourceURI;
     169               0 :   nsresult rv = NS_NewURI(getter_AddRefs(sourceURI), inSourceURIString);
     170               0 :   if (NS_FAILED(rv)) {
     171               0 :     return NS_ERROR_FAILURE;
     172                 :   }
     173                 : 
     174               0 :   nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
     175               0 :   if (!sourceURL) {
     176               0 :     return NS_ERROR_NO_INTERFACE;
     177                 :   }
     178                 : 
     179               0 :   rv = inDestFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
     180               0 :   NS_ENSURE_SUCCESS(rv, rv);
     181                 : 
     182                 :   // we rely on the fact that the WPB is refcounted by the channel etc,
     183                 :   // so we don't keep a ref to it. It will die when finished.
     184                 :   nsCOMPtr<nsIWebBrowserPersist> persist =
     185                 :     do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
     186               0 :                       &rv);
     187               0 :   NS_ENSURE_SUCCESS(rv, rv);
     188                 : 
     189               0 :   persist->SetPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION);
     190                 : 
     191               0 :   return persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull, inDestFile);
     192                 : }
     193                 : 
     194                 : // This is our nsIFlavorDataProvider callback. There are several
     195                 : // assumptions here that make this work:
     196                 : //
     197                 : // 1. Someone put a kFilePromiseURLMime flavor into the transferable
     198                 : //    with the source URI of the file to save (as a string). We did
     199                 : //    that in AddStringsToDataTransfer.
     200                 : //
     201                 : // 2. Someone put a kFilePromiseDirectoryMime flavor into the
     202                 : //    transferable with an nsILocalFile for the directory we are to
     203                 : //    save in. That has to be done by platform-specific code (in
     204                 : //    widget), which gets the destination directory from
     205                 : //    OS-specific drag information.
     206                 : //
     207                 : NS_IMETHODIMP
     208               0 : nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable *aTransferable,
     209                 :                                                  const char *aFlavor,
     210                 :                                                  nsISupports **aData,
     211                 :                                                  PRUint32 *aDataLen)
     212                 : {
     213               0 :   NS_ENSURE_ARG_POINTER(aData && aDataLen);
     214               0 :   *aData = nsnull;
     215               0 :   *aDataLen = 0;
     216                 : 
     217               0 :   nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
     218                 : 
     219               0 :   if (strcmp(aFlavor, kFilePromiseMime) == 0) {
     220                 :     // get the URI from the kFilePromiseURLMime flavor
     221               0 :     NS_ENSURE_ARG(aTransferable);
     222               0 :     nsCOMPtr<nsISupports> tmp;
     223               0 :     PRUint32 dataSize = 0;
     224                 :     aTransferable->GetTransferData(kFilePromiseURLMime,
     225               0 :                                    getter_AddRefs(tmp), &dataSize);
     226                 :     nsCOMPtr<nsISupportsString> supportsString =
     227               0 :       do_QueryInterface(tmp);
     228               0 :     if (!supportsString)
     229               0 :       return NS_ERROR_FAILURE;
     230                 : 
     231               0 :     nsAutoString sourceURLString;
     232               0 :     supportsString->GetData(sourceURLString);
     233               0 :     if (sourceURLString.IsEmpty())
     234               0 :       return NS_ERROR_FAILURE;
     235                 : 
     236                 :     aTransferable->GetTransferData(kFilePromiseDestFilename,
     237               0 :                                    getter_AddRefs(tmp), &dataSize);
     238               0 :     supportsString = do_QueryInterface(tmp);
     239               0 :     if (!supportsString)
     240               0 :       return NS_ERROR_FAILURE;
     241                 : 
     242               0 :     nsAutoString targetFilename;
     243               0 :     supportsString->GetData(targetFilename);
     244               0 :     if (targetFilename.IsEmpty())
     245               0 :       return NS_ERROR_FAILURE;
     246                 : 
     247                 :     // get the target directory from the kFilePromiseDirectoryMime
     248                 :     // flavor
     249               0 :     nsCOMPtr<nsISupports> dirPrimitive;
     250               0 :     dataSize = 0;
     251                 :     aTransferable->GetTransferData(kFilePromiseDirectoryMime,
     252               0 :                                    getter_AddRefs(dirPrimitive), &dataSize);
     253               0 :     nsCOMPtr<nsILocalFile> destDirectory = do_QueryInterface(dirPrimitive);
     254               0 :     if (!destDirectory)
     255               0 :       return NS_ERROR_FAILURE;
     256                 : 
     257               0 :     nsCOMPtr<nsIFile> file;
     258               0 :     rv = destDirectory->Clone(getter_AddRefs(file));
     259               0 :     NS_ENSURE_SUCCESS(rv, rv);
     260                 : 
     261               0 :     file->Append(targetFilename);
     262                 : 
     263               0 :     rv = SaveURIToFile(sourceURLString, file);
     264                 :     // send back an nsILocalFile
     265               0 :     if (NS_SUCCEEDED(rv)) {
     266               0 :       CallQueryInterface(file, aData);
     267               0 :       *aDataLen = sizeof(nsIFile*);
     268                 :     }
     269                 :   }
     270                 : 
     271               0 :   return rv;
     272                 : }
     273                 : 
     274               0 : DragDataProducer::DragDataProducer(nsIDOMWindow* aWindow,
     275                 :                                    nsIContent* aTarget,
     276                 :                                    nsIContent* aSelectionTargetNode,
     277                 :                                    bool aIsAltKeyPressed)
     278                 :   : mWindow(aWindow),
     279                 :     mTarget(aTarget),
     280                 :     mSelectionTargetNode(aSelectionTargetNode),
     281                 :     mIsAltKeyPressed(aIsAltKeyPressed),
     282               0 :     mIsAnchor(false)
     283                 : {
     284               0 : }
     285                 : 
     286                 : 
     287                 : //
     288                 : // FindParentLinkNode
     289                 : //
     290                 : // Finds the parent with the given link tag starting at |inNode|. If
     291                 : // it gets up to the root without finding it, we stop looking and
     292                 : // return null.
     293                 : //
     294                 : already_AddRefed<nsIContent>
     295               0 : DragDataProducer::FindParentLinkNode(nsIContent* inNode)
     296                 : {
     297               0 :   nsIContent* content = inNode;
     298               0 :   if (!content) {
     299                 :     // That must have been the document node; nothing else to do here;
     300               0 :     return nsnull;
     301                 :   }
     302                 : 
     303               0 :   for (; content; content = content->GetParent()) {
     304               0 :     if (nsContentUtils::IsDraggableLink(content)) {
     305               0 :       NS_ADDREF(content);
     306               0 :       return content;
     307                 :     }
     308                 :   }
     309                 : 
     310               0 :   return nsnull;
     311                 : }
     312                 : 
     313                 : 
     314                 : //
     315                 : // GetAnchorURL
     316                 : //
     317                 : void
     318               0 : DragDataProducer::GetAnchorURL(nsIContent* inNode, nsAString& outURL)
     319                 : {
     320               0 :   nsCOMPtr<nsIURI> linkURI;
     321               0 :   if (!inNode || !inNode->IsLink(getter_AddRefs(linkURI))) {
     322                 :     // Not a link
     323               0 :     outURL.Truncate();
     324                 :     return;
     325                 :   }
     326                 : 
     327               0 :   nsCAutoString spec;
     328               0 :   linkURI->GetSpec(spec);
     329               0 :   CopyUTF8toUTF16(spec, outURL);
     330                 : }
     331                 : 
     332                 : 
     333                 : //
     334                 : // CreateLinkText
     335                 : //
     336                 : // Creates the html for an anchor in the form
     337                 : //  <a href="inURL">inText</a>
     338                 : //
     339                 : void
     340               0 : DragDataProducer::CreateLinkText(const nsAString& inURL,
     341                 :                                  const nsAString & inText,
     342                 :                                  nsAString& outLinkText)
     343                 : {
     344                 :   // use a temp var in case |inText| is the same string as
     345                 :   // |outLinkText| to avoid overwriting it while building up the
     346                 :   // string in pieces.
     347               0 :   nsAutoString linkText(NS_LITERAL_STRING("<a href=\"") +
     348               0 :                         inURL +
     349               0 :                         NS_LITERAL_STRING("\">") +
     350               0 :                         inText +
     351               0 :                         NS_LITERAL_STRING("</a>") );
     352                 : 
     353               0 :   outLinkText = linkText;
     354               0 : }
     355                 : 
     356                 : 
     357                 : //
     358                 : // GetNodeString
     359                 : //
     360                 : // Gets the text associated with a node
     361                 : //
     362                 : void
     363               0 : DragDataProducer::GetNodeString(nsIContent* inNode,
     364                 :                                 nsAString & outNodeString)
     365                 : {
     366               0 :   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
     367                 : 
     368               0 :   outNodeString.Truncate();
     369                 : 
     370                 :   // use a range to get the text-equivalent of the node
     371               0 :   nsCOMPtr<nsIDOMDocument> doc;
     372               0 :   node->GetOwnerDocument(getter_AddRefs(doc));
     373               0 :   if (doc) {
     374               0 :     nsCOMPtr<nsIDOMRange> range;
     375               0 :     doc->CreateRange(getter_AddRefs(range));
     376               0 :     if (range) {
     377               0 :       range->SelectNode(node);
     378               0 :       range->ToString(outNodeString);
     379                 :     }
     380                 :   }
     381               0 : }
     382                 : 
     383                 : nsresult
     384               0 : DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
     385                 :                           bool* aCanDrag,
     386                 :                           nsISelection** aSelection,
     387                 :                           nsIContent** aDragNode)
     388                 : {
     389               0 :   NS_PRECONDITION(aCanDrag && aSelection && aDataTransfer && aDragNode,
     390                 :                   "null pointer passed to Produce");
     391               0 :   NS_ASSERTION(mWindow, "window not set");
     392               0 :   NS_ASSERTION(mSelectionTargetNode, "selection target node should have been set");
     393                 : 
     394               0 :   *aDragNode = nsnull;
     395                 : 
     396                 :   nsresult rv;
     397               0 :   nsIContent* dragNode = nsnull;
     398               0 :   *aSelection = nsnull;
     399                 : 
     400                 :   // Find the selection to see what we could be dragging and if what we're
     401                 :   // dragging is in what is selected. If this is an editable textbox, use
     402                 :   // the textbox's selection, otherwise use the window's selection.
     403               0 :   nsCOMPtr<nsISelection> selection;
     404               0 :   nsIContent* editingElement = mSelectionTargetNode->IsEditable() ?
     405               0 :                                mSelectionTargetNode->GetEditingHost() : nsnull;
     406               0 :   nsCOMPtr<nsITextControlElement> textControl(do_QueryInterface(editingElement));
     407               0 :   if (textControl) {
     408               0 :     nsISelectionController* selcon = textControl->GetSelectionController();
     409               0 :     if (selcon) {
     410               0 :       selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
     411                 :     }
     412                 : 
     413               0 :     if (!selection)
     414               0 :       return NS_OK;
     415                 :   }
     416                 :   else {
     417               0 :     mWindow->GetSelection(getter_AddRefs(selection));
     418               0 :     if (!selection)
     419               0 :       return NS_OK;
     420                 : 
     421                 :     // Check if the node is inside a form control. Don't set aCanDrag to false
     422                 :     //however, as we still want to allow the drag.
     423               0 :     nsCOMPtr<nsIContent> findFormNode = mSelectionTargetNode;
     424               0 :     nsIContent* findFormParent = findFormNode->GetParent();
     425               0 :     while (findFormParent) {
     426               0 :       nsCOMPtr<nsIFormControl> form(do_QueryInterface(findFormParent));
     427               0 :       if (form && !form->AllowDraggableChildren()) {
     428               0 :         return NS_OK;
     429                 :       }
     430               0 :       findFormParent = findFormParent->GetParent();
     431                 :     }
     432                 :   }
     433                 :     
     434                 :   // if set, serialize the content under this node
     435               0 :   nsCOMPtr<nsIContent> nodeToSerialize;
     436                 : 
     437               0 :   bool isChromeShell = false;
     438               0 :   nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mWindow);
     439               0 :   nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(webnav);
     440               0 :   if (dsti) {
     441               0 :     PRInt32 type = -1;
     442               0 :     if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
     443                 :         type == nsIDocShellTreeItem::typeChrome) {
     444               0 :       isChromeShell = true;
     445                 :     }
     446                 :   }
     447                 : 
     448                 :   // In chrome shells, only allow dragging inside editable areas.
     449               0 :   if (isChromeShell && !editingElement)
     450               0 :     return NS_OK;
     451                 : 
     452               0 :   if (isChromeShell && textControl) {
     453                 :     // Only use the selection if the target node is in the selection.
     454               0 :     bool selectionContainsTarget = false;
     455               0 :     nsCOMPtr<nsIDOMNode> targetNode = do_QueryInterface(mSelectionTargetNode);
     456               0 :     selection->ContainsNode(targetNode, false, &selectionContainsTarget);
     457               0 :     if (!selectionContainsTarget)
     458               0 :       return NS_OK;
     459                 : 
     460               0 :     selection.swap(*aSelection);
     461                 :   }
     462                 :   else {
     463                 :     // In content shells, a number of checks are made below to determine
     464                 :     // whether an image or a link is being dragged. If so, add additional
     465                 :     // data to the data transfer. This is also done for chrome shells, but
     466                 :     // only when in a non-textbox editor.
     467                 : 
     468               0 :     bool haveSelectedContent = false;
     469                 : 
     470                 :     // possible parent link node
     471               0 :     nsCOMPtr<nsIContent> parentLink;
     472               0 :     nsCOMPtr<nsIContent> draggedNode;
     473                 : 
     474                 :     {
     475                 :       // only drag form elements by using the alt key,
     476                 :       // otherwise buttons and select widgets are hard to use
     477                 : 
     478                 :       // Note that while <object> elements implement nsIFormControl, we should
     479                 :       // really allow dragging them if they happen to be images.
     480               0 :       nsCOMPtr<nsIFormControl> form(do_QueryInterface(mTarget));
     481               0 :       if (form && !mIsAltKeyPressed && form->GetType() != NS_FORM_OBJECT) {
     482               0 :         *aCanDrag = false;
     483               0 :         return NS_OK;
     484                 :       }
     485                 : 
     486               0 :       draggedNode = mTarget;
     487                 :     }
     488                 : 
     489               0 :     nsCOMPtr<nsIDOMHTMLAreaElement>   area;   // client-side image map
     490               0 :     nsCOMPtr<nsIImageLoadingContent>  image;
     491               0 :     nsCOMPtr<nsIDOMHTMLAnchorElement> link;
     492                 : 
     493               0 :     nsCOMPtr<nsIContent> selectedImageOrLinkNode;
     494                 :     GetDraggableSelectionData(selection, mSelectionTargetNode,
     495               0 :                               getter_AddRefs(selectedImageOrLinkNode),
     496               0 :                               &haveSelectedContent);
     497                 : 
     498                 :     // either plain text or anchor text is selected
     499               0 :     if (haveSelectedContent) {
     500               0 :       link = do_QueryInterface(selectedImageOrLinkNode);
     501               0 :       if (link && mIsAltKeyPressed) {
     502                 :         // if alt is pressed, select the link text instead of drag the link
     503               0 :         *aCanDrag = false;
     504               0 :         return NS_OK;
     505                 :       }
     506                 : 
     507               0 :       selection.swap(*aSelection);
     508               0 :     } else if (selectedImageOrLinkNode) {
     509                 :       // an image is selected
     510               0 :       image = do_QueryInterface(selectedImageOrLinkNode);
     511                 :     } else {
     512                 :       // nothing is selected -
     513                 :       //
     514                 :       // look for draggable elements under the mouse
     515                 :       //
     516                 :       // if the alt key is down, don't start a drag if we're in an
     517                 :       // anchor because we want to do selection.
     518               0 :       parentLink = FindParentLinkNode(draggedNode);
     519               0 :       if (parentLink && mIsAltKeyPressed) {
     520               0 :         *aCanDrag = false;
     521               0 :         return NS_OK;
     522                 :       }
     523                 : 
     524               0 :       area  = do_QueryInterface(draggedNode);
     525               0 :       image = do_QueryInterface(draggedNode);
     526               0 :       link  = do_QueryInterface(draggedNode);
     527                 :     }
     528                 : 
     529                 :     {
     530                 :       // set for linked images, and links
     531               0 :       nsCOMPtr<nsIContent> linkNode;
     532                 : 
     533               0 :       if (area) {
     534                 :         // use the alt text (or, if missing, the href) as the title
     535               0 :         area->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
     536               0 :         if (mTitleString.IsEmpty()) {
     537                 :           // this can be a relative link
     538               0 :           area->GetAttribute(NS_LITERAL_STRING("href"), mTitleString);
     539                 :         }
     540                 : 
     541                 :         // we'll generate HTML like <a href="absurl">alt text</a>
     542               0 :         mIsAnchor = true;
     543                 : 
     544                 :         // gives an absolute link
     545               0 :         GetAnchorURL(draggedNode, mUrlString);
     546                 : 
     547               0 :         mHtmlString.AssignLiteral("<a href=\"");
     548               0 :         mHtmlString.Append(mUrlString);
     549               0 :         mHtmlString.AppendLiteral("\">");
     550               0 :         mHtmlString.Append(mTitleString);
     551               0 :         mHtmlString.AppendLiteral("</a>");
     552                 : 
     553               0 :         dragNode = draggedNode;
     554               0 :       } else if (image) {
     555               0 :         mIsAnchor = true;
     556                 :         // grab the href as the url, use alt text as the title of the
     557                 :         // area if it's there.  the drag data is the image tag and src
     558                 :         // attribute.
     559               0 :         nsCOMPtr<nsIURI> imageURI;
     560               0 :         image->GetCurrentURI(getter_AddRefs(imageURI));
     561               0 :         if (imageURI) {
     562               0 :           nsCAutoString spec;
     563               0 :           imageURI->GetSpec(spec);
     564               0 :           CopyUTF8toUTF16(spec, mUrlString);
     565                 :         }
     566                 : 
     567               0 :         nsCOMPtr<nsIDOMElement> imageElement(do_QueryInterface(image));
     568                 :         // XXXbz Shouldn't we use the "title" attr for title?  Using
     569                 :         // "alt" seems very wrong....
     570               0 :         if (imageElement) {
     571               0 :           imageElement->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
     572                 :         }
     573                 : 
     574               0 :         if (mTitleString.IsEmpty()) {
     575               0 :           mTitleString = mUrlString;
     576                 :         }
     577                 : 
     578               0 :         nsCOMPtr<imgIRequest> imgRequest;
     579                 : 
     580                 :         // grab the image data, and its request.
     581                 :         nsCOMPtr<imgIContainer> img =
     582                 :           nsContentUtils::GetImageFromContent(image,
     583               0 :                                               getter_AddRefs(imgRequest));
     584                 : 
     585                 :         nsCOMPtr<nsIMIMEService> mimeService =
     586               0 :           do_GetService("@mozilla.org/mime;1");
     587                 : 
     588                 :         // Fix the file extension in the URL if necessary
     589               0 :         if (imgRequest && mimeService) {
     590               0 :           nsCOMPtr<nsIURI> imgUri;
     591               0 :           imgRequest->GetURI(getter_AddRefs(imgUri));
     592                 : 
     593               0 :           nsCOMPtr<nsIURL> imgUrl(do_QueryInterface(imgUri));
     594                 : 
     595               0 :           if (imgUrl) {
     596               0 :             nsCAutoString extension;
     597               0 :             imgUrl->GetFileExtension(extension);
     598                 : 
     599               0 :             nsXPIDLCString mimeType;
     600               0 :             imgRequest->GetMimeType(getter_Copies(mimeType));
     601                 : 
     602               0 :             nsCOMPtr<nsIMIMEInfo> mimeInfo;
     603               0 :             mimeService->GetFromTypeAndExtension(mimeType, EmptyCString(),
     604               0 :                                                  getter_AddRefs(mimeInfo));
     605                 : 
     606               0 :             if (mimeInfo) {
     607               0 :               nsCAutoString spec;
     608               0 :               imgUrl->GetSpec(spec);
     609                 : 
     610                 :               // pass out the image source string
     611               0 :               CopyUTF8toUTF16(spec, mImageSourceString);
     612                 : 
     613                 :               bool validExtension;
     614               0 :               if (extension.IsEmpty() || 
     615               0 :                   NS_FAILED(mimeInfo->ExtensionExists(extension,
     616                 :                                                       &validExtension)) ||
     617               0 :                   !validExtension) {
     618                 :                 // Fix the file extension in the URL
     619               0 :                 nsresult rv = imgUrl->Clone(getter_AddRefs(imgUri));
     620               0 :                 NS_ENSURE_SUCCESS(rv, rv);
     621                 : 
     622               0 :                 imgUrl = do_QueryInterface(imgUri);
     623                 : 
     624               0 :                 nsCAutoString primaryExtension;
     625               0 :                 mimeInfo->GetPrimaryExtension(primaryExtension);
     626                 : 
     627               0 :                 imgUrl->SetFileExtension(primaryExtension);
     628                 :               }
     629                 : 
     630               0 :               nsCAutoString fileName;
     631               0 :               imgUrl->GetFileName(fileName);
     632                 : 
     633               0 :               NS_UnescapeURL(fileName);
     634                 : 
     635                 :               // make the filename safe for the filesystem
     636                 :               fileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS,
     637               0 :                                    '-');
     638                 : 
     639               0 :               CopyUTF8toUTF16(fileName, mImageDestFileName);
     640                 : 
     641                 :               // and the image object
     642               0 :               mImage = img;
     643                 :             }
     644                 :           }
     645                 :         }
     646                 : 
     647               0 :         if (parentLink) {
     648                 :           // If we are dragging around an image in an anchor, then we
     649                 :           // are dragging the entire anchor
     650               0 :           linkNode = parentLink;
     651               0 :           nodeToSerialize = linkNode;
     652                 :         } else {
     653               0 :           nodeToSerialize = do_QueryInterface(draggedNode);
     654                 :         }
     655               0 :         dragNode = nodeToSerialize;
     656               0 :       } else if (link) {
     657                 :         // set linkNode. The code below will handle this
     658               0 :         linkNode = do_QueryInterface(link);    // XXX test this
     659               0 :         GetNodeString(draggedNode, mTitleString);
     660               0 :       } else if (parentLink) {
     661                 :         // parentLink will always be null if there's selected content
     662               0 :         linkNode = parentLink;
     663               0 :         nodeToSerialize = linkNode;
     664               0 :       } else if (!haveSelectedContent) {
     665                 :         // nothing draggable
     666               0 :         return NS_OK;
     667                 :       }
     668                 : 
     669               0 :       if (linkNode) {
     670               0 :         mIsAnchor = true;
     671               0 :         GetAnchorURL(linkNode, mUrlString);
     672               0 :         dragNode = linkNode;
     673                 :       }
     674                 :     }
     675                 :   }
     676                 : 
     677               0 :   if (nodeToSerialize || *aSelection) {
     678               0 :     mHtmlString.Truncate();
     679               0 :     mContextString.Truncate();
     680               0 :     mInfoString.Truncate();
     681               0 :     mTitleString.Truncate();
     682                 : 
     683               0 :     nsCOMPtr<nsIDOMDocument> domDoc;
     684               0 :     mWindow->GetDocument(getter_AddRefs(domDoc));
     685               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
     686               0 :     NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
     687                 : 
     688                 :     // if we have selected text, use it in preference to the node
     689               0 :     nsCOMPtr<nsITransferable> transferable;
     690               0 :     if (*aSelection) {
     691                 :       rv = nsCopySupport::GetTransferableForSelection(*aSelection, doc,
     692               0 :                                                       getter_AddRefs(transferable));
     693                 :     }
     694                 :     else {
     695                 :       rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
     696               0 :                                                  getter_AddRefs(transferable));
     697                 :     }
     698               0 :     NS_ENSURE_SUCCESS(rv, rv);
     699                 : 
     700               0 :     nsCOMPtr<nsISupportsString> data;
     701                 :     PRUint32 dataSize;
     702               0 :     rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
     703               0 :     if (NS_SUCCEEDED(rv)) {
     704               0 :       data->GetData(mHtmlString);
     705                 :     }
     706               0 :     rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(data), &dataSize);
     707               0 :     if (NS_SUCCEEDED(rv)) {
     708               0 :       data->GetData(mContextString);
     709                 :     }
     710               0 :     rv = transferable->GetTransferData(kHTMLInfo, getter_AddRefs(data), &dataSize);
     711               0 :     if (NS_SUCCEEDED(rv)) {
     712               0 :       data->GetData(mInfoString);
     713                 :     }
     714               0 :     rv = transferable->GetTransferData(kUnicodeMime, getter_AddRefs(data), &dataSize);
     715               0 :     NS_ENSURE_SUCCESS(rv, rv); // require plain text at a minimum
     716               0 :     data->GetData(mTitleString);
     717                 :   }
     718                 : 
     719                 :   // default text value is the URL
     720               0 :   if (mTitleString.IsEmpty()) {
     721               0 :     mTitleString = mUrlString;
     722                 :   }
     723                 : 
     724                 :   // if we haven't constructed a html version, make one now
     725               0 :   if (mHtmlString.IsEmpty() && !mUrlString.IsEmpty())
     726               0 :     CreateLinkText(mUrlString, mTitleString, mHtmlString);
     727                 : 
     728                 :   // if there is no drag node, which will be the case for a selection, just
     729                 :   // use the selection target node.
     730                 :   rv = AddStringsToDataTransfer(
     731               0 :          dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer);
     732               0 :   NS_ENSURE_SUCCESS(rv, rv);
     733                 : 
     734               0 :   NS_IF_ADDREF(*aDragNode = dragNode);
     735               0 :   return NS_OK;
     736                 : }
     737                 : 
     738                 : void
     739               0 : DragDataProducer::AddString(nsDOMDataTransfer* aDataTransfer,
     740                 :                             const nsAString& aFlavor,
     741                 :                             const nsAString& aData,
     742                 :                             nsIPrincipal* aPrincipal)
     743                 : {
     744               0 :   nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
     745               0 :   if (variant) {
     746               0 :     variant->SetAsAString(aData);
     747               0 :     aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
     748                 :   }
     749               0 : }
     750                 : 
     751                 : nsresult
     752               0 : DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
     753                 :                                            nsDOMDataTransfer* aDataTransfer)
     754                 : {
     755               0 :   NS_ASSERTION(aDragNode, "adding strings for null node");
     756                 : 
     757                 :   // set all of the data to have the principal of the node where the data came from
     758               0 :   nsIPrincipal* principal = aDragNode->NodePrincipal();
     759                 : 
     760                 :   // add a special flavor if we're an anchor to indicate that we have
     761                 :   // a URL in the drag data
     762               0 :   if (!mUrlString.IsEmpty() && mIsAnchor) {
     763               0 :     nsAutoString dragData(mUrlString);
     764               0 :     dragData.AppendLiteral("\n");
     765               0 :     dragData += mTitleString;
     766                 : 
     767               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kURLMime), dragData, principal);
     768               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
     769               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kURLDescriptionMime), mTitleString, principal);
     770               0 :     AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
     771                 :   }
     772                 : 
     773                 :   // add a special flavor for the html context data
     774               0 :   if (!mContextString.IsEmpty())
     775               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), mContextString, principal);
     776                 : 
     777                 :   // add a special flavor if we have html info data
     778               0 :   if (!mInfoString.IsEmpty())
     779               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), mInfoString, principal);
     780                 : 
     781                 :   // add the full html
     782               0 :   if (!mHtmlString.IsEmpty())
     783               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kHTMLMime), mHtmlString, principal);
     784                 : 
     785                 :   // add the plain text. we use the url for text/plain data if an anchor is
     786                 :   // being dragged, rather than the title text of the link or the alt text for
     787                 :   // an anchor image.
     788               0 :   AddString(aDataTransfer, NS_LITERAL_STRING(kTextMime),
     789               0 :             mIsAnchor ? mUrlString : mTitleString, principal);
     790                 : 
     791                 :   // add image data, if present. For now, all we're going to do with
     792                 :   // this is turn it into a native data flavor, so indicate that with
     793                 :   // a new flavor so as not to confuse anyone who is really registered
     794                 :   // for image/gif or image/jpg.
     795               0 :   if (mImage) {
     796               0 :     nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
     797               0 :     if (variant) {
     798               0 :       variant->SetAsISupports(mImage);
     799               0 :       aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kNativeImageMime),
     800               0 :                                           variant, 0, principal);
     801                 :     }
     802                 : 
     803                 :     // assume the image comes from a file, and add a file promise. We
     804                 :     // register ourselves as a nsIFlavorDataProvider, and will use the
     805                 :     // GetFlavorData callback to save the image to disk.
     806                 : 
     807                 :     nsCOMPtr<nsIFlavorDataProvider> dataProvider =
     808               0 :       new nsContentAreaDragDropDataProvider();
     809               0 :     if (dataProvider) {
     810               0 :       nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
     811               0 :       if (variant) {
     812               0 :         variant->SetAsISupports(dataProvider);
     813               0 :         aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kFilePromiseMime),
     814               0 :                                             variant, 0, principal);
     815                 :       }
     816                 :     }
     817                 : 
     818               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseURLMime),
     819               0 :               mImageSourceString, principal);
     820               0 :     AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseDestFilename),
     821               0 :               mImageDestFileName, principal);
     822                 : 
     823                 :     // if not an anchor, add the image url
     824               0 :     if (!mIsAnchor) {
     825               0 :       AddString(aDataTransfer, NS_LITERAL_STRING(kURLDataMime), mUrlString, principal);
     826               0 :       AddString(aDataTransfer, NS_LITERAL_STRING("text/uri-list"), mUrlString, principal);
     827                 :     }
     828                 :   }
     829                 : 
     830               0 :   return NS_OK;
     831                 : }
     832                 : 
     833                 : // note that this can return NS_OK, but a null out param (by design)
     834                 : // static
     835                 : nsresult
     836               0 : DragDataProducer::GetDraggableSelectionData(nsISelection* inSelection,
     837                 :                                             nsIContent* inRealTargetNode,
     838                 :                                             nsIContent **outImageOrLinkNode,
     839                 :                                             bool* outDragSelectedText)
     840                 : {
     841               0 :   NS_ENSURE_ARG(inSelection);
     842               0 :   NS_ENSURE_ARG(inRealTargetNode);
     843               0 :   NS_ENSURE_ARG_POINTER(outImageOrLinkNode);
     844                 : 
     845               0 :   *outImageOrLinkNode = nsnull;
     846               0 :   *outDragSelectedText = false;
     847                 : 
     848               0 :   bool selectionContainsTarget = false;
     849                 : 
     850               0 :   bool isCollapsed = false;
     851               0 :   inSelection->GetIsCollapsed(&isCollapsed);
     852               0 :   if (!isCollapsed) {
     853               0 :     nsCOMPtr<nsIDOMNode> realTargetNode = do_QueryInterface(inRealTargetNode);
     854                 :     inSelection->ContainsNode(realTargetNode, false,
     855               0 :                               &selectionContainsTarget);
     856                 : 
     857               0 :     if (selectionContainsTarget) {
     858                 :       // track down the anchor node, if any, for the url
     859               0 :       nsCOMPtr<nsIDOMNode> selectionStart;
     860               0 :       inSelection->GetAnchorNode(getter_AddRefs(selectionStart));
     861                 : 
     862               0 :       nsCOMPtr<nsIDOMNode> selectionEnd;
     863               0 :       inSelection->GetFocusNode(getter_AddRefs(selectionEnd));
     864                 : 
     865                 :       // look for a selection around a single node, like an image.
     866                 :       // in this case, drag the image, rather than a serialization of the HTML
     867                 :       // XXX generalize this to other draggable element types?
     868               0 :       if (selectionStart == selectionEnd) {
     869                 :         bool hasChildren;
     870               0 :         selectionStart->HasChildNodes(&hasChildren);
     871               0 :         if (hasChildren) {
     872                 :           // see if just one node is selected
     873                 :           PRInt32 anchorOffset, focusOffset;
     874               0 :           inSelection->GetAnchorOffset(&anchorOffset);
     875               0 :           inSelection->GetFocusOffset(&focusOffset);
     876               0 :           if (abs(anchorOffset - focusOffset) == 1) {
     877                 :             nsCOMPtr<nsIContent> selStartContent =
     878               0 :               do_QueryInterface(selectionStart);
     879                 : 
     880               0 :             if (selStartContent) {
     881                 :               PRInt32 childOffset =
     882               0 :                 (anchorOffset < focusOffset) ? anchorOffset : focusOffset;
     883                 :               nsIContent *childContent =
     884               0 :                 selStartContent->GetChildAt(childOffset);
     885                 :               // if we find an image, we'll fall into the node-dragging code,
     886                 :               // rather the the selection-dragging code
     887               0 :               if (nsContentUtils::IsDraggableImage(childContent)) {
     888               0 :                 NS_ADDREF(*outImageOrLinkNode = childContent);
     889               0 :                 return NS_OK;
     890                 :               }
     891                 :             }
     892                 :           }
     893                 :         }
     894                 :       }
     895                 : 
     896                 :       // see if the selection is a link;  if so, its node will be returned
     897               0 :       GetSelectedLink(inSelection, outImageOrLinkNode);
     898                 : 
     899                 :       // indicate that a link or text is selected
     900               0 :       *outDragSelectedText = true;
     901                 :     }
     902                 :   }
     903                 : 
     904               0 :   return NS_OK;
     905                 : }
     906                 : 
     907                 : // static
     908                 : void
     909               0 : DragDataProducer::GetSelectedLink(nsISelection* inSelection,
     910                 :                                   nsIContent **outLinkNode)
     911                 : {
     912               0 :   *outLinkNode = nsnull;
     913                 : 
     914               0 :   nsCOMPtr<nsIDOMNode> selectionStartNode;
     915               0 :   inSelection->GetAnchorNode(getter_AddRefs(selectionStartNode));
     916               0 :   nsCOMPtr<nsIDOMNode> selectionEndNode;
     917               0 :   inSelection->GetFocusNode(getter_AddRefs(selectionEndNode));
     918                 : 
     919                 :   // simple case:  only one node is selected
     920                 :   // see if it or its parent is an anchor, then exit
     921                 : 
     922               0 :   if (selectionStartNode == selectionEndNode) {
     923               0 :     nsCOMPtr<nsIContent> selectionStart = do_QueryInterface(selectionStartNode);
     924               0 :     nsCOMPtr<nsIContent> link = FindParentLinkNode(selectionStart);
     925               0 :     if (link) {
     926               0 :       link.swap(*outLinkNode);
     927                 :     }
     928                 : 
     929                 :     return;
     930                 :   }
     931                 : 
     932                 :   // more complicated case:  multiple nodes are selected
     933                 : 
     934                 :   // Unless you use the Alt key while selecting anchor text, it is
     935                 :   // nearly impossible to avoid overlapping into adjacent nodes.
     936                 :   // Deal with this by trimming off the leading and/or trailing
     937                 :   // nodes of the selection if the strings they produce are empty.
     938                 : 
     939                 :   // first, use a range determine if the selection was marked LTR or RTL;
     940                 :   // if the latter, swap endpoints so we trim in the right direction
     941                 : 
     942                 :   PRInt32 startOffset, endOffset;
     943                 :   {
     944               0 :     nsCOMPtr<nsIDOMRange> range;
     945               0 :     inSelection->GetRangeAt(0, getter_AddRefs(range));
     946               0 :     if (!range) {
     947                 :       return;
     948                 :     }
     949                 : 
     950               0 :     nsCOMPtr<nsIDOMNode> tempNode;
     951               0 :     range->GetStartContainer( getter_AddRefs(tempNode));
     952               0 :     if (tempNode != selectionStartNode) {
     953               0 :       selectionEndNode = selectionStartNode;
     954               0 :       selectionStartNode = tempNode;
     955               0 :       inSelection->GetAnchorOffset(&endOffset);
     956               0 :       inSelection->GetFocusOffset(&startOffset);
     957                 :     } else {
     958               0 :       inSelection->GetAnchorOffset(&startOffset);
     959               0 :       inSelection->GetFocusOffset(&endOffset);
     960                 :     }
     961                 :   }
     962                 : 
     963                 :   // trim leading node if the string is empty or
     964                 :   // the selection starts at the end of the text
     965                 : 
     966               0 :   nsAutoString nodeStr;
     967               0 :   selectionStartNode->GetNodeValue(nodeStr);
     968               0 :   if (nodeStr.IsEmpty() ||
     969               0 :       startOffset+1 >= static_cast<PRInt32>(nodeStr.Length())) {
     970               0 :     nsCOMPtr<nsIDOMNode> curr = selectionStartNode;
     971                 :     nsIDOMNode* next;
     972                 : 
     973               0 :     while (curr) {
     974               0 :       curr->GetNextSibling(&next);
     975                 : 
     976               0 :       if (next) {
     977               0 :         selectionStartNode = dont_AddRef(next);
     978               0 :         break;
     979                 :       }
     980                 : 
     981               0 :       curr->GetParentNode(&next);
     982               0 :       curr = dont_AddRef(next);
     983                 :     }
     984                 :   }
     985                 : 
     986                 :   // trim trailing node if the selection ends before its text begins
     987                 : 
     988               0 :   if (endOffset == 0) {
     989               0 :     nsCOMPtr<nsIDOMNode> curr = selectionEndNode;
     990                 :     nsIDOMNode* next;
     991                 : 
     992               0 :     while (curr) {
     993               0 :       curr->GetPreviousSibling(&next);
     994                 : 
     995               0 :       if (next){
     996               0 :         selectionEndNode = dont_AddRef(next);
     997               0 :         break;
     998                 :       }
     999                 : 
    1000               0 :       curr->GetParentNode(&next);
    1001               0 :       curr = dont_AddRef(next);
    1002                 :     }
    1003                 :   }
    1004                 : 
    1005                 :   // see if the leading & trailing nodes are part of the
    1006                 :   // same anchor - if so, return the anchor node
    1007               0 :   nsCOMPtr<nsIContent> selectionStart = do_QueryInterface(selectionStartNode);
    1008               0 :   nsCOMPtr<nsIContent> link = FindParentLinkNode(selectionStart);
    1009               0 :   if (link) {
    1010               0 :     nsCOMPtr<nsIContent> selectionEnd = do_QueryInterface(selectionEndNode);
    1011               0 :     nsCOMPtr<nsIContent> link2 = FindParentLinkNode(selectionEnd);
    1012                 : 
    1013               0 :     if (link == link2) {
    1014               0 :       NS_IF_ADDREF(*outLinkNode = link);
    1015                 :     }
    1016                 :   }
    1017                 : 
    1018                 :   return;
    1019                 : }

Generated by: LCOV version 1.7