Bug 1434565 - Put some meanigful timestamp to nsRemoteService::HandleCommandLine(), r?jhorak
We need to put a timestamp to nsRemoteService::HandleCommandLine() to allow Gtk+ focus
opened Firefox window.
Unfortunately we don't have much choice how to get the timestamp at DBUS remote service
so ask for gtk_get_current_event_time() and when GDK_CURRENT_TIME is returned
(it means we don't have the timestamp) use g_get_monotonic_time() as well
as at nsWindow::GetEventTimeStamp().
MozReview-Commit-ID: 9ilVZ0kPe3x

/* -*- Mode: c++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4; -*- *//* 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/. */#ifndef nsAppShell_h__#define nsAppShell_h__#include<time.h>#include"mozilla/HangMonitor.h"#include"mozilla/LinkedList.h"#include"mozilla/Monitor.h"#include"mozilla/Move.h"#include"mozilla/StaticPtr.h"#include"mozilla/TypeTraits.h"#include"mozilla/UniquePtr.h"#include"mozilla/Unused.h"#include"mozilla/jni/Natives.h"#include"nsBaseAppShell.h"#include"nsCOMPtr.h"#include"nsTArray.h"#include"nsInterfaceHashtable.h"#include"nsIAndroidBridge.h"namespacemozilla{boolProcessNextEvent();voidNotifyEvent();}classnsWindow;classnsAppShell:publicnsBaseAppShell{public:structEvent:mozilla::LinkedListElement<Event>{typedefmozilla::HangMonitor::ActivityTypeType;staticuint64_tGetTime(){timespectime;if(clock_gettime(CLOCK_MONOTONIC,&time)){return0ull;}returnuint64_t(time.tv_sec)*1000000000ull+time.tv_nsec;}uint64_tmPostTime{0};boolHasSameTypeAs(constEvent*other)const{// Compare vtable addresses to determine same type.return*reinterpret_cast<constuintptr_t*>(this)==*reinterpret_cast<constuintptr_t*>(other);}virtual~Event(){}virtualvoidRun()=0;virtualvoidPostTo(mozilla::LinkedList<Event>&queue){queue.insertBack(this);}virtualTypeActivityType()const{returnType::kGeneralActivity;}};template<typenameT>classLambdaEvent:publicEvent{protected:Tlambda;public:LambdaEvent(T&&l):lambda(mozilla::Move(l)){}voidRun()override{returnlambda();}};classProxyEvent:publicEvent{protected:mozilla::UniquePtr<Event>baseEvent;public:ProxyEvent(mozilla::UniquePtr<Event>&&event):baseEvent(mozilla::Move(event)){}voidPostTo(mozilla::LinkedList<Event>&queue)override{baseEvent->PostTo(queue);}voidRun()override{baseEvent->Run();}};staticnsAppShell*Get(){MOZ_ASSERT(NS_IsMainThread());returnsAppShell;}nsAppShell();NS_DECL_ISUPPORTS_INHERITEDNS_DECL_NSIOBSERVERnsresultInit();voidNotifyNativeEvent();boolProcessNextNativeEvent(boolmayWait)override;// Post a subclass of Event.// e.g. PostEvent(mozilla::MakeUnique<MyEvent>());template<typenameT,typenameD>staticvoidPostEvent(mozilla::UniquePtr<T,D>&&event){mozilla::MutexAutoLocklock(*sAppShellLock);if(!sAppShell){return;}sAppShell->mEventQueue.Post(mozilla::Move(event));}// Post a event that will call a lambda// e.g. PostEvent([=] { /* do something */ });template<typenameT>staticvoidPostEvent(T&&lambda){mozilla::MutexAutoLocklock(*sAppShellLock);if(!sAppShell){return;}sAppShell->mEventQueue.Post(mozilla::MakeUnique<LambdaEvent<T>>(mozilla::Move(lambda)));}// Post a event and wait for it to finish running on the Gecko thread.staticvoidSyncRunEvent(Event&&event,mozilla::UniquePtr<Event>(*eventFactory)(mozilla::UniquePtr<Event>&&)=nullptr);template<typenameT>statictypenamemozilla::EnableIf<!mozilla::IsBaseOf<Event,T>::value,void>::TypeSyncRunEvent(T&&lambda){SyncRunEvent(LambdaEvent<T>(mozilla::Forward<T>(lambda)));}staticalready_AddRefed<nsIURI>ResolveURI(constnsCString&aUriStr);voidSetBrowserApp(nsIAndroidBrowserApp*aBrowserApp){mBrowserApp=aBrowserApp;}nsIAndroidBrowserApp*GetBrowserApp(){returnmBrowserApp;}protected:staticnsAppShell*sAppShell;staticmozilla::StaticAutoPtr<mozilla::Mutex>sAppShellLock;staticvoidRecordLatencies();virtual~nsAppShell();nsresultAddObserver(constnsAString&aObserverKey,nsIObserver*aObserver);classNativeCallbackEvent:publicEvent{// Capturing the nsAppShell instance is safe because if the app// shell is detroyed, this lambda will not be called either.nsAppShell*constappShell;public:NativeCallbackEvent(nsAppShell*as):appShell(as){}voidRun()override{appShell->NativeEventCallback();}};voidScheduleNativeEventCallback()override{mEventQueue.Post(mozilla::MakeUnique<NativeCallbackEvent>(this));}classQueue{private:mozilla::MonitormMonitor;mozilla::LinkedList<Event>mQueue;public:enum{LATENCY_UI,LATENCY_OTHER,LATENCY_COUNT};staticuint32_tsLatencyCount[LATENCY_COUNT];staticuint64_tsLatencyTime[LATENCY_COUNT];Queue():mMonitor("nsAppShell.Queue"){}voidSignal(){mozilla::MonitorAutoLocklock(mMonitor);lock.NotifyAll();}voidPost(mozilla::UniquePtr<Event>&&event){MOZ_ASSERT(event&&!event->isInList());mozilla::MonitorAutoLocklock(mMonitor);event->PostTo(mQueue);if(event->isInList()){event->mPostTime=Event::GetTime();// Ownership of event object transfers to the queue.mozilla::Unused<<event.release();}lock.NotifyAll();}mozilla::UniquePtr<Event>Pop(boolmayWait){mozilla::MonitorAutoLocklock(mMonitor);if(mayWait&&mQueue.isEmpty()){#ifdef EARLY_BETA_OR_EARLIER// Record latencies when we're about to be idle.nsAppShell::RecordLatencies();#endiflock.Wait();}// Ownership of event object transfers to the return value.mozilla::UniquePtr<Event>event(mQueue.popFirst());if(!event||!event->mPostTime){returnMove(event);}#ifdef EARLY_BETA_OR_EARLIERconstsize_tlatencyType=(event->ActivityType()==Event::Type::kUIActivity)?LATENCY_UI:LATENCY_OTHER;constuint64_tlatency=Event::GetTime()-event->mPostTime;sLatencyCount[latencyType]++;sLatencyTime[latencyType]+=latency;#endifreturnMove(event);}}mEventQueue;mozilla::CondVarmSyncRunFinished;boolmSyncRunQuit;boolmAllowCoalescingTouches;nsCOMPtr<nsIAndroidBrowserApp>mBrowserApp;nsInterfaceHashtable<nsStringHashKey,nsIObserver>mObserversHash;};#endif // nsAppShell_h__