mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 22:28:36 +00:00
8637eba4b3
- remove poisondata stuff (cf5b5d29e5) - Bug 1218488 - clarify buffer ownership for nsICanvasRenderingContextInternal::GetBuffer; r=Bas,baku (dba4272b73) - Bug 1167215 - Re-apply CompositeUntil calls when we get a new batch of textures. r=roc (d57a8ac9e9) - Bug 1220923 - Make nsIntRegion a typedef for IntRegionTyped<UnknownUnits>. r=nical (a5f4e1e283) - Bug 1220898 - Make nsIntMargin a typedef for mozilla::gfx::IntMargin. r=nical (8bdb2f191a) - Bug 1205913 - Differentiate YCbCr, NV12 and RGB textures when drawing layer borders. r=nical (ff5d3dc7df) - Bug 1203376 - Honor filter region settings for lighting filters. r=mstange (8d0565e99a) - Bug 1220512 - ensure next frame status is updated before notifying MediaDecoder::PlaybackEnded. See bug 1220512 comment 1 for the detail. r=cpearce. (c2f434b5d4) - Bug 1207964 - Remove workaround from bug 1080461. r=jwwang (19bff98c14) - Bug 1199904: Only start decoding ahead after explicitly requesting data. r=gerald (8712637b49) - Bug 1197664: Report the total number of decoded frames. CLOSED TREE r=kentuckyfriedtakahe (422827d1af) - Bug 1178596: Reset frame size queue after flushing. r=cpearce (dd40ac4e6b) - Bug 1205911: P1. Cancel pending demux request when searching for next keyframe. r=edwin (8a03e6904f) - Bug 1188313: P1. Attempt to seek audio near video. r=cpearce (a8b6465d97) - Bug 1205911: P2. Ensure demuxer is reset before performing a seek. r=edwin (e93534a1d1) - bit of Bug 1185886: P2 (c2e89be4a3) - bit of Bug 1211443 (98fbb4a4a2) - Bug 1089586: Abort pending seeks. r=jwwang (e81f453204) - Bug 1195094: P1. Properly detects SPS changes for decoders requiring Annex B. r=cpearce (976febcd7c) - Bug 1195094: P2. Ensure TrackInfo object passed to constructor is never modified. r=cpearce (d5c15b2368) - Bug 1218577: Use only Blank PDM if enabled. r=kamidphish (a7e06549cc) - Bug 1210231 - Enable unencrypted <video> playback using Adobe's GMP for decoding. r=jya (7f80702b89) - Bug 1214932 - Add media.wmf.enabled pref. r=jya (8c183c0dd1) - Bug 1213173: Always use FFmpeg regardless of version. r=kentuckyfriedtakahe (e5af2c0c91) - Bug 1211787 - Improve the accuracy of MediaDecoderStateMachine::GetDecodedAudioDuration(). r=roc. (16d755c555) - Bug 1193614 - Schedule State Machine when VideoQueue() is low. r=cpearce (fe608da5fd) - Bug 1219984. Part 1 - remove EventPassMode::Both. In order to support multiple arguments, all arguments must be either moved or copied. r=kinetik. (2ee049008c) - Bug 1219984. Part 2 - add support for multiple arguments. r=kinetik. (1c70d5d69b) - Bug 1219974 - Add DisconnectIfExists() to MediaEventListener. r=kinetik. (43f6ae90b0) - Bug 1192109 - Fix insufficient includes in MediaEventSource.h. r=kinetik. (09eca240a1) - mData, aData (5e87f70853) - Bug 1219330 - Handle PlanaYCbCrImage::SetData failure. r=jya, jesup (144f3c266f) - Bug 1222308. Assume frames that are very old will never be composited. r=nical (1da9be2527) - space (45b67caa85) - Bug 1182426 - Set PlanarYCbCrImage's size in VP8TrackEncoder GTest. r=roc (d70a4d20c4) - Bug 1217080. Move recycling functionality into RecyclingPlanarYCbCrImage. r=nical (e2b2f650d7) - Bug 1216644 - part 1 - simple s/nsAutoArrayPtr/UniquePtr/ changes in gfx/; r=jrmuizel (d19bc51f94) - Bug 1216644 - part 2 - make gfxFontEntry::mUVSData a UniquePtr; r=jrmuizel (605a1bc6b1) - Bug 1216644 - part 3 - make BufferRecycleBin store UniquePtrs; r=jrmuizel (7781281266) - Add an RAII class to lock and unlock textures. (bug 1222863 part 1, r=nical) (abdec485f3) - Use RAII for more TextureClient locking cases. (bug 1222863 part 2, r=nical) (b35486ed3d) - Bug 1212288 - Make ImageContainer::AllocateProducerID callable on all threads; r=roc (fc569b8e48) - Bug 1140947 - Correct some logging in SourceBufferResource.cpp. r=cajbir (fcbb38056c) - Bug 1199573: [MSE] Properly handle partial media header received prior a discontinuity. r=gerald (f1cda54fa3) - Bug 1213726 - Remove AbstractMediaDecoder::HasInitializationData(). r=kinetik. (62f09f816e) - Bug 1034081 - Never seek before startTime. r=rillian Only adjust seek target up to startTime (44139b20ec) - Bug 1196353 - Use standard Xiph extradata format to pass headers from demuxers to decoders. r=jya (41f8dee5af) - Bug 1202332 - XiphExtradataToHeaders miscalculates final header length. r=derf (eec20f90f0) - Bug 1208799: [webm] Use first track found. r=kinetik (7196355e31) - Bug 1190472 - part 1 - improve MediaRawDataQueue's reference-counting behavior; r=kinetik (47b066b8e8) - Bug 1190472 - part 2 - delete unused MediaRawDataQueue::Push method; r=kinetik (f8246efe1b) - Bug 1190472 - part 3 - optimize pushing an entire queue onto MediaRawDataQueue; r=kinetik (045b389bf8) - Bug 1213024 - Comment the structured clone reading and writing, r=fitzgen (1b64f9f502) - Bug 1201620 - Make SavedFrame stacks structured cloneable; r=sfink (87e9b0a04b) - Bug 1221456 - Avoid C4819 warning spam. r=glandium (3dde3cb10a) - Bug 1213752 - IonMonkey: MIPS: Enable MIPS64 support. r=glandium (36da4cbd99) - Bug 1214175 - Make hash table manipulation infallible in Shape::fixupGetterSetterForBarrier() r=terrence (98e5e601ec) - Bug 1215337 - Cache slotSpan(), r=terrence (3e992f9f06) - No Bug - Include jswin.h in jsobj.cpp to unbreak windows non-unified bustage. (r=terrence over IRC) (92cba3254f) - Bug 1052139 - Make prototype-setting first create Object.prototype so that subsequent prototype chain-splicing will work correctly. r=bz (34a8d00d9f) - Bug 1172076 - Improve js::DumpBacktrace to include raw frame pointers and types. r=jandem (f11eb1763b) - Bug 1052139 - Change the boolean constant controlling whether the global object prototype chain is immutable, to enable immutable-prototype enforcement generally. r=duh (b7a1124feb) - Bug 1215363 - Fix a couple of OOM handling issues and make JS_sprintf funcions crash when passed illegal format strings r=terrence (c778891dd3) - Bug 1211331 - Ensure that GC slices are terminated such that we can safely iterate the heap. r=terrence (440308a333) - Bug 1224048 - Use stable hashing for the temporary tables in the JSON parser; r=jonco (7d058f44c9) - Bug 1215678 - Nuke cross compartment wrappers if we fail to add them to the wrapper map r=terrence (8e9e535a11) - Bug 1200732 - Use stable hashing for AutoCycleDetectorSet; r=jonco (68237bdea4) - more poisondata removal (6479b20220) - Bug 1218488 - clarify buffer ownership for nsICanvasRenderingContextInternal::GetBuffer; r=Bas,baku (ae89d929b2) - Bug 1207378 (Part 1) - Add support for a frame rect to Downscaler. r=tn (234866c32f) - Bug 1207378 (Part 2) - Use Downscaler to remove first-frame padding when downscaling GIFs. r=tn (5e995bdca2) - Bug 1207378 - Add FrameRect to non-skia version of BeginFrame. r=seth (939f0510eb) - Bug 1204394 (part 1) - Using StreamingLexer in the BMP decoder. r=seth. (77eaa1e125) - Bug 1204394 (part 2) - Add bmpsuite to the BMP reftests. r=seth. (237a902461) - Bug 1214476 - Remove unused code for encoding BMPv2 files. r=seth. (b8382357d7) - Bug 1213613 (part 1) - Formatting cleanups for nsBMPEncoder.h. r=seth. (4ee65bc173) - Bug 1213613 (part 2) - Move some BMP-related structs. r=seth. (15289784ce) - Bug 1215156 - move SetPixel* functions into nsBMPDecoder.cpp; r=seth (a143c843d4) - Bug 1215763 - part 1 - remove unnecessary nsAutoPtr.h includes; r=seth (f8a3a1f6b0) - Bug 1180715 (1/4) - Track image LoadTime to compare with file mtime. review=seth (bdbd25752c) - Bug 1180715 (2/4) - Provide a nsIFileURL interface for thumbnails. review=ttaubert (24c506569d) - Bug 1147562 - Update remaining callsites of newChannel before landing the shim in toolkit/ (r=gijs) (f7f2ab798f) - Bug 1163866 - Set originalURI correctly for moz-page-thumb:// channels. r=adw (3c7c97928e) - Bug 1180715 (3/4) - Drop parseURI from newChannel2. review=ttaubert (5b409e7d4b) - Bug 1180715 (4/4) - Use nsIURL methods instead of RegExp. review=ttaubert (1f7a026e06) - Bug 1209705 - Propagate the DrawResult for temporary surfaces to the caller in ClippedImage. r=tn (c5be1c7df4) - Bug 1215763 - part 2 - s/nsAutoPtr/UniquePtr/ in image/; r=seth (58c5da3bd2) - Bug 1215763 - part 3 - s/nsAutoArrayPtr/UniquePtr/ in nsBMPEncoder; r=seth (62bc939286) - Bug 1213613 (part 3) - Fix color-scaling of 16bpp BMP images. r=seth. (d06d511564) - Bug 1214072 (part 1) - Read BMP bitfields during metadata decoding. r=seth. (56cc2c02cd) - Bug 1214072 (part 2) - Implement transparency properly for BMP images. r=seth. (b6b07c2d90) - Bug 1218823 - use UniquePtr<> in preference to delete[] in image/; r=seth (5cd21f89a2) - Bug 1215334 (part 1) - Avoid creating a fake header for BMP files in ICO files. r=seth. (67506fc53e) - Bug 1215334 (part 2) - Avoid creating a fake header for BMP files in ICO files. r=seth. (cf6c3f4553) - spacing (b91c58ec87) - Bug 1196494 - part 1: remove unnecessary GetClientBounds call in CompositorParent. r=jrmuziel (685f49ae9c) - Bug 1180008 - Define gtk_window_get_window_type in mozgtk. r=karlt (e7ca7db4d3) - Bug 863512 - Fixing xul dnd panels for linux. r=enndeakin (5d0faaf0dc) - Bug 1195002 - draw to MozContainer window to allow GTK to draw decorations, r=karlt (7a84272fe9) - Bug 1210249 - don't mess with toplevel widget when client side decorations are enabled. r=karlt (464e9ce3fb) - bug 1180008 use mGdkWindow instead of finding it from gtk_widget_get_window(mShell) r=acomminos (024f8bd5a7) - bug 1180008 don't measure size of decorations for override-redirect windows r=acomminos (416ffda363) - Bug 1026803 part 1 - Factor out a common utility class for converting wrapping native times to TimeStamps; r=karlt (915ecdfc40) - Bug 1026803 part 2 - Add an assertion that SystemTimeConverter's template parameter is unsigned; r=karlt (68ccf1569d) - Bug 1026803 part 3 - Make some simplifications to SystemTimeConverter; r=karlt (c38719b7de) - Bug 1026803 part 4 - Convert GTK native event times to timestamps; r=karlt (74ef903992) - Bug 1026803 part 5 - Convert CurrentXXXTimeGetter classes from functors to helper classes; r=karlt (06d49e5965) - Bug 1026803 part 6 - Make SystemTimeConverter detect clock skew; r=karlt (d663ab72b2) - Bug 1026803 part 7 - Store the CurrentX11TimeGetter as a member object on nsWindow; r=karlt (f6a04e6e9c) - Bug 1026803 part 8 - Add ability for CurrentX11TimeGetter to perform an asynchronous request of the current time; r=karlt (961dab1d91) - Bug 1026803 part 8b - Factor out an IsTimeNewerThanTimeStamp method; r=karlt (1afb9f511a) - Bug 1026803 part 9 - Return DOMHighResTimeStamp objects from Event.timeStamp on Linux for Nightly/Aurora builds; r=karlt (975432dbd8) - Fix bustage from changeset 5c5dc6f367ac (bug 1026803) r=bustage on CLOSED TREE (c0be358f84) - fix bustage (e5e97018b6) - Bug 1196494 - part 2: only update nsWindow client offset when _NET_FRAME_EXTENTS property actually changes. r=eihrul (dd7e913d49) - Bug 1170342 - Disable XInput2 by default on GTK3. r=karlt (6a52d65a98) - Bug 1208904 - Fix a condition in nsWindow::SetNonClientMargins; r=roc (fe8c7b3e77) - Bug 1199892 - "Mouse cursor flickers in Flash object with wmode opaque/transparent". r=roc (6d50037e14) - Bug 1171101 - Remove pointer events and gesture scrolling dependencies. r=smaug (3aa5c89ea4) - Bug 978679. Implement touch events for GTK3. r=karlt (adafe58640) - Bug 1209774 - Transform from GDK coords to layout device pixels before calling DispatchEvent. r=karlt (4c81cf74ea) - Bug 1191293. Remove harmless assertion that is triggered by GTK3. r=masayuki (e0b9eb2c80) - Bug 978679. Convert GDK touch event coordinates properly. r=karlt (dfeae08f47) - restore some XP vs Vista differences, Bug 925599 bits (88ff57f06f) - Bug 1220392 - use UniquePtr<T[]> instead of nsAutoArrayPtr<T> in widget/; r=roc (35026aa4c9) - Bug 1214616 - Remove encoding conversion methods from nsPrimitiveHelpers. r=emk. (3a4bdbbc8e) - Bug 1216611 - add mozilla::MakeUniqueFallible and convert uses throughout the tree; r=Waldo (8672c2e3d9) - Bug 1216964 - remove nsAutoArrayPtr use from ActorsParent; r=khuey (ddff59241a) - Bug 1219903 - use UniquePtr<T[]> instead of delete[] calls in layout/generic/; r=dholbert (8b96067a6e) - Bug 1220190 - use UniquePtr<T[]> instead of delete[] calls in layout/xul/; r=dholbert (065b3c521c) - Bug 1220714 - use UniquePtr<T[]> instead of nsAutoArrayPtr<T> in layout/; r=dholbert (6a8245751c) - Bug 1221550 - use UniquePtr<T[]> instead of nsAutoArrayPtr<T> in intl/; r=smontagu (67868889e2) - Bug 1232374 - remove nsAutoArrayPtr usages from toolkit/; r=froydnj (d65586df26) - Bug 1170522 - expose whether or not we're in tablet mode to xul/js/css, r=jimm,ted (5cb134a8d4) - bug 1163872 - Fix a unified build issue in nsXPLookAndFeel.cpp. r=jimm (925e38abed) - bug 1217602 - remove nsIPKIParamBlock r=Cykesiopka (b5f0fc8dfd) - missing bit of old bug (fdcb4fe143) - Bug 1221453 - Use ObjDirPaths for GENERATED_INCLUDES and merge with LOCAL_INCLUDES. r=gps (a0537fff83) - Bug 1194948 - Build gfx/ipc in unified mode and mark as FAIL_ON_WARNINGS. r=BenWa (c88b356ac8) - Bug 815952 - Stop clearing clipboard data originating from a private window after closing private windows. r=ehsan (b94fea061d) - Bug 943296 - widget/gtk/nsDragService.cpp should assume Gtk uses UTF-8. r=karlt. (3613e87354) - Bug 1186661 - Draw drag and drop alpha pixmap correctly on GTK3. r=karlt (ca884af03b) - Bug 983843 - Switch to GtkOffscreenWindow for drag source widget, fixing ghost tabs on some GTK versions. r=karlt (ab56f9d764) - bug 1216916 clean up when InvokeDragSession() fails r=roc (30c811c33e) - Bug 1198128 - Fix -Wshadow warnings in widget/gtk. r=karlt (06bc60349e) - Merge branch 'dev' of https://github.com/rmottola/Arctic-Fox into dev (c79378b7c9) - Bug 1206915 - Move dumping of compositor textures under its own environment variable. r=mattwoodrow (b8ba4f0fbf) - Bug 1213007 - Part 1. Implementing gfxCrash. r=dvander (e307f9d543) - Bug 1208661 - Show display list and layer textures in-line in the HTML paint dump. r=BenWa (7047c68964) - Relax the driver crash guard on nightly and e10s builds. (bug 1200825, r=jgilbert) (1dd81b1257) - Bug 1214802 - gfxEnv - consolidate environment variables used by the graphics code in one place. r=botond (afb61356c6) - Bug 1217192 - Use gfxCriticalNote where we're already using the non-default construction parameter. r=mchang (d04ca17de5) - addback some crash stuff (8a78973a71) - Fix layers.acceleration.force-enabled not working. (bug 1212659, r=jrmuizel) (5eb85d8f64) - Bug 1142516 - Improve assertions and logging on the compositor side. r=Bas (cca63735e5) - Bug 1194335. Use a StackArray for RECTS so we see them in the minidumps. r=mattwoodrow (1a83a134e8) - Bug 1192058 - For DXGI_PRESENT_PARAMETERS, set pDirtyRects to nullptr if DirtyRectsCount == 0. r=BenWa (f78ff0df24) - Bug 1204922 - More information about crashes. r=bas (53cbd02c12) - Bug 1222033 - Rename gfxCrash to gfxDevCrash. r=jrmuizel (32351d0bc7) - Bug 1209812 (part 1) - Remove casts between cairo_format_t and gfxImageFormat. r=nical. (c1bc5cd74c) - Bug 1209812 (part 2) - Remove gfxImageFormat::A1. r=nical. (99f665ad80) - Bug 1182426 - Sort includes in VP8TrackEncoder.cpp alphabetically. r=roc (5f10334ba8) - Bug 1182426 - Don't try to encode new frames of a size other than the initial in VP8TrackEncoder. r=roc (8fb0b8f0d9) - Bug 1182426 - Flatten YUV formats conversion code in VP8TrackEncoder. r=roc (0853d098f7) - Bug 1182426 - Convert non-PlanarYCbCRImages in VP8TrackEncoder. r=roc (d2d78fa94a) - Bug 1204106 - Use correct alpha blend modes for OVER in CompositorOGL. r=jrmuizel (5cc211b9d6) - Bug 1207326 - Part 1: Correct projection clipping rectangle,r=matt.woodrow (8329afb6a7) - Bug 1207326 - Part 2: Add reftest,r=jmuizelaar (d17d6c5d4f) - Bug 1209446 - Make sure mFrameInProgress flag is set to true only when we actually begin drawing new frame. r=nical (4ff48c4149) - Disable screen and multiply mix-blend-mode support in the D3D11 and OGL compositors. (bug 1135271, r=mattwoodrow) (9b4c11a289) - Bug 1210189 - Use nsScreenGonk in nsWindow::StartRemoteDrawing() r=mwu (2653a33972) - Bug 1210514 - Fix color inversion when BasicCompositor is used on gonk r=nical (141fee3bfb) - Bug 1209812 (part 3) - Rename SurfaceFormat::R5G6B5 as R5G6B5_UINT16. r=Bas. (915e7eaba3) - Bug 1209812 (part 4) - Add comments to SurfaceFormat. r=jrmuizel,Bas. (ef1977582f) - Bug 1209812 (part 5) - Add endian-neutral variants to SurfaceFormat. r=nical,Bas. (93c49df8c5) - Bug 1171671 - Simplify Boot Animation control r=mwu (94c4f89b45) - Bug 1210182 - Implement GrallocTextureHostBasic r=nical (4e5ea5b92c) - Bug 1209812 (follow-up) - Android bustage fix on a CLOSED TREE. r=me. (8b2fa6268d) - Bug 1178513 - Added RGBA8888 to RGB565 converter. r=mattwoodrow (8ba5dbd3c9) - Bug 1160689 - thumbnail image corruption on certain videos. r=sotaro (278a2e29f6) - Bug 1204922: When ResizeBuffers fails, make no attempt to do subsequent paints until it succeeds again. r=milan (0c040d8228) - Bug 1215027 - Fix EndFrameForExternalComposition() r=nical (bab4690e54) - Bug 1215364 - Implement BasicCOmpositor::EndFrameForExternalComposition r=nical (c8b9c7bfb9) - Bug 1213968 - Renew the surface on iOS when resuming the compositor r=kats (73489dc21c) - Bug 1201318 - Factor out AddFamily. r=jdaggett (3f2556b8b4) - Bug 1201318 - revise OSX system font handling. r=mstange (f8a8f5f562) - Bug 1163877 - Part 1: Add storage for other FontFaceSets a FontFace is in. r=jdaggett (ab3a16b597) - Bug 1163877 - Part 2: Allow FontFaces to be added to multiple FontFaceSets. r=jdaggett (9b2dd7e5c9) - Bug 1163877 - Part 3: Update state on, and reflow documents for, all FontFaceSets that contain a FontFace whose user font entry updated. r=jdaggett (215db30569) - Bug 1192986 Fix test_interfaces.html to expect Cache API and font loading to be released. r=ehsan (8db9ef1df8) - Bug 1193019 - Rename CSSFontFaceLoadEvent to FontFaceSetLoadEvent. r=khuey (53f373c53d) - Bug 1163877 - Part 4: Tests. r=jdaggett (c6053ca8b4) - Bug 1180415 - initialize downloadable font pattern from FTFace. r=karlt (04aa59ba79) - Bug 1163491 - map local fontnames to fontconfig patterns. r=karlt (ad10ebde2a) - Bug 543715 p1 - distinguish between italic and oblique. r=jfkthame (4c9a0abf64) - Bug 543715 p2 - italic/oblique reftests. r=jfkthame (90fb927148) - bug 1178733 - enable APZ for iOS. r=kats (e41702d9cd) - Bug 1169956. Backout bug 1073209 for tiled image regressions on OS X. r=jrmuizel (a80a29aaa3) - Bug 1073209 - Eliminate usage of CreateSamplingRestrictedDrawable on d2d backends. r=jrmuizel (9ac8781a52) - Bug 1204136 - Align DisplayPort on non-tiling platform. r=botond (1d8be17663) - Bug 1122918 - Put the logical values for 'float' and 'clear' behind a pref, and enable them only on nightly builds and for B2G. r=heycam (a428b34d66) - Bug 1183484 - Cycle collect FontFaceSetIterator. r=bzbarsky (dc49f3f098) - Bug 1027579 - Do not load fonts from the cache if LOAD_BYPASS_CACHE is set. r=jfkthame r=bz (6cf20c9119) - Bug 1201318 - Use nsAutoReleasePool from nsCocoaUtils.h. r=jdaggett (bfe5f05086) - Bug 1201403 - streamline MacOSFontEntry::HasFontTable implementation. r=jfkthame (da06064b86) - Bug 1165611 - fix font smoothing under Linux. r=karlt (166a96603b) - Bug 1160506 - support intra-family font fallback. r=heycam (f56f0507d0) - Bug 1165693 - Cache the result of calling FcConfigSubstitute for our sentinel font name, to make gfxFcPlatformFontList::FindFamily less expensive. r=jdaggett (09ace74bc1) - Bug 1165693 - patch 2 - Cache family-name lookups in gfxFcPlatformFontList::FindFamily, to avoid repeating expensive calls to FcConfigSubstitute. r=jdaggett (ab34bf45c0) - Bug 1174946 - Back out the (incorrectly-implemented) caching of sentinelFirstFamily from bug 1165693, which should be largely overshadowed by the mFcSubstituteCache anyway. r=jdaggett (9b7784b7a6) - Bug 1165766 - Crash in AddFontSetFamilies() r=jtd (13cba8e6c7) - Bug 1170421 - return first font suggested by fontconfig as the default font. r=karlt (426c6bd348) - Bug 1008169 - Font selection and font size dropdowns are reacting very slowly on press up/down,r=jaws (8e395026e1) - Bug 1166161 - Display available font from font.name-list.{family}.{lang} as fallback default font, instead of empty string. (045855761a) - Bug 1187680 - Use NSVisualEffectMaterialMenu for menus if it's available. r=smichaud (0cede2f295) - Bug 1190257. Use the previous vsync timestamp on windows 10. r=jrmuizel (7cf7e2644f) - Bug 1220699 - Add telemetry probe to measure vsync latency in the parent refresh driver. r=avih (347936dffb) - Bug 1221674 - Add telemetry probe in the content process to measure the time between refresh driver ticks. r=kats (1d1b885f10) - Bug 1198362 - Delete PreciseRefreshDriverTimer. r=roc (8fdcca758f) - Bug 1197898 - Delete vsync refresh driver preference. r=kats (eab85ba8dd) - Bug 1210250. Fallback to GDI fonts with a skia backend. r=jwatt (8c374b4bd3) - Bug 1208927 - Initialize queryD3DKMTStatistics so that it can't be accessed uninitialized; r=jrmuizel (69c6781a82) - Bug 1144946 - Delete PreciseRefreshDriverTimerWindowsDwmVsync refresh driver timer. r=roc (a78ccb3d42) - Bug 1187784 (part 4) - Replace nsBaseHashtable::EnumerateRead() calls in layout/ with iterators. r=heycam. (6a09016e6d) - Bug 1187784 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in layout/ with iterators. r=heycam. (1ce8abd863) - Bug 1187784 (part 2) - Replace nsBaseHashtable::EnumerateRead() calls in layout/ with iterators. r=heycam. (cd98be2f19) - Bug 1187784 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in layout/ with iterators. r=heycam. (09022514a9) - Bug 1217230 - Set mNeedToRecomputeVisibility true only when style or layout flush. r=seth (8f3edd57c0) - Bug 1167281 - sort scalable fonts first when resolving generic families under Linux. r=karlt (e2ecb89f31) - Bug 1186875 - check if FcFontSort returns non-null. r=jtd (087905da51) - Bug 1218617 - Invalidate whole widget area after external composition r=mattwoodrow (3901f416f5) - Bug 1153499 - Enable push and sw prefs. r=dougt,ehsan (ca0f3a105d) - Bug 1141415 - add expire setting of permission to SpecialPowers. r=jmaher (372bc0c930) - partial Bug 1196665 - Add originAttributes into SpecialPowers. r=bholley (b8407a1bcc) - Bug 1213151 - Part 1: Add a SpecialPowers API for cleaning up the STS data that works in both e10s and non-e10s modes; r=jdm (04bba17fd3) - Bug 1213151 - Part 2: Use SpecialPowers.cleanUpSTSData() in a few tests; r=jdm (cce5f23dac) - Bug 1214593 - Remove service worker periodic updater. r=ehsan (87cfebcd0d) - fix tests, fix spaces (9cba57e7ff) - Bug 1207499 - Part 10: Remove use of expression closure from testing/. r=jmaher (652faa8963) - Bug 1204154 - Clean up jar manifests that needlessly specify the source file. r=dao (f116e33bed) - Bug 1222943 (part 1) - Change Touch::mRadius from nsIntPoint to LayoutDeviceIntPoint. r=kats. (dcc6c15797) - Bug 1222943 (part 2) - Remove an unnecessary call to ToUnknownSize(). r=botond. (08f644f194) - Bug 1220925 - Event::GetScreenCoords should return CSSIntPoint instead of LayoutDevicePoint. r=botond (4e4f54e8e7) - Bug 943294 - Leave dealing with legacy codepages for clipboard data to Windows itself. r=jmathies. (124ecbfa3e) - Bug 1243507 - Reimplement non-Unicode clipboard formats as bug 943294 broke drag and drop between some Unicode-unaware apps. r=jimm (02edc31ed9) - ported Bug 1254980 - Ensure that text/html is still written to the clipboard. r=enndeakin a=sylvestre (9cd4c0e41a) - nsWindow: build fix (1c3e798a89)
1351 lines
38 KiB
C++
1351 lines
38 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsFilePicker.h"
|
|
|
|
#include <shlobj.h>
|
|
#include <shlwapi.h>
|
|
#include <cderr.h>
|
|
|
|
#include "mozilla/UniquePtr.h"
|
|
#include "mozilla/WindowsVersion.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsWindow.h"
|
|
#include "nsILoadContext.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIURL.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsEnumeratorUtils.h"
|
|
#include "nsCRT.h"
|
|
#include "nsString.h"
|
|
#include "nsToolkit.h"
|
|
#include "WinUtils.h"
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
using mozilla::IsVistaOrLater;
|
|
using mozilla::MakeUnique;
|
|
using mozilla::UniquePtr;
|
|
using namespace mozilla::widget;
|
|
|
|
char16_t *nsFilePicker::mLastUsedUnicodeDirectory;
|
|
char nsFilePicker::mLastUsedDirectory[MAX_PATH+1] = { 0 };
|
|
|
|
static const wchar_t kDialogPtrProp[] = L"DialogPtrProperty";
|
|
static const DWORD kDialogTimerID = 9999;
|
|
static const unsigned long kDialogTimerTimeout = 300;
|
|
|
|
#define MAX_EXTENSION_LENGTH 10
|
|
#define FILE_BUFFER_SIZE 4096
|
|
|
|
typedef DWORD FILEOPENDIALOGOPTIONS;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Helper classes
|
|
|
|
// Manages matching SuppressBlurEvents calls on the parent widget.
|
|
class AutoSuppressEvents
|
|
{
|
|
public:
|
|
explicit AutoSuppressEvents(nsIWidget* aWidget) :
|
|
mWindow(static_cast<nsWindow *>(aWidget)) {
|
|
SuppressWidgetEvents(true);
|
|
}
|
|
|
|
~AutoSuppressEvents() {
|
|
SuppressWidgetEvents(false);
|
|
}
|
|
private:
|
|
void SuppressWidgetEvents(bool aFlag) {
|
|
if (mWindow) {
|
|
mWindow->SuppressBlurEvents(aFlag);
|
|
}
|
|
}
|
|
RefPtr<nsWindow> mWindow;
|
|
};
|
|
|
|
// Manages the current working path.
|
|
class AutoRestoreWorkingPath
|
|
{
|
|
public:
|
|
AutoRestoreWorkingPath() {
|
|
DWORD bufferLength = GetCurrentDirectoryW(0, nullptr);
|
|
mWorkingPath = MakeUnique<wchar_t[]>(bufferLength);
|
|
if (GetCurrentDirectoryW(bufferLength, mWorkingPath.get()) == 0) {
|
|
mWorkingPath = nullptr;
|
|
}
|
|
}
|
|
|
|
~AutoRestoreWorkingPath() {
|
|
if (HasWorkingPath()) {
|
|
::SetCurrentDirectoryW(mWorkingPath.get());
|
|
}
|
|
}
|
|
|
|
inline bool HasWorkingPath() const {
|
|
return mWorkingPath != nullptr;
|
|
}
|
|
private:
|
|
UniquePtr<wchar_t[]> mWorkingPath;
|
|
};
|
|
|
|
// Manages NS_NATIVE_TMP_WINDOW child windows. NS_NATIVE_TMP_WINDOWs are
|
|
// temporary child windows of mParentWidget created to address RTL issues
|
|
// in picker dialogs. We are responsible for destroying these.
|
|
class AutoDestroyTmpWindow
|
|
{
|
|
public:
|
|
explicit AutoDestroyTmpWindow(HWND aTmpWnd) :
|
|
mWnd(aTmpWnd) {
|
|
}
|
|
|
|
~AutoDestroyTmpWindow() {
|
|
if (mWnd)
|
|
DestroyWindow(mWnd);
|
|
}
|
|
|
|
inline HWND get() const { return mWnd; }
|
|
private:
|
|
HWND mWnd;
|
|
};
|
|
|
|
// Manages matching PickerOpen/PickerClosed calls on the parent widget.
|
|
class AutoWidgetPickerState
|
|
{
|
|
public:
|
|
explicit AutoWidgetPickerState(nsIWidget* aWidget) :
|
|
mWindow(static_cast<nsWindow *>(aWidget)) {
|
|
PickerState(true);
|
|
}
|
|
|
|
~AutoWidgetPickerState() {
|
|
PickerState(false);
|
|
}
|
|
private:
|
|
void PickerState(bool aFlag) {
|
|
if (mWindow) {
|
|
if (aFlag)
|
|
mWindow->PickerOpen();
|
|
else
|
|
mWindow->PickerClosed();
|
|
}
|
|
}
|
|
RefPtr<nsWindow> mWindow;
|
|
};
|
|
|
|
// Manages a simple callback timer
|
|
class AutoTimerCallbackCancel
|
|
{
|
|
public:
|
|
AutoTimerCallbackCancel(nsFilePicker* aTarget,
|
|
nsTimerCallbackFunc aCallbackFunc) {
|
|
Init(aTarget, aCallbackFunc);
|
|
}
|
|
|
|
~AutoTimerCallbackCancel() {
|
|
if (mPickerCallbackTimer) {
|
|
mPickerCallbackTimer->Cancel();
|
|
}
|
|
}
|
|
|
|
private:
|
|
void Init(nsFilePicker* aTarget,
|
|
nsTimerCallbackFunc aCallbackFunc) {
|
|
mPickerCallbackTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
if (!mPickerCallbackTimer) {
|
|
NS_WARNING("do_CreateInstance for timer failed??");
|
|
return;
|
|
}
|
|
mPickerCallbackTimer->InitWithFuncCallback(aCallbackFunc,
|
|
aTarget,
|
|
kDialogTimerTimeout,
|
|
nsITimer::TYPE_REPEATING_SLACK);
|
|
}
|
|
nsCOMPtr<nsITimer> mPickerCallbackTimer;
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// nsIFilePicker
|
|
|
|
nsFilePicker::nsFilePicker() :
|
|
mSelectedType(1)
|
|
, mDlgWnd(nullptr)
|
|
, mFDECookie(0)
|
|
{
|
|
CoInitialize(nullptr);
|
|
}
|
|
|
|
nsFilePicker::~nsFilePicker()
|
|
{
|
|
if (mLastUsedUnicodeDirectory) {
|
|
NS_Free(mLastUsedUnicodeDirectory);
|
|
mLastUsedUnicodeDirectory = nullptr;
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker)
|
|
|
|
NS_IMETHODIMP nsFilePicker::Init(nsIDOMWindow *aParent, const nsAString& aTitle, int16_t aMode)
|
|
{
|
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aParent);
|
|
nsIDocShell* docShell = window ? window->GetDocShell() : nullptr;
|
|
mLoadContext = do_QueryInterface(docShell);
|
|
|
|
return nsBaseFilePicker::Init(aParent, aTitle, aMode);
|
|
}
|
|
|
|
STDMETHODIMP nsFilePicker::QueryInterface(REFIID refiid, void** ppvResult)
|
|
{
|
|
*ppvResult = nullptr;
|
|
if (IID_IUnknown == refiid ||
|
|
refiid == IID_IFileDialogEvents) {
|
|
*ppvResult = this;
|
|
}
|
|
|
|
if (nullptr != *ppvResult) {
|
|
((LPUNKNOWN)*ppvResult)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
/*
|
|
* XP picker callbacks
|
|
*/
|
|
|
|
// Show - Display the file dialog
|
|
int CALLBACK
|
|
BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
if (uMsg == BFFM_INITIALIZED)
|
|
{
|
|
char16_t * filePath = (char16_t *) lpData;
|
|
if (filePath)
|
|
::SendMessageW(hwnd, BFFM_SETSELECTIONW,
|
|
TRUE /* true because lpData is a path string */,
|
|
lpData);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
EnsureWindowVisible(HWND hwnd)
|
|
{
|
|
// Obtain the monitor which has the largest area of intersection
|
|
// with the window, or nullptr if there is no intersection.
|
|
HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
|
|
if (!monitor) {
|
|
// The window is not visible, we should reposition it to the same place as its parent
|
|
HWND parentHwnd = GetParent(hwnd);
|
|
RECT parentRect;
|
|
GetWindowRect(parentHwnd, &parentRect);
|
|
SetWindowPos(hwnd, nullptr, parentRect.left, parentRect.top, 0, 0,
|
|
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
}
|
|
|
|
// Callback hook which will ensure that the window is visible. Currently
|
|
// only in use on os <= XP.
|
|
UINT_PTR CALLBACK
|
|
nsFilePicker::FilePickerHook(HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch(msg) {
|
|
case WM_NOTIFY:
|
|
{
|
|
LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
|
|
if (!lpofn || !lpofn->lpOFN) {
|
|
return 0;
|
|
}
|
|
|
|
if (CDN_INITDONE == lpofn->hdr.code) {
|
|
// The Window will be automatically moved to the last position after
|
|
// CDN_INITDONE. We post a message to ensure the window will be visible
|
|
// so it will be done after the automatic last position window move.
|
|
PostMessage(hwnd, MOZ_WM_ENSUREVISIBLE, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
case MOZ_WM_ENSUREVISIBLE:
|
|
EnsureWindowVisible(GetParent(hwnd));
|
|
break;
|
|
case WM_INITDIALOG:
|
|
{
|
|
OPENFILENAMEW* pofn = reinterpret_cast<OPENFILENAMEW*>(lParam);
|
|
SetProp(hwnd, kDialogPtrProp, (HANDLE)pofn->lCustData);
|
|
nsFilePicker* picker = reinterpret_cast<nsFilePicker*>(pofn->lCustData);
|
|
if (picker) {
|
|
picker->SetDialogHandle(hwnd);
|
|
SetTimer(hwnd, kDialogTimerID, kDialogTimerTimeout, nullptr);
|
|
}
|
|
}
|
|
break;
|
|
case WM_TIMER:
|
|
{
|
|
// Check to see if our parent has been torn down, if so, we close too.
|
|
if (wParam == kDialogTimerID) {
|
|
nsFilePicker* picker =
|
|
reinterpret_cast<nsFilePicker*>(GetProp(hwnd, kDialogPtrProp));
|
|
if (picker && picker->ClosePickerIfNeeded(true)) {
|
|
KillTimer(hwnd, kDialogTimerID);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Callback hook which will dynamically allocate a buffer large enough
|
|
// for the file picker dialog. Currently only in use on os <= XP.
|
|
UINT_PTR CALLBACK
|
|
nsFilePicker::MultiFilePickerHook(HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
// Finds the child drop down of a File Picker dialog and sets the
|
|
// maximum amount of text it can hold when typed in manually.
|
|
// A wParam of 0 mean 0x7FFFFFFE characters.
|
|
HWND comboBox = FindWindowEx(GetParent(hwnd), nullptr,
|
|
L"ComboBoxEx32", nullptr );
|
|
if(comboBox)
|
|
SendMessage(comboBox, CB_LIMITTEXT, 0, 0);
|
|
// Store our nsFilePicker ptr for future use
|
|
OPENFILENAMEW* pofn = reinterpret_cast<OPENFILENAMEW*>(lParam);
|
|
SetProp(hwnd, kDialogPtrProp, (HANDLE)pofn->lCustData);
|
|
nsFilePicker* picker =
|
|
reinterpret_cast<nsFilePicker*>(pofn->lCustData);
|
|
if (picker) {
|
|
picker->SetDialogHandle(hwnd);
|
|
SetTimer(hwnd, kDialogTimerID, kDialogTimerTimeout, nullptr);
|
|
}
|
|
}
|
|
break;
|
|
case WM_NOTIFY:
|
|
{
|
|
LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
|
|
if (!lpofn || !lpofn->lpOFN) {
|
|
return 0;
|
|
}
|
|
// CDN_SELCHANGE is sent when the selection in the list box of the file
|
|
// selection dialog changes
|
|
if (lpofn->hdr.code == CDN_SELCHANGE) {
|
|
HWND parentHWND = GetParent(hwnd);
|
|
|
|
// Get the required size for the selected files buffer
|
|
UINT newBufLength = 0;
|
|
int requiredBufLength = CommDlg_OpenSave_GetSpecW(parentHWND,
|
|
nullptr, 0);
|
|
if(requiredBufLength >= 0)
|
|
newBufLength += requiredBufLength;
|
|
else
|
|
newBufLength += MAX_PATH;
|
|
|
|
// If the user selects multiple files, the buffer contains the
|
|
// current directory followed by the file names of the selected
|
|
// files. So make room for the directory path. If the user
|
|
// selects a single file, it is no harm to add extra space.
|
|
requiredBufLength = CommDlg_OpenSave_GetFolderPathW(parentHWND,
|
|
nullptr, 0);
|
|
if(requiredBufLength >= 0)
|
|
newBufLength += requiredBufLength;
|
|
else
|
|
newBufLength += MAX_PATH;
|
|
|
|
// Check if lpstrFile and nMaxFile are large enough
|
|
if (newBufLength > lpofn->lpOFN->nMaxFile) {
|
|
if (lpofn->lpOFN->lpstrFile)
|
|
delete[] lpofn->lpOFN->lpstrFile;
|
|
|
|
// We allocate FILE_BUFFER_SIZE more bytes than is needed so that
|
|
// if the user selects a file and holds down shift and down to
|
|
// select additional items, we will not continuously reallocate
|
|
newBufLength += FILE_BUFFER_SIZE;
|
|
|
|
wchar_t* filesBuffer = new wchar_t[newBufLength];
|
|
ZeroMemory(filesBuffer, newBufLength * sizeof(wchar_t));
|
|
|
|
lpofn->lpOFN->lpstrFile = filesBuffer;
|
|
lpofn->lpOFN->nMaxFile = newBufLength;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case WM_TIMER:
|
|
{
|
|
// Check to see if our parent has been torn down, if so, we close too.
|
|
if (wParam == kDialogTimerID) {
|
|
nsFilePicker* picker =
|
|
reinterpret_cast<nsFilePicker*>(GetProp(hwnd, kDialogPtrProp));
|
|
if (picker && picker->ClosePickerIfNeeded(true)) {
|
|
KillTimer(hwnd, kDialogTimerID);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FilePickerHook(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
/*
|
|
* Vista+ callbacks
|
|
*/
|
|
|
|
HRESULT
|
|
nsFilePicker::OnFileOk(IFileDialog *pfd)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
nsFilePicker::OnFolderChanging(IFileDialog *pfd,
|
|
IShellItem *psiFolder)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
nsFilePicker::OnFolderChange(IFileDialog *pfd)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
nsFilePicker::OnSelectionChange(IFileDialog *pfd)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
nsFilePicker::OnShareViolation(IFileDialog *pfd,
|
|
IShellItem *psi,
|
|
FDE_SHAREVIOLATION_RESPONSE *pResponse)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
nsFilePicker::OnTypeChange(IFileDialog *pfd)
|
|
{
|
|
// Failures here result in errors due to security concerns.
|
|
RefPtr<IOleWindow> win;
|
|
pfd->QueryInterface(IID_IOleWindow, getter_AddRefs(win));
|
|
if (!win) {
|
|
NS_ERROR("Could not retrieve the IOleWindow interface for IFileDialog.");
|
|
return S_OK;
|
|
}
|
|
HWND hwnd = nullptr;
|
|
win->GetWindow(&hwnd);
|
|
if (!hwnd) {
|
|
NS_ERROR("Could not retrieve the HWND for IFileDialog.");
|
|
return S_OK;
|
|
}
|
|
|
|
SetDialogHandle(hwnd);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
nsFilePicker::OnOverwrite(IFileDialog *pfd,
|
|
IShellItem *psi,
|
|
FDE_OVERWRITE_RESPONSE *pResponse)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* Close on parent close logic
|
|
*/
|
|
|
|
bool
|
|
nsFilePicker::ClosePickerIfNeeded(bool aIsXPDialog)
|
|
{
|
|
if (!mParentWidget || !mDlgWnd)
|
|
return false;
|
|
|
|
nsWindow *win = static_cast<nsWindow *>(mParentWidget.get());
|
|
// Note, the xp callbacks hand us an inner window, so we have to step up
|
|
// one to get the actual dialog.
|
|
HWND dlgWnd;
|
|
if (aIsXPDialog)
|
|
dlgWnd = GetParent(mDlgWnd);
|
|
else
|
|
dlgWnd = mDlgWnd;
|
|
if (IsWindow(dlgWnd) && IsWindowVisible(dlgWnd) && win->DestroyCalled()) {
|
|
wchar_t className[64];
|
|
// Make sure we have the right window
|
|
if (GetClassNameW(dlgWnd, className, mozilla::ArrayLength(className)) &&
|
|
!wcscmp(className, L"#32770") &&
|
|
DestroyWindow(dlgWnd)) {
|
|
mDlgWnd = nullptr;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
nsFilePicker::PickerCallbackTimerFunc(nsITimer *aTimer, void *aCtx)
|
|
{
|
|
nsFilePicker* picker = (nsFilePicker*)aCtx;
|
|
if (picker->ClosePickerIfNeeded(false)) {
|
|
aTimer->Cancel();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsFilePicker::SetDialogHandle(HWND aWnd)
|
|
{
|
|
if (!aWnd || mDlgWnd)
|
|
return;
|
|
mDlgWnd = aWnd;
|
|
}
|
|
|
|
/*
|
|
* Folder picker invocation
|
|
*/
|
|
|
|
// Open the older XP style folder picker dialog. We end up in this call
|
|
// on XP systems or when platform is built without the longhorn SDK.
|
|
bool
|
|
nsFilePicker::ShowXPFolderPicker(const nsString& aInitialDir)
|
|
{
|
|
bool result = false;
|
|
|
|
auto dirBuffer = MakeUnique<wchar_t[]>(FILE_BUFFER_SIZE);
|
|
wcsncpy(dirBuffer.get(), aInitialDir.get(), FILE_BUFFER_SIZE);
|
|
dirBuffer[FILE_BUFFER_SIZE-1] = '\0';
|
|
|
|
AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ?
|
|
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
|
|
|
|
BROWSEINFOW browserInfo = {0};
|
|
browserInfo.pidlRoot = nullptr;
|
|
browserInfo.pszDisplayName = dirBuffer.get();
|
|
browserInfo.lpszTitle = mTitle.get();
|
|
browserInfo.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
|
|
browserInfo.hwndOwner = adtw.get();
|
|
browserInfo.iImage = 0;
|
|
browserInfo.lParam = reinterpret_cast<LPARAM>(this);
|
|
|
|
if (!aInitialDir.IsEmpty()) {
|
|
// the dialog is modal so that |initialDir.get()| will be valid in
|
|
// BrowserCallbackProc. Thus, we don't need to clone it.
|
|
browserInfo.lParam = (LPARAM) aInitialDir.get();
|
|
browserInfo.lpfn = &BrowseCallbackProc;
|
|
} else {
|
|
browserInfo.lParam = 0;
|
|
browserInfo.lpfn = nullptr;
|
|
}
|
|
|
|
LPITEMIDLIST list = ::SHBrowseForFolderW(&browserInfo);
|
|
if (list) {
|
|
result = ::SHGetPathFromIDListW(list, dirBuffer.get());
|
|
if (result)
|
|
mUnicodeFile.Assign(static_cast<const wchar_t*>(dirBuffer.get()));
|
|
// free PIDL
|
|
CoTaskMemFree(list);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Show a folder picker post Windows XP
|
|
*
|
|
* @param aInitialDir The initial directory, the last used directory will be
|
|
* used if left blank.
|
|
* @param aWasInitError Out parameter will hold true if there was an error
|
|
* before the folder picker is shown.
|
|
* @return true if a file was selected successfully.
|
|
*/
|
|
bool
|
|
nsFilePicker::ShowFolderPicker(const nsString& aInitialDir, bool &aWasInitError)
|
|
{
|
|
RefPtr<IFileOpenDialog> dialog;
|
|
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
|
|
IID_IFileOpenDialog,
|
|
getter_AddRefs(dialog)))) {
|
|
aWasInitError = true;
|
|
return false;
|
|
}
|
|
aWasInitError = false;
|
|
|
|
// hook up event callbacks
|
|
dialog->Advise(this, &mFDECookie);
|
|
|
|
// options
|
|
FILEOPENDIALOGOPTIONS fos = FOS_PICKFOLDERS;
|
|
dialog->SetOptions(fos);
|
|
|
|
// initial strings
|
|
dialog->SetTitle(mTitle.get());
|
|
if (!aInitialDir.IsEmpty()) {
|
|
RefPtr<IShellItem> folder;
|
|
if (SUCCEEDED(
|
|
WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), nullptr,
|
|
IID_IShellItem,
|
|
getter_AddRefs(folder)))) {
|
|
dialog->SetFolder(folder);
|
|
}
|
|
}
|
|
|
|
AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ?
|
|
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
|
|
|
|
// display
|
|
RefPtr<IShellItem> item;
|
|
if (FAILED(dialog->Show(adtw.get())) ||
|
|
FAILED(dialog->GetResult(getter_AddRefs(item))) ||
|
|
!item) {
|
|
dialog->Unadvise(mFDECookie);
|
|
return false;
|
|
}
|
|
dialog->Unadvise(mFDECookie);
|
|
|
|
// results
|
|
|
|
// If the user chose a Win7 Library, resolve to the library's
|
|
// default save folder.
|
|
RefPtr<IShellItem> folderPath;
|
|
RefPtr<IShellLibrary> shellLib;
|
|
CoCreateInstance(CLSID_ShellLibrary, nullptr, CLSCTX_INPROC,
|
|
IID_IShellLibrary, getter_AddRefs(shellLib));
|
|
if (shellLib &&
|
|
SUCCEEDED(shellLib->LoadLibraryFromItem(item, STGM_READ)) &&
|
|
SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem,
|
|
getter_AddRefs(folderPath)))) {
|
|
item.swap(folderPath);
|
|
}
|
|
|
|
// get the folder's file system path
|
|
return WinUtils::GetShellItemPath(item, mUnicodeFile);
|
|
}
|
|
|
|
/*
|
|
* File open and save picker invocation
|
|
*/
|
|
|
|
/* static */ bool
|
|
nsFilePicker::GetFileNameWrapper(OPENFILENAMEW* ofn, PickerType aType)
|
|
{
|
|
MOZ_SEH_TRY {
|
|
if (aType == PICKER_TYPE_OPEN)
|
|
return ::GetOpenFileNameW(ofn);
|
|
else if (aType == PICKER_TYPE_SAVE)
|
|
return ::GetSaveFileNameW(ofn);
|
|
} MOZ_SEH_EXCEPT(true) {
|
|
NS_ERROR("nsFilePicker GetFileName win32 call generated an exception! This is bad!");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
nsFilePicker::FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType)
|
|
{
|
|
if (!ofn)
|
|
return false;
|
|
AutoWidgetPickerState awps(mParentWidget);
|
|
return GetFileNameWrapper(ofn, aType);
|
|
}
|
|
|
|
bool
|
|
nsFilePicker::ShowXPFilePicker(const nsString& aInitialDir)
|
|
{
|
|
OPENFILENAMEW ofn = {0};
|
|
ofn.lStructSize = sizeof(ofn);
|
|
nsString filterBuffer = mFilterList;
|
|
|
|
auto fileBuffer = MakeUnique<wchar_t[]>(FILE_BUFFER_SIZE);
|
|
wcsncpy(fileBuffer.get(), mDefaultFilePath.get(), FILE_BUFFER_SIZE);
|
|
fileBuffer[FILE_BUFFER_SIZE-1] = '\0'; // null terminate in case copy truncated
|
|
|
|
if (!aInitialDir.IsEmpty()) {
|
|
ofn.lpstrInitialDir = aInitialDir.get();
|
|
}
|
|
|
|
AutoDestroyTmpWindow adtw((HWND) (mParentWidget.get() ?
|
|
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
|
|
|
|
ofn.lpstrTitle = (LPCWSTR)mTitle.get();
|
|
ofn.lpstrFilter = (LPCWSTR)filterBuffer.get();
|
|
ofn.nFilterIndex = mSelectedType;
|
|
ofn.lpstrFile = fileBuffer.get();
|
|
ofn.nMaxFile = FILE_BUFFER_SIZE;
|
|
ofn.hwndOwner = adtw.get();
|
|
ofn.lCustData = reinterpret_cast<LPARAM>(this);
|
|
ofn.Flags = OFN_SHAREAWARE | OFN_LONGNAMES | OFN_OVERWRITEPROMPT |
|
|
OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_ENABLESIZING |
|
|
OFN_EXPLORER;
|
|
|
|
// Windows Vista and up won't allow you to use the new looking dialogs with
|
|
// a hook procedure. The hook procedure fixes a problem on XP dialogs for
|
|
// file picker visibility. Vista and up automatically ensures the file
|
|
// picker is always visible.
|
|
if (!IsVistaOrLater()) {
|
|
ofn.lpfnHook = FilePickerHook;
|
|
ofn.Flags |= OFN_ENABLEHOOK;
|
|
}
|
|
|
|
// Handle add to recent docs settings
|
|
if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
|
|
ofn.Flags |= OFN_DONTADDTORECENT;
|
|
}
|
|
|
|
NS_NAMED_LITERAL_STRING(htmExt, "html");
|
|
|
|
if (!mDefaultExtension.IsEmpty()) {
|
|
ofn.lpstrDefExt = mDefaultExtension.get();
|
|
} else if (IsDefaultPathHtml()) {
|
|
// Get file extension from suggested filename to detect if we are
|
|
// saving an html file.
|
|
// This is supposed to append ".htm" if user doesn't supply an
|
|
// extension but the behavior is sort of weird:
|
|
// - Often appends ".html" even if you have an extension
|
|
// - It obeys your extension if you put quotes around name
|
|
ofn.lpstrDefExt = htmExt.get();
|
|
}
|
|
|
|
// When possible, instead of using OFN_NOCHANGEDIR to ensure the current
|
|
// working directory will not change from this call, we will retrieve the
|
|
// current working directory before the call and restore it after the
|
|
// call. This flag causes problems on Windows XP for paths that are
|
|
// selected like C:test.txt where the user is currently at C:\somepath
|
|
// In which case expected result should be C:\somepath\test.txt
|
|
AutoRestoreWorkingPath restoreWorkingPath;
|
|
// If we can't get the current working directory, the best case is to
|
|
// use the OFN_NOCHANGEDIR flag
|
|
if (!restoreWorkingPath.HasWorkingPath()) {
|
|
ofn.Flags |= OFN_NOCHANGEDIR;
|
|
}
|
|
|
|
bool result = false;
|
|
|
|
switch(mMode) {
|
|
case modeOpen:
|
|
// FILE MUST EXIST!
|
|
ofn.Flags |= OFN_FILEMUSTEXIST;
|
|
result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
|
|
break;
|
|
|
|
case modeOpenMultiple:
|
|
ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
|
|
|
|
// The hook set here ensures that the buffer returned will always be
|
|
// large enough to hold all selected files. The hook may modify the
|
|
// value of ofn.lpstrFile and deallocate the old buffer that it pointed
|
|
// to (fileBuffer). The hook assumes that the passed in value is heap
|
|
// allocated and that the returned value should be freed by the caller.
|
|
// If the hook changes the buffer, it will deallocate the old buffer.
|
|
// This fix would be nice to have in Vista and up, but it would force
|
|
// the file picker to use the old style dialogs because hooks are not
|
|
// allowed in the new file picker UI. We need to eventually move to
|
|
// the new Common File Dialogs for Vista and up.
|
|
if (!IsVistaOrLater()) {
|
|
ofn.lpfnHook = MultiFilePickerHook;
|
|
fileBuffer.release();
|
|
result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
|
|
fileBuffer.reset(ofn.lpstrFile);
|
|
} else {
|
|
result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
|
|
}
|
|
break;
|
|
|
|
case modeSave:
|
|
{
|
|
ofn.Flags |= OFN_NOREADONLYRETURN;
|
|
|
|
// Don't follow shortcuts when saving a shortcut, this can be used
|
|
// to trick users (bug 271732)
|
|
if (IsDefaultPathLink())
|
|
ofn.Flags |= OFN_NODEREFERENCELINKS;
|
|
|
|
result = FilePickerWrapper(&ofn, PICKER_TYPE_SAVE);
|
|
if (!result) {
|
|
// Error, find out what kind.
|
|
if (GetLastError() == ERROR_INVALID_PARAMETER ||
|
|
CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
|
|
// Probably the default file name is too long or contains illegal
|
|
// characters. Try again, without a starting file name.
|
|
ofn.lpstrFile[0] = L'\0';
|
|
result = FilePickerWrapper(&ofn, PICKER_TYPE_SAVE);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
NS_NOTREACHED("unsupported file picker mode");
|
|
return false;
|
|
}
|
|
|
|
if (!result)
|
|
return false;
|
|
|
|
// Remember what filter type the user selected
|
|
mSelectedType = (int16_t)ofn.nFilterIndex;
|
|
|
|
// Single file selection, we're done
|
|
if (mMode != modeOpenMultiple) {
|
|
GetQualifiedPath(fileBuffer.get(), mUnicodeFile);
|
|
return true;
|
|
}
|
|
|
|
// Set user-selected location of file or directory. From msdn's "Open and
|
|
// Save As Dialog Boxes" section:
|
|
// If you specify OFN_EXPLORER, the directory and file name strings are '\0'
|
|
// separated, with an extra '\0' character after the last file name. This
|
|
// format enables the Explorer-style dialog boxes to return long file names
|
|
// that include spaces.
|
|
wchar_t *current = fileBuffer.get();
|
|
|
|
nsAutoString dirName(current);
|
|
// Sometimes dirName contains a trailing slash and sometimes it doesn't:
|
|
if (current[dirName.Length() - 1] != '\\')
|
|
dirName.Append((char16_t)'\\');
|
|
|
|
while (current && *current && *(current + wcslen(current) + 1)) {
|
|
current = current + wcslen(current) + 1;
|
|
|
|
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
|
|
NS_ENSURE_TRUE(file, false);
|
|
|
|
// Only prepend the directory if the path specified is a relative path
|
|
nsAutoString path;
|
|
if (PathIsRelativeW(current)) {
|
|
path = dirName + nsDependentString(current);
|
|
} else {
|
|
path = current;
|
|
}
|
|
|
|
nsAutoString canonicalizedPath;
|
|
GetQualifiedPath(path.get(), canonicalizedPath);
|
|
if (NS_FAILED(file->InitWithPath(canonicalizedPath)) ||
|
|
!mFiles.AppendObject(file))
|
|
return false;
|
|
}
|
|
|
|
// Handle the case where the user selected just one file. From msdn: If you
|
|
// specify OFN_ALLOWMULTISELECT and the user selects only one file the
|
|
// lpstrFile string does not have a separator between the path and file name.
|
|
if (current && *current && (current == fileBuffer.get())) {
|
|
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
|
|
NS_ENSURE_TRUE(file, false);
|
|
|
|
nsAutoString canonicalizedPath;
|
|
GetQualifiedPath(current, canonicalizedPath);
|
|
if (NS_FAILED(file->InitWithPath(canonicalizedPath)) ||
|
|
!mFiles.AppendObject(file))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Show a file picker post Windows XP
|
|
*
|
|
* @param aInitialDir The initial directory, the last used directory will be
|
|
* used if left blank.
|
|
* @param aWasInitError Out parameter will hold true if there was an error
|
|
* before the file picker is shown.
|
|
* @return true if a file was selected successfully.
|
|
*/
|
|
bool
|
|
nsFilePicker::ShowFilePicker(const nsString& aInitialDir, bool &aWasInitError)
|
|
{
|
|
RefPtr<IFileDialog> dialog;
|
|
if (mMode != modeSave) {
|
|
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
|
|
IID_IFileOpenDialog,
|
|
getter_AddRefs(dialog)))) {
|
|
aWasInitError = true;
|
|
return false;
|
|
}
|
|
} else {
|
|
if (FAILED(CoCreateInstance(CLSID_FileSaveDialog, nullptr, CLSCTX_INPROC,
|
|
IID_IFileSaveDialog,
|
|
getter_AddRefs(dialog)))) {
|
|
aWasInitError = true;
|
|
return false;
|
|
}
|
|
}
|
|
aWasInitError = false;
|
|
|
|
// hook up event callbacks
|
|
dialog->Advise(this, &mFDECookie);
|
|
|
|
// options
|
|
|
|
FILEOPENDIALOGOPTIONS fos = 0;
|
|
fos |= FOS_SHAREAWARE | FOS_OVERWRITEPROMPT |
|
|
FOS_FORCEFILESYSTEM;
|
|
|
|
// Handle add to recent docs settings
|
|
if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
|
|
fos |= FOS_DONTADDTORECENT;
|
|
}
|
|
|
|
// Msdn claims FOS_NOCHANGEDIR is not needed. We'll add this
|
|
// just in case.
|
|
AutoRestoreWorkingPath arw;
|
|
|
|
// mode specific
|
|
switch(mMode) {
|
|
case modeOpen:
|
|
fos |= FOS_FILEMUSTEXIST;
|
|
break;
|
|
|
|
case modeOpenMultiple:
|
|
fos |= FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT;
|
|
break;
|
|
|
|
case modeSave:
|
|
fos |= FOS_NOREADONLYRETURN;
|
|
// Don't follow shortcuts when saving a shortcut, this can be used
|
|
// to trick users (bug 271732)
|
|
if (IsDefaultPathLink())
|
|
fos |= FOS_NODEREFERENCELINKS;
|
|
break;
|
|
}
|
|
|
|
dialog->SetOptions(fos);
|
|
|
|
// initial strings
|
|
|
|
// title
|
|
dialog->SetTitle(mTitle.get());
|
|
|
|
// default filename
|
|
if (!mDefaultFilename.IsEmpty()) {
|
|
dialog->SetFileName(mDefaultFilename.get());
|
|
}
|
|
|
|
NS_NAMED_LITERAL_STRING(htmExt, "html");
|
|
|
|
// default extension to append to new files
|
|
if (!mDefaultExtension.IsEmpty()) {
|
|
dialog->SetDefaultExtension(mDefaultExtension.get());
|
|
} else if (IsDefaultPathHtml()) {
|
|
dialog->SetDefaultExtension(htmExt.get());
|
|
}
|
|
|
|
// initial location
|
|
if (!aInitialDir.IsEmpty()) {
|
|
RefPtr<IShellItem> folder;
|
|
if (SUCCEEDED(
|
|
WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), nullptr,
|
|
IID_IShellItem,
|
|
getter_AddRefs(folder)))) {
|
|
dialog->SetFolder(folder);
|
|
}
|
|
}
|
|
|
|
// filter types and the default index
|
|
if (!mComFilterList.IsEmpty()) {
|
|
dialog->SetFileTypes(mComFilterList.Length(), mComFilterList.get());
|
|
dialog->SetFileTypeIndex(mSelectedType);
|
|
}
|
|
|
|
// display
|
|
|
|
{
|
|
AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ?
|
|
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
|
|
AutoTimerCallbackCancel atcc(this, PickerCallbackTimerFunc);
|
|
AutoWidgetPickerState awps(mParentWidget);
|
|
|
|
if (FAILED(dialog->Show(adtw.get()))) {
|
|
dialog->Unadvise(mFDECookie);
|
|
return false;
|
|
}
|
|
dialog->Unadvise(mFDECookie);
|
|
}
|
|
|
|
// results
|
|
|
|
// Remember what filter type the user selected
|
|
UINT filterIdxResult;
|
|
if (SUCCEEDED(dialog->GetFileTypeIndex(&filterIdxResult))) {
|
|
mSelectedType = (int16_t)filterIdxResult;
|
|
}
|
|
|
|
// single selection
|
|
if (mMode != modeOpenMultiple) {
|
|
RefPtr<IShellItem> item;
|
|
if (FAILED(dialog->GetResult(getter_AddRefs(item))) || !item)
|
|
return false;
|
|
return WinUtils::GetShellItemPath(item, mUnicodeFile);
|
|
}
|
|
|
|
// multiple selection
|
|
RefPtr<IFileOpenDialog> openDlg;
|
|
dialog->QueryInterface(IID_IFileOpenDialog, getter_AddRefs(openDlg));
|
|
if (!openDlg) {
|
|
// should not happen
|
|
return false;
|
|
}
|
|
|
|
RefPtr<IShellItemArray> items;
|
|
if (FAILED(openDlg->GetResults(getter_AddRefs(items))) || !items) {
|
|
return false;
|
|
}
|
|
|
|
DWORD count = 0;
|
|
items->GetCount(&count);
|
|
for (unsigned int idx = 0; idx < count; idx++) {
|
|
RefPtr<IShellItem> item;
|
|
nsAutoString str;
|
|
if (SUCCEEDED(items->GetItemAt(idx, getter_AddRefs(item)))) {
|
|
if (!WinUtils::GetShellItemPath(item, str))
|
|
continue;
|
|
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
|
|
if (file && NS_SUCCEEDED(file->InitWithPath(str)))
|
|
mFiles.AppendObject(file);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// nsIFilePicker impl.
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::ShowW(int16_t *aReturnVal)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aReturnVal);
|
|
|
|
*aReturnVal = returnCancel;
|
|
|
|
AutoSuppressEvents supress(mParentWidget);
|
|
|
|
nsAutoString initialDir;
|
|
if (mDisplayDirectory)
|
|
mDisplayDirectory->GetPath(initialDir);
|
|
|
|
// If no display directory, re-use the last one.
|
|
if(initialDir.IsEmpty()) {
|
|
// Allocate copy of last used dir.
|
|
initialDir = mLastUsedUnicodeDirectory;
|
|
}
|
|
|
|
// Clear previous file selections
|
|
mUnicodeFile.Truncate();
|
|
mFiles.Clear();
|
|
|
|
// Launch the XP file/folder picker on XP and as a fallback on Vista+.
|
|
// The CoCreateInstance call to CLSID_FileOpenDialog fails with "(0x80040111)
|
|
// ClassFactory cannot supply requested class" when the checkbox for
|
|
// Disable Visual Themes is on in the compatability tab within the shortcut
|
|
// properties.
|
|
bool result = false, wasInitError = true;
|
|
if (mMode == modeGetFolder) {
|
|
if (IsVistaOrLater())
|
|
result = ShowFolderPicker(initialDir, wasInitError);
|
|
if (!result && wasInitError)
|
|
result = ShowXPFolderPicker(initialDir);
|
|
} else {
|
|
if (IsVistaOrLater())
|
|
result = ShowFilePicker(initialDir, wasInitError);
|
|
if (!result && wasInitError)
|
|
result = ShowXPFilePicker(initialDir);
|
|
}
|
|
|
|
// exit, and return returnCancel in aReturnVal
|
|
if (!result)
|
|
return NS_OK;
|
|
|
|
RememberLastUsedDirectory();
|
|
|
|
int16_t retValue = returnOK;
|
|
if (mMode == modeSave) {
|
|
// Windows does not return resultReplace, we must check if file
|
|
// already exists.
|
|
nsCOMPtr<nsIFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
|
|
bool flag = false;
|
|
if (file && NS_SUCCEEDED(file->InitWithPath(mUnicodeFile)) &&
|
|
NS_SUCCEEDED(file->Exists(&flag)) && flag) {
|
|
retValue = returnReplace;
|
|
}
|
|
}
|
|
|
|
*aReturnVal = retValue;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::Show(int16_t *aReturnVal)
|
|
{
|
|
return ShowW(aReturnVal);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::GetFile(nsIFile **aFile)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aFile);
|
|
*aFile = nullptr;
|
|
|
|
if (mUnicodeFile.IsEmpty())
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
|
|
|
|
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
|
|
|
|
file->InitWithPath(mUnicodeFile);
|
|
|
|
NS_ADDREF(*aFile = file);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::GetFileURL(nsIURI **aFileURL)
|
|
{
|
|
*aFileURL = nullptr;
|
|
nsCOMPtr<nsIFile> file;
|
|
nsresult rv = GetFile(getter_AddRefs(file));
|
|
if (!file)
|
|
return rv;
|
|
|
|
return NS_NewFileURI(aFileURL, file);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aFiles);
|
|
return NS_NewArrayEnumerator(aFiles, mFiles);
|
|
}
|
|
|
|
// Get the file + path
|
|
NS_IMETHODIMP
|
|
nsBaseWinFilePicker::SetDefaultString(const nsAString& aString)
|
|
{
|
|
mDefaultFilePath = aString;
|
|
|
|
// First, make sure the file name is not too long.
|
|
int32_t nameLength;
|
|
int32_t nameIndex = mDefaultFilePath.RFind("\\");
|
|
if (nameIndex == kNotFound)
|
|
nameIndex = 0;
|
|
else
|
|
nameIndex ++;
|
|
nameLength = mDefaultFilePath.Length() - nameIndex;
|
|
mDefaultFilename.Assign(Substring(mDefaultFilePath, nameIndex));
|
|
|
|
if (nameLength > MAX_PATH) {
|
|
int32_t extIndex = mDefaultFilePath.RFind(".");
|
|
if (extIndex == kNotFound)
|
|
extIndex = mDefaultFilePath.Length();
|
|
|
|
// Let's try to shave the needed characters from the name part.
|
|
int32_t charsToRemove = nameLength - MAX_PATH;
|
|
if (extIndex - nameIndex >= charsToRemove) {
|
|
mDefaultFilePath.Cut(extIndex - charsToRemove, charsToRemove);
|
|
}
|
|
}
|
|
|
|
// Then, we need to replace illegal characters. At this stage, we cannot
|
|
// replace the backslash as the string might represent a file path.
|
|
mDefaultFilePath.ReplaceChar(FILE_ILLEGAL_CHARACTERS, '-');
|
|
mDefaultFilename.ReplaceChar(FILE_ILLEGAL_CHARACTERS, '-');
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsBaseWinFilePicker::GetDefaultString(nsAString& aString)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// The default extension to use for files
|
|
NS_IMETHODIMP
|
|
nsBaseWinFilePicker::GetDefaultExtension(nsAString& aExtension)
|
|
{
|
|
aExtension = mDefaultExtension;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsBaseWinFilePicker::SetDefaultExtension(const nsAString& aExtension)
|
|
{
|
|
mDefaultExtension = aExtension;
|
|
return NS_OK;
|
|
}
|
|
|
|
// Set the filter index
|
|
NS_IMETHODIMP
|
|
nsFilePicker::GetFilterIndex(int32_t *aFilterIndex)
|
|
{
|
|
// Windows' filter index is 1-based, we use a 0-based system.
|
|
*aFilterIndex = mSelectedType - 1;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::SetFilterIndex(int32_t aFilterIndex)
|
|
{
|
|
// Windows' filter index is 1-based, we use a 0-based system.
|
|
mSelectedType = aFilterIndex + 1;
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsFilePicker::InitNative(nsIWidget *aParent,
|
|
const nsAString& aTitle)
|
|
{
|
|
mParentWidget = aParent;
|
|
mTitle.Assign(aTitle);
|
|
}
|
|
|
|
void
|
|
nsFilePicker::GetQualifiedPath(const wchar_t *aInPath, nsString &aOutPath)
|
|
{
|
|
// Prefer a qualified path over a non qualified path.
|
|
// Things like c:file.txt would be accepted in Win XP but would later
|
|
// fail to open from the download manager.
|
|
wchar_t qualifiedFileBuffer[MAX_PATH];
|
|
if (PathSearchAndQualifyW(aInPath, qualifiedFileBuffer, MAX_PATH)) {
|
|
aOutPath.Assign(qualifiedFileBuffer);
|
|
} else {
|
|
aOutPath.Assign(aInPath);
|
|
}
|
|
}
|
|
|
|
void
|
|
nsFilePicker::AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter)
|
|
{
|
|
mFilterList.Append(aTitle);
|
|
mFilterList.Append(char16_t('\0'));
|
|
|
|
if (aFilter.EqualsLiteral("..apps"))
|
|
mFilterList.AppendLiteral("*.exe;*.com");
|
|
else
|
|
{
|
|
nsAutoString filter(aFilter);
|
|
filter.StripWhitespace();
|
|
if (filter.EqualsLiteral("*"))
|
|
filter.AppendLiteral(".*");
|
|
mFilterList.Append(filter);
|
|
}
|
|
|
|
mFilterList.Append(char16_t('\0'));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
|
|
{
|
|
if (IsVistaOrLater()) {
|
|
mComFilterList.Append(aTitle, aFilter);
|
|
} else {
|
|
AppendXPFilter(aTitle, aFilter);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsFilePicker::RememberLastUsedDirectory()
|
|
{
|
|
nsCOMPtr<nsIFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
|
|
if (!file || NS_FAILED(file->InitWithPath(mUnicodeFile))) {
|
|
NS_WARNING("RememberLastUsedDirectory failed to init file path.");
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIFile> dir;
|
|
nsAutoString newDir;
|
|
if (NS_FAILED(file->GetParent(getter_AddRefs(dir))) ||
|
|
!(mDisplayDirectory = do_QueryInterface(dir)) ||
|
|
NS_FAILED(mDisplayDirectory->GetPath(newDir)) ||
|
|
newDir.IsEmpty()) {
|
|
NS_WARNING("RememberLastUsedDirectory failed to get parent directory.");
|
|
return;
|
|
}
|
|
|
|
if (mLastUsedUnicodeDirectory) {
|
|
NS_Free(mLastUsedUnicodeDirectory);
|
|
mLastUsedUnicodeDirectory = nullptr;
|
|
}
|
|
mLastUsedUnicodeDirectory = ToNewUnicode(newDir);
|
|
}
|
|
|
|
bool
|
|
nsFilePicker::IsPrivacyModeEnabled()
|
|
{
|
|
return mLoadContext && mLoadContext->UsePrivateBrowsing();
|
|
}
|
|
|
|
bool
|
|
nsFilePicker::IsDefaultPathLink()
|
|
{
|
|
NS_ConvertUTF16toUTF8 ext(mDefaultFilePath);
|
|
ext.Trim(" .", false, true); // watch out for trailing space and dots
|
|
ToLowerCase(ext);
|
|
if (StringEndsWith(ext, NS_LITERAL_CSTRING(".lnk")) ||
|
|
StringEndsWith(ext, NS_LITERAL_CSTRING(".pif")) ||
|
|
StringEndsWith(ext, NS_LITERAL_CSTRING(".url")))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
nsFilePicker::IsDefaultPathHtml()
|
|
{
|
|
int32_t extIndex = mDefaultFilePath.RFind(".");
|
|
if (extIndex >= 0) {
|
|
nsAutoString ext;
|
|
mDefaultFilePath.Right(ext, mDefaultFilePath.Length() - extIndex);
|
|
if (ext.LowerCaseEqualsLiteral(".htm") ||
|
|
ext.LowerCaseEqualsLiteral(".html") ||
|
|
ext.LowerCaseEqualsLiteral(".shtml"))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
nsFilePicker::ComDlgFilterSpec::Append(const nsAString& aTitle, const nsAString& aFilter)
|
|
{
|
|
COMDLG_FILTERSPEC* pSpecForward = mSpecList.AppendElement();
|
|
if (!pSpecForward) {
|
|
NS_WARNING("mSpecList realloc failed.");
|
|
return;
|
|
}
|
|
memset(pSpecForward, 0, sizeof(*pSpecForward));
|
|
nsString* pStr = mStrings.AppendElement(aTitle);
|
|
if (!pStr) {
|
|
NS_WARNING("mStrings.AppendElement failed.");
|
|
return;
|
|
}
|
|
pSpecForward->pszName = pStr->get();
|
|
pStr = mStrings.AppendElement(aFilter);
|
|
if (!pStr) {
|
|
NS_WARNING("mStrings.AppendElement failed.");
|
|
return;
|
|
}
|
|
if (aFilter.EqualsLiteral("..apps"))
|
|
pStr->AssignLiteral("*.exe;*.com");
|
|
else {
|
|
pStr->StripWhitespace();
|
|
if (pStr->EqualsLiteral("*"))
|
|
pStr->AppendLiteral(".*");
|
|
}
|
|
pSpecForward->pszSpec = pStr->get();
|
|
}
|