forked from mirrors/gecko-dev
		
	 6adf9223ce
			
		
	
	
		6adf9223ce
		
	
	
	
	
		
			
			Differential Revision: https://phabricator.services.mozilla.com/D3730 --HG-- extra : rebase_source : 935f166ec2c6581ba6f3fffe912404e81c8dc3d6 extra : histedit_source : ba701801de5205dcce6cfdccabe7b26aa7c7859c
		
			
				
	
	
		
			228 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* eslint-env mozilla/frame-script */
 | |
| 
 | |
| ChromeUtils.import("resource://gre/modules/Services.jsm");
 | |
| ChromeUtils.import("resource://gre/modules/Timer.jsm");
 | |
| 
 | |
| // Define these to make EventUtils happy.
 | |
| let window = this;
 | |
| let parent = {};
 | |
| 
 | |
| let EventUtils = {};
 | |
| Services.scriptloader.loadSubScript(
 | |
|   "chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
 | |
|   EventUtils
 | |
| );
 | |
| 
 | |
| addMessageListener("handlePrompt", msg => {
 | |
|   handlePromptWhenItAppears(msg.action, msg.isTabModal, msg.isSelect);
 | |
| });
 | |
| 
 | |
| function handlePromptWhenItAppears(action, isTabModal, isSelect) {
 | |
|   let interval = setInterval(() => {
 | |
|     if (handlePrompt(action, isTabModal, isSelect)) {
 | |
|       clearInterval(interval);
 | |
|     }
 | |
|   }, 100);
 | |
| }
 | |
| 
 | |
| function handlePrompt(action, isTabModal, isSelect) {
 | |
|   let ui;
 | |
| 
 | |
|   if (isTabModal) {
 | |
|     let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
 | |
|     let gBrowser = browserWin.gBrowser;
 | |
|     let promptManager = gBrowser.getTabModalPromptBox(gBrowser.selectedBrowser);
 | |
|     let prompts = promptManager.listPrompts();
 | |
|     if (!prompts.length) {
 | |
|       return false; // try again in a bit
 | |
|     }
 | |
| 
 | |
|     ui = prompts[0].Dialog.ui;
 | |
|   } else {
 | |
|     let doc = getDialogDoc();
 | |
|     if (!doc) {
 | |
|       return false; // try again in a bit
 | |
|     }
 | |
| 
 | |
|     if (isSelect)
 | |
|       ui = doc;
 | |
|     else
 | |
|       ui = doc.defaultView.Dialog.ui;
 | |
| 
 | |
|   }
 | |
| 
 | |
|   let promptState;
 | |
|   if (isSelect) {
 | |
|     promptState = getSelectState(ui);
 | |
|     dismissSelect(ui, action);
 | |
|   } else {
 | |
|     promptState = getPromptState(ui);
 | |
|     dismissPrompt(ui, action);
 | |
|   }
 | |
|   sendAsyncMessage("promptHandled", { promptState });
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| function getSelectState(ui) {
 | |
|   let listbox = ui.getElementById("list");
 | |
| 
 | |
|   let state = {};
 | |
|   state.msg = ui.getElementById("info.txt").value;
 | |
|   state.selectedIndex = listbox.selectedIndex;
 | |
|   state.items = [];
 | |
| 
 | |
|   for (let i = 0; i < listbox.itemCount; i++) {
 | |
|     let item = listbox.getItemAtIndex(i).label;
 | |
|     state.items.push(item);
 | |
|   }
 | |
| 
 | |
|   return state;
 | |
| }
 | |
| 
 | |
| function getPromptState(ui) {
 | |
|   let state = {};
 | |
|   state.msg         = ui.infoBody.textContent;
 | |
|   state.titleHidden = ui.infoTitle.getAttribute("hidden") == "true";
 | |
|   state.textHidden  = ui.loginContainer.hidden;
 | |
|   state.passHidden  = ui.password1Container.hidden;
 | |
|   state.checkHidden = ui.checkboxContainer.hidden;
 | |
|   state.checkMsg    = ui.checkbox.label;
 | |
|   state.checked     = ui.checkbox.checked;
 | |
|   // tab-modal prompts don't have an infoIcon
 | |
|   state.iconClass   = ui.infoIcon ? ui.infoIcon.className : null;
 | |
|   state.textValue   = ui.loginTextbox.getAttribute("value");
 | |
|   state.passValue   = ui.password1Textbox.getAttribute("value");
 | |
| 
 | |
|   state.butt0Label  = ui.button0.label;
 | |
|   state.butt1Label  = ui.button1.label;
 | |
|   state.butt2Label  = ui.button2.label;
 | |
| 
 | |
|   state.butt0Disabled = ui.button0.disabled;
 | |
|   state.butt1Disabled = ui.button1.disabled;
 | |
|   state.butt2Disabled = ui.button2.disabled;
 | |
| 
 | |
|   function isDefaultButton(b) {
 | |
|       return (b.hasAttribute("default") &&
 | |
|               b.getAttribute("default") == "true");
 | |
|   }
 | |
|   state.defButton0 = isDefaultButton(ui.button0);
 | |
|   state.defButton1 = isDefaultButton(ui.button1);
 | |
|   state.defButton2 = isDefaultButton(ui.button2);
 | |
| 
 | |
|   let e = Services.focus.focusedElement;
 | |
| 
 | |
|   if (e == null) {
 | |
|     state.focused = null;
 | |
|   } else if (ui.button0.isSameNode(e)) {
 | |
|     state.focused = "button0";
 | |
|   } else if (ui.button1.isSameNode(e)) {
 | |
|     state.focused = "button1";
 | |
|   } else if (ui.button2.isSameNode(e)) {
 | |
|     state.focused = "button2";
 | |
|   } else if (ui.loginTextbox.inputField.isSameNode(e)) {
 | |
|     state.focused = "textField";
 | |
|   } else if (ui.password1Textbox.inputField.isSameNode(e)) {
 | |
|     state.focused = "passField";
 | |
|   } else if (ui.infoBody.isSameNode(e)) {
 | |
|     state.focused = "infoBody";
 | |
|   } else {
 | |
|     state.focused = "ERROR: unexpected element focused: " + (e ? e.localName : "<null>");
 | |
|   }
 | |
| 
 | |
|   return state;
 | |
| }
 | |
| 
 | |
| function dismissSelect(ui, action) {
 | |
|   let dialog = ui.getElementsByTagName("dialog")[0];
 | |
|   let listbox = ui.getElementById("list");
 | |
| 
 | |
|   if (action.selectItem) {
 | |
|       listbox.selectedIndex = 1;
 | |
|   }
 | |
| 
 | |
|   if (action.buttonClick == "ok") {
 | |
|       dialog.acceptDialog();
 | |
|   } else if (action.buttonClick == "cancel") {
 | |
|       dialog.cancelDialog();
 | |
|   }
 | |
| }
 | |
| 
 | |
| function dismissPrompt(ui, action) {
 | |
|   if (action.setCheckbox) {
 | |
|     // Annoyingly, the prompt code is driven by oncommand.
 | |
|     ui.checkbox.setChecked(true);
 | |
|     ui.checkbox.doCommand();
 | |
|   }
 | |
| 
 | |
|   if ("textField" in action) {
 | |
|     ui.loginTextbox.setAttribute("value", action.textField);
 | |
|   }
 | |
| 
 | |
|   if ("passField" in action) {
 | |
|     ui.password1Textbox.setAttribute("value", action.passField);
 | |
|   }
 | |
| 
 | |
|   switch (action.buttonClick) {
 | |
|     case "ok":
 | |
|     case 0:
 | |
|       ui.button0.click();
 | |
|       break;
 | |
|     case "cancel":
 | |
|     case 1:
 | |
|       ui.button1.click();
 | |
|       break;
 | |
|     case 2:
 | |
|       ui.button2.click();
 | |
|       break;
 | |
|     case "ESC":
 | |
|       // XXX This is assuming tab-modal.
 | |
|       let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
 | |
|       EventUtils.synthesizeKey("KEY_Escape", {}, browserWin);
 | |
|       break;
 | |
|     case "pollOK":
 | |
|       // Buttons are disabled at the moment, poll until they're reenabled.
 | |
|       // Can't use setInterval here, because the window's in a modal state
 | |
|       // and thus DOM events are suppressed.
 | |
|       let interval = setInterval(() => {
 | |
|         if (ui.button0.disabled)
 | |
|           return;
 | |
|         ui.button0.click();
 | |
|         clearInterval(interval);
 | |
|       }, 100);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       throw "dismissPrompt action listed unknown button.";
 | |
|   }
 | |
| }
 | |
| 
 | |
| function getDialogDoc() {
 | |
|   // Trudge through all the open windows, until we find the one
 | |
|   // that has either commonDialog.xul or selectDialog.xul loaded.
 | |
|   // var enumerator = Services.wm.getEnumerator("navigator:browser");
 | |
|   for (let {docShell} of Services.wm.getEnumerator(null)) {
 | |
|     var containedDocShells = docShell.getDocShellEnumerator(
 | |
|                                       docShell.typeChrome,
 | |
|                                       docShell.ENUMERATE_FORWARDS);
 | |
|     for (let childDocShell of containedDocShells) {
 | |
|         // Get the corresponding document for this docshell
 | |
|         // We don't want it if it's not done loading.
 | |
|         if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
 | |
|           continue;
 | |
|         var childDoc = childDocShell.contentViewer.DOMDocument;
 | |
| 
 | |
|         if (childDoc.location.href != "chrome://global/content/commonDialog.xul" &&
 | |
|             childDoc.location.href != "chrome://global/content/selectDialog.xul")
 | |
|           continue;
 | |
| 
 | |
|         // We're expecting the dialog to be focused. If it's not yet, try later.
 | |
|         // (In particular, this is needed on Linux to reliably check focused elements.)
 | |
|         if (Services.focus.focusedWindow != childDoc.defaultView)
 | |
|           continue;
 | |
| 
 | |
|         return childDoc;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return null;
 | |
| }
 |