LCOV - code coverage report
Current view: directory - content/base/src - nsCopySupport.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 329 0 0.0 %
Date: 2012-06-02 Functions: 13 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.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Kathleen Brade <brade@netscape.com>
      24                 :  *   David Gardiner <david.gardiner@unisa.edu.au>
      25                 :  *   Mats Palmgren <matpal@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsCopySupport.h"
      42                 : #include "nsIDocumentEncoder.h"
      43                 : #include "nsISupports.h"
      44                 : #include "nsIContent.h"
      45                 : #include "nsIComponentManager.h" 
      46                 : #include "nsIServiceManager.h"
      47                 : #include "nsIClipboard.h"
      48                 : #include "nsISelection.h"
      49                 : #include "nsWidgetsCID.h"
      50                 : #include "nsXPCOM.h"
      51                 : #include "nsISupportsPrimitives.h"
      52                 : #include "nsIDOMRange.h"
      53                 : #include "nsRange.h"
      54                 : #include "imgIContainer.h"
      55                 : #include "nsIPresShell.h"
      56                 : #include "nsFocusManager.h"
      57                 : #include "nsEventDispatcher.h"
      58                 : 
      59                 : #include "nsIDocShell.h"
      60                 : #include "nsIContentViewerEdit.h"
      61                 : #include "nsIClipboardDragDropHooks.h"
      62                 : #include "nsIClipboardDragDropHookList.h"
      63                 : #include "nsIClipboardHelper.h"
      64                 : #include "nsISelectionController.h"
      65                 : 
      66                 : #include "nsPIDOMWindow.h"
      67                 : #include "nsIDocument.h"
      68                 : #include "nsIDOMNode.h"
      69                 : #include "nsIDOMElement.h"
      70                 : #include "nsIDOMDocument.h"
      71                 : #include "nsIHTMLDocument.h"
      72                 : #include "nsGkAtoms.h"
      73                 : #include "nsGUIEvent.h"
      74                 : #include "nsIFrame.h"
      75                 : 
      76                 : // image copy stuff
      77                 : #include "nsIImageLoadingContent.h"
      78                 : #include "nsIInterfaceRequestorUtils.h"
      79                 : #include "nsContentUtils.h"
      80                 : #include "nsContentCID.h"
      81                 : 
      82                 : #include "mozilla/dom/Element.h"
      83                 : 
      84                 : #include "mozilla/Preferences.h"
      85                 : 
      86                 : using namespace mozilla;
      87                 : 
      88                 : nsresult NS_NewDomSelection(nsISelection **aDomSelection);
      89                 : 
      90                 : static NS_DEFINE_CID(kCClipboardCID,           NS_CLIPBOARD_CID);
      91                 : static NS_DEFINE_CID(kCTransferableCID,        NS_TRANSFERABLE_CID);
      92                 : static NS_DEFINE_CID(kHTMLConverterCID,        NS_HTMLFORMATCONVERTER_CID);
      93                 : 
      94                 : // copy string data onto the transferable
      95                 : static nsresult AppendString(nsITransferable *aTransferable,
      96                 :                              const nsAString& aString,
      97                 :                              const char* aFlavor);
      98                 : 
      99                 : // copy HTML node data
     100                 : static nsresult AppendDOMNode(nsITransferable *aTransferable,
     101                 :                               nsIDOMNode *aDOMNode);
     102                 : 
     103                 : // Helper used for HTMLCopy and GetTransferableForSelection since both routines
     104                 : // share common code.
     105                 : static nsresult
     106               0 : SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
     107                 :                     bool doPutOnClipboard, PRInt16 aClipboardID,
     108                 :                     PRUint32 aFlags, nsITransferable ** aTransferable)
     109                 : {
     110                 :   // Clear the output parameter for the transferable, if provided.
     111               0 :   if (aTransferable) {
     112               0 :     *aTransferable = nsnull;
     113                 :   }
     114                 : 
     115               0 :   nsresult rv = NS_OK;
     116                 :   
     117               0 :   bool bIsPlainTextContext = false;
     118                 : 
     119               0 :   rv = nsCopySupport::IsPlainTextContext(aSel, aDoc, &bIsPlainTextContext);
     120               0 :   if (NS_FAILED(rv)) 
     121               0 :     return rv;
     122                 : 
     123               0 :   bool bIsHTMLCopy = !bIsPlainTextContext;
     124               0 :   nsAutoString mimeType;
     125                 : 
     126               0 :   nsCOMPtr<nsIDocumentEncoder> docEncoder;
     127                 : 
     128               0 :   docEncoder = do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
     129               0 :   NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
     130                 : 
     131                 :   // We always require a plaintext version
     132                 :   
     133                 :   // note that we assign text/unicode as mime type, but in fact nsHTMLCopyEncoder
     134                 :   // ignore it and use text/html or text/plain depending where the selection
     135                 :   // is. if it is a selection into input/textarea element or in a html content
     136                 :   // with pre-wrap style : text/plain. Otherwise text/html.
     137                 :   // see nsHTMLCopyEncoder::SetSelection
     138               0 :   mimeType.AssignLiteral(kUnicodeMime);
     139                 :   
     140                 :   // we want preformatted for the case where the selection is inside input/textarea
     141                 :   // and we don't want pretty printing for others cases, to not have additionnal
     142                 :   // line breaks which are then converted into spaces by the htmlConverter (see bug #524975)
     143                 :   PRUint32 flags = aFlags | nsIDocumentEncoder::OutputPreformatted
     144               0 :                           | nsIDocumentEncoder::OutputRaw;
     145                 : 
     146               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
     147               0 :   NS_ASSERTION(domDoc, "Need a document");
     148                 : 
     149               0 :   rv = docEncoder->Init(domDoc, mimeType, flags);
     150               0 :   if (NS_FAILED(rv)) 
     151               0 :     return rv;
     152                 : 
     153               0 :   rv = docEncoder->SetSelection(aSel);
     154               0 :   if (NS_FAILED(rv)) 
     155               0 :     return rv;
     156                 : 
     157               0 :   nsAutoString buffer, parents, info, textBuffer, plaintextBuffer;
     158                 : 
     159               0 :   rv = docEncoder->EncodeToString(textBuffer);
     160               0 :   if (NS_FAILED(rv)) 
     161               0 :     return rv;
     162                 : 
     163                 :   // If the selection was in a text input, in textarea or in pre, the encoder
     164                 :   // already produced plain text. Otherwise,the encoder produced HTML. In that
     165                 :   // case, we need to create an additional plain text serialization and an
     166                 :   // addition HTML serialization that encodes context.
     167               0 :   if (bIsHTMLCopy) {
     168                 : 
     169                 :     // First, create the plain text serialization
     170               0 :     mimeType.AssignLiteral("text/plain");
     171                 : 
     172                 :     flags =
     173                 :       nsIDocumentEncoder::OutputSelectionOnly |
     174                 :       nsIDocumentEncoder::OutputAbsoluteLinks |
     175                 :       nsIDocumentEncoder::SkipInvisibleContent |
     176                 :       nsIDocumentEncoder::OutputDropInvisibleBreak |
     177               0 :       (aFlags & nsIDocumentEncoder::OutputNoScriptContent);
     178                 : 
     179               0 :     rv = docEncoder->Init(domDoc, mimeType, flags);
     180               0 :     if (NS_FAILED(rv))
     181               0 :       return rv;
     182                 : 
     183               0 :     rv = docEncoder->SetSelection(aSel);
     184               0 :     if (NS_FAILED(rv))
     185               0 :       return rv;
     186                 : 
     187               0 :     rv = docEncoder->EncodeToString(plaintextBuffer);
     188               0 :     if (NS_FAILED(rv))
     189               0 :       return rv;
     190                 : 
     191                 :     // Emulate the collateral damage from bug 564737. Remove the following
     192                 :     // line to fix bug 739537.
     193               0 :     plaintextBuffer.Trim(" ", true, false);
     194                 : 
     195                 :     // Now create the version that shows HTML context
     196                 : 
     197               0 :     mimeType.AssignLiteral(kHTMLMime);
     198                 : 
     199               0 :     flags = aFlags;
     200                 : 
     201               0 :     rv = docEncoder->Init(domDoc, mimeType, flags);
     202               0 :     NS_ENSURE_SUCCESS(rv, rv);
     203                 : 
     204               0 :     rv = docEncoder->SetSelection(aSel);
     205               0 :     NS_ENSURE_SUCCESS(rv, rv);
     206                 : 
     207                 :     // encode the selection as html with contextual info
     208               0 :     rv = docEncoder->EncodeToStringWithContext(parents, info, buffer);
     209               0 :     NS_ENSURE_SUCCESS(rv, rv);
     210                 :   }
     211                 :   
     212                 :   // Get the Clipboard
     213               0 :   nsCOMPtr<nsIClipboard> clipboard;
     214               0 :   if (doPutOnClipboard) {
     215               0 :     clipboard = do_GetService(kCClipboardCID, &rv);
     216               0 :     if (NS_FAILED(rv))
     217               0 :       return rv;
     218                 :   }
     219                 : 
     220               0 :   if ((doPutOnClipboard && clipboard) || aTransferable != nsnull) {
     221                 :     // Create a transferable for putting data on the Clipboard
     222               0 :     nsCOMPtr<nsITransferable> trans = do_CreateInstance(kCTransferableCID);
     223               0 :     if (trans) {
     224               0 :       if (bIsHTMLCopy) {
     225                 :         // Set up a format converter so that clipboard flavor queries work.
     226                 :         // This converter isn't really used for conversions.
     227                 :         nsCOMPtr<nsIFormatConverter> htmlConverter =
     228               0 :           do_CreateInstance(kHTMLConverterCID);
     229               0 :         trans->SetConverter(htmlConverter);
     230                 : 
     231               0 :         if (!buffer.IsEmpty()) {
     232                 :           // Add the html DataFlavor to the transferable
     233               0 :           rv = AppendString(trans, buffer, kHTMLMime);
     234               0 :           NS_ENSURE_SUCCESS(rv, rv);
     235                 :         }
     236                 : 
     237                 :         // Add the htmlcontext DataFlavor to the transferable
     238                 :         // Even if parents is empty string, this flavor should
     239                 :         // be attached to the transferable
     240               0 :         rv = AppendString(trans, parents, kHTMLContext);
     241               0 :         NS_ENSURE_SUCCESS(rv, rv);
     242                 : 
     243               0 :         if (!info.IsEmpty()) {
     244                 :           // Add the htmlinfo DataFlavor to the transferable
     245               0 :           rv = AppendString(trans, info, kHTMLInfo);
     246               0 :           NS_ENSURE_SUCCESS(rv, rv);
     247                 :         }
     248                 : 
     249               0 :         if (!plaintextBuffer.IsEmpty()) {
     250                 :           // unicode text
     251                 :           // Add the unicode DataFlavor to the transferable
     252                 :           // If we didn't have this, then nsDataObj::GetData matches text/unicode against
     253                 :           // the kURLMime flavour which is not desirable (eg. when pasting into Notepad)
     254               0 :           rv = AppendString(trans, plaintextBuffer, kUnicodeMime);
     255               0 :           NS_ENSURE_SUCCESS(rv, rv);
     256                 :         }
     257                 : 
     258                 :         // Try and get source URI of the items that are being dragged
     259               0 :         nsIURI *uri = aDoc->GetDocumentURI();
     260               0 :         if (uri) {
     261               0 :           nsCAutoString spec;
     262               0 :           uri->GetSpec(spec);
     263               0 :           if (!spec.IsEmpty()) {
     264               0 :             nsAutoString shortcut;
     265               0 :             AppendUTF8toUTF16(spec, shortcut);
     266                 : 
     267                 :             // Add the URL DataFlavor to the transferable. Don't use kURLMime, as it will
     268                 :             // cause an unnecessary UniformResourceLocator to be added which confuses
     269                 :             // some apps eg. Outlook 2000 - (See Bug 315370). Don't use
     270                 :             // kURLDataMime, as it will cause a bogus 'url ' flavor to
     271                 :             // show up on the Mac clipboard, confusing other apps, like
     272                 :             // Terminal (see bug 336012).
     273               0 :             rv = AppendString(trans, shortcut, kURLPrivateMime);
     274               0 :             NS_ENSURE_SUCCESS(rv, rv);
     275                 :           }
     276                 :         }
     277                 :       } else {
     278               0 :         if (!textBuffer.IsEmpty()) {
     279                 :           // Add the unicode DataFlavor to the transferable
     280               0 :           rv = AppendString(trans, textBuffer, kUnicodeMime);
     281               0 :           NS_ENSURE_SUCCESS(rv, rv);
     282                 :         }
     283                 :       }
     284                 : 
     285               0 :       if (doPutOnClipboard && clipboard) {
     286               0 :         bool actuallyPutOnClipboard = true;
     287               0 :         nsCopySupport::DoHooks(aDoc, trans, &actuallyPutOnClipboard);
     288                 : 
     289                 :         // put the transferable on the clipboard
     290               0 :         if (actuallyPutOnClipboard)
     291               0 :           clipboard->SetData(trans, nsnull, aClipboardID);
     292                 :       }
     293                 : 
     294                 :       // Return the transferable to the caller if requested.
     295               0 :       if (aTransferable != nsnull) {
     296               0 :         trans.swap(*aTransferable);
     297                 :       }
     298                 :     }
     299                 :   }
     300               0 :   return rv;
     301                 : }
     302                 : 
     303                 : nsresult
     304               0 : nsCopySupport::HTMLCopy(nsISelection* aSel, nsIDocument* aDoc,
     305                 :                         PRInt16 aClipboardID)
     306                 : {
     307                 :   return SelectionCopyHelper(aSel, aDoc, true, aClipboardID,
     308                 :                              nsIDocumentEncoder::SkipInvisibleContent,
     309               0 :                              nsnull);
     310                 : }
     311                 : 
     312                 : nsresult
     313               0 : nsCopySupport::GetTransferableForSelection(nsISelection* aSel,
     314                 :                                            nsIDocument* aDoc,
     315                 :                                            nsITransferable** aTransferable)
     316                 : {
     317                 :   return SelectionCopyHelper(aSel, aDoc, false, 0,
     318                 :                              nsIDocumentEncoder::SkipInvisibleContent,
     319               0 :                              aTransferable);
     320                 : }
     321                 : 
     322                 : nsresult
     323               0 : nsCopySupport::GetTransferableForNode(nsINode* aNode,
     324                 :                                       nsIDocument* aDoc,
     325                 :                                       nsITransferable** aTransferable)
     326                 : {
     327               0 :   nsCOMPtr<nsISelection> selection;
     328                 :   // Make a temporary selection with aNode in a single range.
     329               0 :   nsresult rv = NS_NewDomSelection(getter_AddRefs(selection));
     330               0 :   NS_ENSURE_SUCCESS(rv, rv);
     331               0 :   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
     332               0 :   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
     333               0 :   nsRefPtr<nsRange> range = new nsRange();
     334               0 :   rv = range->SelectNode(node);
     335               0 :   NS_ENSURE_SUCCESS(rv, rv);
     336               0 :   rv = selection->AddRange(range);
     337               0 :   NS_ENSURE_SUCCESS(rv, rv);
     338                 :   // It's not the primary selection - so don't skip invisible content.
     339               0 :   PRUint32 flags = 0;
     340                 :   return SelectionCopyHelper(selection, aDoc, false, 0, flags,
     341               0 :                              aTransferable);
     342                 : }
     343                 : 
     344               0 : nsresult nsCopySupport::DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
     345                 :                                 bool *aDoPutOnClipboard)
     346                 : {
     347               0 :   NS_ENSURE_ARG(aDoc);
     348                 : 
     349               0 :   *aDoPutOnClipboard = true;
     350                 : 
     351               0 :   nsCOMPtr<nsISupports> container = aDoc->GetContainer();
     352               0 :   nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(container);
     353               0 :   if (!hookObj) return NS_ERROR_FAILURE;
     354                 : 
     355               0 :   nsCOMPtr<nsISimpleEnumerator> enumerator;
     356               0 :   hookObj->GetHookEnumerator(getter_AddRefs(enumerator));
     357               0 :   if (!enumerator) return NS_ERROR_FAILURE;
     358                 : 
     359                 :   // the logic here should follow the behavior specified in
     360                 :   // nsIClipboardDragDropHooks.h
     361                 : 
     362               0 :   nsCOMPtr<nsIClipboardDragDropHooks> override;
     363               0 :   nsCOMPtr<nsISupports> isupp;
     364               0 :   bool hasMoreHooks = false;
     365               0 :   nsresult rv = NS_OK;
     366               0 :   while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
     367                 :          && hasMoreHooks)
     368                 :   {
     369               0 :     rv = enumerator->GetNext(getter_AddRefs(isupp));
     370               0 :     if (NS_FAILED(rv)) break;
     371               0 :     override = do_QueryInterface(isupp);
     372               0 :     if (override)
     373                 :     {
     374                 : #ifdef DEBUG
     375                 :       nsresult hookResult =
     376                 : #endif
     377               0 :       override->OnCopyOrDrag(nsnull, aTrans, aDoPutOnClipboard);
     378               0 :       NS_ASSERTION(NS_SUCCEEDED(hookResult), "OnCopyOrDrag hook failed");
     379               0 :       if (!*aDoPutOnClipboard)
     380               0 :         break;
     381                 :     }
     382                 :   }
     383                 : 
     384               0 :   return rv;
     385                 : }
     386                 : 
     387               0 : nsresult nsCopySupport::IsPlainTextContext(nsISelection *aSel, nsIDocument *aDoc, bool *aIsPlainTextContext)
     388                 : {
     389                 :   nsresult rv;
     390                 : 
     391               0 :   if (!aSel || !aIsPlainTextContext)
     392               0 :     return NS_ERROR_NULL_POINTER;
     393                 : 
     394               0 :   *aIsPlainTextContext = false;
     395                 :   
     396               0 :   nsCOMPtr<nsIDOMRange> range;
     397               0 :   nsCOMPtr<nsIDOMNode> commonParent;
     398               0 :   PRInt32 count = 0;
     399                 : 
     400               0 :   rv = aSel->GetRangeCount(&count);
     401               0 :   NS_ENSURE_SUCCESS(rv, rv);
     402                 : 
     403                 :   // if selection is uninitialized return
     404               0 :   if (!count)
     405               0 :     return NS_ERROR_FAILURE;
     406                 :   
     407                 :   // we'll just use the common parent of the first range.  Implicit assumption
     408                 :   // here that multi-range selections are table cell selections, in which case
     409                 :   // the common parent is somewhere in the table and we don't really care where.
     410               0 :   rv = aSel->GetRangeAt(0, getter_AddRefs(range));
     411               0 :   NS_ENSURE_SUCCESS(rv, rv);
     412               0 :   if (!range)
     413               0 :     return NS_ERROR_NULL_POINTER;
     414               0 :   range->GetCommonAncestorContainer(getter_AddRefs(commonParent));
     415                 : 
     416               0 :   for (nsCOMPtr<nsIContent> selContent(do_QueryInterface(commonParent));
     417               0 :        selContent;
     418               0 :        selContent = selContent->GetParent())
     419                 :   {
     420                 :     // checking for selection inside a plaintext form widget
     421                 : 
     422               0 :     if (!selContent->IsHTML()) {
     423               0 :       continue;
     424                 :     }
     425                 : 
     426               0 :     nsIAtom *atom = selContent->Tag();
     427                 : 
     428               0 :     if (atom == nsGkAtoms::input ||
     429                 :         atom == nsGkAtoms::textarea)
     430                 :     {
     431               0 :       *aIsPlainTextContext = true;
     432               0 :       break;
     433                 :     }
     434                 : 
     435               0 :     if (atom == nsGkAtoms::body)
     436                 :     {
     437                 :       // check for moz prewrap style on body.  If it's there we are 
     438                 :       // in a plaintext editor.  This is pretty cheezy but I haven't 
     439                 :       // found a good way to tell if we are in a plaintext editor.
     440               0 :       nsCOMPtr<nsIDOMElement> bodyElem = do_QueryInterface(selContent);
     441               0 :       nsAutoString wsVal;
     442               0 :       rv = bodyElem->GetAttribute(NS_LITERAL_STRING("style"), wsVal);
     443               0 :       if (NS_SUCCEEDED(rv) && (kNotFound != wsVal.Find(NS_LITERAL_STRING("pre-wrap"))))
     444                 :       {
     445               0 :         *aIsPlainTextContext = true;
     446                 :         break;
     447                 :       }
     448                 :     }
     449                 :   }
     450                 :   
     451                 :   // also consider ourselves in a text widget if we can't find an html
     452                 :   // document. Note that XHTML is not counted as HTML here, because we can't
     453                 :   // copy it properly (all the copy code for non-plaintext assumes using HTML
     454                 :   // serializers and parsers is OK, and those mess up XHTML).
     455               0 :   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDoc);
     456               0 :   if (!(htmlDoc && aDoc->IsHTML()))
     457               0 :     *aIsPlainTextContext = true;
     458                 : 
     459               0 :   return NS_OK;
     460                 : }
     461                 : 
     462                 : nsresult
     463               0 : nsCopySupport::GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata)
     464                 : {
     465               0 :   nsresult rv = NS_OK;
     466                 :   
     467               0 :   nsCOMPtr<nsIDocumentEncoder> docEncoder;
     468                 : 
     469               0 :   nsCAutoString encoderContractID(NS_DOC_ENCODER_CONTRACTID_BASE);
     470               0 :   encoderContractID.Append(aMimeType);
     471                 :     
     472               0 :   docEncoder = do_CreateInstance(encoderContractID.get());
     473               0 :   NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
     474                 : 
     475               0 :   PRUint32 flags = aFlags | nsIDocumentEncoder::SkipInvisibleContent;
     476                 :   
     477               0 :   if (aMimeType.Equals("text/plain"))
     478               0 :     flags |= nsIDocumentEncoder::OutputPreformatted;
     479                 : 
     480               0 :   NS_ConvertASCIItoUTF16 unicodeMimeType(aMimeType);
     481                 : 
     482               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
     483               0 :   NS_ASSERTION(domDoc, "Need a document");
     484                 : 
     485               0 :   rv = docEncoder->Init(domDoc, unicodeMimeType, flags);
     486               0 :   if (NS_FAILED(rv)) return rv;
     487                 :   
     488               0 :   if (aSel)
     489                 :   {
     490               0 :     rv = docEncoder->SetSelection(aSel);
     491               0 :     if (NS_FAILED(rv)) return rv;
     492                 :   } 
     493                 :   
     494                 :   // encode the selection
     495               0 :   return docEncoder->EncodeToString(outdata);
     496                 : }
     497                 : 
     498                 : 
     499                 : nsresult
     500               0 : nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
     501                 :                          PRInt32 aCopyFlags)
     502                 : {
     503                 :   nsresult rv;
     504                 : 
     505                 :   // create a transferable for putting data on the Clipboard
     506               0 :   nsCOMPtr<nsITransferable> trans(do_CreateInstance(kCTransferableCID, &rv));
     507               0 :   NS_ENSURE_SUCCESS(rv, rv);
     508                 : 
     509               0 :   if (aCopyFlags & nsIContentViewerEdit::COPY_IMAGE_TEXT) {
     510                 :     // get the location from the element
     511               0 :     nsCOMPtr<nsIURI> uri;
     512               0 :     rv = aImageElement->GetCurrentURI(getter_AddRefs(uri));
     513               0 :     NS_ENSURE_SUCCESS(rv, rv);
     514               0 :     NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
     515                 : 
     516               0 :     nsCAutoString location;
     517               0 :     rv = uri->GetSpec(location);
     518               0 :     NS_ENSURE_SUCCESS(rv, rv);
     519                 : 
     520                 :     // append the string to the transferable
     521               0 :     rv = AppendString(trans, NS_ConvertUTF8toUTF16(location), kUnicodeMime);
     522               0 :     NS_ENSURE_SUCCESS(rv, rv);
     523                 :   }
     524                 : 
     525               0 :   if (aCopyFlags & nsIContentViewerEdit::COPY_IMAGE_HTML) {
     526                 :     // append HTML data to the transferable
     527               0 :     nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aImageElement, &rv));
     528               0 :     NS_ENSURE_SUCCESS(rv, rv);
     529                 : 
     530               0 :     rv = AppendDOMNode(trans, node);
     531               0 :     NS_ENSURE_SUCCESS(rv, rv);
     532                 :   }
     533                 : 
     534               0 :   if (aCopyFlags & nsIContentViewerEdit::COPY_IMAGE_DATA) {
     535                 :     // get the image data from the element
     536                 :     nsCOMPtr<imgIContainer> image =
     537               0 :       nsContentUtils::GetImageFromContent(aImageElement);
     538               0 :     NS_ENSURE_TRUE(image, NS_ERROR_FAILURE);
     539                 : 
     540                 :     nsCOMPtr<nsISupportsInterfacePointer>
     541               0 :       imgPtr(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
     542               0 :     NS_ENSURE_SUCCESS(rv, rv);
     543                 : 
     544               0 :     rv = imgPtr->SetData(image);
     545               0 :     NS_ENSURE_SUCCESS(rv, rv);
     546                 : 
     547                 :     // copy the image data onto the transferable
     548               0 :     rv = trans->SetTransferData(kNativeImageMime, imgPtr,
     549               0 :                                 sizeof(nsISupports*));
     550               0 :     NS_ENSURE_SUCCESS(rv, rv);
     551                 :   }
     552                 : 
     553                 :   // get clipboard
     554               0 :   nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     555               0 :   NS_ENSURE_SUCCESS(rv, rv);
     556                 : 
     557                 :   // check whether the system supports the selection clipboard or not.
     558                 :   bool selectionSupported;
     559               0 :   rv = clipboard->SupportsSelectionClipboard(&selectionSupported);
     560               0 :   NS_ENSURE_SUCCESS(rv, rv);
     561                 : 
     562                 :   // put the transferable on the clipboard
     563               0 :   if (selectionSupported) {
     564               0 :     rv = clipboard->SetData(trans, nsnull, nsIClipboard::kSelectionClipboard);
     565               0 :     NS_ENSURE_SUCCESS(rv, rv);
     566                 :   }
     567                 : 
     568               0 :   return clipboard->SetData(trans, nsnull, nsIClipboard::kGlobalClipboard);
     569                 : }
     570                 : 
     571               0 : static nsresult AppendString(nsITransferable *aTransferable,
     572                 :                              const nsAString& aString,
     573                 :                              const char* aFlavor)
     574                 : {
     575                 :   nsresult rv;
     576                 : 
     577                 :   nsCOMPtr<nsISupportsString>
     578               0 :     data(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
     579               0 :   NS_ENSURE_SUCCESS(rv, rv);
     580                 : 
     581               0 :   rv = data->SetData(aString);
     582               0 :   NS_ENSURE_SUCCESS(rv, rv);
     583                 : 
     584               0 :   rv = aTransferable->AddDataFlavor(aFlavor);
     585               0 :   NS_ENSURE_SUCCESS(rv, rv);
     586                 : 
     587                 :   return aTransferable->SetTransferData(aFlavor, data,
     588               0 :                                         aString.Length() * sizeof(PRUnichar));
     589                 : }
     590                 : 
     591               0 : static nsresult AppendDOMNode(nsITransferable *aTransferable,
     592                 :                               nsIDOMNode *aDOMNode)
     593                 : {
     594                 :   nsresult rv;
     595                 :   
     596                 :   // selializer
     597                 :   nsCOMPtr<nsIDocumentEncoder>
     598               0 :     docEncoder(do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID, &rv));
     599               0 :   NS_ENSURE_SUCCESS(rv, rv);
     600                 : 
     601                 :   // get document for the encoder
     602               0 :   nsCOMPtr<nsIDOMDocument> domDocument;
     603               0 :   rv = aDOMNode->GetOwnerDocument(getter_AddRefs(domDocument));
     604               0 :   NS_ENSURE_SUCCESS(rv, rv);
     605               0 :   nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument, &rv));
     606               0 :   NS_ENSURE_SUCCESS(rv, rv);
     607                 : 
     608                 :   // Note that XHTML is not counted as HTML here, because we can't copy it
     609                 :   // properly (all the copy code for non-plaintext assumes using HTML
     610                 :   // serializers and parsers is OK, and those mess up XHTML).
     611               0 :   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(domDocument, &rv);
     612               0 :   NS_ENSURE_SUCCESS(rv, NS_OK);
     613                 : 
     614               0 :   NS_ENSURE_TRUE(document->IsHTML(), NS_OK);
     615                 : 
     616                 :   // init encoder with document and node
     617               0 :   rv = docEncoder->Init(domDocument, NS_LITERAL_STRING(kHTMLMime),
     618                 :                         nsIDocumentEncoder::OutputAbsoluteLinks |
     619               0 :                         nsIDocumentEncoder::OutputEncodeW3CEntities);
     620               0 :   NS_ENSURE_SUCCESS(rv, rv);
     621                 : 
     622               0 :   rv = docEncoder->SetNode(aDOMNode);
     623               0 :   NS_ENSURE_SUCCESS(rv, rv);
     624                 : 
     625                 :   // serialize to string
     626               0 :   nsAutoString html, context, info;
     627               0 :   rv = docEncoder->EncodeToStringWithContext(context, info, html);
     628               0 :   NS_ENSURE_SUCCESS(rv, rv);
     629                 : 
     630                 :   // copy them to the transferable
     631               0 :   if (!html.IsEmpty()) {
     632               0 :     rv = AppendString(aTransferable, html, kHTMLMime);
     633               0 :     NS_ENSURE_SUCCESS(rv, rv);
     634                 :   }
     635                 : 
     636               0 :   if (!info.IsEmpty()) {
     637               0 :     rv = AppendString(aTransferable, info, kHTMLInfo);
     638               0 :     NS_ENSURE_SUCCESS(rv, rv);
     639                 :   }
     640                 : 
     641                 :   // add a special flavor, even if we don't have html context data
     642               0 :   return AppendString(aTransferable, context, kHTMLContext);
     643                 : }
     644                 : 
     645                 : nsIContent*
     646               0 : nsCopySupport::GetSelectionForCopy(nsIDocument* aDocument, nsISelection** aSelection)
     647                 : {
     648               0 :   *aSelection = nsnull;
     649                 : 
     650               0 :   nsIPresShell* presShell = aDocument->GetShell();
     651               0 :   if (!presShell)
     652               0 :     return nsnull;
     653                 : 
     654                 :   // check if the focused node in the window has a selection
     655               0 :   nsCOMPtr<nsPIDOMWindow> focusedWindow;
     656                 :   nsIContent* content =
     657                 :     nsFocusManager::GetFocusedDescendant(aDocument->GetWindow(), false,
     658               0 :                                          getter_AddRefs(focusedWindow));
     659               0 :   if (content) {
     660               0 :     nsIFrame* frame = content->GetPrimaryFrame();
     661               0 :     if (frame) {
     662               0 :       nsCOMPtr<nsISelectionController> selCon;
     663               0 :       frame->GetSelectionController(presShell->GetPresContext(), getter_AddRefs(selCon));
     664               0 :       if (selCon) {
     665               0 :         selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);
     666               0 :         return content;
     667                 :       }
     668                 :     }
     669                 :   }
     670                 : 
     671                 :   // if no selection was found, use the main selection for the window
     672               0 :   NS_IF_ADDREF(*aSelection = presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL));
     673               0 :   return nsnull;
     674                 : }
     675                 : 
     676                 : bool
     677               0 : nsCopySupport::CanCopy(nsIDocument* aDocument)
     678                 : {
     679               0 :   if (!aDocument)
     680               0 :     return false;
     681                 : 
     682               0 :   nsCOMPtr<nsISelection> sel;
     683               0 :   GetSelectionForCopy(aDocument, getter_AddRefs(sel));
     684               0 :   NS_ENSURE_TRUE(sel, false);
     685                 : 
     686                 :   bool isCollapsed;
     687               0 :   sel->GetIsCollapsed(&isCollapsed);
     688               0 :   return !isCollapsed;
     689                 : }
     690                 : 
     691                 : bool
     692               0 : nsCopySupport::FireClipboardEvent(PRInt32 aType, nsIPresShell* aPresShell, nsISelection* aSelection)
     693                 : {
     694               0 :   NS_ASSERTION(aType == NS_CUT || aType == NS_COPY || aType == NS_PASTE,
     695                 :                "Invalid clipboard event type");
     696                 : 
     697               0 :   nsCOMPtr<nsIPresShell> presShell = aPresShell;
     698               0 :   if (!presShell)
     699               0 :     return false;
     700                 : 
     701               0 :   nsCOMPtr<nsIDocument> doc = presShell->GetDocument();
     702               0 :   if (!doc)
     703               0 :     return false;
     704                 : 
     705               0 :   nsCOMPtr<nsPIDOMWindow> piWindow = doc->GetWindow();
     706               0 :   if (!piWindow)
     707               0 :     return false;
     708                 : 
     709                 :   // if a selection was not supplied, try to find it
     710               0 :   nsCOMPtr<nsIContent> content;
     711               0 :   nsCOMPtr<nsISelection> sel = aSelection;
     712               0 :   if (!sel)
     713               0 :     content = GetSelectionForCopy(doc, getter_AddRefs(sel));
     714                 : 
     715                 :   // retrieve the event target node from the start of the selection
     716               0 :   if (sel) {
     717                 :     // Only cut or copy when there is an uncollapsed selection
     718               0 :     if (aType == NS_CUT || aType == NS_COPY) {
     719                 :       bool isCollapsed;
     720               0 :       sel->GetIsCollapsed(&isCollapsed);
     721               0 :       if (isCollapsed)
     722               0 :         return false;
     723                 :     }
     724                 : 
     725               0 :     nsCOMPtr<nsIDOMRange> range;
     726               0 :     nsresult rv = sel->GetRangeAt(0, getter_AddRefs(range));
     727               0 :     if (NS_SUCCEEDED(rv) && range) {
     728               0 :       nsCOMPtr<nsIDOMNode> startContainer;
     729               0 :       range->GetStartContainer(getter_AddRefs(startContainer));
     730               0 :       if (startContainer)
     731               0 :         content = do_QueryInterface(startContainer);
     732                 :     }
     733                 :   }
     734                 : 
     735                 :   // if no content node was set, just get the root
     736               0 :   if (!content) {
     737               0 :     content = doc->GetRootElement();
     738               0 :     if (!content)
     739               0 :       return false;
     740                 :   }
     741                 : 
     742                 :   // It seems to be unsafe to fire an event handler during reflow (bug 393696)
     743               0 :   if (!nsContentUtils::IsSafeToRunScript())
     744               0 :     return false;
     745                 : 
     746                 :   // next, fire the cut or copy event
     747               0 :   if (Preferences::GetBool("dom.event.clipboardevents.enabled", true)) {
     748               0 :     nsEventStatus status = nsEventStatus_eIgnore;
     749               0 :     nsEvent evt(true, aType);
     750                 :     nsEventDispatcher::Dispatch(content, presShell->GetPresContext(), &evt, nsnull,
     751               0 :                                 &status);
     752                 :     // if the event was cancelled, don't do the clipboard operation
     753               0 :     if (status == nsEventStatus_eConsumeNoDefault)
     754               0 :       return false;
     755                 :   }
     756                 :   
     757               0 :   if (presShell->IsDestroying())
     758               0 :     return false;
     759                 : 
     760                 :   // No need to do anything special during a paste. Either an event listener
     761                 :   // took care of it and cancelled the event, or the caller will handle it.
     762                 :   // Return true to indicate the event wasn't cancelled.
     763               0 :   if (aType == NS_PASTE)
     764               0 :     return true;
     765                 : 
     766                 :   // Update the presentation in case the event handler modified the selection,
     767                 :   // see bug 602231.
     768               0 :   presShell->FlushPendingNotifications(Flush_Frames);
     769               0 :   if (presShell->IsDestroying())
     770               0 :     return false;
     771                 : 
     772                 :   // call the copy code
     773               0 :   if (NS_FAILED(nsCopySupport::HTMLCopy(sel, doc, nsIClipboard::kGlobalClipboard)))
     774               0 :     return false;
     775                 : 
     776                 :   // Now that we have copied, update the clipboard commands. This should have
     777                 :   // the effect of updating the paste menu item.
     778               0 :   piWindow->UpdateCommands(NS_LITERAL_STRING("clipboard"));
     779                 : 
     780               0 :   return true;
     781                 : }

Generated by: LCOV version 1.7