Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | const Ci = SpecialPowers.Ci; |
michael@0 | 2 | const Cc = SpecialPowers.Cc; |
michael@0 | 3 | ok(Ci != null, "Access Ci"); |
michael@0 | 4 | ok(Cc != null, "Access Cc"); |
michael@0 | 5 | |
michael@0 | 6 | var didDialog; |
michael@0 | 7 | |
michael@0 | 8 | var isSelectDialog = false; |
michael@0 | 9 | var isTabModal = false; |
michael@0 | 10 | var usePromptService = true; |
michael@0 | 11 | |
michael@0 | 12 | var timer; // keep in outer scope so it's not GC'd before firing |
michael@0 | 13 | function startCallbackTimer() { |
michael@0 | 14 | didDialog = false; |
michael@0 | 15 | |
michael@0 | 16 | // Delay before the callback twiddles the prompt. |
michael@0 | 17 | const dialogDelay = 10; |
michael@0 | 18 | |
michael@0 | 19 | // Use a timer to invoke a callback to twiddle the authentication dialog |
michael@0 | 20 | timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
michael@0 | 21 | timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT); |
michael@0 | 22 | } |
michael@0 | 23 | |
michael@0 | 24 | |
michael@0 | 25 | var observer = { |
michael@0 | 26 | QueryInterface : function (iid) { |
michael@0 | 27 | const interfaces = [Ci.nsIObserver, |
michael@0 | 28 | Ci.nsISupports, Ci.nsISupportsWeakReference]; |
michael@0 | 29 | |
michael@0 | 30 | if (!interfaces.some( function(v) { return iid.equals(v) } )) |
michael@0 | 31 | throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE; |
michael@0 | 32 | return this; |
michael@0 | 33 | }, |
michael@0 | 34 | |
michael@0 | 35 | observe : SpecialPowers.wrapCallback(function (subject, topic, data) { |
michael@0 | 36 | try { |
michael@0 | 37 | if (isTabModal) { |
michael@0 | 38 | var promptBox = getTabModalPromptBox(window); |
michael@0 | 39 | ok(promptBox, "got tabmodal promptbox"); |
michael@0 | 40 | var prompts = SpecialPowers.wrap(promptBox).listPrompts(); |
michael@0 | 41 | if (prompts.length) |
michael@0 | 42 | handleDialog(prompts[0].Dialog.ui, testNum); |
michael@0 | 43 | else |
michael@0 | 44 | startCallbackTimer(); // try again in a bit |
michael@0 | 45 | } else { |
michael@0 | 46 | var doc = getDialogDoc(); |
michael@0 | 47 | if (isSelectDialog && doc) |
michael@0 | 48 | handleDialog(doc, testNum); |
michael@0 | 49 | else if (doc) |
michael@0 | 50 | handleDialog(doc.defaultView.Dialog.ui, testNum); |
michael@0 | 51 | else |
michael@0 | 52 | startCallbackTimer(); // try again in a bit |
michael@0 | 53 | } |
michael@0 | 54 | } catch (e) { |
michael@0 | 55 | ok(false, "Exception thrown in the timer callback: " + e + " at " + (e.fileName || e.filename) + ":" + (e.lineNumber || e.linenumber)); |
michael@0 | 56 | } |
michael@0 | 57 | }) |
michael@0 | 58 | }; |
michael@0 | 59 | |
michael@0 | 60 | function getTabModalPromptBox(domWin) { |
michael@0 | 61 | var promptBox = null; |
michael@0 | 62 | |
michael@0 | 63 | // Given a content DOM window, returns the chrome window it's in. |
michael@0 | 64 | function getChromeWindow(aWindow) { |
michael@0 | 65 | var chromeWin = SpecialPowers.wrap(aWindow).QueryInterface(Ci.nsIInterfaceRequestor) |
michael@0 | 66 | .getInterface(Ci.nsIWebNavigation) |
michael@0 | 67 | .QueryInterface(Ci.nsIDocShell) |
michael@0 | 68 | .chromeEventHandler.ownerDocument.defaultView; |
michael@0 | 69 | return chromeWin; |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | try { |
michael@0 | 73 | // Get the topmost window, in case we're in a frame. |
michael@0 | 74 | var promptWin = domWin.top; |
michael@0 | 75 | |
michael@0 | 76 | // Get the chrome window for the content window we're using. |
michael@0 | 77 | var chromeWin = getChromeWindow(promptWin); |
michael@0 | 78 | |
michael@0 | 79 | if (chromeWin.getTabModalPromptBox) |
michael@0 | 80 | promptBox = chromeWin.getTabModalPromptBox(promptWin); |
michael@0 | 81 | } catch (e) { |
michael@0 | 82 | // If any errors happen, just assume no tabmodal prompter. |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | // Callers get confused by a wrapped promptBox here. |
michael@0 | 86 | return SpecialPowers.unwrap(promptBox); |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | function getDialogDoc() { |
michael@0 | 90 | // Trudge through all the open windows, until we find the one |
michael@0 | 91 | // that has either commonDialog.xul or selectDialog.xul loaded. |
michael@0 | 92 | var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. |
michael@0 | 93 | getService(Ci.nsIWindowMediator); |
michael@0 | 94 | //var enumerator = wm.getEnumerator("navigator:browser"); |
michael@0 | 95 | var enumerator = wm.getXULWindowEnumerator(null); |
michael@0 | 96 | |
michael@0 | 97 | while (enumerator.hasMoreElements()) { |
michael@0 | 98 | var win = enumerator.getNext(); |
michael@0 | 99 | var windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell; |
michael@0 | 100 | |
michael@0 | 101 | var containedDocShells = windowDocShell.getDocShellEnumerator( |
michael@0 | 102 | Ci.nsIDocShellTreeItem.typeChrome, |
michael@0 | 103 | Ci.nsIDocShell.ENUMERATE_FORWARDS); |
michael@0 | 104 | while (containedDocShells.hasMoreElements()) { |
michael@0 | 105 | // Get the corresponding document for this docshell |
michael@0 | 106 | var childDocShell = containedDocShells.getNext(); |
michael@0 | 107 | // We don't want it if it's not done loading. |
michael@0 | 108 | if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE) |
michael@0 | 109 | continue; |
michael@0 | 110 | var childDoc = childDocShell.QueryInterface(Ci.nsIDocShell) |
michael@0 | 111 | .contentViewer |
michael@0 | 112 | .DOMDocument; |
michael@0 | 113 | |
michael@0 | 114 | //ok(true, "Got window: " + childDoc.location.href); |
michael@0 | 115 | if (childDoc.location.href == "chrome://global/content/commonDialog.xul") |
michael@0 | 116 | return childDoc; |
michael@0 | 117 | if (childDoc.location.href == "chrome://global/content/selectDialog.xul") |
michael@0 | 118 | return childDoc; |
michael@0 | 119 | } |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | return null; |
michael@0 | 123 | } |