Files
palemoon27/layout/generic/nsPluginFrame.cpp
T
roytam1 ebda1f73c4 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1208341 - Make NativeObject::goodElementsAllocationAmount fallible. r=Waldo (64eac96aa2)
- minor reformat (95d27e5332)
- Bug 1214049 - Use ReportOutOfMemory in NativeObject::goodElementsAllocationAmount. r=Waldo (6779dd81c6)
- Bug 1206700 - Fix an bug in property assignment, recently exposed by Reflect.set. r=waldo (0a7484ab70)
- Bug 1186810 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (05a550c94f)
- Bug 1186810 (part 2) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (f1659abf38)
- Bug 1186810 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (cda73950f3)
- Bug 1186810 (part 4) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (555e83bacb)
- Bug 1186810 (part 5) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (c9520dbc5f)
- Bug 1186810 (part 6) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=khuey. (24fcdfd772)
- Bug 1186810 (part 7) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=khuey. (657cd575fb)
- Bug 1186810 (part 8) - Replace nsBaseHashtable::Enumerate() calls in dom/workers/ with iterators. r=khuey. (0ff6a5e5ff)
- Bug 1205020 - Disable optimizations in TestTuple.cpp since it breaks the build on VS2013 Windows 10. r=froydnj (1c98d8485c)
- Bug 1199068 - Soothe a unused variable warning in TestSplayTree.cpp. r=nfroyd (d4d4ab56fe)
- Bug 1209751 - Make sync decoding more reliable when nsImageRenderer is used with -moz-element. r=roc (95c99bb907)
- Bug 1209731 - Return DrawResult::NOT_READY from PaintBackgroundWithSC if we couldn't prepare the nsImageRenderer. r=tn (8bd98872cb)
- Bug 1209715 - Add operator overloads for combining DrawResults. r=tn (f3a9806d03)
- Bug 1209725 - Use DrawResult combining operators in nsCSSRendering::PaintBackgroundWithSC. r=tn (420cfde63e)
- Bug 1211363. Calculate min inset blur with max border radius. r=mstange (5e408bc67f)
- Bug 1213545. Carry x,y offsets with inset box shadows. r=mstange (52c20715bc)
- Bug 1209739 - Make nsImageRenderer::PrepareImage() fail unless an image has STATUS_LOAD_COMPLETE. r=tn (c1cc4d79d8)
- Bug 1209765 (Part 1) - Support sync decoding of border-image in nsCSSRendering. r=tn (3a54b7d117)
- Bug 1209765 (Part 2) - Support sync decoding and track draw results in nsDisplayBorder. r=tn (03abe63e67)
- Bug 1209765 (Part 3) - Support sync decoding and track draw results when drawing borders in nsButtonFrameRenderer. r=tn (107b9bb851)
- Bug 1209765 (Part 4) - Support sync decoding and track draw results when drawing borders in nsFieldSetFrame. r=tn (16fd30aba3)
- Bug 1209765 (Part 5) - Support sync decoding and track draw results when drawing borders in nsRangeFrame. r=tn (289de3c17e)
- Bug 1209765 (Part 6) - Support sync decoding and track draw results when drawing borders in nsColumnSetFrame. r=tn (0317d6a914)
- Bug 1143267 - Make nsDisplayAltFeedback use nsGenericImageGeometry. r=tn (8fc6372d48)
- Bug 1176081. Add a pref to control drawing of the image loading place holder icon and border, and disable it. r=seth (792e8ec9b3)
- Bug 1209765 (Part 7) - Support sync decoding and track draw results when drawing borders in nsImageFrame. r=tn (70d9af60a3)
- Bug 1209765 (Part 8) - Support sync decoding and track draw results when drawing borders in MathML code. r=tn (555bff2635)
- Bug 1209765 (Part 9) - Support sync decoding and track draw results when drawing borders in nsTableFrame. r=tn (d242dc5c79)
- Bug 1209765 (Part 10) - Support sync decoding and track draw results when drawing borders in nsGroupBoxFrame. r=tn (a7187cfa5d)
- Bug 1209765 (Part 11) - Support sync decoding and track draw results when drawing borders in nsTreeBodyFrame. r=tn (21bd2b3285)
- Bug 1209765 (Followup) - Add very minor fuzz to underline-button-2.html on OS X 10.10. r=me (04cff3c2ff)
- Bug 1209765 (Followup) - Add very minor fuzz to underline-button-1.html on OS X 10.10. r=me DONTBUILD (187fdb4106)
- Bug 1217069 - Don't attempt to mis-optimize JSON.stringify's filter-list creation for replacer arrays with trailing holes. r=arai (04fb907d42)
- Bug 1156463 - Add a preference option to disable the scale transform applied to MathML operators. r=karl (415a041117)
- Bug 1174143 - Remove private tables for Standard Symbols L and MathJax fonts. r=karlt (1f58d14229)
- Bug 1222297 - Use channel->Open2() in netwerk/base/nsNetUtil.cpp (r=sicking) (cbd12ebb0a)
- Bug 1139709. Remove unused parameters from nsMathMLChar::GetMaxWidth. r=mats (6ea90a0a02)
- Bug 1160635 patch 1 - Add reftests. r=dholbert (b58f8fd7fa)
- Bug 1160635 patch 2 - Stop making image resizing optimization when image has percent width or height. r=dholbert (9ae3621baf)
- Bug 1156097 - Make nsImageFrame::mImageMap an nsRefPtr; r=roc (b49157e424)
- Bug 1176156. Make sure images are asked to decode if we are drawing the alt feedback instead of the image. r=seth (8d7a09622e)
- Bug 1207355 (Part 2) - Stop requesting decodes in nsImageLoadingContent. r=tn (c781285098)
- Bug 1207355 (Part 3) - Request decodes intelligently in nsImageFrame. r=tn (c61b7591fb)
- Bug 1156028 - Teach clang-analyzer about XPCOM assertion macros; r=froydnj (4d8b7ecf03)
- Bug 1207355 (Part 4) - Request decodes intelligently in nsBulletFrame. r=tn (2d7ced9c0f)
- Bug 1207355 (Part 5) - Request decodes intelligently in MultipartImage. r=tn (c0cb580838)
- Bug 1207355 (Part 6) - Only respect StartDecoding() in imgRequest/imgRequestProxy. r=tn (0e108cda4c)
- Bug 1207355 (Part 7) - Only trigger intrinsic size decode in FinalizeDecoder() if StartDecoding() was called. r=tn (a71fc0d1b7)
- Bug 1207355 (Part 8) - Remove imgIContainer::RequestDecode() and imgIRequest::RequestDecode(). r=tn (fbce1ccbe1)
- Bug 1215596 - outline: auto; will render as outline: solid; when disabled. r=roc (b8ea369628)
- Bug 1180966. Remove code that made no sense. r=mstange (eac62913ef)
- Bug 1217905. Don't transform dest rects if destination context has a rotation with inset box shadows. r=mstange (53cf4d6f86)
- Bug 1189010. In ScrollFrameHelper::BuildDisplayList decide if we are building a scrollable layer before we call AppendScrollPartsTo because it needs this information. r=mstange (a008c7e34d)
- Bug 1204535 - Flatten conditional structure one level. r=tn (152ff398a0)
- Bug 1204535 - Remove no-op code. r=tn (95d17e64c3)
- Bug 1204535 - Collapse redundant conditional block. r=tn (d0e90b8d80)
- Bug 1204535 - Rename usingDisplayport to usingDisplayPort for consistency. r=tn (516757a933)
- Bug 1204535 - Relocate comment to go with the line of code it's commenting. r=tn (70ae0c5e71)
- Bug 1204535 - Hoist out the code to initially compute usingDisplayPort. r=tn (4a5336a480)
- Bug 1210578. Part 1. Rename mShouldBuildScrollableLayer to mWillBuildScrollableLayer to better capture the meaning of the variable. r=mstange (d13bb100f4)
- Bug 1210578. Part 2. Rename shouldBuildLayer to couldBuildLayer to better reflect it's actual meaning. r=mstange (ae21c687c2)
- Bug 1151663 - Only call GetOrMaybeCreateDisplayPort() in nsLayoutUtils::PaintFrame() if we are using containers for root scroll frames. r=tn (2bef3f9457)
- Bug 1195431 - Small refactoring to use conditionals consistently. r=tn (897eb0f42a)
- Bug 1167069 - Initialize nsPluginFrame::mInstanceOwner to null. r=jmathies (6ce1fcb8c2)
- Bug 1137944 - Add support for hiding plugin windows during async dom scroll operations managed in the content process. r=roc (730a0ed004)
- Bug 1210578. Part 3. Create DecideScrollableLayer that encapsulates all logic to create display ports and build scrollable layers. r=mstange (994ac6ec5e)
- Bug 376679 part.1 Change the result of EventStateManager::ComputeScrollTarget() from nsIScrollableFrame* to nsIFrame* r=smaug (914878edbd)
- Bug 376679 part.2 EventStateManager should treat plugin frame as scrollable frame if the plugin wants to handle wheel events as default action r=smaug (58c146b7ba)
- Bug 376679 part.3 Compute default action target frame for wheel event before deciding the action because plugin should decide what is the default action when the target is a plugin frame r=smaug (334cbfcf53)
- Bug 376679 part.4 Manage wheel transaction at sending a wheel event to target plugin r=smaug (d76062a429)
- Bug 376679 part.5 nsPluginInstanceOwner::ProcessEvent() should create WM_MOUSE*WHEEL message from WidgetWheelEvent data r=smaug+jimm (56ee6bdf90)
- Bug 376679 part.6 nsPluginInstanceOwner::ProcessEvent() should refer both deltaMode and system scroll amount settings when it generates WM_MOSUE*WHEEL messages r=jimm (927cb10a3b)
- Bug 1145546 - Add missing nsBidiPresUtils.h include to nsGfxScrollFrame.cpp to fix non-unified bustage. r=jfkthame (af4043c024)
- Bug 1137944 - Add plugin window handling for apz related notifications received by the content process. r=mstange (798e9676fd)
- Bug 1208819 - Fix irregexp overrecursion check to ignore interrupts. r=bhackett (c845e65a2e)
- Bug 1218640 - IonMonkey: MIPS64: Add support into irregexp. r=arai (613ddd95ef)
- Bug 1211964 - Fix a couple of OOM handling issues in regexp code r=terrence (bb269eef3e)
- Bug 1200734 - Use stable hashing for LiveScopesMap; r=shu (1d717c8f53)
- Bug 1223853 - Use stable hashing for ObjectValueMap; r=jonco (c91f3b1b21)
- Bug 1223863 - Use stable hashing for WeakGlobalObjectSet; r=jonco (eb29e841f1)
- Bug 1223918 - Use stable hashing for WatchPointMap; r=jonco (7a69630c83)
- Bug 1212011 - Replace more uses of CrashAtUnhandlableOOM() with AutoEnterOOMUnsafeRegion r=terrence (0079439d90)
- Bug 1224347 - Use stable hashing for DebuggerWeakMaps; r=jonco (d2a627e077)
- Bug 1219418 - Always access minEmptyChunkCount under the GC lock; r=jonco (f67f74ca57)
- Bug 1202923 - Encapsulate GC begin and end notification callbacks in an RAII guard; r=jonco (46f63fd090)
- Bug 1212624 - Tests for LinkedList, r=Waldo (3d48b12918)
- Bug 1215752 - Weakmap refactoring, r=terrence (90cbf4d294)
- Bug 1216744 - Move weakKeys to the zone, r=terrence (5fdb1d57bf)
- Bug 1215336 - Measure unmark gray time, r=terrence (278e0ee562)
- Bug 1211939 - Don't call JSRuntime::onOutOfMemory from helper threads. r=jonco (86c6906421)
- Bug 1218638 - IonMonkey: MIPS64: Add support into jit/shared. r=lth (e4f2904c53)
- Bug 1216277 - Don't assert properties of the buffer location if the assembler is out of memory r=jandem (65556e83ce)
- Bug 1211962 - addNativeToBytecodeEntry: Check that the masm.currentOffset() returns a valid result. r=djvj (3c5723c65a)
- Bug 1090957 - IonMonkey: Add temp registers for mips atomics. r=lth (00f23fe2e9)
- Bug 1218967 - Do not stop executing autospider.sh on test failure. r=sfink (75f912efbb)
- Bug 1213881 - Run jsapi-tests in the arm64-sim autospider. r=sfink (2e731f14e7)
- Bug 1216607 - Fix assertion failure ARM assembler on OOM r=jandem (0bc2dcb5db)
- Bug 1209515 part 1 - IonBuilder: Attach hit counts on the MIRGraph. r=bhackett (f5448d9596)
- Bug 1209515 part 2 - Ensure that MPhi removal considers removed uses. r=bhackett (95de413c50)
- Bug 1209515 part 3 - IonMonkey: Add branch pruning based on code coverage counters. r=bhackett (fb71022658)
- Bug 1209515 part 0 - Move callerResumePoint field next to other resume points of basic blocks. r=bbouvier (394b52860d)
- Bug 1209515 part 4 - Increment code coverage counters on bailouts. r=bhackett (22edac5c24)
- Bug 1209515 part 5 - Ensure that we recompile when we have frequent bailouts caused by the first execution. r=jandem (bca0fa4118)
- Bug 1209515 part 7 - IonBuilder: pushLoop should not infer the continuepc from the entry block. r=jandem (025d10fd57)
- Bug 1209515 part 8 - IonBuilder: newOsrPreheader should not use the hit-count of the loop. r=jandem (5db05ef17f)
- Bug 1209515 part 9 - IonBuilder: Loop header should use the hit count of the loop, instead of before the loop. r=jandem (b259b490bf)
- Bug 1209515 part 10 - Prevent PruneUnusedBranches from being greedy while removing branches which have only be visited a few times. r=bhackett (4a1a7b34b6)
- Bug 1209515 part 11 - Increase JitSpewer mask size to avoid overflow. r=bbouvier (28546de94e)
- Bug 1219401 - Don't call script->hasIonScript() off-thread, fixes a TSan race. r=h4writer (8f31724484)
- Bug 1172076 - Assert that SnapshotIterator::initInstructionResults always match the recover instructions data. r=jandem (6ed0eebc65)
- Bug 1209260 - Don't use sincos on iOS r=npb (eaa3cacac7)
- Bug 1222499 - "JitSpew/IonSpew: warmupCounter should use PRIu32 instead of PRIuSIZE". r=nbp (50b80b985a)
- Bug 1216182: Rename MODE_MASK to MODE_BITS_MASK, r=hv1989 (f28e461d94)
- Bug 1137944 - Add a pref to control plugin window hiding. r=roc (691dc99b94)
- Bug 1214878 - When async scrolling with e10s hide windowed plugins in sub documents. r=roc (79c0eac459)
- Bug 1215434 part.1 If scroll target is a plugin frame, EventStateManager::PostHandleEvent() should send the wheel event to the plugin frame even if APZC already handled it r=smaug (f2e8e33d7f)
- Bug 1215434 part.2 Add plugin frame rect to dispatch-to-content region if it wants to handle wheel event as default action r=mstange (dbecb1e256)
- Fix inactive scroll frames sometimes creating very large, incorrect hit regions. (bug 1190112, r=tn) (2056d8d63e)
- Fix scrollbars on subframes not directing APZ events to the correct scrollframe. (bug 1213324, r=tn) (0594923ab2)
- Bug 1182017. Call Send__delete__ immediately rather than through an event. r=nical (90714b065b)
- Bug 1212656 - ARM64: Fix automation build failures. (r=efaust) (5695518dd1)
- Bug 1137944 - Simplify the api associated with hiding e10s plugin widgets. r=roc (dfbfda4d31)
- Bug 1137944 - Fire before and after composite events. r=matt.woodrow (0048aeb8cb)
- Bug 1201660 - When layer tree updates get dropped, hide plugins associated with the tree. Fixes a bug where we were hiding all plugins associated with the window. r=matt.woodrow (9352150c73)
- Bug 1137944 - Backout compositor bits (cset b4711fa5f734) which caused a telemetry metric regression. r=backout (241659d6a8)
- Bug 1127270: Only acquire a hold on the compositor thread once the channel for a parent actor has been succesfully connected. r=nical (1d1b077d68)
- Bug 1207270 - Ensure that the TaskThrottler objects are created on the main thread. r=botond (b43af025f1)
- Bug 1194876 - Add test. r=botond (440c72ec81)
- Bug 1152051 - Gtest. r=Cwiiis,kats (011f066f37)
- Bug 1144112 - Update the FlingStop tests to check if events are flowing properly after the fast-motion blocks are done. r=botond (25f71629d7)
- Bug 1092128 - Ensure that when touch-action is enabled the gtests always provide default touch behaviours where expected. r=botond (3f0d1229f3)
- Bug 1144112 - Only set the default allowed touch behaviour if the event is not consumed, to have the tests better reflect reality. r=botond (1548bd14bb)
- Bug 1163845 - Unify handling of time in APZ gtests. r=kats (b73a16ef5e)
- Bug 1159398 - Set the controller thread when running APZ gtests. r=dvander (96b551036e)
- Bug 1159985 - Gtest. r=kats (23d7d86492)
- Bug 1159985 - In APZ gtests, allow panning in both directions. r=kats (14f4b1156a)
- Bug 1169695 - Make the test timestamp privately held by the MockContentControllerDelayed. r=botond (ffe04249c1)
- Bug 1198900 - Add a gtest to ensure we don't crash when prevent-defaulting a wheel event. r=botond, a=topcrash (c9e5993f18)
- Bug 1169690 - Gtests. r=kats (7e825b34ac)
- Bug 1207270 - Update tests to ensure that TaskThrottlers are created as appropriate. r=botond (7bb6f1f406)
- Bug 1169695 - Ensure timed tasks are dispatched appropriately when advancing the time. r=botond (af1fbe0a85)
- Bug 1204837, Part 1: Make ClosingService thread Nuwa-friedly. r=khuey (eb790b5215)
- Bug 1204837, Part 2: Cloned ImageBridgeParent and CompositorParent should hold a reference to the compositor thread. r=nical (cd742df2e2)
- Bug 1205016: double ClosingService thread stack size to avoid stack overflow r=glandium (cb9acc828f)
- Bug 1163570 - Ignore pending plugin updates and hide plugin windows when a remote layer tree associated with a tab is no longer in use. r=roc (ae852ad442)
- Bug 1196539 - Apply plugin config using AutoResolveRefLayers during composition. r=matt.woodrow (12dbdb6222)
- Bug 1137944 - Cache compositor plugin update data to avoid sending updates to the main thread when the data doesn't change. r=roc (63c503d2f6)
- Bug 1137944 - On Windows defer composition until we receive confirmation plugin window metrics have been updated. r=roc (39d5786519)
- Bug 1137944 - Move plugin window metrics updates to a point during comososition where we know the remote layer tree is hooked up to the chrome layer tree. r=matt.woodrow (a32f77ffb1)
- Bug 1213671 - CompositorParent::UpdatePluginWindowState should always return an accurate result indicating when an ipc request for plugin geometry updates was sent. r=roc (311e65a8ce)
- Bug 1214267 - Send the side to which fixed-pos items are attached so that we can move them in the compositor more correctly when the viewport size is changing. r=mattwoodrow (fa2de207cd)
- Bug 1209964 - In AlignFixedAndStickyLayers(), properly handle the case where a fixed or sticky layer is its own subtree root and has a local transform. r=kats (1a6922699a)
- Bug 1213762 - Clear AsyncCompositionManager::mIsFirstPaint on non-Android platforms, too. r=mstange (c4cf2b722a)
- Bug 1223436 - Fix AsyncCompositionManager so that mLayersUpdated is only set to false after SyncFrameMetrics has been called. r=kats (f3fa84325b)
- bits of 1073545 (3bc7d76081)
- Bug 1213795, Part 1: Don't fire timers in the Nuwa process to fix test case test_NuwaProcessDeadlock.html. r=khuey (5ebca946e5)
- Bug 1213795, Part 2: Fix protocol cloning of actor CrossProcessCompositorParent. r=khuey (92969e2b06)
- spacing (f4857ed898)
- Bug 1213758 - Aquire the inderect layer trees data lock during plugin window update calculations. r=matt.woodrow (ae70d955ec)
- Bug 1208502 - Use more smart pointers in XULDocument. r=smaug (20a92d72e8)
- Bug 1193086 - Remove some null checks of infallible new code in XUL. r=baku (2f463c5a3d)
- Bug 1217190 - Make PrintingParent return an nsresult when attempting to show print progress. r=bobowen (addf31f3a7)
- Bug 1217190 - Make sure to initialize outparam in PrintingParent::RecvShowProgress. r=bobowen (f6c11a0181)
- Bug 1152921 - Don't send an uninitialized PrintData over IPC when cancelling print dialog (or failing ShowPrintDialog for other reasons). r=mconley (4ea146ccf1)
- Bug 1178233 - [non-e10s] The update process doesn't work within about:serviceworkers in non-e10s mode. r=baku (7a08441bec)
- Bug 929846 - Considering key size when calculating quota usage. r=jdm (a97ddc7906)
- Bug 1194049 - Part 3: support device update; r=fabrice (6ba600a03d)
- Bug 1194049 - Part 1: add thread assertion; r=schien (68c4658ae0)
- Bug 1194049 - Part 2: add discovery timeout support; r=schien (14f5f537d5)
- Bug 1194049 - Part 4: clear discovered devices when re-discover; r=schien (e2ecdb573f)
- Bug 1136565 - report session request from device provider. r=xeonchen,junior,seanlin. (19daa67751)
- Bug 1216398 - support non-discoverable controlling device. r=junior,xeonchen. (7383401dbc)
- Bug 1200132 - Use adderss to create socketTransport, r=schien, junior (263d253562)
- Bug 1200132 - Part1: Get address info after service resolved, r=mcmanus (9bcc344d20)
- Bug 1200132 - Part2: Get IP address by calling InetAddress.getHostAddress(), r=mcmanus, rnewman (502c243314)
- Bug 1173334: Open nfcd connections with socket type SOCK_SEQPACKET, allstars.chh (03a11dc077)
- Bug 1173802: Move NFC socket and messaging code into |NfcConsumer|, r=allstars.chh (f92946b40e)
- Bug 1173802: Run |NfcConsumer| on NFC thread, r=allstars.chh (87989483a7)
- Bug 1173802: Clean up |NfcEventDispatcher|, r=allstars.chh (87f58b7310)
- Bug 1173802: Replace |assertIsNfcServiceThread| with thread-safe checks, r=allstars.chh (1a6a76ae05)
- Bug 1173802: Store global NFC service in ref-counted variable, r=allstars.chh (a33c025976)
- Bug 1188639 - Fix typo in BrowserElement.webidl and add tests for it. r=yoshi,bz (7b657a335d)
- Bug 1175387 - close file descriptor after detached from STS. r=mcmanus (377943bad5)
- Bug 1190069 - Fix uninitialized variable in MDNSResponderOperator.cpp. r=xeonchen (ebf47b613e)
- Bug 1217807 - Part 1: use ServiceWatcher to extend life cycle of mDNS operators; r=schien (70201259d2)
- missing namespace (c6bccda1e5)
- Bug 1209843 - Stop checking for UNKNOWN_APP_ID in all places except those where AppId() is explicitly queried. r=sicking (e364223906)
- Bug 1168337: Kill the processes on startup of the Nuwa test case fix the abort in the preallocated process. r=khuey (501a30cb9b)
- Bug 1202424 - Free shared memory when IPC system shuts down, not after. r=mrbkap (f718cbf801)
- Bug 1209987 - webrtc.org Engine creation and destruction should happen on the WebRTC threads. r=jesup (4bbab795cf)
- Bug 1214675 - Factor out cleanup functions to avoid deadlock/dispatch-without-IPC. r=jesup (bd466c85e4)
- Bug 1210560 - Part 2: Convert some simple users to use PushGroupForBlendBack. r=jrmuizel (158b532f9f)
- Bug 1174785 - Part 0: Use mozilla/StaticPtr.h in signaling. r=jesup (c98ec23ee0)
- Bug 1174785 - Part 1: Add LogModule, LogModuleManager, and LazyLogModule. r=froydnj (e797bca424)
- Bug 1195867 - Hoist StateWatching and StateMirroring into XPCOM. r=froydnj (a62fbbf749)
- Bug 1194631 - Make firefox build with --disable-logging. r=jrmuizel (ba8238dc42)
- Bug 1174785 - Part 2: Convert xpcom over to LogModule. r=froydnj (ccb119d496)
- Bug 1205237 - Part 2: add PresentationNetworkHelper; r=schien (be47702ffe)
- Bug 1205237 - Part 3: get self Wi-Fi IP address; r=seanlin (f31163e895)
- Bug 1217683 - Add sendIceCandidate and implement |close(aReason)| in TCPControlChannel. r=fabrice (0004ea93f1)
- Bug 1217807 - Part 2: Handle network online/offline event in TCPPresentationServer; r=junior (48c9236adb)
- Bug 1217807 - disable MDNS discovery. r=xeonchen. (ee3cb0ddb6)
2022-11-23 13:32:46 +08:00

2032 lines
63 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* 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/. */
/* rendering objects for replaced elements implemented by a plugin */
#include "nsPluginFrame.h"
#include "gfx2DGlue.h"
#include "gfxMatrix.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/MouseEvents.h"
#ifdef XP_WIN
// This is needed for DoublePassRenderingEvent.
#include "mozilla/plugins/PluginMessageUtils.h"
#endif
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsWidgetsCID.h"
#include "nsView.h"
#include "nsViewManager.h"
#include "nsString.h"
#include "nsGkAtoms.h"
#include "nsIPluginInstanceOwner.h"
#include "nsNPAPIPluginInstance.h"
#include "nsIDOMElement.h"
#include "nsRenderingContext.h"
#include "npapi.h"
#include "nsIObjectLoadingContent.h"
#include "nsContentUtils.h"
#include "nsDisplayList.h"
#include "nsFocusManager.h"
#include "nsLayoutUtils.h"
#include "nsFrameManager.h"
#include "nsIObserverService.h"
#include "GeckoProfiler.h"
#include <algorithm>
#include "nsIObjectFrame.h"
#include "nsPluginNativeWindow.h"
#include "FrameLayerBuilder.h"
#include "ImageLayers.h"
#include "nsPluginInstanceOwner.h"
#ifdef XP_WIN
#include "gfxWindowsNativeDrawing.h"
#include "gfxWindowsSurface.h"
#endif
#include "Layers.h"
#include "ReadbackLayer.h"
#include "ImageContainer.h"
// accessibility support
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
#endif
#ifdef MOZ_LOGGING
#define FORCE_PR_LOG 1 /* Allow logging in the release build */
#endif /* MOZ_LOGGING */
#include "mozilla/Logging.h"
#ifdef XP_MACOSX
#include "gfxQuartzNativeDrawing.h"
#include "mozilla/gfx/QuartzSupport.h"
#endif
#ifdef MOZ_X11
#include "mozilla/X11Util.h"
using mozilla::DefaultXDisplay;
#endif
#ifdef XP_WIN
#include <wtypes.h>
#include <winuser.h>
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#include "GLContext.h"
#endif
#include "mozilla/dom/TabChild.h"
#ifdef CreateEvent // Thank you MS.
#undef CreateEvent
#endif
static PRLogModuleInfo *
GetObjectFrameLog()
{
static PRLogModuleInfo *sLog;
if (!sLog)
sLog = PR_NewLogModule("nsPluginFrame");
return sLog;
}
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
class PluginBackgroundSink : public ReadbackSink {
public:
PluginBackgroundSink(nsPluginFrame* aFrame, uint64_t aStartSequenceNumber)
: mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
~PluginBackgroundSink()
{
if (mFrame) {
mFrame->mBackgroundSink = nullptr;
}
}
virtual void SetUnknown(uint64_t aSequenceNumber)
{
if (!AcceptUpdate(aSequenceNumber))
return;
mFrame->mInstanceOwner->SetBackgroundUnknown();
}
virtual already_AddRefed<gfxContext>
BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber)
{
if (!AcceptUpdate(aSequenceNumber))
return nullptr;
return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
}
virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect)
{
return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect);
}
void Destroy() { mFrame = nullptr; }
protected:
bool AcceptUpdate(uint64_t aSequenceNumber) {
if (aSequenceNumber > mLastSequenceNumber && mFrame &&
mFrame->mInstanceOwner) {
mLastSequenceNumber = aSequenceNumber;
return true;
}
return false;
}
uint64_t mLastSequenceNumber;
nsPluginFrame* mFrame;
};
nsPluginFrame::nsPluginFrame(nsStyleContext* aContext)
: nsPluginFrameSuper(aContext)
, mInstanceOwner(nullptr)
, mReflowCallbackPosted(false)
, mIsHiddenDueToScroll(false)
{
MOZ_LOG(GetObjectFrameLog(), LogLevel::Debug,
("Created new nsPluginFrame %p\n", this));
}
nsPluginFrame::~nsPluginFrame()
{
MOZ_LOG(GetObjectFrameLog(), LogLevel::Debug,
("nsPluginFrame %p deleted\n", this));
}
NS_QUERYFRAME_HEAD(nsPluginFrame)
NS_QUERYFRAME_ENTRY(nsPluginFrame)
NS_QUERYFRAME_ENTRY(nsIObjectFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsPluginFrameSuper)
#ifdef ACCESSIBILITY
a11y::AccType
nsPluginFrame::AccessibleType()
{
return a11y::ePluginType;
}
#ifdef XP_WIN
NS_IMETHODIMP nsPluginFrame::GetPluginPort(HWND *aPort)
{
*aPort = (HWND) mInstanceOwner->GetPluginPort();
return NS_OK;
}
#endif
#endif
void
nsPluginFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
MOZ_LOG(GetObjectFrameLog(), LogLevel::Debug,
("Initializing nsPluginFrame %p for content %p\n", this, aContent));
nsPluginFrameSuper::Init(aContent, aParent, aPrevInFlow);
}
void
nsPluginFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
if (mReflowCallbackPosted) {
PresContext()->PresShell()->CancelReflowCallback(this);
}
// Tell content owner of the instance to disconnect its frame.
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
NS_ASSERTION(objContent, "Why not an object loading content?");
// The content might not have a reference to the instance owner any longer in
// the case of re-entry during instantiation or teardown, so make sure we're
// dissociated.
if (mInstanceOwner) {
mInstanceOwner->SetFrame(nullptr);
}
objContent->HasNewFrame(nullptr);
if (mBackgroundSink) {
mBackgroundSink->Destroy();
}
nsPluginFrameSuper::DestroyFrom(aDestructRoot);
}
/* virtual */ void
nsPluginFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
{
if (HasView()) {
nsView* view = GetView();
nsViewManager* vm = view->GetViewManager();
if (vm) {
nsViewVisibility visibility =
IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
vm->SetViewVisibility(view, visibility);
}
}
nsPluginFrameSuper::DidSetStyleContext(aOldStyleContext);
}
nsIAtom*
nsPluginFrame::GetType() const
{
return nsGkAtoms::objectFrame;
}
#ifdef DEBUG_FRAME_DUMP
nsresult
nsPluginFrame::GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("PluginFrame"), aResult);
}
#endif
nsresult
nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
{
mWidget = aWidget;
nsView* view = GetView();
NS_ASSERTION(view, "Object frames must have views");
if (!view) {
return NS_ERROR_FAILURE;
}
nsViewManager* viewMan = view->GetViewManager();
// mark the view as hidden since we don't know the (x,y) until Paint
// XXX is the above comment correct?
viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
//this is ugly. it was ripped off from didreflow(). MMP
// Position and size view relative to its parent, not relative to our
// parent frame (our parent frame may not have a view).
nsView* parentWithView;
nsPoint origin;
nsRect r(0, 0, mRect.width, mRect.height);
GetOffsetFromView(origin, &parentWithView);
viewMan->ResizeView(view, r);
viewMan->MoveViewTo(view, origin.x, origin.y);
nsPresContext* presContext = PresContext();
nsRootPresContext* rpc = presContext->GetRootPresContext();
if (!rpc) {
return NS_ERROR_FAILURE;
}
if (mWidget) {
// Disallow windowed plugins in popups
nsIFrame* rootFrame = rpc->PresShell()->FrameManager()->GetRootFrame();
nsIWidget* parentWidget = rootFrame->GetNearestWidget();
if (!parentWidget || nsLayoutUtils::GetDisplayRootFrame(this) != rootFrame) {
return NS_ERROR_FAILURE;
}
mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view);
if (!mInnerView) {
NS_ERROR("Could not create inner view");
return NS_ERROR_OUT_OF_MEMORY;
}
viewMan->InsertChild(view, mInnerView, nullptr, true);
mWidget->SetParent(parentWidget);
mWidget->Show(true);
mWidget->Enable(true);
// Set the plugin window to have an empty clip region until we know
// what our true position, size and clip region are. These
// will be reset when nsRootPresContext computes our true
// geometry. The plugin window does need to have a good size here, so
// set the size explicitly to a reasonable guess.
nsAutoTArray<nsIWidget::Configuration,1> configurations;
nsIWidget::Configuration* configuration = configurations.AppendElement();
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
configuration->mChild = mWidget;
configuration->mBounds.width = NSAppUnitsToIntPixels(mRect.width, appUnitsPerDevPixel);
configuration->mBounds.height = NSAppUnitsToIntPixels(mRect.height, appUnitsPerDevPixel);
parentWidget->ConfigureChildren(configurations);
RefPtr<nsDeviceContext> dx = viewMan->GetDeviceContext();
mInnerView->AttachWidgetEventHandler(mWidget);
#ifdef XP_MACOSX
// On Mac, we need to invalidate ourselves since even windowed
// plugins are painted through Thebes and we need to ensure
// the PaintedLayer containing the plugin is updated.
if (parentWidget == GetNearestWidget()) {
InvalidateFrame();
}
#endif
RegisterPluginForGeometryUpdates();
// Here we set the background color for this widget because some plugins will use
// the child window background color when painting. If it's not set, it may default to gray
// Sometimes, a frame doesn't have a background color or is transparent. In this
// case, walk up the frame tree until we do find a frame with a background color
for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
nscolor bgcolor =
frame->GetVisitedDependentColor(eCSSProperty_background_color);
if (NS_GET_A(bgcolor) > 0) { // make sure we got an actual color
mWidget->SetBackgroundColor(bgcolor);
break;
}
}
} else {
// Changing to windowless mode changes the NPWindow geometry.
FixupWindow(GetContentRectRelativeToSelf().Size());
RegisterPluginForGeometryUpdates();
}
if (!IsHidden()) {
viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
}
#ifdef ACCESSIBILITY
nsAccessibilityService* accService = nsIPresShell::AccService();
if (accService) {
accService->RecreateAccessible(PresContext()->PresShell(), mContent);
}
#endif
return NS_OK;
}
#define EMBED_DEF_WIDTH 240
#define EMBED_DEF_HEIGHT 200
/* virtual */ nscoord
nsPluginFrame::GetMinISize(nsRenderingContext *aRenderingContext)
{
nscoord result = 0;
if (!IsHidden(false)) {
if (mContent->IsAnyOfHTMLElements(nsGkAtoms::applet,
nsGkAtoms::embed)) {
bool vertical = GetWritingMode().IsVertical();
result = nsPresContext::CSSPixelsToAppUnits(
vertical ? EMBED_DEF_HEIGHT : EMBED_DEF_WIDTH);
}
}
DISPLAY_MIN_WIDTH(this, result);
return result;
}
/* virtual */ nscoord
nsPluginFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
{
return nsPluginFrame::GetMinISize(aRenderingContext);
}
void
nsPluginFrame::GetWidgetConfiguration(nsTArray<nsIWidget::Configuration>* aConfigurations)
{
if (!mWidget) {
return;
}
if (!mWidget->GetParent()) {
// Plugin widgets should not be toplevel except when they're out of the
// document, in which case the plugin should not be registered for
// geometry updates and this should not be called. But apparently we
// have bugs where mWidget sometimes is toplevel here. Bail out.
NS_ERROR("Plugin widgets registered for geometry updates should not be toplevel");
return;
}
nsIWidget::Configuration* configuration = aConfigurations->AppendElement();
configuration->mChild = mWidget;
configuration->mBounds = mNextConfigurationBounds;
configuration->mClipRegion = mNextConfigurationClipRegion;
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
if (XRE_IsContentProcess()) {
configuration->mWindowID = (uintptr_t)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
configuration->mVisible = mWidget->IsVisible();
}
#endif // defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
}
void
nsPluginFrame::GetDesiredSize(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aMetrics)
{
// By default, we have no area
aMetrics.ClearSize();
if (IsHidden(false)) {
return;
}
aMetrics.Width() = aReflowState.ComputedWidth();
aMetrics.Height() = aReflowState.ComputedHeight();
// for EMBED and APPLET, default to 240x200 for compatibility
if (mContent->IsAnyOfHTMLElements(nsGkAtoms::applet,
nsGkAtoms::embed)) {
if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
aReflowState.ComputedMinWidth(),
aReflowState.ComputedMaxWidth());
}
if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
aReflowState.ComputedMinHeight(),
aReflowState.ComputedMaxHeight());
}
#if defined(MOZ_WIDGET_GTK)
// We need to make sure that the size of the object frame does not
// exceed the maximum size of X coordinates. See bug #225357 for
// more information. In theory Gtk2 can handle large coordinates,
// but underlying plugins can't.
aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height());
aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width());
#endif
}
// At this point, the width has an unconstrained value only if we have
// nothing to go on (no width set, no information from the plugin, nothing).
// Make up a number.
if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
aMetrics.Width() =
(aReflowState.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ?
aReflowState.ComputedMinWidth() : 0;
}
// At this point, the height has an unconstrained value only in two cases:
// a) We are in standards mode with percent heights and parent is auto-height
// b) We have no height information at all.
// In either case, we have to make up a number.
if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
aMetrics.Height() =
(aReflowState.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ?
aReflowState.ComputedMinHeight() : 0;
}
// XXXbz don't add in the border and padding, because we screw up our
// plugin's size and positioning if we do... Eventually we _do_ want to
// paint borders, though! At that point, we will need to adjust the desired
// size either here or in Reflow.... Further, we will need to fix Paint() to
// call the superclass in all cases.
}
void
nsPluginFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
MarkInReflow();
DO_GLOBAL_REFLOW_COUNT("nsPluginFrame");
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
// Get our desired size
GetDesiredSize(aPresContext, aReflowState, aMetrics);
aMetrics.SetOverflowAreasToDesiredBounds();
FinishAndStoreOverflow(&aMetrics);
// delay plugin instantiation until all children have
// arrived. Otherwise there may be PARAMs or other stuff that the
// plugin needs to see that haven't arrived yet.
if (!GetContent()->IsDoneAddingChildren()) {
aStatus = NS_FRAME_COMPLETE;
return;
}
// if we are printing or print previewing, bail for now
if (aPresContext->Medium() == nsGkAtoms::print) {
aStatus = NS_FRAME_COMPLETE;
return;
}
nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
r.Deflate(aReflowState.ComputedPhysicalBorderPadding());
if (mInnerView) {
nsViewManager* vm = mInnerView->GetViewManager();
vm->MoveViewTo(mInnerView, r.x, r.y);
vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true);
}
FixupWindow(r.Size());
if (!mReflowCallbackPosted) {
mReflowCallbackPosted = true;
aPresContext->PresShell()->PostReflowCallback(this);
}
aStatus = NS_FRAME_COMPLETE;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
}
///////////// nsIReflowCallback ///////////////
bool
nsPluginFrame::ReflowFinished()
{
mReflowCallbackPosted = false;
CallSetWindow();
return true;
}
void
nsPluginFrame::ReflowCallbackCanceled()
{
mReflowCallbackPosted = false;
}
void
nsPluginFrame::FixupWindow(const nsSize& aSize)
{
nsPresContext* presContext = PresContext();
if (!mInstanceOwner)
return;
NPWindow *window;
mInstanceOwner->GetWindow(window);
NS_ENSURE_TRUE_VOID(window);
bool windowless = (window->type == NPWindowTypeDrawable);
nsIntPoint origin = GetWindowOriginInPixels(windowless);
// window must be in "display pixels"
double scaleFactor = 1.0;
if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
scaleFactor = 1.0;
}
int intScaleFactor = ceil(scaleFactor);
window->x = origin.x / intScaleFactor;
window->y = origin.y / intScaleFactor;
window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
#ifndef XP_MACOSX
mInstanceOwner->UpdateWindowPositionAndClipRect(false);
#endif
NotifyPluginReflowObservers();
}
nsresult
nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
{
NPWindow *win = nullptr;
nsresult rv = NS_ERROR_FAILURE;
RefPtr<nsNPAPIPluginInstance> pi;
if (!mInstanceOwner ||
NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) ||
!pi ||
NS_FAILED(rv = mInstanceOwner->GetWindow(win)) ||
!win)
return rv;
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
if (aCheckIsHidden && IsHidden())
return NS_ERROR_FAILURE;
// Calling either nsPluginInstanceOwner::FixUpPluginWindow() (here,
// on OS X) or SetWindow() (below, on all platforms) can destroy this
// frame. (FixUpPluginWindow() calls SetWindow()). So grab a safe
// reference to mInstanceOwner which we can use below, if needed.
RefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
// refresh the plugin port as well
#ifdef XP_MACOSX
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
// Bail now if our frame has been destroyed.
if (!instanceOwnerRef->GetFrame()) {
return NS_ERROR_FAILURE;
}
#endif
window->window = mInstanceOwner->GetPluginPort();
// Adjust plugin dimensions according to pixel snap results
// and reduce amount of SetWindow calls
nsPresContext* presContext = PresContext();
nsRootPresContext* rootPC = presContext->GetRootPresContext();
if (!rootPC)
return NS_ERROR_FAILURE;
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
nsIFrame* rootFrame = rootPC->PresShell()->FrameManager()->GetRootFrame();
nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame);
nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
// In e10s, this returns the offset to the top level window, in non-e10s
// it return 0,0.
LayoutDeviceIntPoint intOffset = GetRemoteTabChromeOffset();
intBounds.x += intOffset.x;
intBounds.y += intOffset.y;
// window must be in "display pixels"
double scaleFactor = 1.0;
if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
scaleFactor = 1.0;
}
size_t intScaleFactor = ceil(scaleFactor);
window->x = intBounds.x / intScaleFactor;
window->y = intBounds.y / intScaleFactor;
window->width = intBounds.width / intScaleFactor;
window->height = intBounds.height / intScaleFactor;
// This will call pi->SetWindow and take care of window subclassing
// if needed, see bug 132759. Calling SetWindow can destroy this frame
// so check for that before doing anything else with this frame's memory.
if (mInstanceOwner->UseAsyncRendering()) {
rv = pi->AsyncSetWindow(window);
}
else {
rv = window->CallSetWindow(pi);
}
instanceOwnerRef->ReleasePluginPort(window->window);
return rv;
}
void
nsPluginFrame::RegisterPluginForGeometryUpdates()
{
nsRootPresContext* rpc = PresContext()->GetRootPresContext();
NS_ASSERTION(rpc, "We should have a root pres context!");
if (mRootPresContextRegisteredWith == rpc || !rpc) {
// Already registered with current root pres context,
// or null root pres context...
return;
}
if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) {
// Registered to some other root pres context. Unregister, and
// re-register with our current one...
UnregisterPluginForGeometryUpdates();
}
mRootPresContextRegisteredWith = rpc;
mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent);
}
void
nsPluginFrame::UnregisterPluginForGeometryUpdates()
{
if (!mRootPresContextRegisteredWith) {
// Not registered...
return;
}
mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent);
mRootPresContextRegisteredWith = nullptr;
}
void
nsPluginFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
{
// The ownership model here is historically fuzzy. This should only be called
// by nsPluginInstanceOwner when it is given a new frame, and
// nsObjectLoadingContent should be arbitrating frame-ownership via its
// HasNewFrame callback.
mInstanceOwner = aOwner;
if (mInstanceOwner) {
return;
}
UnregisterPluginForGeometryUpdates();
if (mWidget && mInnerView) {
mInnerView->DetachWidgetEventHandler(mWidget);
// Make sure the plugin is hidden in case an update of plugin geometry
// hasn't happened since this plugin became hidden.
nsIWidget* parent = mWidget->GetParent();
if (parent) {
nsTArray<nsIWidget::Configuration> configurations;
nsIWidget::Configuration* configuration = configurations.AppendElement();
configuration->mChild = mWidget;
parent->ConfigureChildren(configurations);
mWidget->Show(false);
mWidget->Enable(false);
mWidget->SetParent(nullptr);
}
}
}
bool
nsPluginFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
{
if (aTabIndex)
*aTabIndex = -1;
return nsPluginFrameSuper::IsFocusable(aTabIndex, aWithMouse);
}
bool
nsPluginFrame::IsHidden(bool aCheckVisibilityStyle) const
{
if (aCheckVisibilityStyle) {
if (!StyleVisibility()->IsVisibleOrCollapsed())
return true;
}
// only <embed> tags support the HIDDEN attribute
if (mContent->IsHTMLElement(nsGkAtoms::embed)) {
// Yes, these are really the kooky ways that you could tell 4.x
// not to hide the <embed> once you'd put the 'hidden' attribute
// on the tag...
// HIDDEN w/ no attributes gets translated as we are hidden for
// compatibility w/ 4.x and IE so we don't create a non-painting
// widget in layout. See bug 188959.
nsAutoString hidden;
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) &&
(hidden.IsEmpty() ||
(!hidden.LowerCaseEqualsLiteral("false") &&
!hidden.LowerCaseEqualsLiteral("no") &&
!hidden.LowerCaseEqualsLiteral("off")))) {
return true;
}
}
return false;
}
// Clips windowed plugin frames during remote content scroll operations managed
// by nsGfxScrollFrame.
void
nsPluginFrame::SetScrollVisibility(bool aState)
{
// Limit this setting to windowed plugins by checking if we have a widget
if (mWidget) {
bool changed = mIsHiddenDueToScroll != aState;
mIsHiddenDueToScroll = aState;
// Force a paint so plugin window visibility gets flushed via
// the compositor.
if (changed) {
SchedulePaint();
}
}
}
mozilla::LayoutDeviceIntPoint
nsPluginFrame::GetRemoteTabChromeOffset()
{
LayoutDeviceIntPoint offset;
if (XRE_IsContentProcess()) {
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetContent()->OwnerDoc()->GetWindow());
if (window) {
nsCOMPtr<nsPIDOMWindow> topWindow = window->GetTop();
if (topWindow) {
dom::TabChild* tc = dom::TabChild::GetFrom(topWindow);
if (tc) {
offset += tc->GetChromeDisplacement();
}
}
}
}
return offset;
}
nsIntPoint
nsPluginFrame::GetWindowOriginInPixels(bool aWindowless)
{
nsView * parentWithView;
nsPoint origin(0,0);
GetOffsetFromView(origin, &parentWithView);
// if it's windowless, let's make sure we have our origin set right
// it may need to be corrected, like after scrolling
if (aWindowless && parentWithView) {
nsPoint offsetToWidget;
parentWithView->GetNearestWidget(&offsetToWidget);
origin += offsetToWidget;
}
origin += GetContentRectRelativeToSelf().TopLeft();
nsIntPoint pt(PresContext()->AppUnitsToDevPixels(origin.x),
PresContext()->AppUnitsToDevPixels(origin.y));
// If we're in the content process offsetToWidget is tied to the top level
// widget we can access in the child process, which is the tab. We need the
// offset all the way up to the top level native window here. (If this is
// non-e10s this routine will return 0,0.)
if (aWindowless) {
mozilla::LayoutDeviceIntPoint lpt = GetRemoteTabChromeOffset();
pt += nsIntPoint(lpt.x, lpt.y);
}
return pt;
}
void
nsPluginFrame::DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus)
{
// Do this check before calling the superclass, as that clears
// NS_FRAME_FIRST_REFLOW
if (aStatus == nsDidReflowStatus::FINISHED &&
(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
NS_ASSERTION(objContent, "Why not an object loading content?");
objContent->HasNewFrame(this);
}
nsPluginFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
// The view is created hidden; once we have reflowed it and it has been
// positioned then we show it.
if (aStatus != nsDidReflowStatus::FINISHED)
return;
if (HasView()) {
nsView* view = GetView();
nsViewManager* vm = view->GetViewManager();
if (vm)
vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow);
}
}
/* static */ void
nsPluginFrame::PaintPrintPlugin(nsIFrame* aFrame, nsRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
gfxContext* ctx = aCtx->ThebesContext();
// Translate the context:
nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft();
gfxPoint devPixelPt =
nsLayoutUtils::PointToGfxPoint(pt, aFrame->PresContext()->AppUnitsPerDevPixel());
gfxContextMatrixAutoSaveRestore autoSR(ctx);
ctx->SetMatrix(ctx->CurrentMatrix().Translate(devPixelPt));
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
static_cast<nsPluginFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
}
/**
* nsDisplayPluginReadback creates an active ReadbackLayer. The ReadbackLayer
* obtains from the compositor the contents of the window underneath
* the ReadbackLayer, which we then use as an opaque buffer for plugins to
* asynchronously draw onto.
*/
class nsDisplayPluginReadback : public nsDisplayItem {
public:
nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
{
MOZ_COUNT_CTOR(nsDisplayPluginReadback);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayPluginReadback() {
MOZ_COUNT_DTOR(nsDisplayPluginReadback);
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) override;
NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override
{
return static_cast<nsPluginFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return LAYER_ACTIVE;
}
};
static nsRect
GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
{
// XXX For slightly more accurate region computations we should pixel-snap this
return aFrame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
}
nsRect
nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return GetDisplayItemBounds(aBuilder, this, mFrame);
}
#ifdef MOZ_WIDGET_ANDROID
class nsDisplayPluginVideo : public nsDisplayItem {
public:
nsDisplayPluginVideo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
: nsDisplayItem(aBuilder, aFrame), mVideoInfo(aVideoInfo)
{
MOZ_COUNT_CTOR(nsDisplayPluginVideo);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayPluginVideo() {
MOZ_COUNT_DTOR(nsDisplayPluginVideo);
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) override;
NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO)
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override
{
return static_cast<nsPluginFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override
{
return LAYER_ACTIVE;
}
nsNPAPIPluginInstance::VideoInfo* VideoInfo() { return mVideoInfo; }
private:
nsNPAPIPluginInstance::VideoInfo* mVideoInfo;
};
nsRect
nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return GetDisplayItemBounds(aBuilder, this, mFrame);
}
#endif
nsRect
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = true;
return GetDisplayItemBounds(aBuilder, this, mFrame);
}
void
nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
nsPluginFrame* f = static_cast<nsPluginFrame*>(mFrame);
bool snap;
f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder, &snap));
}
bool
nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion)
{
if (aBuilder->IsForPluginGeometry()) {
nsPluginFrame* f = static_cast<nsPluginFrame*>(mFrame);
if (!aBuilder->IsInTransform() || f->IsPaintedByGecko()) {
// Since transforms induce reference frames, we don't need to worry
// about this method fluffing out due to non-rectilinear transforms.
nsRect rAncestor = nsLayoutUtils::TransformFrameRectToAncestor(f,
f->GetContentRectRelativeToSelf(), ReferenceFrame());
nscoord appUnitsPerDevPixel =
ReferenceFrame()->PresContext()->AppUnitsPerDevPixel();
f->mNextConfigurationBounds = rAncestor.ToNearestPixels(appUnitsPerDevPixel);
nsRegion visibleRegion;
visibleRegion.And(*aVisibleRegion, GetClippedBounds(aBuilder));
// Make visibleRegion relative to f
visibleRegion.MoveBy(-ToReferenceFrame());
f->mNextConfigurationClipRegion.Clear();
nsRegionRectIterator iter(visibleRegion);
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
nsRect rAncestor =
nsLayoutUtils::TransformFrameRectToAncestor(f, *r, ReferenceFrame());
nsIntRect rPixels = rAncestor.ToNearestPixels(appUnitsPerDevPixel)
- f->mNextConfigurationBounds.TopLeft();
if (!rPixels.IsEmpty()) {
f->mNextConfigurationClipRegion.AppendElement(rPixels);
}
}
}
if (f->mInnerView) {
// This should produce basically the same rectangle (but not relative
// to the root frame). We only call this here for the side-effect of
// setting mViewToWidgetOffset on the view.
f->mInnerView->CalcWidgetBounds(eWindowType_plugin);
}
}
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion);
}
nsRegion
nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap)
{
*aSnap = false;
nsRegion result;
nsPluginFrame* f = static_cast<nsPluginFrame*>(mFrame);
if (!aBuilder->IsForPluginGeometry()) {
nsIWidget* widget = f->GetWidget();
if (widget) {
// Be conservative and treat plugins with widgets as not opaque,
// because that's simple and we might need the content under the widget
// if the widget is unexpectedly clipped away. (As can happen when
// chrome content over a plugin forces us to clip out the plugin for
// security reasons.)
// We shouldn't be repainting the content under plugins much anyway
// since there generally shouldn't be anything to invalidate or paint
// in PaintedLayers there.
return result;
}
}
if (f->IsOpaque()) {
nsRect bounds = GetBounds(aBuilder, aSnap);
if (aBuilder->IsForPluginGeometry() ||
(f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) {
// We can treat this as opaque
result = bounds;
}
}
return result;
}
nsresult
nsPluginFrame::PluginEventNotifier::Run() {
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
obsSvc->NotifyObservers(nullptr, "plugin-changed-event", mEventType.get());
return NS_OK;
}
void
nsPluginFrame::NotifyPluginReflowObservers()
{
nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
}
void
nsPluginFrame::DidSetWidgetGeometry()
{
#if defined(XP_MACOSX)
if (mInstanceOwner) {
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
}
#else
if (!mWidget && mInstanceOwner) {
// UpdateWindowVisibility will notify the plugin of position changes
// by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
// We treat windowless plugins inside popups as always visible, since
// plugins inside popups don't get valid mNextConfigurationBounds
// set up.
mInstanceOwner->UpdateWindowVisibility(
nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
!mNextConfigurationBounds.IsEmpty());
}
#endif
}
bool
nsPluginFrame::IsOpaque() const
{
// Insure underlying content gets painted when we clip windowed plugins
// during remote content scroll operations managed by nsGfxScrollFrame.
if (mIsHiddenDueToScroll) {
return false;
}
#if defined(XP_MACOSX)
return false;
#elif defined(MOZ_WIDGET_ANDROID)
// We don't know, so just assume transparent
return false;
#else
return !IsTransparentMode();
#endif
}
bool
nsPluginFrame::IsTransparentMode() const
{
#if defined(XP_MACOSX)
return false;
#else
if (!mInstanceOwner)
return false;
NPWindow *window = nullptr;
mInstanceOwner->GetWindow(window);
if (!window) {
return false;
}
if (window->type != NPWindowTypeDrawable)
return false;
nsresult rv;
RefPtr<nsNPAPIPluginInstance> pi;
rv = mInstanceOwner->GetInstance(getter_AddRefs(pi));
if (NS_FAILED(rv) || !pi)
return false;
bool transparent = false;
pi->IsTransparent(&transparent);
return transparent;
#endif
}
void
nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// Clip windowed plugin frames from the list during remote content scroll
// operations managed by nsGfxScrollFrame.
if (mIsHiddenDueToScroll) {
return;
}
// XXX why are we painting collapsed object frames?
if (!IsVisibleOrCollapsedForPainting(aBuilder))
return;
DisplayBorderBackgroundOutline(aBuilder, aLists);
nsPresContext::nsPresContextType type = PresContext()->Type();
// If we are painting in Print Preview do nothing....
if (type == nsPresContext::eContext_PrintPreview)
return;
DO_GLOBAL_REFLOW_COUNT_DSP("nsPluginFrame");
#ifndef XP_MACOSX
if (mWidget && aBuilder->IsInTransform()) {
// Windowed plugins should not be rendered inside a transform.
return;
}
#endif
if (aBuilder->IsForPainting() && mInstanceOwner) {
#ifdef XP_MACOSX
mInstanceOwner->ResolutionMayHaveChanged();
mInstanceOwner->WindowFocusMayHaveChanged();
#endif
if (mInstanceOwner->UseAsyncRendering()) {
NPWindow* window = nullptr;
mInstanceOwner->GetWindow(window);
bool isVisible = window && window->width > 0 && window->height > 0;
if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
#ifndef XP_MACOSX
mInstanceOwner->UpdateWindowVisibility(true);
#endif
}
mInstanceOwner->NotifyPaintWaiter(aBuilder);
}
}
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
clip(aBuilder, this);
// determine if we are printing
if (type == nsPresContext::eContext_Print) {
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
nsDisplayItem::TYPE_PRINT_PLUGIN));
} else {
LayerState state = GetLayerState(aBuilder, nullptr);
if (state == LAYER_INACTIVE &&
nsDisplayItem::ForceActiveLayers()) {
state = LAYER_ACTIVE;
}
// We don't need this on Android, and it just confuses things
#if !MOZ_WIDGET_ANDROID
if (aBuilder->IsPaintingToWindow() &&
state == LAYER_ACTIVE &&
IsTransparentMode()) {
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayPluginReadback(aBuilder, this));
}
#endif
#if MOZ_WIDGET_ANDROID
if (aBuilder->IsPaintingToWindow() &&
state == LAYER_ACTIVE) {
nsTArray<nsNPAPIPluginInstance::VideoInfo*> videos;
mInstanceOwner->GetVideos(videos);
for (uint32_t i = 0; i < videos.Length(); i++) {
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayPluginVideo(aBuilder, this, videos[i]));
}
}
#endif
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayPlugin(aBuilder, this));
}
}
void
nsPluginFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
if (!obj)
return;
nsIFrame* frame = nullptr;
obj->GetPrintFrame(&frame);
if (!frame)
return;
nsPresContext* presContext = PresContext();
// make sure this is REALLY an nsIObjectFrame
// we may need to go through the children to get it
nsIObjectFrame* objectFrame = do_QueryFrame(frame);
if (!objectFrame)
objectFrame = GetNextObjectFrame(presContext,frame);
if (!objectFrame)
return;
// finally we can get our plugin instance
RefPtr<nsNPAPIPluginInstance> pi;
if (NS_FAILED(objectFrame->GetPluginInstance(getter_AddRefs(pi))) || !pi)
return;
// now we need to setup the correct location for printing
NPWindow window;
window.window = nullptr;
// prepare embedded mode printing struct
NPPrint npprint;
npprint.mode = NP_EMBED;
// we need to find out if we are windowless or not
bool windowless = false;
pi->IsWindowless(&windowless);
window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow;
window.clipRect.bottom = 0; window.clipRect.top = 0;
window.clipRect.left = 0; window.clipRect.right = 0;
// platform specific printing code
#if defined(XP_UNIX) || defined(XP_MACOSX)
// Doesn't work in a thebes world, or on OS X.
(void)window;
(void)npprint;
#elif defined(XP_WIN)
/* On Windows, we use the win32 printing surface to print. This, in
* turn, uses the Cairo paginated surface, which in turn uses the
* meta surface to record all operations and then play them back.
* This doesn't work too well for plugins, because if plugins render
* directly into the DC, the meta surface won't have any knowledge
* of them, and so at the end when it actually does the replay step,
* it'll fill the background with white and draw over whatever was
* rendered before.
*
* So, to avoid this, we use PushGroup, which creates a new windows
* surface, the plugin renders to that, and then we use normal
* cairo methods to composite that in such that it's recorded using the
* meta surface.
*/
/* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
nsSize contentSize = GetContentRectRelativeToSelf().Size();
window.x = 0;
window.y = 0;
window.width = presContext->AppUnitsToDevPixels(contentSize.width);
window.height = presContext->AppUnitsToDevPixels(contentSize.height);
gfxContext *ctx = aRenderingContext.ThebesContext();
ctx->Save();
/* Make sure plugins don't do any damage outside of where they're supposed to */
ctx->NewPath();
gfxRect r(window.x, window.y, window.width, window.height);
ctx->Rectangle(r);
ctx->Clip();
gfxWindowsNativeDrawing nativeDraw(ctx, r);
do {
HDC dc = nativeDraw.BeginNativeDrawing();
if (!dc)
return;
// XXX don't we need to call nativeDraw.TransformToNativeRect here?
npprint.print.embedPrint.platformPrint = dc;
npprint.print.embedPrint.window = window;
// send off print info to plugin
pi->Print(&npprint);
nativeDraw.EndNativeDrawing();
} while (nativeDraw.ShouldRenderAgain());
nativeDraw.PaintToContext();
ctx->Restore();
#endif
// XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
// XXX Calling DidReflow here makes no sense!!!
nsDidReflowStatus status = nsDidReflowStatus::FINISHED; // should we use a special status?
frame->DidReflow(presContext,
nullptr, status); // DidReflow will take care of it
}
nsRect
nsPluginFrame::GetPaintedRect(nsDisplayPlugin* aItem)
{
if (!mInstanceOwner)
return nsRect();
nsRect r = GetContentRectRelativeToSelf();
if (!mInstanceOwner->UseAsyncRendering())
return r;
nsIntSize size = mInstanceOwner->GetCurrentImageSize();
nsPresContext* pc = PresContext();
r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width),
pc->DevPixelsToAppUnits(size.height)));
return r;
}
LayerState
nsPluginFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager)
{
if (!mInstanceOwner)
return LAYER_NONE;
#ifdef MOZ_WIDGET_ANDROID
// We always want a layer on Honeycomb and later
if (AndroidBridge::Bridge()->GetAPIVersion() >= 11)
return LAYER_ACTIVE;
#endif
if (!mInstanceOwner->UseAsyncRendering()) {
return LAYER_NONE;
}
return LAYER_ACTIVE;
}
already_AddRefed<Layer>
nsPluginFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsDisplayItem* aItem,
const ContainerLayerParameters& aContainerParameters)
{
if (!mInstanceOwner)
return nullptr;
NPWindow* window = nullptr;
mInstanceOwner->GetWindow(window);
if (!window)
return nullptr;
if (window->width <= 0 || window->height <= 0)
return nullptr;
// window is in "display pixels", but size needs to be in device pixels
double scaleFactor = 1.0;
if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
scaleFactor = 1.0;
}
int intScaleFactor = ceil(scaleFactor);
IntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
// to provide crisper and faster drawing.
r.Round();
RefPtr<Layer> layer =
(aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
// Create image
RefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
if (!container) {
// This can occur if our instance is gone.
return nullptr;
}
if (!layer) {
mInstanceOwner->NotifyPaintWaiter(aBuilder);
// Initialize ImageLayer
layer = aManager->CreateImageLayer();
if (!layer)
return nullptr;
}
NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
#ifdef XP_MACOSX
if (!mInstanceOwner->UseAsyncRendering()) {
mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
}
#endif
imglayer->SetScaleToSize(size, ScaleMode::STRETCH);
imglayer->SetContainer(container);
Filter filter = nsLayoutUtils::GetGraphicsFilterForFrame(this);
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
if (!aManager->IsCompositingCheap()) {
// Pixman just horrible with bilinear filter scaling
filter = Filter::POINT;
}
#endif
imglayer->SetFilter(filter);
layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
#ifdef MOZ_WIDGET_ANDROID
} else if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_VIDEO) {
nsDisplayPluginVideo* videoItem = reinterpret_cast<nsDisplayPluginVideo*>(aItem);
nsNPAPIPluginInstance::VideoInfo* videoInfo = videoItem->VideoInfo();
RefPtr<ImageContainer> container = mInstanceOwner->GetImageContainerForVideo(videoInfo);
if (!container)
return nullptr;
if (!layer) {
// Initialize ImageLayer
layer = aManager->CreateImageLayer();
if (!layer)
return nullptr;
}
ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
imglayer->SetContainer(container);
layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
// Set the offset and size according to the video dimensions
r.MoveBy(videoInfo->mDimensions.TopLeft());
size.width = videoInfo->mDimensions.width;
size.height = videoInfo->mDimensions.height;
#endif
} else {
NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
"Unknown item type");
MOZ_ASSERT(!IsOpaque(), "Opaque plugins don't use backgrounds");
if (!layer) {
layer = aManager->CreateReadbackLayer();
if (!layer)
return nullptr;
}
NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
if (readback->GetSize() != size) {
// This will destroy any old background sink and notify us that the
// background is now unknown
readback->SetSink(nullptr);
readback->SetSize(size);
if (mBackgroundSink) {
// Maybe we still have a background sink associated with another
// readback layer that wasn't recycled for some reason? Unhook it
// now so that if this frame goes away, it doesn't have a dangling
// reference to us.
mBackgroundSink->Destroy();
}
mBackgroundSink =
new PluginBackgroundSink(this,
readback->AllocateSequenceNumber());
readback->SetSink(mBackgroundSink);
// The layer has taken ownership of our sink. When either the sink dies
// or the frame dies, the connection from the surviving object is nulled out.
}
}
// Set a transform on the layer to draw the plugin in the right place
gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
Matrix transform = Matrix::Translation(p.x, p.y);
layer->SetBaseTransform(Matrix4x4::From2D(transform));
return layer.forget();
}
void
nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, const nsRect& aPluginRect)
{
#if defined(XP_MACOSX)
DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
#endif
#if defined(MOZ_WIDGET_ANDROID)
if (mInstanceOwner) {
gfxRect frameGfxRect =
PresContext()->AppUnitsToGfxUnits(aPluginRect);
gfxRect dirtyGfxRect =
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
gfxContext* ctx = aRenderingContext.ThebesContext();
mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
return;
}
#endif
// Screen painting code
#if defined(XP_MACOSX)
// delegate all painting to the plugin instance.
if (mInstanceOwner) {
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics ||
mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
mInstanceOwner->GetDrawingModel() ==
NPDrawingModelInvalidatingCoreAnimation) {
int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
// Clip to the content area where the plugin should be drawn. If
// we don't do this, the plugin can draw outside its bounds.
nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel);
nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel);
nsIntRect clipPixels;
clipPixels.IntersectRect(contentPixels, dirtyPixels);
// Don't invoke the drawing code if the clip is empty.
if (clipPixels.IsEmpty())
return;
gfxRect nativeClipRect(clipPixels.x, clipPixels.y,
clipPixels.width, clipPixels.height);
gfxContext* ctx = aRenderingContext.ThebesContext();
gfxContextAutoSaveRestore save(ctx);
ctx->NewPath();
ctx->Rectangle(nativeClipRect);
ctx->Clip();
gfxPoint offset(contentPixels.x, contentPixels.y);
ctx->SetMatrix(
ctx->CurrentMatrix().Translate(offset));
gfxQuartzNativeDrawing nativeDrawing(aDrawTarget,
ToRect(nativeClipRect - offset));
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
if (!cgContext) {
NS_WARNING("null CGContextRef during PaintPlugin");
return;
}
RefPtr<nsNPAPIPluginInstance> inst;
GetPluginInstance(getter_AddRefs(inst));
if (!inst) {
NS_WARNING("null plugin instance during PaintPlugin");
nativeDrawing.EndNativeDrawing();
return;
}
NPWindow* window;
mInstanceOwner->GetWindow(window);
if (!window) {
NS_WARNING("null plugin window during PaintPlugin");
nativeDrawing.EndNativeDrawing();
return;
}
NP_CGContext* cgPluginPortCopy =
static_cast<NP_CGContext*>(mInstanceOwner->GetPluginPortCopy());
if (!cgPluginPortCopy) {
NS_WARNING("null plugin port copy during PaintPlugin");
nativeDrawing.EndNativeDrawing();
return;
}
mInstanceOwner->BeginCGPaint();
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
mInstanceOwner->GetDrawingModel() ==
NPDrawingModelInvalidatingCoreAnimation) {
// CoreAnimation is updated, render the layer and perform a readback.
mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height);
} else {
mInstanceOwner->Paint(nativeClipRect - offset, cgContext);
}
mInstanceOwner->EndCGPaint();
nativeDrawing.EndNativeDrawing();
} else {
gfxContext* ctx = aRenderingContext.ThebesContext();
// Translate the context:
gfxPoint devPixelPt =
nsLayoutUtils::PointToGfxPoint(aPluginRect.TopLeft(),
PresContext()->AppUnitsPerDevPixel());
gfxContextMatrixAutoSaveRestore autoSR(ctx);
ctx->SetMatrix(ctx->CurrentMatrix().Translate(devPixelPt));
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
// this rect is used only in the CoreGraphics drawing model
gfxRect tmpRect(0, 0, 0, 0);
mInstanceOwner->Paint(tmpRect, nullptr);
}
}
#elif defined(MOZ_X11)
if (mInstanceOwner) {
NPWindow *window;
mInstanceOwner->GetWindow(window);
if (window->type == NPWindowTypeDrawable) {
gfxRect frameGfxRect =
PresContext()->AppUnitsToGfxUnits(aPluginRect);
gfxRect dirtyGfxRect =
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
gfxContext* ctx = aRenderingContext.ThebesContext();
mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
}
}
#elif defined(XP_WIN)
RefPtr<nsNPAPIPluginInstance> inst;
GetPluginInstance(getter_AddRefs(inst));
if (inst) {
gfxRect frameGfxRect =
PresContext()->AppUnitsToGfxUnits(aPluginRect);
gfxRect dirtyGfxRect =
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
gfxContext *ctx = aRenderingContext.ThebesContext();
gfxMatrix currentMatrix = ctx->CurrentMatrix();
if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) {
dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect);
ctx->SetMatrix(gfxMatrix());
}
dirtyGfxRect.RoundOut();
// Look if it's windowless
NPWindow *window;
mInstanceOwner->GetWindow(window);
if (window->type == NPWindowTypeDrawable) {
// the offset of the DC
nsPoint origin;
gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
if (nativeDraw.IsDoublePass()) {
// OOP plugin specific: let the shim know before we paint if we are doing a
// double pass render. If this plugin isn't oop, the register window message
// will be ignored.
NPEvent pluginEvent;
pluginEvent.event = plugins::DoublePassRenderingEvent();
pluginEvent.wParam = 0;
pluginEvent.lParam = 0;
if (pluginEvent.event)
inst->HandleEvent(&pluginEvent, nullptr);
}
do {
HDC hdc = nativeDraw.BeginNativeDrawing();
if (!hdc)
return;
RECT dest;
nativeDraw.TransformToNativeRect(frameGfxRect, dest);
RECT dirty;
nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty);
window->window = hdc;
window->x = dest.left;
window->y = dest.top;
window->clipRect.left = 0;
window->clipRect.top = 0;
// if we're painting, we're visible.
window->clipRect.right = window->width;
window->clipRect.bottom = window->height;
// Windowless plugins on windows need a special event to update their location,
// see bug 135737.
//
// bug 271442: note, the rectangle we send is now purely the bounds of the plugin
// relative to the window it is contained in, which is useful for the plugin to
// correctly translate mouse coordinates.
//
// this does not mesh with the comments for bug 135737 which imply that the rectangle
// must be clipped in some way to prevent the plugin attempting to paint over areas
// it shouldn't.
//
// since the two uses of the rectangle are mutually exclusive in some cases, and
// since I don't see any incorrect painting (at least with Flash and ViewPoint -
// the originator of bug 135737), it seems that windowless plugins are not relying
// on information here for clipping their drawing, and we can safely use this message
// to tell the plugin exactly where it is in all cases.
nsIntPoint origin = GetWindowOriginInPixels(true);
nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
if (!mWindowlessRect.IsEqualEdges(winlessRect)) {
mWindowlessRect = winlessRect;
WINDOWPOS winpos;
memset(&winpos, 0, sizeof(winpos));
winpos.x = mWindowlessRect.x;
winpos.y = mWindowlessRect.y;
winpos.cx = mWindowlessRect.width;
winpos.cy = mWindowlessRect.height;
// finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
NPEvent pluginEvent;
pluginEvent.event = WM_WINDOWPOSCHANGED;
pluginEvent.wParam = 0;
pluginEvent.lParam = (LPARAM)&winpos;
inst->HandleEvent(&pluginEvent, nullptr);
}
inst->SetWindow(window);
mInstanceOwner->Paint(dirty, hdc);
nativeDraw.EndNativeDrawing();
} while (nativeDraw.ShouldRenderAgain());
nativeDraw.PaintToContext();
}
ctx->SetMatrix(currentMatrix);
}
#endif
}
nsresult
nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
WidgetGUIEvent* anEvent,
nsEventStatus* anEventStatus)
{
NS_ENSURE_ARG_POINTER(anEvent);
NS_ENSURE_ARG_POINTER(anEventStatus);
nsresult rv = NS_OK;
if (!mInstanceOwner)
return NS_ERROR_NULL_POINTER;
mInstanceOwner->ConsiderNewEventloopNestingLevel();
if (anEvent->mMessage == ePluginActivate) {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetContent());
if (fm && elem)
return fm->SetFocus(elem, 0);
}
else if (anEvent->mMessage == ePluginFocus) {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIContent> content = GetContent();
return fm->FocusPlugin(content);
}
}
if (mInstanceOwner->SendNativeEvents() &&
anEvent->IsNativeEventDelivererForPlugin()) {
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
// Due to plugin code reentering Gecko, this frame may be dead at this
// point.
return rv;
}
#ifdef XP_WIN
rv = nsPluginFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
return rv;
#endif
#ifdef XP_MACOSX
// we want to process some native mouse events in the cocoa event model
if ((anEvent->mMessage == eMouseEnterIntoWidget ||
anEvent->mMessage == eWheel) &&
mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
// Due to plugin code reentering Gecko, this frame may be dead at this
// point.
return rv;
}
// These two calls to nsIPresShell::SetCapturingContext() (on mouse-down
// and mouse-up) are needed to make the routing of mouse events while
// dragging conform to standard OS X practice, and to the Cocoa NPAPI spec.
// See bug 525078 and bug 909678.
if (anEvent->mMessage == eMouseDown) {
nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
}
#endif
rv = nsPluginFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
// We need to be careful from this point because the call to
// nsPluginFrameSuper::HandleEvent() might have killed us.
#ifdef XP_MACOSX
if (anEvent->mMessage == eMouseUp) {
nsIPresShell::SetCapturingContent(nullptr, 0);
}
#endif
return rv;
}
void
nsPluginFrame::HandleWheelEventAsDefaultAction(WidgetWheelEvent* aWheelEvent)
{
MOZ_ASSERT(WantsToHandleWheelEventAsDefaultAction());
MOZ_ASSERT(!aWheelEvent->mFlags.mDefaultPrevented);
if (NS_WARN_IF(!mInstanceOwner) ||
NS_WARN_IF(aWheelEvent->mMessage != eWheel)) {
return;
}
// If the wheel event has native message, it should may be handled by
// HandleEvent() in the future. In such case, we should do nothing here.
if (NS_WARN_IF(!!aWheelEvent->mPluginEvent)) {
return;
}
mInstanceOwner->ProcessEvent(*aWheelEvent);
// We need to assume that the event is always consumed/handled by the
// plugin. There is no way to know if it's actually consumed/handled.
aWheelEvent->mViewPortIsOverscrolled = false;
aWheelEvent->overflowDeltaX = 0;
aWheelEvent->overflowDeltaY = 0;
// Consume the event explicitly.
aWheelEvent->PreventDefault();
}
bool
nsPluginFrame::WantsToHandleWheelEventAsDefaultAction() const
{
#ifdef XP_WIN
if (!mInstanceOwner) {
return false;
}
NPWindow* window = nullptr;
mInstanceOwner->GetWindow(window);
// On Windows, only when the plugin is windowless, we need to send wheel
// events as default action.
return window->type == NPWindowTypeDrawable;
#else
return false;
#endif
}
nsresult
nsPluginFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
{
*aPluginInstance = nullptr;
if (!mInstanceOwner) {
return NS_OK;
}
return mInstanceOwner->GetInstance(aPluginInstance);
}
nsresult
nsPluginFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
{
if (!mInstanceOwner) {
return NS_ERROR_FAILURE;
}
RefPtr<nsNPAPIPluginInstance> inst;
mInstanceOwner->GetInstance(getter_AddRefs(inst));
if (!inst) {
return NS_ERROR_FAILURE;
}
bool useDOMCursor = static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor();
if (!useDOMCursor) {
return NS_ERROR_FAILURE;
}
return nsPluginFrameSuper::GetCursor(aPoint, aCursor);
}
void
nsPluginFrame::SetIsDocumentActive(bool aIsActive)
{
if (mInstanceOwner) {
mInstanceOwner->UpdateDocumentActiveState(aIsActive);
}
}
// static
nsIObjectFrame *
nsPluginFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
{
nsIFrame* child = aRoot->GetFirstPrincipalChild();
while (child) {
nsIObjectFrame* outFrame = do_QueryFrame(child);
if (outFrame) {
RefPtr<nsNPAPIPluginInstance> pi;
outFrame->GetPluginInstance(getter_AddRefs(pi)); // make sure we have a REAL plugin
if (pi)
return outFrame;
}
outFrame = GetNextObjectFrame(aPresContext, child);
if (outFrame)
return outFrame;
child = child->GetNextSibling();
}
return nullptr;
}
/*static*/ void
nsPluginFrame::BeginSwapDocShells(nsISupports* aSupports, void*)
{
NS_PRECONDITION(aSupports, "");
nsCOMPtr<nsIContent> content(do_QueryInterface(aSupports));
if (!content) {
return;
}
// This function is called from a document content enumerator so we need
// to filter out the nsPluginFrames and ignore the rest.
nsIObjectFrame* obj = do_QueryFrame(content->GetPrimaryFrame());
if (!obj)
return;
nsPluginFrame* objectFrame = static_cast<nsPluginFrame*>(obj);
NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(),
"Plugin windows must not be toplevel");
objectFrame->UnregisterPluginForGeometryUpdates();
}
/*static*/ void
nsPluginFrame::EndSwapDocShells(nsISupports* aSupports, void*)
{
NS_PRECONDITION(aSupports, "");
nsCOMPtr<nsIContent> content(do_QueryInterface(aSupports));
if (!content) {
return;
}
// This function is called from a document content enumerator so we need
// to filter out the nsPluginFrames and ignore the rest.
nsIObjectFrame* obj = do_QueryFrame(content->GetPrimaryFrame());
if (!obj)
return;
nsPluginFrame* objectFrame = static_cast<nsPluginFrame*>(obj);
nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
NS_ASSERTION(rootPC, "unable to register the plugin frame");
nsIWidget* widget = objectFrame->mWidget;
if (widget) {
// Reparent the widget.
nsIWidget* parent =
rootPC->PresShell()->GetRootFrame()->GetNearestWidget();
widget->SetParent(parent);
nsWeakFrame weakFrame(objectFrame);
objectFrame->CallSetWindow();
if (!weakFrame.IsAlive()) {
return;
}
}
objectFrame->RegisterPluginForGeometryUpdates();
}
nsIFrame*
NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsPluginFrame(aContext);
}
bool
nsPluginFrame::IsPaintedByGecko() const
{
#ifdef XP_MACOSX
return true;
#else
return !mWidget;
#endif
}
NS_IMPL_FRAMEARENA_HELPERS(nsPluginFrame)