53 #include <nsAutoLock.h>
54 #include <nsIDOMDocument.h>
55 #include <nsIDOMElement.h>
56 #include <nsIDOMEvent.h>
57 #include <nsIProxyObjectManager.h>
59 #include <nsServiceManagerUtils.h>
67 static PRLogModuleInfo* gWindowWatcherLog = nsnull;
68 #define TRACE(args) PR_LOG(gWindowWatcherLog, PR_LOG_DEBUG, args)
69 #define LOG(args) PR_LOG(gWindowWatcherLog, PR_LOG_WARN, args)
121 NS_ENSURE_ARG_POINTER(aCallback);
129 nsCOMPtr<sbIWindowWatcher> proxyWindowWatcher;
130 rv = GetProxiedWindowWatcher(getter_AddRefs(proxyWindowWatcher));
131 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
138 rv = proxyWindowWatcher->CallWithWindow(aWindowType, aCallback, aWait);
139 if (NS_SUCCEEDED(rv) || !aWait)
141 if (rv != NS_ERROR_NOT_AVAILABLE)
142 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
145 rv = WaitForWindow(aWindowType);
146 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
148 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
154 nsAutoMonitor autoMonitor(mMonitor);
157 nsCOMPtr<nsIDOMWindow>
window;
158 rv = GetWindow(aWindowType, getter_AddRefs(window));
159 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
164 if (window || mIsShuttingDown) {
165 aCallback->HandleWindowCallback(window);
171 return NS_ERROR_NOT_AVAILABLE;
174 CallWithWindowInfo callWithWindowInfo;
175 callWithWindowInfo.windowType = aWindowType;
176 callWithWindowInfo.callback = aCallback;
177 mCallWithWindowList.AppendElement(callWithWindowInfo);
197 sbWindowWatcher::GetWindow(
const nsAString& aWindowType,
201 NS_ENSURE_ARG_POINTER(_retval);
204 nsCOMPtr<nsIDOMWindow> retWindow;
212 nsAutoMonitor autoMonitor(mMonitor);
216 nsCOMPtr<nsISimpleEnumerator> enumerator;
217 rv = mWindowMediator->GetEnumerator(aWindowType.BeginReading(),
218 getter_AddRefs(enumerator));
219 NS_ENSURE_SUCCESS(rv, rv);
226 rv = enumerator->HasMoreElements(&hasMoreElements);
227 NS_ENSURE_SUCCESS(rv, rv);
228 while (hasMoreElements) {
231 nsCOMPtr<nsIDOMWindow>
window;
232 rv = enumerator->GetNext(getter_AddRefs(_window));
233 NS_ENSURE_SUCCESS(rv, rv);
234 window = do_QueryInterface(_window, &rv);
235 NS_ENSURE_SUCCESS(rv, rv);
236 rv = enumerator->HasMoreElements(&hasMoreElements);
237 NS_ENSURE_SUCCESS(rv, rv);
240 WindowInfo* windowInfo;
241 success = mWindowInfoTable.Get(window, &windowInfo);
242 if (!success || !(windowInfo->isReady))
246 nsAutoString windowType;
247 rv = GetWindowType(window, windowType);
252 if (aWindowType.Equals(windowType)) {
258 NS_IF_ADDREF(*_retval = retWindow);
273 sbWindowWatcher::WaitForWindow(
const nsAString& aWindowType)
283 nsAutoMonitor autoMonitor(mMonitor);
291 NS_ENSURE_SUCCESS(rv, rv);
294 rv = waitForWindow->Wait(aWindowType);
295 NS_ENSURE_SUCCESS(rv, rv);
311 sbWindowWatcher::GetIsShuttingDown(PRBool* aIsShuttingDown)
314 NS_ENSURE_ARG_POINTER(aIsShuttingDown);
317 nsAutoMonitor autoMonitor(mMonitor);
320 *aIsShuttingDown = mIsShuttingDown;
353 const PRUnichar*
aData)
357 TRACE((
"%s: observing %s", __FUNCTION__, aTopic));
360 if (!strcmp(aTopic,
"domwindowopened")) {
361 rv = OnDOMWindowOpened(aSubject, aData);
362 NS_ENSURE_SUCCESS(rv, rv);
363 }
else if (!strcmp(aTopic,
"domwindowclosed")) {
364 rv = OnDOMWindowClosed(aSubject, aData);
365 NS_ENSURE_SUCCESS(rv, rv);
366 }
else if (!strcmp(aTopic,
"quit-application-granted")) {
367 rv = OnQuitApplicationGranted();
368 NS_ENSURE_SUCCESS(rv, rv);
383 sbWindowWatcher::OnDOMWindowOpened(
nsISupports* aSubject,
384 const PRUnichar* aData)
387 NS_ASSERTION(aSubject,
"aSubject is null");
394 nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(aSubject, &rv);
395 NS_ENSURE_SUCCESS(rv, rv);
398 rv = AddWindow(window);
399 NS_ENSURE_SUCCESS(rv, rv);
413 sbWindowWatcher::OnDOMWindowClosed(
nsISupports* aSubject,
414 const PRUnichar* aData)
417 NS_ASSERTION(aSubject,
"aSubject is null");
424 nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(aSubject, &rv);
425 NS_ENSURE_SUCCESS(rv, rv);
428 rv = RemoveWindow(window);
429 NS_ENSURE_SUCCESS(rv, rv);
440 sbWindowWatcher::OnQuitApplicationGranted()
463 mSentMainWinPresentedNotification(PR_FALSE),
464 mIsShuttingDown(PR_FALSE),
465 mServicingCallWithWindowList(PR_FALSE)
468 if (!gWindowWatcherLog)
469 gWindowWatcherLog= PR_NewLogModule(
"sbWindowWatcher");
495 mWindowWatcher = do_GetService(
"@mozilla.org/embedcomp/window-watcher;1",
497 NS_ENSURE_SUCCESS(rv, rv);
500 mWindowMediator = do_GetService(
"@mozilla.org/appshell/window-mediator;1",
502 NS_ENSURE_SUCCESS(rv, rv);
505 mObserverService = do_GetService(
"@mozilla.org/observer-service;1", &rv);
506 NS_ENSURE_SUCCESS(rv, rv);
510 mThreadManager = do_GetService(
"@mozilla.org/thread-manager;1", &rv);
511 NS_ENSURE_SUCCESS(rv, rv);
514 mMonitor = nsAutoMonitor::NewMonitor(
"sbWindowWatcher::mMonitor");
515 NS_ENSURE_TRUE(mMonitor, NS_ERROR_OUT_OF_MEMORY);
518 mWindowInfoTable.Init();
521 rv = mWindowWatcher->RegisterNotification(
this);
522 NS_ENSURE_SUCCESS(rv, rv);
525 rv = mObserverService->AddObserver(
this,
526 "quit-application-granted",
528 NS_ENSURE_SUCCESS(rv, rv);
541 TRACE((
"%s", __FUNCTION__));
550 nsAutoMonitor::DestroyMonitor(mMonitor);
554 mWindowWatcher = nsnull;
555 mWindowMediator = nsnull;
557 mWindowInfoTable.Clear();
558 mCallWithWindowList.Clear();
576 sbWindowWatcher::Shutdown()
583 nsAutoMonitor autoMonitor(mMonitor);
590 mIsShuttingDown = PR_TRUE;
594 mObserverService->RemoveObserver(
this,
"quit-application-granted");
597 InvokeCallWithWindowCallbacks(nsnull);
601 mWindowWatcher->UnregisterNotification(
this);
615 NS_ASSERTION(aWindow,
"aWindow is null");
622 nsAutoMonitor autoMonitor(mMonitor);
625 nsAutoPtr<WindowInfo> windowInfo;
626 windowInfo =
new WindowInfo();
627 NS_ENSURE_TRUE(windowInfo, NS_ERROR_OUT_OF_MEMORY);
628 windowInfo->window = aWindow;
631 nsCOMPtr<nsIDOMWindow2> window2 = do_QueryInterface(aWindow, &rv);
632 NS_ENSURE_SUCCESS(rv, rv);
633 nsCOMPtr<nsIDOMEventTarget> windowEventTarget;
634 rv = window2->GetWindowRoot(getter_AddRefs(windowEventTarget));
635 NS_ENSURE_SUCCESS(rv, rv);
636 windowInfo->eventTarget = windowEventTarget;
639 nsRefPtr<sbWindowWatcherEventListener> eventListener;
643 NS_ENSURE_SUCCESS(rv, rv);
644 windowInfo->eventListener = eventListener;
647 success = mWindowInfoTable.Put(aWindow, windowInfo.forget());
648 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
651 success = mWindowList.AppendObject(aWindow);
652 NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
657 const char* DOM_WINDOW_READY_EVENT_TYPES[] = {
"resize",
"sb-overlay-load" };
659 for (
unsigned int i = 0;
i < NS_ARRAY_LENGTH(DOM_WINDOW_READY_EVENT_TYPES); ++
i) {
660 rv = eventListener->AddEventListener(DOM_WINDOW_READY_EVENT_TYPES[
i]);
661 NS_ENSURE_SUCCESS(rv, rv);
679 NS_ASSERTION(aWindow,
"aWindow is null");
686 nsAutoMonitor autoMonitor(mMonitor);
689 WindowInfo* windowInfo;
690 success = mWindowInfoTable.Get(aWindow, &windowInfo);
696 rv = windowInfo->eventListener->ClearEventListeners();
697 NS_ENSURE_SUCCESS(rv, rv);
701 mWindowInfoTable.Remove(aWindow);
704 mWindowList.RemoveObject(aWindow);
717 sbWindowWatcher::RemoveAllWindows()
720 nsAutoMonitor autoMonitor(mMonitor);
723 PRInt32 windowCount = mWindowList.Count();
724 for (PRInt32
i = windowCount - 1;
i >= 0;
i--) {
725 RemoveWindow(mWindowList[
i]);
740 NS_ENSURE_TRUE(aWindow, );
747 if (!mSentMainWinPresentedNotification) {
748 nsAutoString windowType;
749 rv = GetWindowType(aWindow, windowType);
750 NS_ENSURE_SUCCESS(rv, );
751 if (windowType.EqualsLiteral(
"Songbird:Main")) {
752 rv = mObserverService->NotifyObservers(aWindow,
753 "songbird-main-window-presented",
755 NS_ENSURE_SUCCESS(rv, );
756 mSentMainWinPresentedNotification = PR_TRUE;
762 nsAutoMonitor autoMonitor(mMonitor);
765 WindowInfo* windowInfo;
766 success = mWindowInfoTable.Get(aWindow, &windowInfo);
767 NS_ENSURE_TRUE(success, );
770 windowInfo->isReady = PR_TRUE;
774 InvokeCallWithWindowCallbacks(aWindow);
787 nsAString& aWindowType)
790 NS_ASSERTION(aWindow,
"aWindow is null.");
796 nsCOMPtr<nsIDOMElement>
element;
797 nsCOMPtr<nsIDOMDocument> document;
798 rv = aWindow->GetDocument(getter_AddRefs(document));
799 NS_ENSURE_SUCCESS(rv, rv);
801 return NS_ERROR_NOT_AVAILABLE;
802 rv = document->GetDocumentElement(getter_AddRefs(element));
803 NS_ENSURE_SUCCESS(rv, rv);
805 return NS_ERROR_NOT_AVAILABLE;
808 rv = element->GetAttribute(NS_LITERAL_STRING(
"windowtype"), aWindowType);
809 NS_ENSURE_SUCCESS(rv, rv);
823 sbWindowWatcher::InvokeCallWithWindowCallbacks(
nsIDOMWindow* aWindow)
829 nsAutoString windowType;
831 rv = GetWindowType(aWindow, windowType);
832 NS_ENSURE_SUCCESS(rv, rv);
836 nsAutoMonitor autoMonitor(mMonitor);
839 if (mServicingCallWithWindowList)
843 mServicingCallWithWindowList = PR_TRUE;
846 for (PRUint32
i = 0;
i < mCallWithWindowList.Length();) {
848 CallWithWindowInfo& callWithWindowInfo = mCallWithWindowList[
i];
852 if (!aWindow || windowType.Equals(callWithWindowInfo.windowType)) {
853 callWithWindowInfo.callback->HandleWindowCallback(aWindow);
854 mCallWithWindowList.RemoveElementAt(
i);
861 mServicingCallWithWindowList = PR_FALSE;
877 NS_ASSERTION(aWindowWatcher,
"aWindowWatcher is null");
883 nsCOMPtr<nsIProxyObjectManager>
884 proxyObjectManager = do_GetService(
"@mozilla.org/xpcomproxy;1", &rv);
885 NS_ENSURE_SUCCESS(rv, rv);
886 rv = proxyObjectManager->GetProxyForObject
887 (NS_PROXY_TO_MAIN_THREAD,
890 nsIProxyObjectManager::INVOKE_SYNC |
891 nsIProxyObjectManager::FORCE_PROXY_CREATION,
892 (
void**) aWindowWatcher);
893 NS_ENSURE_SUCCESS(rv, rv);
937 NS_ENSURE_ARG_POINTER(event);
942 nsresult rv =
event->GetType(type);
943 if (NS_SUCCEEDED(rv)) {
944 TRACE((
"%s: got event %s",
946 NS_ConvertUTF16toUTF8(type).
get()));
955 nsCOMPtr<sbIWindowWatcher>
956 windowWatcher = do_QueryReferent(mWeakSBWindowWatcher, &rv);
957 NS_ENSURE_SUCCESS(rv, rv);
960 nsAutoString eventType;
961 rv =
event->GetType(eventType);
962 NS_ENSURE_SUCCESS(rv, rv);
965 if (mOutstandingEvents.Contains(eventType)) {
966 nsCOMPtr<nsIDOMEventTarget>
target;
967 rv =
event->GetCurrentTarget(getter_AddRefs(target));
968 NS_ENSURE_SUCCESS(rv, rv);
969 rv = target->RemoveEventListener(eventType,
this, PR_TRUE);
970 NS_ENSURE_SUCCESS(rv, rv);
971 mOutstandingEvents.RemoveElement(eventType);
972 TRACE((
"%s: removed event %s listener %p from %p",
974 NS_ConvertUTF16toUTF8(eventType).
get(),
977 if (mOutstandingEvents.IsEmpty()) {
978 mSBWindowWatcher->OnWindowReady(mWindow);
1011 NS_ENSURE_ARG_POINTER(aListener);
1017 nsRefPtr<sbWindowWatcherEventListener>
listener;
1019 NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
1022 rv = listener->Initialize();
1023 NS_ENSURE_SUCCESS(rv, rv);
1026 return CallQueryInterface(listener.get(), aListener);
1041 sbWindowWatcherEventListener::Initialize()
1046 nsCOMPtr<nsISupportsWeakReference>
1047 weakSBWindowWatcher =
1050 NS_ENSURE_SUCCESS(rv, rv);
1051 rv = weakSBWindowWatcher->GetWeakReference
1052 (getter_AddRefs(mWeakSBWindowWatcher));
1053 NS_ENSURE_SUCCESS(rv, rv);
1056 nsCOMPtr<nsIDOMWindow2> window2 = do_QueryInterface(mWindow, &rv);
1057 NS_ENSURE_SUCCESS(rv, rv);
1058 rv = window2->GetWindowRoot(getter_AddRefs(mEventTarget));
1059 NS_ENSURE_SUCCESS(rv, rv);
1074 NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_INITIALIZED);
1076 NS_ConvertASCIItoUTF16 eventName(aEventName);
1078 if (mOutstandingEvents.Contains(eventName)) {
1082 rv = mEventTarget->AddEventListener(eventName,
this, PR_TRUE);
1083 NS_ENSURE_SUCCESS(rv, rv);
1085 mOutstandingEvents.AppendElement(eventName);
1086 TRACE((
"%s: Added event %s listener %p to %p",
1090 mEventTarget.get()));
1104 TRACE((
"%s: clearing %p from %p",
1107 mEventTarget.get()));
1109 NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_INITIALIZED);
1111 for (PRUint32
i = mOutstandingEvents.Length() - 1;
i != PRUint32(-1); --
i) {
1112 TRACE((
"%s: Removing event %s listener %p from %p",
1114 NS_ConvertUTF16toUTF8(mOutstandingEvents[
i]).
get(),
1116 mEventTarget.get()));
1117 rv = mEventTarget->RemoveEventListener(mOutstandingEvents[i],
1120 NS_ENSURE_SUCCESS(rv, rv);
1121 mOutstandingEvents.RemoveElementAt(i);
1123 NS_ASSERTION(mOutstandingEvents.IsEmpty(),
1124 "unexpected outstanding listeners!");
1163 nsAutoMonitor autoReadyMonitor(mReadyMonitor);
1170 autoReadyMonitor.Notify();
1194 NS_ENSURE_ARG_POINTER(aWaitForWindow);
1200 nsRefPtr<sbWindowWatcherWaitForWindow> waitForWindow;
1202 NS_ENSURE_TRUE(waitForWindow, NS_ERROR_OUT_OF_MEMORY);
1205 rv = waitForWindow->Initialize();
1206 NS_ENSURE_SUCCESS(rv, rv);
1209 NS_ADDREF(*aWaitForWindow = waitForWindow);
1223 nsAutoMonitor::DestroyMonitor(mReadyMonitor);
1224 mReadyMonitor = nsnull;
1227 mSBWindowWatcher = nsnull;
1245 rv = mSBWindowWatcher->CallWithWindow(aWindowType,
this,
false);
1246 NS_ENSURE_SUCCESS(rv, rv);
1249 nsAutoMonitor autoReadyMonitor(mReadyMonitor);
1253 rv = autoReadyMonitor.Wait();
1254 NS_ENSURE_SUCCESS(rv, rv);
1271 sbWindowWatcherWaitForWindow::sbWindowWatcherWaitForWindow() :
1272 mReadyMonitor(nsnull),
1283 sbWindowWatcherWaitForWindow::Initialize()
1289 do_GetService(
"@songbirdnest.com/Songbird/window-watcher;1", &rv);
1290 NS_ENSURE_SUCCESS(rv, rv);
1294 nsAutoMonitor::NewMonitor(
"sbWindowWatcherWaitForWindow::mReadyMonitor");
1295 NS_ENSURE_TRUE(mReadyMonitor, NS_ERROR_OUT_OF_MEMORY);
A callback interface that is called with a window.
void waitForWindow(in AString aWindowType)
Wait until a window of the type specified by aWindowType is available or until shutdown. This method may not be called on the main thread. Since the available window can only be used on the main thread, the available window may become unavailable after waitForWindow returns but before processing continues on the main thread.
NS_IMPL_THREADSAFE_ISUPPORTS3(sbWindowWatcher, sbIWindowWatcher, nsIObserver, nsISupportsWeakReference) NS_IMETHODIMP sbWindowWatcher
Call callback specified by aCallback with a window of the type specified by aWindowType. Wait until a window of the specified type is available or until shutdown. Call callback with null window on shutdown. Call callback on main thread. If aWait is true, don't return until callback is called.
Songbird Window Watcher Definitions.
nsresult AddEventListener(const char *aEventName)
NS_DECL_ISUPPORTS static NS_DECL_SBICALLWITHWINDOWCALLBACK nsresult New(sbWindowWatcherWaitForWindow **aWaitForWindow)
PRBool SB_IsMainThread(nsIThreadManager *aThreadManager)
virtual ~sbWindowWatcherWaitForWindow()
Songbird Thread Utilities Definitions.
nsresult Wait(const nsAString &aWindowType)
Wait until a window of the type specified by aWindowType is available or until shutdown.
NS_DECL_ISUPPORTS NS_DECL_SBIWINDOWWATCHER NS_DECL_NSIOBSERVER sbWindowWatcher()
virtual ~sbWindowWatcher()
NS_DECL_ISUPPORTS static NS_DECL_NSIDOMEVENTLISTENER nsresult New(sbWindowWatcherEventListener **aListener, sbWindowWatcher *aSBWindowWatcher, nsIDOMWindow *aWindow)
SimpleArrayEnumerator prototype hasMoreElements
NS_IMPL_THREADSAFE_ISUPPORTS1(sbWindowWatcherEventListener, nsIDOMEventListener) NS_IMETHODIMP sbWindowWatcherEventListener
nsresult ClearEventListeners()
_getSelectedPageStyle s i
_updateTextAndScrollDataForFrame aData