widget/cocoa/nsDragService.mm

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifdef MOZ_LOGGING
     7 #define FORCE_PR_LOG
     8 #endif
     9 #include "prlog.h"
    11 #include "nsDragService.h"
    12 #include "nsObjCExceptions.h"
    13 #include "nsITransferable.h"
    14 #include "nsString.h"
    15 #include "nsClipboard.h"
    16 #include "nsXPCOM.h"
    17 #include "nsISupportsPrimitives.h"
    18 #include "nsCOMPtr.h"
    19 #include "nsPrimitiveHelpers.h"
    20 #include "nsLinebreakConverter.h"
    21 #include "nsIMacUtils.h"
    22 #include "nsIDOMNode.h"
    23 #include "nsRect.h"
    24 #include "nsPoint.h"
    25 #include "nsIIOService.h"
    26 #include "nsNetUtil.h"
    27 #include "nsIDocument.h"
    28 #include "nsIContent.h"
    29 #include "nsView.h"
    30 #include "gfxContext.h"
    31 #include "nsCocoaUtils.h"
    32 #include "mozilla/gfx/2D.h"
    33 #include "gfxPlatform.h"
    35 using namespace mozilla;
    36 using namespace mozilla::gfx;
    38 #ifdef PR_LOGGING
    39 extern PRLogModuleInfo* sCocoaLog;
    40 #endif
    42 extern void EnsureLogInitialized();
    44 extern NSPasteboard* globalDragPboard;
    45 extern NSView* gLastDragView;
    46 extern NSEvent* gLastDragMouseDownEvent;
    47 extern bool gUserCancelledDrag;
    49 // This global makes the transferable array available to Cocoa's promised
    50 // file destination callback.
    51 nsISupportsArray *gDraggedTransferables = nullptr;
    53 NSString* const kWildcardPboardType = @"MozillaWildcard";
    54 NSString* const kCorePboardType_url  = @"CorePasteboardFlavorType 0x75726C20"; // 'url '  url
    55 NSString* const kCorePboardType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld'  desc
    56 NSString* const kCorePboardType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln'  title
    58 nsDragService::nsDragService()
    59 {
    60   mNativeDragView = nil;
    61   mNativeDragEvent = nil;
    63   EnsureLogInitialized();
    64 }
    66 nsDragService::~nsDragService()
    67 {
    68 }
    70 static nsresult SetUpDragClipboard(nsISupportsArray* aTransferableArray)
    71 {
    72   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
    74   if (!aTransferableArray)
    75     return NS_ERROR_FAILURE;
    77   uint32_t count = 0;
    78   aTransferableArray->Count(&count);
    80   NSPasteboard* dragPBoard = [NSPasteboard pasteboardWithName:NSDragPboard];
    82   for (uint32_t i = 0; i < count; i++) {
    83     nsCOMPtr<nsISupports> currentTransferableSupports;
    84     aTransferableArray->GetElementAt(i, getter_AddRefs(currentTransferableSupports));
    85     if (!currentTransferableSupports)
    86       return NS_ERROR_FAILURE;
    88     nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
    89     if (!currentTransferable)
    90       return NS_ERROR_FAILURE;
    92     // Transform the transferable to an NSDictionary
    93     NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(currentTransferable);
    94     if (!pasteboardOutputDict)
    95       return NS_ERROR_FAILURE;
    97     // write everything out to the general pasteboard
    98     unsigned int typeCount = [pasteboardOutputDict count];
    99     NSMutableArray* types = [NSMutableArray arrayWithCapacity:typeCount + 1];
   100     [types addObjectsFromArray:[pasteboardOutputDict allKeys]];
   101     // Gecko is initiating this drag so we always want its own views to consider
   102     // it. Add our wildcard type to the pasteboard to accomplish this.
   103     [types addObject:kWildcardPboardType]; // we don't increase the count for the loop below on purpose
   104     [dragPBoard declareTypes:types owner:nil];
   105     for (unsigned int i = 0; i < typeCount; i++) {
   106       NSString* currentKey = [types objectAtIndex:i];
   107       id currentValue = [pasteboardOutputDict valueForKey:currentKey];
   108       if (currentKey == NSStringPboardType ||
   109           currentKey == kCorePboardType_url ||
   110           currentKey == kCorePboardType_urld ||
   111           currentKey == kCorePboardType_urln) {
   112         [dragPBoard setString:currentValue forType:currentKey];
   113       }
   114       else if (currentKey == NSHTMLPboardType) {
   115         [dragPBoard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
   116                       forType:currentKey];
   117       }
   118       else if (currentKey == NSTIFFPboardType) {
   119         [dragPBoard setData:currentValue forType:currentKey];
   120       }
   121       else if (currentKey == NSFilesPromisePboardType ||
   122                currentKey == NSFilenamesPboardType) {
   123         [dragPBoard setPropertyList:currentValue forType:currentKey];        
   124       }
   125     }
   126   }
   128   return NS_OK;
   130   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
   131 }
   133 NSImage*
   134 nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode,
   135                                   nsIntRect* aDragRect,
   136                                   nsIScriptableRegion* aRegion)
   137 {
   138   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
   140   NSPoint screenPoint =
   141     [[gLastDragView window] convertBaseToScreen:
   142       [gLastDragMouseDownEvent locationInWindow]];
   143   // Y coordinates are bottom to top, so reverse this
   144   screenPoint.y = nsCocoaUtils::FlippedScreenY(screenPoint.y);
   146   CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
   148   RefPtr<SourceSurface> surface;
   149   nsPresContext* pc;
   150   nsresult rv = DrawDrag(aDOMNode, aRegion,
   151                          NSToIntRound(screenPoint.x),
   152                          NSToIntRound(screenPoint.y),
   153                          aDragRect, &surface, &pc);
   154   if (!aDragRect->width || !aDragRect->height) {
   155     // just use some suitable defaults
   156     int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor);
   157     aDragRect->SetRect(nsCocoaUtils::CocoaPointsToDevPixels(screenPoint.x, scaleFactor),
   158                        nsCocoaUtils::CocoaPointsToDevPixels(screenPoint.y, scaleFactor),
   159                        size, size);
   160   }
   162   if (NS_FAILED(rv) || !surface)
   163     return nil;
   165   uint32_t width = aDragRect->width;
   166   uint32_t height = aDragRect->height;
   168   nsRefPtr<gfxImageSurface> imgSurface = new gfxImageSurface(
   169     gfxIntSize(width, height), gfxImageFormat::ARGB32);
   170   if (!imgSurface)
   171     return nil;
   173   RefPtr<DrawTarget> dt =
   174     gfxPlatform::GetPlatform()->
   175       CreateDrawTargetForSurface(imgSurface, IntSize(width, height));
   176   if (!dt)
   177     return nil;
   179   dt->FillRect(gfx::Rect(0, 0, width, height),
   180                SurfacePattern(surface, ExtendMode::CLAMP),
   181                DrawOptions(1.0f, CompositionOp::OP_SOURCE));
   183   uint32_t* imageData = (uint32_t*)imgSurface->Data();
   184   int32_t stride = imgSurface->Stride();
   186   NSBitmapImageRep* imageRep =
   187     [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
   188                                             pixelsWide:width
   189                                             pixelsHigh:height
   190                                          bitsPerSample:8
   191                                        samplesPerPixel:4
   192                                               hasAlpha:YES
   193                                               isPlanar:NO
   194                                         colorSpaceName:NSDeviceRGBColorSpace
   195                                            bytesPerRow:width * 4
   196                                           bitsPerPixel:32];
   198   uint8_t* dest = [imageRep bitmapData];
   199   for (uint32_t i = 0; i < height; ++i) {
   200     uint8_t* src = (uint8_t *)imageData + i * stride;
   201     for (uint32_t j = 0; j < width; ++j) {
   202       // Reduce transparency overall by multipying by a factor. Remember, Alpha
   203       // is premultipled here. Also, Quartz likes RGBA, so do that translation as well.
   204 #ifdef IS_BIG_ENDIAN
   205       dest[0] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
   206       dest[1] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
   207       dest[2] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
   208       dest[3] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
   209 #else
   210       dest[0] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
   211       dest[1] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
   212       dest[2] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
   213       dest[3] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
   214 #endif
   215       src += 4;
   216       dest += 4;
   217     }
   218   }
   220   NSImage* image =
   221     [[NSImage alloc] initWithSize:NSMakeSize(width / scaleFactor,
   222                                              height / scaleFactor)];
   223   [image addRepresentation:imageRep];
   224   [imageRep release];
   226   return [image autorelease];
   228   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
   229 }
   231 // We can only invoke NSView's 'dragImage:at:offset:event:pasteboard:source:slideBack:' from
   232 // within NSView's 'mouseDown:' or 'mouseDragged:'. Luckily 'mouseDragged' is always on the
   233 // stack when InvokeDragSession gets called.
   234 NS_IMETHODIMP
   235 nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransferableArray,
   236                                  nsIScriptableRegion* aDragRgn, uint32_t aActionType)
   237 {
   238   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
   240   nsresult rv = nsBaseDragService::InvokeDragSession(aDOMNode,
   241                                                      aTransferableArray,
   242                                                      aDragRgn, aActionType);
   243   NS_ENSURE_SUCCESS(rv, rv);
   245   mDataItems = aTransferableArray;
   247   // put data on the clipboard
   248   if (NS_FAILED(SetUpDragClipboard(aTransferableArray)))
   249     return NS_ERROR_FAILURE;
   251   nsIntRect dragRect(0, 0, 20, 20);
   252   NSImage* image = ConstructDragImage(aDOMNode, &dragRect, aDragRgn);
   253   if (!image) {
   254     // if no image was returned, just draw a rectangle
   255     NSSize size;
   256     size.width = dragRect.width;
   257     size.height = dragRect.height;
   258     image = [[NSImage alloc] initWithSize:size];
   259     [image lockFocus];
   260     [[NSColor grayColor] set];
   261     NSBezierPath* path = [NSBezierPath bezierPath];
   262     [path setLineWidth:2.0];
   263     [path moveToPoint:NSMakePoint(0, 0)];
   264     [path lineToPoint:NSMakePoint(0, size.height)];
   265     [path lineToPoint:NSMakePoint(size.width, size.height)];
   266     [path lineToPoint:NSMakePoint(size.width, 0)];
   267     [path lineToPoint:NSMakePoint(0, 0)];
   268     [path stroke];
   269     [image unlockFocus];
   270   }
   272   nsIntPoint pt(dragRect.x, dragRect.YMost());
   273   CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView);
   274   NSPoint point = nsCocoaUtils::DevPixelsToCocoaPoints(pt, scaleFactor);
   275   point.y = nsCocoaUtils::FlippedScreenY(point.y);
   277   point = [[gLastDragView window] convertScreenToBase: point];
   278   NSPoint localPoint = [gLastDragView convertPoint:point fromView:nil];
   280   // Save the transferables away in case a promised file callback is invoked.
   281   gDraggedTransferables = aTransferableArray;
   283   nsBaseDragService::StartDragSession();
   284   nsBaseDragService::OpenDragPopup();
   286   // We need to retain the view and the event during the drag in case either gets destroyed.
   287   mNativeDragView = [gLastDragView retain];
   288   mNativeDragEvent = [gLastDragMouseDownEvent retain];
   290   gUserCancelledDrag = false;
   291   [mNativeDragView dragImage:image
   292                           at:localPoint
   293                       offset:NSZeroSize
   294                        event:mNativeDragEvent
   295                   pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
   296                       source:mNativeDragView
   297                    slideBack:YES];
   298   gUserCancelledDrag = false;
   300   if (mDoingDrag)
   301     nsBaseDragService::EndDragSession(false);
   303   return NS_OK;
   305   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
   306 }
   308 NS_IMETHODIMP
   309 nsDragService::GetData(nsITransferable* aTransferable, uint32_t aItemIndex)
   310 {
   311   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
   313   if (!aTransferable)
   314     return NS_ERROR_FAILURE;
   316   // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
   317   nsCOMPtr<nsISupportsArray> flavorList;
   318   nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
   319   if (NS_FAILED(rv))
   320     return NS_ERROR_FAILURE;
   322   uint32_t acceptableFlavorCount;
   323   flavorList->Count(&acceptableFlavorCount);
   325   // if this drag originated within Mozilla we should just use the cached data from
   326   // when the drag started if possible
   327   if (mDataItems) {
   328     nsCOMPtr<nsISupports> currentTransferableSupports;
   329     mDataItems->GetElementAt(aItemIndex, getter_AddRefs(currentTransferableSupports));
   330     if (currentTransferableSupports) {
   331       nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
   332       if (currentTransferable) {
   333         for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
   334           nsCOMPtr<nsISupports> genericFlavor;
   335           flavorList->GetElementAt(i, getter_AddRefs(genericFlavor));
   336           nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
   337           if (!currentFlavor)
   338             continue;
   339           nsXPIDLCString flavorStr;
   340           currentFlavor->ToString(getter_Copies(flavorStr));
   342           nsCOMPtr<nsISupports> dataSupports;
   343           uint32_t dataSize = 0;
   344           rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
   345           if (NS_SUCCEEDED(rv)) {
   346             aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
   347             return NS_OK; // maybe try to fill in more types? Is there a point?
   348           }
   349         }
   350       }
   351     }
   352   }
   354   // now check the actual clipboard for data
   355   for (uint32_t i = 0; i < acceptableFlavorCount; i++) {
   356     nsCOMPtr<nsISupports> genericFlavor;
   357     flavorList->GetElementAt(i, getter_AddRefs(genericFlavor));
   358     nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
   360     if (!currentFlavor)
   361       continue;
   363     nsXPIDLCString flavorStr;
   364     currentFlavor->ToString(getter_Copies(flavorStr));
   366     PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("nsDragService::GetData: looking for clipboard data of type %s\n", flavorStr.get()));
   368     if (flavorStr.EqualsLiteral(kFileMime)) {
   369       NSArray* pFiles = [globalDragPboard propertyListForType:NSFilenamesPboardType];
   370       if (!pFiles || [pFiles count] < (aItemIndex + 1))
   371         continue;
   373       NSString* filePath = [pFiles objectAtIndex:aItemIndex];
   374       if (!filePath)
   375         continue;
   377       unsigned int stringLength = [filePath length];
   378       unsigned int dataLength = (stringLength + 1) * sizeof(char16_t); // in bytes
   379       char16_t* clipboardDataPtr = (char16_t*)malloc(dataLength);
   380       if (!clipboardDataPtr)
   381         return NS_ERROR_OUT_OF_MEMORY;
   382       [filePath getCharacters:reinterpret_cast<unichar*>(clipboardDataPtr)];
   383       clipboardDataPtr[stringLength] = 0; // null terminate
   385       nsCOMPtr<nsIFile> file;
   386       nsresult rv = NS_NewLocalFile(nsDependentString(clipboardDataPtr), true, getter_AddRefs(file));
   387       free(clipboardDataPtr);
   388       if (NS_FAILED(rv))
   389         continue;
   391       aTransferable->SetTransferData(flavorStr, file, dataLength);
   393       break;
   394     }
   396     NSString *pboardType = NSStringPboardType;
   398     if (nsClipboard::IsStringType(flavorStr, &pboardType) ||
   399         flavorStr.EqualsLiteral(kURLMime) ||
   400         flavorStr.EqualsLiteral(kURLDataMime) ||
   401         flavorStr.EqualsLiteral(kURLDescriptionMime)) {
   402       NSString* pString = [globalDragPboard stringForType:pboardType];
   403       if (!pString)
   404         continue;
   406       NSData* stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding];
   407       unsigned int dataLength = [stringData length];
   408       void* clipboardDataPtr = malloc(dataLength);
   409       if (!clipboardDataPtr)
   410         return NS_ERROR_OUT_OF_MEMORY;
   411       [stringData getBytes:clipboardDataPtr];
   413       // The DOM only wants LF, so convert from MacOS line endings to DOM line endings.
   414       int32_t signedDataLength = dataLength;
   415       nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength);
   416       dataLength = signedDataLength;
   418       // skip BOM (Byte Order Mark to distinguish little or big endian)      
   419       char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr;
   420       if ((dataLength > 2) &&
   421           ((clipboardDataPtrNoBOM[0] == 0xFEFF) ||
   422            (clipboardDataPtrNoBOM[0] == 0xFFFE))) {
   423         dataLength -= sizeof(char16_t);
   424         clipboardDataPtrNoBOM += 1;
   425       }
   427       nsCOMPtr<nsISupports> genericDataWrapper;
   428       nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
   429                                                  getter_AddRefs(genericDataWrapper));
   430       aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
   431       free(clipboardDataPtr);
   432       break;
   433     }
   435     // We have never supported this on Mac OS X, we should someday. Normally dragging images
   436     // in is accomplished with a file path drag instead of the image data itself.
   437     /*
   438     if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) ||
   439         flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime)) {
   441     }
   442     */
   443   }
   444   return NS_OK;
   446   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
   447 }
   449 NS_IMETHODIMP
   450 nsDragService::IsDataFlavorSupported(const char *aDataFlavor, bool *_retval)
   451 {
   452   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
   454   *_retval = false;
   456   if (!globalDragPboard)
   457     return NS_ERROR_FAILURE;
   459   nsDependentCString dataFlavor(aDataFlavor);
   461   // first see if we have data for this in our cached transferable
   462   if (mDataItems) {
   463     uint32_t dataItemsCount;
   464     mDataItems->Count(&dataItemsCount);
   465     for (unsigned int i = 0; i < dataItemsCount; i++) {
   466       nsCOMPtr<nsISupports> currentTransferableSupports;
   467       mDataItems->GetElementAt(i, getter_AddRefs(currentTransferableSupports));
   468       if (!currentTransferableSupports)
   469         continue;
   471       nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
   472       if (!currentTransferable)
   473         continue;
   475       nsCOMPtr<nsISupportsArray> flavorList;
   476       nsresult rv = currentTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
   477       if (NS_FAILED(rv))
   478         continue;
   480       uint32_t flavorCount;
   481       flavorList->Count(&flavorCount);
   482       for (uint32_t j = 0; j < flavorCount; j++) {
   483         nsCOMPtr<nsISupports> genericFlavor;
   484         flavorList->GetElementAt(j, getter_AddRefs(genericFlavor));
   485         nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
   486         if (!currentFlavor)
   487           continue;
   488         nsXPIDLCString flavorStr;
   489         currentFlavor->ToString(getter_Copies(flavorStr));
   490         if (dataFlavor.Equals(flavorStr)) {
   491           *_retval = true;
   492           return NS_OK;
   493         }
   494       }
   495     }
   496   }
   498   NSString *pboardType = nil;
   500   if (dataFlavor.EqualsLiteral(kFileMime)) {
   501     NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObject:NSFilenamesPboardType]];
   502     if (availableType && [availableType isEqualToString:NSFilenamesPboardType])
   503       *_retval = true;
   504   }
   505   else if (dataFlavor.EqualsLiteral(kURLMime)) {
   506     NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObject:kCorePboardType_url]];
   507     if (availableType && [availableType isEqualToString:kCorePboardType_url])
   508       *_retval = true;
   509   }
   510   else if (nsClipboard::IsStringType(dataFlavor, &pboardType)) {
   511     NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObject:pboardType]];
   512     if (availableType && [availableType isEqualToString:pboardType])
   513       *_retval = true;
   514   }
   516   return NS_OK;
   518   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
   519 }
   521 NS_IMETHODIMP
   522 nsDragService::GetNumDropItems(uint32_t* aNumItems)
   523 {
   524   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
   526   *aNumItems = 0;
   528   // first check to see if we have a number of items cached
   529   if (mDataItems) {
   530     mDataItems->Count(aNumItems);
   531     return NS_OK;
   532   }
   534   // if there is a clipboard and there is something on it, then there is at least 1 item
   535   NSArray* clipboardTypes = [globalDragPboard types];
   536   if (globalDragPboard && [clipboardTypes count] > 0)
   537     *aNumItems = 1;
   538   else 
   539     return NS_OK;
   541   // if there is a list of files, send the number of files in that list
   542   NSArray* fileNames = [globalDragPboard propertyListForType:NSFilenamesPboardType];
   543   if (fileNames)
   544     *aNumItems = [fileNames count];
   546   return NS_OK;
   548   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
   549 }
   551 NS_IMETHODIMP
   552 nsDragService::EndDragSession(bool aDoneDrag)
   553 {
   554   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
   556   if (mNativeDragView) {
   557     [mNativeDragView release];
   558     mNativeDragView = nil;
   559   }
   560   if (mNativeDragEvent) {
   561     [mNativeDragEvent release];
   562     mNativeDragEvent = nil;
   563   }
   565   mUserCancelled = gUserCancelledDrag;
   567   nsresult rv = nsBaseDragService::EndDragSession(aDoneDrag);
   568   mDataItems = nullptr;
   569   return rv;
   571   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
   572 }

mercurial