To guarantee that GeckoInputConnection and GeckoEditable are not used by
GeckoView after GeckoEditable has been destroyed, we need to make sure a
certain sequence is followed. We should first unset the
InputConnectionListener in GeckoView on the UI thread; then unset the
GeckoEditableListener on the IC thread; and finally finish destroying
the GeckoEditable instance through disposeNative. This patch merges this
logic with the initialization logic in GeckoEditable.onViewChange, so
that onViewChange can be used for both initialization and destruction.
Handle all text change scenarios efficiently but correctly. In
particular, when we have a pending "replace text" action, make sure we
preserve old and new spans as much as we can, and make sure we merge the
text from the pending action with the actual changed text.
Use an Activity as the Context when we have one. This avoids the crash
and also avoids an ugly black flash when you cancel the intent chooser.
When we don't have an activity, use an application context and add the
new task flag.
LayerView used to call GeckoLayerClient.onGeckoReady directly if Gecko
is sufficiently loaded. However, onGeckoReady indirectly calls
GLController.createCompositor, and it's possible for the
createCompositor event to be prioritized so that it happens before we
initialize GLController, causing a crash. This patch moves the
onGeckoReady call to the Gecko thread, after GLController is
initialized, to avoid this race condition.
Only three GLController events -- CreateCompositor, PauseCompositor, and
OnResumedCompositor should be prioritized through GLControllerEvent. The
other GLController events should follow the normal event queue ordering
to prevent race conditions.
GeckoThread.queueNativeCallLocked tries to execute a queued native call
if it's already overdue, but it incorrectly checked that the queue is
not empty. That check is not necessary, and an overdue native call
should always be executed. One-line patch, r=me.
This patch:
- Maintains a consistent ordering between the lists of fields in the
FrameMetrics constructor, operator==, IPC read/write functions, and the
actual order of fields in FrameMetrics. As part of this, missing default
initializers are added to the FrameMetrics constructor, and fields omitted
from the operator== are explicitly noted.
- Moves all the boolean values to the end of the set of field (for better
packing).
- Moves the scroll id and parent scroll id to the front of the list, so that
the operator== can fail faster in the common case.
--HG--
extra : commitid : 6ink6xmxH38
We have both NativeSurfaceType::CAIRO_CONTEXT and
NativeSurfaceType::CAIRO_SURFACE. They both refer to DrawTargets with Cairo
backends. The only reason for having both is so you can call GetNativeSurface()
and get either the |cairo_t*| or the underlying |cairo_surface_t*|.
I argue that this convenience confuses things more than it helps. This patch
removes CAIRO_SURFACE, and adds explicit cairo_get_target() calls where
necessary.
--HG--
extra : rebase_source : 6f1701a8131d854c7f623272182029847876754e
RunExpiredTimeouts has "fudging" code to always ensure that we execute at least one timeout. This is intended to cover cases where an nsITimer fires slightly early, but it means we must be careful not to fire a timer more times than we intend to or we'll execute a timeout prematurely.
Consider a sequences of setTimeout calls alternating in delay between 0ms and 1000ms. When the 1000ms timeout fires, it schedules a 0ms timeout. The setTimeout call itself calls RescheduleTimeoutTimer, which schedules the timer for a 0 ms delay. And once we unwind the 1000ms timeout RunExpiredTimeouts will also schedule the timer for a 0 ms delay. If the timer has fired (remember, it's processed on a completely different thread) in the meantime, we ultimately will get two callbacks from nsITimer for our 0 ms timeout. The first will run the 0 ms timeout and schedule a 1000 ms timeout, and the second will run the 1000 ms timeout (remember, RunExpiredTimeouts always runs at least one timeout!) ~999 ms ahead of schedule.
The solution is to cancel the timer in RescheduleTimeoutTimer, so that when we call it the second time it will cause any pending events from the first scheduling to be canceled. But this actually doesn't work at all, because of how we use nsITimer. Before worker threads were capable of accepting arbitrary runnables we created TimerThreadEventTarget, which translates the timer firing to the special worker event queue when the timer thread attempts to *dispatch* a runnable to the worker. We still need this for some of the other types of timers (which use control runnables that interrupt JS, and not the regular event queue). But setTimeout can simply run like a normal nsITimer callback now. We need that here, or calling nsITimer::Cancel won't actually do anything, because the timer's event was ignored and TimerThreadEventTarget created its own event.
Initialize GMPStorage::mShutdown to true, so that if Init() has not completed
yet or if it failed, other methods will not try and access a null mStorage.