From b5c85c563355e76b773bccba6b3620c24cf12ac4 Mon Sep 17 00:00:00 2001 From: Jan Odvarko Date: Tue, 15 Dec 2015 13:04:41 +0100 Subject: [PATCH 01/25] Bug 1232613 - JSON Viewer: fix colors. r=jryans --- devtools/client/jsonview/css/reps.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/devtools/client/jsonview/css/reps.css b/devtools/client/jsonview/css/reps.css index 85a633ad03d3..bd4c73f64fe7 100644 --- a/devtools/client/jsonview/css/reps.css +++ b/devtools/client/jsonview/css/reps.css @@ -175,7 +175,7 @@ .theme-dark .domLabel, .theme-light .domLabel { - color: var(--theme-highlight-bluegrey); + color: var(--theme-highlight-blue); } .theme-dark .objectBox-array .length, @@ -207,7 +207,7 @@ .theme-light .objectBox-object { font-family: Lucida Grande, sans-serif; font-weight: normal; - color: var(--theme-highlight-bluegrey); + color: var(--theme-highlight-blue); white-space: pre-wrap; } @@ -215,5 +215,5 @@ .theme-light .caption { font-family: Lucida Grande, Tahoma, sans-serif; font-weight: normal; - color: var(--theme-highlight-bluegrey); + color: var(--theme-highlight-blue); } From 12afd8c645e6e85bfcb06b1da306b1b8658d080c Mon Sep 17 00:00:00 2001 From: Jan Odvarko Date: Tue, 15 Dec 2015 13:01:59 +0100 Subject: [PATCH 02/25] Bug 1232614 - JSON Viewer: better icons for tree expanders; r=jryans --- .../jsonview/components/reps/tree-view.js | 1 + devtools/client/jsonview/css/controls.png | Bin 0 -> 1630 bytes devtools/client/jsonview/css/controls@2x.png | Bin 0 -> 2045 bytes devtools/client/jsonview/css/dom-tree.css | 90 +++++++++++++++--- devtools/client/jsonview/css/moz.build | 2 + 5 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 devtools/client/jsonview/css/controls.png create mode 100644 devtools/client/jsonview/css/controls@2x.png diff --git a/devtools/client/jsonview/components/reps/tree-view.js b/devtools/client/jsonview/components/reps/tree-view.js index a08534d68ed7..f3bae27c532d 100644 --- a/devtools/client/jsonview/components/reps/tree-view.js +++ b/devtools/client/jsonview/components/reps/tree-view.js @@ -153,6 +153,7 @@ var TreeNode = React.createFactory(React.createClass({ return ( DOM.div({className: classNames.join(" "), onClick: this.onClick}, DOM.span({className: "memberLabelCell"}, + DOM.span({className: "memberIcon"}), DOM.span({className: "memberLabel " + member.type + "Label"}, member.name) ), diff --git a/devtools/client/jsonview/css/controls.png b/devtools/client/jsonview/css/controls.png new file mode 100644 index 0000000000000000000000000000000000000000..569c266e4e4c79a60c4b023728b1ee3e648fe551 GIT binary patch literal 1630 zcmbVMeNYr-7+(%NkOUbpzr&sN3zfayJ@!8Kh67FxyhHi$xJDXBYwzwo*kEtZ+l9L$ zKaMPcY5W2;w1Nam!9hf`$+U5t2+)x+CNif{N|2hADWISz()N(E{&4)Go!Ncg=Y5~w z^ZcH#t<1?<7ZJWN9D<+-qd{*HSGD*q4wH&s^5XU+aakawCD=sHs6(u7SBt;PMupB26FapQq6iN^pQl%l3@brU- z-dr}j#-vZ5_9aSMq(Bgy8Vqy0-7#NFPOl;G@h!> zo4rnenE=lfyR2e8>`Mb+F?Y{)Z6<>?9#q z+DX)c6H1g+Dk+p!6AF~DSS(7MCKPt1Enw$qcwDVlQ+l511-_uytGqIXf7oY{sW#+h|Ko{f`a015{a85Wi6^_fKt&GDj zukzREamae$VoHE5-Nmu+RFXB!QwRXkM&l}#4OPk&6iUi1c9g;aj*=>?B0*`ls(}h1 z(|FteO&%ta!u*}`pUw#!iS6j$KA8hicrr=AA&!qroD=VFz7YtLlo|Cpv*%mO z@0l8tqEr&%cG5BL@Q*j@hENn$y!QLg#XHCDAD;h0VrOK#B4ub+d%bz=`=;Cz*E2FQ zN_Reb*c~484q;9280g#&Vxptxo@{EmQ-3!9y6=))3B)Ux$6jd}CtzwS>?{2Ft#rsm<-H*YG>ojEgkye#yDq%Ah8Tr%<^oE6f)E9G`b zd))ZOQwNX zaBxKR3b`j}FCi^5RyP~xNQ+o@c4tS2ti(kw=84qV9yY;e#wB7D@q_{@xHsd^z`(Nu>FIEMUBV1<3Ii4{TWeoD|;~Uem^rzRp^7=mrRaRmE literal 0 HcmV?d00001 diff --git a/devtools/client/jsonview/css/controls@2x.png b/devtools/client/jsonview/css/controls@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fb062516db8e49e90b5081f63bd7881ebfc5df65 GIT binary patch literal 2045 zcmbVNdsGu=7Ej6}$g5}piB>y=qGHKoLLMZNN|G@OC4vyzv@2*PnLH%Pgk*q#h#F%d zwt}k#3RVO~k%w@wP@zaUt*mTaSa4CRa-^a{vC5Hp5T$Z#CkpQV;prbc=gfTfe&6r@ z?)~oLj3Z&=dLPdvo&*BHCuRebh_5F6jr4HGzoGYYWATNIt&?L(s2a;sm=S_dg~A9B zV^C<2L`0#=PX7^!A`o0GI++}kOXK)T)Id`>F*K{eNkt$;t+kpI$}|K6U__%c3Mdad zx+s87C7^u7mNKL!F{0IN$T1^HIU8lloHQj*MOphk5M|}#1O^0C09J$EXyIE0loz~w zTy}2LDZmQ|mL{OQ3`#Cd0K}*n0oXJ)Rmot20GCGt*(@Fih679n7(oXabS94qf_xU2 z4|0IHhk|=EtJM5NNHXUO*8~(ThMD+udRA5zEh~bCnl*Hg$K%l%OgfWE#Sv6Xwh>cU zsYXl4JOhMSlxCd?)1gMd$*6$Q3`{`5BYk-VgGnlVMQpUpB??a&-KsFrK^lW@FgWk^ z0&T$(k^hGATC_!$Z9?dYhy~3sEAe`$L*|X~-2Js9ClHT@A8*#-MN#M>RGDEwj93gL zpx`Gol}^P+)GUz6QM0Hp1LROy91f4Fhy>YG5Qbq6LjkhY9MwF}>+BhkP$UnEWbs50 z8wA%y@IY3i7-B#yp->2}<3-Hd#uzP_!l*>%ed}=FbG8wGY0DRz5e0^tWhknj?}7v^ zilG)QY68S!V3ky%)ES+6n6pMNuM8n(T_&QEm{9}pBFTK+YXX2lE|05(nN$vg$)&Pj zCY!2Ib3iJ{fg{vB1dfCe4rR_>_5UW1jt50|cFO;B&ioeMj!yB_9N@~UNkWYH_?YoI zSqym(5eTk83?!6UZ#+0G(E1Dgdo)E}j`eV~)IaInZ3?|V9J~Pzh5zoqZ?Eem$^I=w zukS_Rky;t#7DCzgPQiYW$EmFg0|pnwRN0;;YoTKYgC334{<5A&}`p{7O&9e06 zvtP%ZDQj>4x%coBwdTlXT2I5hG~IJ$%;SCXCC{Q}J`KGzd^wI&GR;g5Xg*sScySqG zZ2CF5u%q)k=GmW$q3vP!?cSy;VhFb`!~Rv+sIln-^Y$Gv-)J zT^uK1KQ!&s^{qMUdn5Kp{oY2hd(o4LpvNePU8^Qv^PcdRjOCuc)hg21pI<4vD_UB$ z!$z9%NU`UU-#~pZa$V)4547AblF3_rT1eX#v^6dN_0zFUGixy4@(NLiwqAU+Mc0+Flptk#>yvWL3xb&f@qGb>;np zjX}*+T72_S_3E>0TO{WORnj{Zw+jZkGE3hZO}iOT)!$Xy)t_(G1`JiX2i3>Lm(=wGUB?H`!>g02Z=Q2GZ42~hobnpo?$$vPTw#6t zU^ge)$F)eD8$Xl!eU5I~W%J4l|0*_S?!WzPNe$`H^2VtHlUd)nSG<{2wJ*DJs5nr6 zZPbRf3XkSR?JCSa9d`w)==cvRnhC%hw#9EX^G@vqclc~%PpCG;Ek9s@(n7 z`!(k={B8x7tR+s{N4X{YEmh=i8{NAlF2umXhpo-CI>PavqLYG|DZwR+y5$Asr+4T1 zm3_`$__*O8h^~9v$;zImQ6D?}%BtDvAuUnxvf1pBl<9~1+Amn5t8op764p!P^~r}F zJ_oPfD>vWW%>*7P$2Mtviw^VzWYoB%My#y<%_F;Evm;klaA#p~$(l}wXL>lLn>V=h z<2B&h@Csr<`shhR_>E`zCq&-8QiRwWYucj-E{sk$gufI6TbmCYbVWBLy2``5+eUtr z_xunYp7YVF&;=E}1d0c|X!63lSIMs6<&xA`&?@xH$Y1OVPUY!ih1NVj>F!@h&DDKV zEypIIf+G2Iw||E1x#jSi`HWWF&^>tlUiC;o`l(ony`B;kw$K=RsjSo .memberLabelCell > .memberIcon:hover, +.memberRow.cropped > .memberLabelCell > .memberIcon:hover { + cursor: pointer; +} + .memberRow.hasChildren > .memberLabelCell > .memberLabel:hover, .memberRow.cropped > .memberLabelCell > .memberLabel:hover { cursor: pointer; @@ -71,6 +74,10 @@ background-color: #EFEFEF; } +.memberRow { + padding: 3px 0 3px 0; +} + .panelNode-dom .memberRow td, .panelNode-domSide .memberRow td { border-bottom: 1px solid #EFEFEF; @@ -116,19 +123,38 @@ /******************************************************************************/ /* Twisties */ -.memberRow.hasChildren > .memberLabelCell > .memberLabel, -.memberRow.cropped > .memberLabelCell > .memberLabel { - background-image: url(twisty-closed.svg); - background-repeat: no-repeat; - background-position: 2px calc(0.5em - 3px); - min-height: 12px; +.memberRow > .memberLabelCell > .memberIcon { + height: 14px; + width: 14px; + display: inline-block; + line-height: 15px; + vertical-align: bottom; + padding-right: 2px; + margin-left: 3px; } -.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel, -.memberRow.cropped.opened > .memberLabelCell > .memberLabel { - background-image: url(twisty-open.svg); +.memberRow.hasChildren > .memberLabelCell > .memberIcon, +.memberRow.cropped > .memberLabelCell > .memberIcon { + background-image: url("./twisty-closed.svg"); background-repeat: no-repeat; - min-height: 12px; +} + +.memberRow.hasChildren.opened > .memberLabelCell > .memberIcon, +.memberRow.cropped.opened > .memberLabelCell > .memberIcon { + background-image: url("./twisty-open.svg"); + background-repeat: no-repeat; +} + +@media (min-resolution: 1.1dppx) { +.memberRow.hasChildren > .memberLabelCell > .memberIcon, +.memberRow.cropped > .memberLabelCell > .memberIcon { + background-image: url("./controls@2x.png"); +} + +.memberRow.hasChildren.opened > .memberLabelCell > .memberIcon, +.memberRow.cropped.opened > .memberLabelCell > .memberIcon { + background-image: url("./controls@2x.png"); +} } /******************************************************************************/ @@ -140,7 +166,6 @@ .memberLabelCell, .memberValueCell { - display: table-cell; } .memberLabelCell { @@ -150,3 +175,42 @@ .memberRow:hover { background-color: transparent !important; } + +/******************************************************************************/ +/* Themes */ + +.theme-light .memberRow.hasChildren > .memberLabelCell > .memberIcon, +.theme-light .memberRow.cropped > .memberLabelCell > .memberIcon { + background-image: url("./controls.png"); + background-size: 56px 28px; + background-repeat: no-repeat; + background-position: 0 -14px; +} + +.theme-light .memberRow.hasChildren.opened > .memberLabelCell > .memberIcon, +.theme-light .memberRow.cropped.opened > .memberLabelCell > .memberIcon { + background-image: url("./controls.png"); + background-size: 56px 28px; + background-repeat: no-repeat; + background-position: -14px -14px; +} + +.theme-dark .memberRow.hasChildren > .memberLabelCell > .memberIcon, +.theme-dark .memberRow.cropped > .memberLabelCell > .memberIcon { + background-image: url("./controls.png"); + background-size: 56px 28px; + background-repeat: no-repeat; + background-position: -28px -14px; +} + +.theme-dark .memberRow.hasChildren.opened > .memberLabelCell > .memberIcon, +.theme-dark .memberRow.cropped.opened > .memberLabelCell > .memberIcon { + background-image: url("./controls.png"); + background-size: 56px 28px; + background-repeat: no-repeat; + background-position: -42px -14px; +} + +.theme-dark .memberRow:hover { + background-color: var(--theme-selection-background-semitransparent); +} diff --git a/devtools/client/jsonview/css/moz.build b/devtools/client/jsonview/css/moz.build index be368cb8bba6..a71ba20ada79 100644 --- a/devtools/client/jsonview/css/moz.build +++ b/devtools/client/jsonview/css/moz.build @@ -6,6 +6,8 @@ DevToolsModules( + 'controls.png', + 'controls@2x.png', 'dom-tree.css', 'general.css', 'headers-panel.css', From 91795d36320c7589cee67362bb152e5cf4cabda0 Mon Sep 17 00:00:00 2001 From: Jan Odvarko Date: Tue, 15 Dec 2015 13:27:53 +0100 Subject: [PATCH 03/25] Bug 1232634 - Only clicking on the label expands the tree. r=jryans --- devtools/client/jsonview/components/reps/tree-view.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/devtools/client/jsonview/components/reps/tree-view.js b/devtools/client/jsonview/components/reps/tree-view.js index f3bae27c532d..3452e1c62587 100644 --- a/devtools/client/jsonview/components/reps/tree-view.js +++ b/devtools/client/jsonview/components/reps/tree-view.js @@ -51,9 +51,8 @@ var TreeView = React.createClass({ } return ( - DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0, - onClick: this.onClick}, - children + DOM.div({className: "domTable", cellPadding: 0, cellSpacing: 0}, + children ) ); }, @@ -151,8 +150,8 @@ var TreeNode = React.createFactory(React.createClass({ } return ( - DOM.div({className: classNames.join(" "), onClick: this.onClick}, - DOM.span({className: "memberLabelCell"}, + DOM.div({className: classNames.join(" ")}, + DOM.span({className: "memberLabelCell", onClick: this.onClick}, DOM.span({className: "memberIcon"}), DOM.span({className: "memberLabel " + member.type + "Label"}, member.name) From d99c19e16d8e64528062675163f78d327fe214a8 Mon Sep 17 00:00:00 2001 From: Brian Grinstead Date: Mon, 4 Jan 2016 09:52:28 -0800 Subject: [PATCH 04/25] Bug 1234801 - Extra specificity for codemirror dialog since light/dark theme are now loading before the page styles. r=pbrosset --HG-- extra : transplant_source : %04%B6jV%A2%24%2B%A7%7BS%1A%9Dj%A4%DFy%EF%F7%D4%81 --- devtools/client/themes/dark-theme.css | 2 +- devtools/client/themes/light-theme.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/devtools/client/themes/dark-theme.css b/devtools/client/themes/dark-theme.css index 57f642d5d5e8..6e92d449bb54 100644 --- a/devtools/client/themes/dark-theme.css +++ b/devtools/client/themes/dark-theme.css @@ -168,7 +168,7 @@ body { .devtools-toolbar, .devtools-sidebar-tabs tabs, .devtools-sidebar-alltabs, -.CodeMirror-dialog { /* General toolbar styling */ +.cm-s-mozilla .CodeMirror-dialog { /* General toolbar styling */ color: var(--theme-body-color-alt); background-color: var(--theme-toolbar-background); border-color: hsla(210,8%,5%,.6); diff --git a/devtools/client/themes/light-theme.css b/devtools/client/themes/light-theme.css index 5d0d522f7c5d..148213943b76 100644 --- a/devtools/client/themes/light-theme.css +++ b/devtools/client/themes/light-theme.css @@ -171,7 +171,7 @@ body { .devtools-toolbar, .devtools-sidebar-tabs tabs, .devtools-sidebar-alltabs, -.CodeMirror-dialog { /* General toolbar styling */ +.cm-s-mozilla .CodeMirror-dialog { /* General toolbar styling */ color: var(--theme-body-color-alt); background-color: var(--theme-toolbar-background); border-color: var(--theme-splitter-color); From 5fb3720954976e7727e5c5b59b676e80ad192f8d Mon Sep 17 00:00:00 2001 From: Jan Odvarko Date: Mon, 4 Jan 2016 17:31:01 +0100 Subject: [PATCH 05/25] Bug 1235118 - JSON Viewer: remove support for .json URL extensions; r=jryans --- devtools/client/jsonview/converter-sniffer.js | 5 ---- devtools/shared/webconsole/network-helper.js | 30 ------------------- 2 files changed, 35 deletions(-) diff --git a/devtools/client/jsonview/converter-sniffer.js b/devtools/client/jsonview/converter-sniffer.js index 0160ddc3144d..bc913dd316ec 100644 --- a/devtools/client/jsonview/converter-sniffer.js +++ b/devtools/client/jsonview/converter-sniffer.js @@ -22,7 +22,6 @@ const CONTRACT_ID = "@mozilla.org/devtools/jsonview-sniffer;1"; const CLASS_ID = "{4148c488-dca1-49fc-a621-2a0097a62422}"; const JSON_VIEW_MIME_TYPE = "application/vnd.mozilla.json.view"; const JSON_VIEW_TYPE = "JSON View"; -const JSON_EXTENSION = "json"; const CONTENT_SNIFFER_CATEGORY = "net-content-sniffers"; /** @@ -64,10 +63,6 @@ var Sniffer = Class({ if (aRequest.contentType == JSON_TYPE) { return JSON_VIEW_MIME_TYPE; } - - if (NetworkHelper.getFileExtension(aRequest.name) == JSON_EXTENSION) { - return JSON_VIEW_MIME_TYPE; - } } return ""; diff --git a/devtools/shared/webconsole/network-helper.js b/devtools/shared/webconsole/network-helper.js index ac5df06367e0..c6bc763ae8ef 100644 --- a/devtools/shared/webconsole/network-helper.js +++ b/devtools/shared/webconsole/network-helper.js @@ -803,36 +803,6 @@ var NetworkHelper = { let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL); aStore.set(aUrl, uri); return uri; - }, - - /** - * Returns extension for file URLs (e.g. 'json'). - * Not everyURL has an extension and this method works as follows: - * 1) Remove query string - * 2) Get part after the last slash (a file name) - * 3) Look for the last dot (an extension) - */ - getFileExtension: function(aUrl) { - if (!aUrl) { - return; - } - - // Remove query string from the URL if any. - let queryString = aUrl.indexOf("?"); - if (queryString != -1) { - aUrl = aUrl.substr(0, queryString); - } - - // Look for the part after last slash - var lastSlash = aUrl.lastIndexOf("/"); - var fileName = aUrl.substr(lastSlash + 1); - if (!fileName) { - return; - } - - // Now get the file extension. - var lastDot = fileName.lastIndexOf("."); - return fileName.substr(lastDot + 1); } }; From 577fbe977456a942c2704a753b86a2a895a69f8d Mon Sep 17 00:00:00 2001 From: Lin Clark Date: Thu, 31 Dec 2015 06:29:00 +0100 Subject: [PATCH 06/25] Bug 1236032 - Fix typo in debugger event constant. r=ejpbruel --- devtools/client/debugger/debugger-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/client/debugger/debugger-controller.js b/devtools/client/debugger/debugger-controller.js index a4a89b69c8cb..bd02b82c3012 100644 --- a/devtools/client/debugger/debugger-controller.js +++ b/devtools/client/debugger/debugger-controller.js @@ -18,7 +18,7 @@ const CALL_STACK_PAGE_SIZE = 25; // frames const EVENTS = { // When the debugger's source editor instance finishes loading or unloading. EDITOR_LOADED: "Debugger:EditorLoaded", - EDITOR_UNLOADED: "Debugger:EditorUnoaded", + EDITOR_UNLOADED: "Debugger:EditorUnloaded", // When new sources are received from the debugger server. NEW_SOURCE: "Debugger:NewSource", From b4604965822d78eb312e34a3ebbf6fc4ce2bffb0 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 5 Jan 2016 02:41:49 -0800 Subject: [PATCH 07/25] Bug 1225108 - Introduce an addon to easily work on devtools codebase. r=jryans --- devtools/bootstrap.js | 99 +++++++++++++++++++++++++ devtools/chrome.manifest | 6 ++ devtools/client/framework/gDevTools.jsm | 18 +++-- devtools/install.rdf | 27 +++++++ 4 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 devtools/bootstrap.js create mode 100644 devtools/chrome.manifest create mode 100644 devtools/install.rdf diff --git a/devtools/bootstrap.js b/devtools/bootstrap.js new file mode 100644 index 000000000000..109d56a3f771 --- /dev/null +++ b/devtools/bootstrap.js @@ -0,0 +1,99 @@ +/* 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/. */ + +"use strict"; + +const Cu = Components.utils; +const Ci = Components.interfaces; +const {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); + +// Helper to listen to a key on all windows +function MultiWindowKeyListener({ keyCode, ctrlKey, altKey, callback }) { + let keyListener = function (event) { + if (event.ctrlKey == !!ctrlKey && + event.altKey == !!altKey && + event.keyCode === keyCode) { + callback(event); + + // Call preventDefault to avoid duplicated events when + // doing the key stroke within a tab. + event.preventDefault(); + } + }; + + let observer = function (window, topic, data) { + // Listen on keyup to call keyListener only once per stroke + if (topic === "domwindowopened") { + window.addEventListener("keyup", keyListener); + } else { + window.removeEventListener("keyup", keyListener); + } + }; + + return { + start: function () { + // Automatically process already opened windows + let e = Services.ww.getWindowEnumerator(); + while (e.hasMoreElements()) { + let window = e.getNext(); + observer(window, "domwindowopened", null); + } + // And listen for new ones to come + Services.ww.registerNotification(observer); + }, + + stop: function () { + Services.ww.unregisterNotification(observer); + let e = Services.ww.getWindowEnumerator(); + while (e.hasMoreElements()) { + let window = e.getNext(); + observer(window, "domwindowclosed", null); + } + } + }; +}; + +let getTopLevelWindow = function (window) { + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem) + .rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); +}; + +function reload(event) { + // We automatically reload the toolbox if we are on a browser tab + // with a toolbox already opened + let top = getTopLevelWindow(event.view) + let isBrowser = top.location.href.includes("/browser.xul") && top.gDevToolsBrowser; + let reloadToolbox = false; + if (isBrowser && top.gDevToolsBrowser.hasToolboxOpened) { + reloadToolbox = top.gDevToolsBrowser.hasToolboxOpened(top); + } + dump("Reload DevTools. (reload-toolbox:"+reloadToolbox+")\n"); + + // Invalidate xul cache in order to see changes made to chrome:// files + Services.obs.notifyObservers(null, "startupcache-invalidate", null); + + // Ask the loader to update itself and reopen the toolbox if needed + const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {}); + devtools.reload(reloadToolbox); +} + +let listener; +function startup() { + dump("DevTools addon started.\n"); + listener = new MultiWindowKeyListener({ + keyCode: Ci.nsIDOMKeyEvent.DOM_VK_R, ctrlKey: true, altKey: true, + callback: reload + }); + listener.start(); +} +function shutdown() { + listener.stop(); + listener = null; +} +function install() {} +function uninstall() {} diff --git a/devtools/chrome.manifest b/devtools/chrome.manifest new file mode 100644 index 000000000000..bcf3431992d0 --- /dev/null +++ b/devtools/chrome.manifest @@ -0,0 +1,6 @@ +content devtools client/ +skin devtools classic/1.0 client/themes/ +resource devtools . + +content webide client/webide/content/ +skin webide classic/1.0 client/webide/themes/ diff --git a/devtools/client/framework/gDevTools.jsm b/devtools/client/framework/gDevTools.jsm index cb3d0b3ac4fa..d90030d132ac 100644 --- a/devtools/client/framework/gDevTools.jsm +++ b/devtools/client/framework/gDevTools.jsm @@ -1161,6 +1161,16 @@ var gDevToolsBrowser = { }; }, + hasToolboxOpened: function(win) { + let tab = win.gBrowser.selectedTab; + for (let [target, toolbox] of gDevTools._toolboxes) { + if (target.tab == tab) { + return true; + } + } + return false; + }, + /** * Update the "Toggle Tools" checkbox in the developer tools menu. This is * called when a toolbox is created or destroyed. @@ -1168,13 +1178,7 @@ var gDevToolsBrowser = { _updateMenuCheckbox: function DT_updateMenuCheckbox() { for (let win of gDevToolsBrowser._trackedBrowserWindows) { - let hasToolbox = false; - if (TargetFactory.isKnownTab(win.gBrowser.selectedTab)) { - let target = TargetFactory.forTab(win.gBrowser.selectedTab); - if (gDevTools._toolboxes.has(target)) { - hasToolbox = true; - } - } + let hasToolbox = gDevToolsBrowser.hasToolboxOpened(win); let broadcaster = win.document.getElementById("devtoolsMenuBroadcaster_DevToolbox"); if (hasToolbox) { diff --git a/devtools/install.rdf b/devtools/install.rdf new file mode 100644 index 000000000000..fbef350794ac --- /dev/null +++ b/devtools/install.rdf @@ -0,0 +1,27 @@ + + + + + + + true + + + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + 44.0a1 + * + + + + From e73331bccfe90e9315d58d433d1a7a7f2e60336d Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 5 Jan 2016 02:41:50 -0800 Subject: [PATCH 08/25] Bug 1236457 - Stop using deprecated dbg-server.jsm/dbg-client.jsm from /devtools. r=jryans --- devtools/client/shared/components/test/mochitest/head.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/devtools/client/shared/components/test/mochitest/head.js b/devtools/client/shared/components/test/mochitest/head.js index e61d1de027fe..089bbbabc936 100644 --- a/devtools/client/shared/components/test/mochitest/head.js +++ b/devtools/client/shared/components/test/mochitest/head.js @@ -20,10 +20,10 @@ Services.prefs.setBoolPref("devtools.memory.enabled", true); var { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {}); var { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {}); var { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}); -var { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {}); -var { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {}); -var DevToolsUtils = require("devtools/shared/DevToolsUtils"); var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {}); +var { DebuggerServer } = require("devtools/server/main"); +var { DebuggerClient } = require("devtools/shared/client/main"); +var DevToolsUtils = require("devtools/shared/DevToolsUtils"); var { TargetFactory } = require("devtools/client/framework/target"); var { Toolbox } = require("devtools/client/framework/toolbox"); From 7ec278bec3b98ce974e5a33988156a598372e99d Mon Sep 17 00:00:00 2001 From: Sebastian Kaspari Date: Tue, 22 Dec 2015 10:28:10 +0100 Subject: [PATCH 09/25] Bug 1236507 - DownloadContentService: Skip download if file system is not writable. r=rnewman --HG-- extra : commitid : CjHJIIbrS6x extra : rebase_source : 42b7aa2220de59343e4e8fa20c135ebef0824092 extra : histedit_source : e386e1f900aae8e05b2e83f6f09de04f40ef1786 --- .../org/mozilla/gecko/dlc/DownloadAction.java | 17 +++++++++- .../mozilla/gecko/dlc/TestDownloadAction.java | 31 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java b/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java index ac8aedc86f9e..afa3898dabdf 100644 --- a/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java +++ b/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java @@ -87,6 +87,11 @@ public class DownloadAction extends BaseAction { temporaryFile = createTemporaryFile(context, content); + if (!canWrite(temporaryFile, destinationFile)) { + throw new RecoverableDownloadContentException(RecoverableDownloadContentException.DISK_IO, + "Temporary or destination file not writeable"); + } + if (!hasEnoughDiskSpace(content, destinationFile, temporaryFile)) { Log.d(LOGTAG, "Not enough disk space to save content. Skipping download."); continue; @@ -125,7 +130,7 @@ public class DownloadAction extends BaseAction { temporaryFile.delete(); } } catch (RecoverableDownloadContentException e) { - Log.w(LOGTAG, "Downloading content failed (Recoverable): " + content , e); + Log.w(LOGTAG, "Downloading content failed (Recoverable): " + content, e); if (e.shouldBeCountedAsFailure()) { catalog.rememberFailure(content, e.getErrorType()); @@ -336,4 +341,14 @@ public class DownloadAction extends BaseAction { return true; } + + protected boolean canWrite(File... files) { + for (File file : files) { + if (!file.canWrite()) { + return false; + } + } + + return true; + } } diff --git a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/dlc/TestDownloadAction.java b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/dlc/TestDownloadAction.java index 18cca87f6d59..6c206c067d1a 100644 --- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/dlc/TestDownloadAction.java +++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/dlc/TestDownloadAction.java @@ -168,6 +168,7 @@ public class TestDownloadAction { doReturn(file).when(action).createTemporaryFile(RuntimeEnvironment.application, content); doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content); + doReturn(true).when(action).canWrite(any(File.class), any(File.class)); doReturn(false).when(action).verify(eq(file), anyString()); doNothing().when(action).download(any(HttpClient.class), anyString(), eq(file)); doReturn(true).when(action).verify(eq(file), anyString()); @@ -202,6 +203,7 @@ public class TestDownloadAction { DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); + doReturn(true).when(action).canWrite(any(File.class), any(File.class)); File temporaryFile = mockFileWithSize(1337L); doReturn(temporaryFile).when(action).createTemporaryFile(RuntimeEnvironment.application, content); @@ -301,6 +303,7 @@ public class TestDownloadAction { File destinationFile = mockNotExistingFile(); doReturn(destinationFile).when(action).getDestinationFile(RuntimeEnvironment.application, content); + doReturn(true).when(action).canWrite(any(File.class), any(File.class)); doReturn(true).when(action).verify(eq(temporaryFile), anyString()); doNothing().when(action).extract(eq(temporaryFile), eq(destinationFile), anyString()); @@ -333,6 +336,7 @@ public class TestDownloadAction { DownloadAction action = spy(new DownloadAction(null)); doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); + doReturn(true).when(action).canWrite(any(File.class), any(File.class)); doNothing().when(action).download(any(HttpClient.class), anyString(), any(File.class)); doReturn(false).when(action).verify(any(File.class), anyString()); @@ -443,6 +447,7 @@ public class TestDownloadAction { doReturn(mockNotExistingFile()).when(action).createTemporaryFile(RuntimeEnvironment.application, content); doReturn(mockNotExistingFile()).when(action).getDestinationFile(RuntimeEnvironment.application, content); doReturn(true).when(action).hasEnoughDiskSpace(eq(content), any(File.class), any(File.class)); + doReturn(true).when(action).canWrite(any(File.class), any(File.class)); HttpClient client = mock(HttpClient.class); doThrow(IOException.class).when(client).execute(any(HttpUriRequest.class)); @@ -499,6 +504,32 @@ public class TestDownloadAction { verify(catalog, times(11)).rememberFailure(eq(content), anyInt()); } + /** + * Scenario: Temporary or destination file is not writable. + * + * Verify that: + * * No download is performed + * * Error is counted as failure + */ + @Test + public void testNoDownIsPerformedIfFilesAreNotWritable() throws Exception{ + DownloadContent content = createFont(); + DownloadContentCatalog catalog = mockCatalogWithScheduledDownloads(content); + + DownloadAction action = spy(new DownloadAction(null)); + doReturn(true).when(action).isConnectedToNetwork(RuntimeEnvironment.application); + doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application); + doReturn(mockNotExistingFile()).when(action).createTemporaryFile(RuntimeEnvironment.application, content); + doReturn(mockNotExistingFile()).when(action).getDestinationFile(RuntimeEnvironment.application, content); + doReturn(false).when(action).canWrite(any(File.class), any(File.class)); + + action.perform(RuntimeEnvironment.application, catalog); + + verify(action).canWrite(any(File.class), any(File.class)); + verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class)); + verify(catalog).rememberFailure(eq(content), anyInt()); + } + private DownloadContent createFont() { return createFontWithSize(102400L); } From 6afe554637fc2dbf744498ebc14a7b13e203e4b8 Mon Sep 17 00:00:00 2001 From: Sebastian Kaspari Date: Fri, 18 Dec 2015 13:08:58 +0100 Subject: [PATCH 10/25] Bug 1233693 - AppMenuComponent: Search for views with exactly matching text. r=mcomella --HG-- extra : commitid : 4IydKYGBjSa extra : rebase_source : 59d68eb5e96b81c1fb27314417580b3954467a00 extra : amend_source : ae23760ca70eea7ccc0dd4fa44efcfa358b29acf --- .../mozilla/gecko/tests/components/AppMenuComponent.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java index f40f34049ee1..17ccc1e4d040 100644 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java +++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java @@ -159,7 +159,7 @@ public class AppMenuComponent extends BaseComponent { * This method is dependent on not having two views with equivalent contentDescription / text. */ private View findAppMenuItemView(String text) { - mSolo.waitForText(text, 1, MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS); + mSolo.waitForText(String.format("^%s$", text), 1, MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS); final List views = mSolo.getViews(); @@ -298,7 +298,8 @@ public class AppMenuComponent extends BaseComponent { private boolean isLegacyMoreMenuOpen() { // Check if the first menu option is visible. - return mSolo.searchText(mSolo.getString(R.string.share), true); + final String shareTitle = mSolo.getString(R.string.share); + return mSolo.searchText(String.format("^%s$", shareTitle), true); } /** @@ -310,7 +311,7 @@ public class AppMenuComponent extends BaseComponent { */ private boolean isMenuOpen(String menuItemTitle) { final View menuItemView = findAppMenuItemView(menuItemTitle); - return isMenuOpen(menuItemView) ? true : mSolo.searchText(menuItemTitle, true); + return isMenuOpen(menuItemView) ? true : mSolo.searchText(String.format("^%s$", menuItemTitle), true); } /** From 3433b432cf8d83df7b289247e49d611640bc80b5 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Mon, 14 Dec 2015 16:04:31 +0000 Subject: [PATCH 11/25] Bug 1231112 - work around tab groups migration issue in safe mode, r=ttaubert --HG-- extra : commitid : 6GVsgSDEQkg extra : rebase_source : 43cdb84e108dec4a4dce12a5a2f5d0dc83ed5bb9 --- browser/components/nsBrowserGlue.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index a8790fd17f7a..dec6f6aa7244 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -803,6 +803,15 @@ BrowserGlue.prototype = { this._sanitizer.onStartup(); // check if we're in safe mode if (Services.appinfo.inSafeMode) { + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1231112#c7 . We need to + // register the observer early if we have to migrate tab groups + let currentUIVersion = 0; + try { + currentUIVersion = Services.prefs.getIntPref("browser.migration.version"); + } catch(ex) {} + if (currentUIVersion < 35) { + this._maybeMigrateTabGroups(); + } Services.ww.openWindow(null, "chrome://browser/content/safeMode.xul", "_blank", "chrome,centerscreen,modal,resizable=no", null); } @@ -2241,7 +2250,8 @@ BrowserGlue.prototype = { this._notifyNotificationsUpgrade().catch(Cu.reportError); } - if (currentUIVersion < 35) { + // Only do this outside of safe mode, because in safe mode we do this earlier. + if (currentUIVersion < 35 && !Services.appinfo.inSafeMode) { this._maybeMigrateTabGroups(); } From c2227545717cdf260c5de56256ea31db50ccb53b Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Tue, 17 Nov 2015 15:19:47 +0000 Subject: [PATCH 12/25] Bug 1224713 - fix sidebar header text in devedition theme on linux and windows, r=bgrins --HG-- extra : commitid : Byiz1bpdB7Z extra : rebase_source : 379912046673c2e1b63b29e1149fa4d41035b640 --- browser/themes/linux/browser.css | 4 ++++ browser/themes/linux/devedition.css | 11 +++++++---- browser/themes/windows/browser-aero.css | 4 ++-- browser/themes/windows/browser.css | 12 ++++++++++++ browser/themes/windows/devedition.css | 10 ++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css index fdb981842519..b50a82e13a8d 100644 --- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -1440,6 +1440,10 @@ richlistitem[type~="action"][actiontype$="tab"] > .ac-url-box > .ac-action-icon background-color: Window; } +#sidebar-header > .close-icon:not(:hover):-moz-lwtheme-brighttext { + background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64); +} + .browserContainer > findbar { background-color: -moz-dialog; color: -moz-DialogText; diff --git a/browser/themes/linux/devedition.css b/browser/themes/linux/devedition.css index 0f4f1c7ddb2e..66a5274c3fcb 100644 --- a/browser/themes/linux/devedition.css +++ b/browser/themes/linux/devedition.css @@ -4,6 +4,8 @@ %include ../shared/devedition.inc.css +:root[devtoolstheme="dark"] .findbar-closebutton:not(:hover), +:root[devtoolstheme="dark"] #sidebar-header > .close-icon:not(:hover), .tab-close-button[visuallyselected]:not(:hover) { background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64); } @@ -76,8 +78,9 @@ border-top-width: 0 !important; } -/* Prevent devedition foreground color from seeping into the sidebar-box (since - * its background colors aren't affected by the devedition theme) */ -#sidebar-box { - color: initial; +/* Fix the bad-looking text-shadow in the sidebar header: */ +.sidebar-header, +#sidebar-header { + text-shadow: none; } + diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css index 79514f98761d..eb423a3f87b1 100644 --- a/browser/themes/windows/browser-aero.css +++ b/browser/themes/windows/browser-aero.css @@ -52,8 +52,8 @@ @media (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { - .sidebar-header, - #sidebar-header { + .sidebar-header:not(:-moz-lwtheme), + #sidebar-header:not(:-moz-lwtheme) { background-color: #EEF3FA; } diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index e50275eb6594..eab731fac895 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -1872,6 +1872,18 @@ richlistitem[type~="action"][actiontype$="tab"] > .ac-url-box > .ac-action-icon border: none; } +@media not all and (min-resolution: 1.1dppx) { + #sidebar-header > .close-icon:-moz-lwtheme-brighttext { + list-style-image: url("chrome://global/skin/icons/close-inverted.png"); + } +} + +@media (min-resolution: 1.1dppx) { + #sidebar-header > .close-icon:-moz-lwtheme-brighttext { + list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png"); + } +} + @media (-moz-os-version: windows-xp), (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { diff --git a/browser/themes/windows/devedition.css b/browser/themes/windows/devedition.css index ec945c22c11c..f441bf95e8a5 100644 --- a/browser/themes/windows/devedition.css +++ b/browser/themes/windows/devedition.css @@ -107,6 +107,7 @@ } :root[devtoolstheme="dark"] .findbar-closebutton, +:root[devtoolstheme="dark"] #sidebar-header > .close-icon, /* Tab styling - make sure to use an inverted icon for the selected tab (brighttext only covers the unselected tabs) */ .tab-close-button[visuallyselected=true] { @@ -115,6 +116,7 @@ @media (min-resolution: 1.1dppx) { :root[devtoolstheme="dark"] .findbar-closebutton, + :root[devtoolstheme="dark"] #sidebar-header > .close-icon, .tab-close-button[visuallyselected=true] { list-style-image: url("chrome://global/skin/icons/close-inverted@2x.png"); } @@ -254,6 +256,14 @@ border-right: none !important; } +/* The sidebar header has no background now that the background of the #browser-panel + * has no image and is transparent. Fix: */ +.sidebar-header:-moz-lwtheme, +#sidebar-header { + background-color: var(--chrome-background-color); + color: var(--chrome-color); +} + @media (-moz-os-version: windows-vista), (-moz-os-version: windows-win7), (-moz-os-version: windows-win8) { From f9c6c36436cebc4bec7f54eebfe5d159345e8509 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Mon, 4 Jan 2016 13:46:40 -0500 Subject: [PATCH 13/25] Bug 1218594 - Fix some bad test assertion strings. r=felipe --HG-- extra : commitid : 3FIPSOKEnYS extra : rebase_source : 4bf04136cba0c19bf444db94b127fcd36d335e7c extra : histedit_source : 7336bc9c3b80c30fe2ac1a71b5913f88b9c932cb --- dom/tests/browser/browser_test_toolbars_visibility.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dom/tests/browser/browser_test_toolbars_visibility.js b/dom/tests/browser/browser_test_toolbars_visibility.js index 77c15e67bd66..26367e3bd2a2 100644 --- a/dom/tests/browser/browser_test_toolbars_visibility.js +++ b/dom/tests/browser/browser_test_toolbars_visibility.js @@ -98,15 +98,15 @@ function testNonDefaultContentToolbars(toolbars) { function testNonDefaultChromeToolbars(toolbars) { // None of the toolbars should be visible if hidden with chrome privileges ok(!toolbars.locationbar, - "locationbar should be visible on default window.open()"); + "locationbar should not be visible with location=no"); ok(!toolbars.menubar, - "menubar be visible on default window.open()"); + "menubar should not be visible with menubar=no"); ok(!toolbars.personalbar, - "personalbar should be visible on default window.open()"); + "personalbar should not be visible with personalbar=no"); ok(!toolbars.statusbar, - "statusbar should be visible on default window.open()"); + "statusbar should not be visible with status=no"); ok(!toolbars.toolbar, - "toolbar should be visible on default window.open()"); + "toolbar should not be visible with toolbar=no"); } /** From 5433e47dd60b1b1af2df7469953f56fe6e667ef9 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Mon, 4 Jan 2016 13:46:58 -0500 Subject: [PATCH 14/25] Bug 1218594 - Regression test. r=felipe --HG-- extra : commitid : GFWHfGonWSr extra : rebase_source : a5cf935ce2f1cb1ead5a70b162e3a93be03e8269 extra : histedit_source : f75bab77d2743c8b549d10da5654b3b57294f90f --- .../browser_test_toolbars_visibility.js | 37 ++++++++++++++++++- .../test_new_window_from_content_child.html | 6 +++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/dom/tests/browser/browser_test_toolbars_visibility.js b/dom/tests/browser/browser_test_toolbars_visibility.js index 26367e3bd2a2..90e724b02e2d 100644 --- a/dom/tests/browser/browser_test_toolbars_visibility.js +++ b/dom/tests/browser/browser_test_toolbars_visibility.js @@ -147,7 +147,42 @@ add_task(function*() { let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser); testNonDefaultContentToolbars(popupToolbars); - // Cleanup + // Ensure that chrome toolbars agree with content + let chromeToolbars = getToolbarsFromWindowChrome(popupWindow); + testNonDefaultContentToolbars(chromeToolbars); + + // Close the new window + yield BrowserTestUtils.closeWindow(popupWindow); + }); +}); + +/** + * Ensure that toolbars of a window opened to about:blank in the content context + * have the correct visibility. + * + * A window opened with "location=no, personalbar=no, toolbar=no, scrollbars=no, + * menubar=no, status=no", should only have location visible. + */ +add_task(function*() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: CONTENT_PAGE, + }, function*(browser) { + // Open a blank window with toolbars hidden + let winPromise = BrowserTestUtils.waitForNewWindow(); + yield BrowserTestUtils.synthesizeMouseAtCenter("#winOpenNoURLNonDefault", {}, browser); + let popupWindow = yield winPromise; + + // No need to wait for this window to load, since it's loading about:blank + let popupBrowser = popupWindow.gBrowser.selectedBrowser; + let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser); + testNonDefaultContentToolbars(popupToolbars); + + // Ensure that chrome toolbars agree with content + let chromeToolbars = getToolbarsFromWindowChrome(popupWindow); + testNonDefaultContentToolbars(chromeToolbars); + + // Close the new window yield BrowserTestUtils.closeWindow(popupWindow); }); }); diff --git a/dom/tests/browser/test_new_window_from_content_child.html b/dom/tests/browser/test_new_window_from_content_child.html index 5d2733ba180a..e5da60b42b28 100644 --- a/dom/tests/browser/test_new_window_from_content_child.html +++ b/dom/tests/browser/test_new_window_from_content_child.html @@ -7,6 +7,7 @@

Open a new window via window.open with default features.

Open a new window via window.open with non-default features.

Open a new window via window.open with dialog=1.

+

Open a blank new window via window.open with non-default features.

Open a new window via target="_blank".

@@ -16,4 +17,9 @@ function openWindow(aFeatures="") { window.open("about:robots", "_blank", aFeatures); return false; } + +function openBlankWindow(aFeatures="") { + window.open("", "_blank", aFeatures); + return false; +} From 6738c457613b53a7037acb37b19963be9426bd69 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Tue, 5 Jan 2016 17:29:39 +0100 Subject: [PATCH 15/25] Bug 1236481 - 'Synced Tabs' History menuitem not shown. r=markh --- browser/base/content/browser-places.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 8156c43f0b1d..3ef0308f31e6 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -739,8 +739,6 @@ HistoryMenu.prototype = { return; } - let enabled = PlacesUIUtils.shouldEnableTabsFromOtherComputersMenuitem(); - menuitem.setAttribute("disabled", !enabled); menuitem.setAttribute("hidden", false); }, From b388bb74595fca3051b99ad35212b32f65bacd77 Mon Sep 17 00:00:00 2001 From: Chenxia Liu Date: Mon, 21 Dec 2015 14:51:26 -0800 Subject: [PATCH 16/25] Bug 1022464 - Returning to URL bar containing search terms doesn't re-enter search mode. r=mcomella --HG-- extra : commitid : 1guyMEjEXPL extra : rebase_source : 386e18b74e71f5ac6656685c06e1a10762c7a1da --- .../java/org/mozilla/gecko/BrowserApp.java | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java index e7de311fe61c..61282c09b9d9 100644 --- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java +++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java @@ -2170,13 +2170,21 @@ public class BrowserApp extends GeckoApp final Tab tab = Tabs.getInstance().getSelectedTab(); if (tab != null) { - final String userRequested = tab.getUserRequested(); + final String userSearchTerm = tab.getUserRequested(); // Check to see if there's a user-entered search term, // which we save whenever the user performs a search. - url = (TextUtils.isEmpty(userRequested) ? tab.getURL() : userRequested); - } + String telemetryMsg; + if (!TextUtils.isEmpty(userSearchTerm)) { + url = userSearchTerm; + telemetryMsg = "urlbar-userEntered"; + } else { + url = tab.getURL(); + telemetryMsg = url.isEmpty() ? "urlbar-empty" : "urlbar-url"; + } + Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.ACTIONBAR, telemetryMsg); + } enterEditingMode(url); } @@ -2210,7 +2218,13 @@ public class BrowserApp extends GeckoApp mBrowserToolbar.startEditing(url, animator); - showHomePagerWithAnimator(panelId, animator); + final boolean isUserSearchTerm = !TextUtils.isEmpty(selectedTab.getUserRequested()); + if (isUserSearchTerm && AppConstants.NIGHTLY_BUILD) { + showBrowserSearchAfterAnimation(animator); + hideWebContentOnPropertyAnimationEnd(animator); + } else { + showHomePagerWithAnimator(panelId, animator); + } animator.start(); Telemetry.startUISession(TelemetryContract.Session.AWESOMESCREEN); @@ -2622,6 +2636,24 @@ public class BrowserApp extends GeckoApp refreshToolbarHeight(); } + private void showBrowserSearchAfterAnimation(PropertyAnimator animator) { + if (animator == null) { + showBrowserSearch(); + return; + } + + animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { + @Override + public void onPropertyAnimationStart() { + } + + @Override + public void onPropertyAnimationEnd() { + showBrowserSearch(); + } + }); + } + private void showBrowserSearch() { if (mBrowserSearch.getUserVisibleHint()) { return; @@ -2672,7 +2704,10 @@ public class BrowserApp extends GeckoApp // To prevent overdraw, the HomePager is hidden when BrowserSearch is displayed: // reverse that. - mHomePagerContainer.setVisibility(View.VISIBLE); + showHomePager(Tabs.getInstance().getSelectedTab().getMostRecentHomePanel()); + + // Prevent race in hiding web content - see declaration for more info. + mHideWebContentOnAnimationEnd = false; mBrowserSearchContainer.setVisibility(View.INVISIBLE); From 1139893d6f426a5c29f67fd49d98b25909773a38 Mon Sep 17 00:00:00 2001 From: Michael Comella Date: Tue, 5 Jan 2016 10:46:59 -0800 Subject: [PATCH 17/25] Bug 1022464 - review: Make changes for review comments while liuche is out. r=me There is one review comment questioning a change that, upon testing, seems to be necessary upon testing - I didn't make any changes for that change but I still don't entirely understand why it's necessary. --HG-- extra : commitid : Htc38uQZfMY extra : rebase_source : 7b2b71aa8548ae88169a4bb39b112755f3f273f9 --- .../base/java/org/mozilla/gecko/BrowserApp.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java index 61282c09b9d9..93f156e8dce2 100644 --- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java +++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java @@ -2174,16 +2174,16 @@ public class BrowserApp extends GeckoApp // Check to see if there's a user-entered search term, // which we save whenever the user performs a search. - String telemetryMsg; + final String telemetryMsg; if (!TextUtils.isEmpty(userSearchTerm)) { url = userSearchTerm; - telemetryMsg = "urlbar-userEntered"; + telemetryMsg = "urlbar-userentered"; } else { url = tab.getURL(); telemetryMsg = url.isEmpty() ? "urlbar-empty" : "urlbar-url"; } - Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH, TelemetryContract.Method.ACTIONBAR, telemetryMsg); + Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.ACTIONBAR, telemetryMsg); } enterEditingMode(url); } @@ -2221,7 +2221,6 @@ public class BrowserApp extends GeckoApp final boolean isUserSearchTerm = !TextUtils.isEmpty(selectedTab.getUserRequested()); if (isUserSearchTerm && AppConstants.NIGHTLY_BUILD) { showBrowserSearchAfterAnimation(animator); - hideWebContentOnPropertyAnimationEnd(animator); } else { showHomePagerWithAnimator(panelId, animator); } @@ -2706,9 +2705,6 @@ public class BrowserApp extends GeckoApp // reverse that. showHomePager(Tabs.getInstance().getSelectedTab().getMostRecentHomePanel()); - // Prevent race in hiding web content - see declaration for more info. - mHideWebContentOnAnimationEnd = false; - mBrowserSearchContainer.setVisibility(View.INVISIBLE); getSupportFragmentManager().beginTransaction() From 0d37a8bacb4f49353c2e87fa2aa3b0f9e5407a4b Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Thu, 3 Dec 2015 08:44:25 -0800 Subject: [PATCH 18/25] Bug 1227300, Part 1 - Add an alert notification component. r=MattN,wchen --HG-- extra : commitid : Jd0utRQq7sC extra : rebase_source : 1ff47988d3e031af5fb7169e2c604b3dbf76c2d8 --- .../components/alerts/AlertNotification.cpp | 125 ++++++++++++++++++ toolkit/components/alerts/AlertNotification.h | 44 ++++++ .../alerts/AlertNotificationIPCSerializer.h | 119 +++++++++++++++++ toolkit/components/alerts/moz.build | 6 + .../components/alerts/nsIAlertsService.idl | 85 ++++++++++++ toolkit/components/build/nsToolkitCompsCID.h | 3 + .../components/build/nsToolkitCompsModule.cpp | 5 + 7 files changed, 387 insertions(+) create mode 100644 toolkit/components/alerts/AlertNotification.cpp create mode 100644 toolkit/components/alerts/AlertNotification.h create mode 100644 toolkit/components/alerts/AlertNotificationIPCSerializer.h diff --git a/toolkit/components/alerts/AlertNotification.cpp b/toolkit/components/alerts/AlertNotification.cpp new file mode 100644 index 000000000000..c3e1e85aca7f --- /dev/null +++ b/toolkit/components/alerts/AlertNotification.cpp @@ -0,0 +1,125 @@ +/* This Source Code Form is subject to the terms of the Mozilla Pub + * License, v. 2.0. If a copy of the MPL was not distributed with t + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/AlertNotification.h" + +namespace mozilla { + +NS_IMPL_CYCLE_COLLECTION(AlertNotification, mPrincipal) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AlertNotification) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAlertNotification) + NS_INTERFACE_MAP_ENTRY(nsIAlertNotification) +NS_INTERFACE_MAP_END +NS_IMPL_CYCLE_COLLECTING_ADDREF(AlertNotification) +NS_IMPL_CYCLE_COLLECTING_RELEASE(AlertNotification) + +AlertNotification::AlertNotification() + : mTextClickable(false) + , mPrincipal(nullptr) + , mInPrivateBrowsing(false) +{} + +AlertNotification::~AlertNotification() +{} + +NS_IMETHODIMP +AlertNotification::Init(const nsAString& aName, const nsAString& aImageURL, + const nsAString& aTitle, const nsAString& aText, + bool aTextClickable, const nsAString& aCookie, + const nsAString& aDir, const nsAString& aLang, + const nsAString& aData, nsIPrincipal* aPrincipal, + bool aInPrivateBrowsing) +{ + mName = aName; + mImageURL = aImageURL; + mTitle = aTitle; + mText = aText; + mTextClickable = aTextClickable; + mCookie = aCookie; + mDir = aDir; + mLang = aLang; + mData = aData; + mPrincipal = aPrincipal; + mInPrivateBrowsing = aInPrivateBrowsing; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetName(nsAString& aName) +{ + aName = mName; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetImageURL(nsAString& aImageURL) +{ + aImageURL = mImageURL; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetTitle(nsAString& aTitle) +{ + aTitle = mTitle; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetText(nsAString& aText) +{ + aText = mText; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetTextClickable(bool* aTextClickable) +{ + *aTextClickable = mTextClickable; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetCookie(nsAString& aCookie) +{ + aCookie = mCookie; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetDir(nsAString& aDir) +{ + aDir = mDir; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetLang(nsAString& aLang) +{ + aLang = mLang; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetData(nsAString& aData) +{ + aData = mData; + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetPrincipal(nsIPrincipal** aPrincipal) +{ + NS_IF_ADDREF(*aPrincipal = mPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +AlertNotification::GetInPrivateBrowsing(bool* aInPrivateBrowsing) +{ + *aInPrivateBrowsing = mInPrivateBrowsing; + return NS_OK; +} + +} // namespace mozilla diff --git a/toolkit/components/alerts/AlertNotification.h b/toolkit/components/alerts/AlertNotification.h new file mode 100644 index 000000000000..420e899c87f8 --- /dev/null +++ b/toolkit/components/alerts/AlertNotification.h @@ -0,0 +1,44 @@ +/* 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 mozilla_AlertNotification_h__ +#define mozilla_AlertNotification_h__ + +#include "nsIAlertsService.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIPrincipal.h" +#include "nsString.h" + +namespace mozilla { + +class AlertNotification final : public nsIAlertNotification +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(AlertNotification, + nsIAlertNotification) + NS_DECL_NSIALERTNOTIFICATION + AlertNotification(); + +protected: + virtual ~AlertNotification(); + +private: + nsString mName; + nsString mImageURL; + nsString mTitle; + nsString mText; + bool mTextClickable; + nsString mCookie; + nsString mDir; + nsString mLang; + nsString mData; + nsCOMPtr mPrincipal; + bool mInPrivateBrowsing; +}; + +} // namespace mozilla + +#endif /* mozilla_AlertNotification_h__ */ diff --git a/toolkit/components/alerts/AlertNotificationIPCSerializer.h b/toolkit/components/alerts/AlertNotificationIPCSerializer.h new file mode 100644 index 000000000000..9eaefacda581 --- /dev/null +++ b/toolkit/components/alerts/AlertNotificationIPCSerializer.h @@ -0,0 +1,119 @@ +/* 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 mozilla_AlertNotificationIPCSerializer_h__ +#define mozilla_AlertNotificationIPCSerializer_h__ + +#include "nsComponentManagerUtils.h" +#include "nsCOMPtr.h" +#include "nsIAlertsService.h" +#include "nsIPrincipal.h" +#include "nsString.h" + +#include "ipc/IPCMessageUtils.h" + +#include "mozilla/dom/PermissionMessageUtils.h" + +typedef nsIAlertNotification* AlertNotificationType; + +namespace IPC { + +template <> +struct ParamTraits +{ + typedef AlertNotificationType paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + bool isNull = !aParam; + if (isNull) { + WriteParam(aMsg, isNull); + return; + } + + nsString name, imageURL, title, text, cookie, dir, lang, data; + bool textClickable, inPrivateBrowsing; + nsCOMPtr principal; + + if (NS_WARN_IF(NS_FAILED(aParam->GetName(name))) || + NS_WARN_IF(NS_FAILED(aParam->GetImageURL(imageURL))) || + NS_WARN_IF(NS_FAILED(aParam->GetTitle(title))) || + NS_WARN_IF(NS_FAILED(aParam->GetText(text))) || + NS_WARN_IF(NS_FAILED(aParam->GetTextClickable(&textClickable))) || + NS_WARN_IF(NS_FAILED(aParam->GetCookie(cookie))) || + NS_WARN_IF(NS_FAILED(aParam->GetDir(dir))) || + NS_WARN_IF(NS_FAILED(aParam->GetLang(lang))) || + NS_WARN_IF(NS_FAILED(aParam->GetData(data))) || + NS_WARN_IF(NS_FAILED(aParam->GetPrincipal(getter_AddRefs(principal)))) || + NS_WARN_IF(NS_FAILED(aParam->GetInPrivateBrowsing(&inPrivateBrowsing)))) { + + // Write a `null` object if any getter returns an error. Otherwise, the + // receiver will try to deserialize an incomplete object and crash. + WriteParam(aMsg, /* isNull */ true); + return; + } + + WriteParam(aMsg, isNull); + WriteParam(aMsg, name); + WriteParam(aMsg, imageURL); + WriteParam(aMsg, title); + WriteParam(aMsg, text); + WriteParam(aMsg, textClickable); + WriteParam(aMsg, cookie); + WriteParam(aMsg, dir); + WriteParam(aMsg, lang); + WriteParam(aMsg, data); + WriteParam(aMsg, IPC::Principal(principal)); + WriteParam(aMsg, inPrivateBrowsing); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + bool isNull; + NS_ENSURE_TRUE(ReadParam(aMsg, aIter, &isNull), false); + if (isNull) { + *aResult = nullptr; + return true; + } + + nsString name, imageURL, title, text, cookie, dir, lang, data; + bool textClickable, inPrivateBrowsing; + IPC::Principal principal; + + if (!ReadParam(aMsg, aIter, &name) || + !ReadParam(aMsg, aIter, &imageURL) || + !ReadParam(aMsg, aIter, &title) || + !ReadParam(aMsg, aIter, &text) || + !ReadParam(aMsg, aIter, &textClickable) || + !ReadParam(aMsg, aIter, &cookie) || + !ReadParam(aMsg, aIter, &dir) || + !ReadParam(aMsg, aIter, &lang) || + !ReadParam(aMsg, aIter, &data) || + !ReadParam(aMsg, aIter, &principal) || + !ReadParam(aMsg, aIter, &inPrivateBrowsing)) { + + return false; + } + + nsCOMPtr alert = + do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID); + if (NS_WARN_IF(!alert)) { + *aResult = nullptr; + return true; + } + nsresult rv = alert->Init(name, imageURL, title, text, textClickable, + cookie, dir, lang, data, principal, + inPrivateBrowsing); + if (NS_WARN_IF(NS_FAILED(rv))) { + *aResult = nullptr; + return true; + } + alert.forget(aResult); + return true; + } +}; + +} // namespace IPC + +#endif /* mozilla_AlertNotificationIPCSerializer_h__ */ diff --git a/toolkit/components/alerts/moz.build b/toolkit/components/alerts/moz.build index ddcc6029126c..bf862d0901fc 100644 --- a/toolkit/components/alerts/moz.build +++ b/toolkit/components/alerts/moz.build @@ -16,7 +16,13 @@ EXPORTS += [ 'nsAlertsUtils.h', ] +EXPORTS.mozilla += [ + 'AlertNotification.h', + 'AlertNotificationIPCSerializer.h', +] + UNIFIED_SOURCES += [ + 'AlertNotification.cpp', 'nsAlertsService.cpp', 'nsAlertsUtils.cpp', 'nsXULAlerts.cpp', diff --git a/toolkit/components/alerts/nsIAlertsService.idl b/toolkit/components/alerts/nsIAlertsService.idl index 5ebc8586df91..e84aea2200fe 100644 --- a/toolkit/components/alerts/nsIAlertsService.idl +++ b/toolkit/components/alerts/nsIAlertsService.idl @@ -8,6 +8,91 @@ interface nsIPrincipal; +%{C++ +#define ALERT_NOTIFICATION_CONTRACTID "@mozilla.org/alert-notification;1" +%} + +[scriptable, uuid(b26b4a67-81b0-4270-8311-1e00a097ef92)] +interface nsIAlertNotification : nsISupports +{ + /** Initializes an alert notification. */ + void init([optional] in AString name, + [optional] in AString imageURL, + [optional] in AString title, + [optional] in AString text, + [optional] in boolean textClickable, + [optional] in AString cookie, + [optional] in AString dir, + [optional] in AString lang, + [optional] in AString data, + [optional] in nsIPrincipal principal, + [optional] in boolean inPrivateBrowsing); + + /** + * The name of the notification. This is currently only used on Android and + * OS X. On Android, the name is hashed and used as a notification ID. + * Notifications will replace previous notifications with the same name. + */ + readonly attribute AString name; + + /** + * A URL identifying the image to put in the alert. The OS X backend limits + * the amount of time it will wait for the image to load to six seconds. After + * that time, the alert will show without an image. + */ + readonly attribute AString imageURL; + + /** The title for the alert. */ + readonly attribute AString title; + + /** The contents of the alert. */ + readonly attribute AString text; + + /** + * Controls the click behavior. If true, the alert listener will be notified + * when the user clicks on the alert. + */ + readonly attribute boolean textClickable; + + /** + * An opaque cookie that will be passed to the alert listener for each + * callback. + */ + readonly attribute AString cookie; + + /** + * Bidi override for the title and contents. Valid values are "auto", "ltr", + * or "rtl". Ignored if the backend doesn't support localization. + */ + readonly attribute AString dir; + + /** + * Language of the title and text. Ignored if the backend doesn't support + * localization. + */ + readonly attribute AString lang; + + /** + * A Base64-encoded structured clone buffer containing data associated with + * this alert. Only used for web notifications. Chrome callers should use a + * cookie instead. + */ + readonly attribute AString data; + + /** + * The principal of the page that created the alert. Used for IPC security + * checks, and to determine whether the alert should show the source string + * and action buttons. + */ + readonly attribute nsIPrincipal principal; + + /** + * Controls the image loading behavior. If true, the image URL will be loaded + * in private browsing mode. + */ + readonly attribute boolean inPrivateBrowsing; +}; + [scriptable, uuid(9d0284bf-db40-42da-8f0d-c2769dbde7aa)] interface nsIAlertsService : nsISupports { diff --git a/toolkit/components/build/nsToolkitCompsCID.h b/toolkit/components/build/nsToolkitCompsCID.h index 0f6d20d2f3a9..edfc26c09261 100644 --- a/toolkit/components/build/nsToolkitCompsCID.h +++ b/toolkit/components/build/nsToolkitCompsCID.h @@ -97,6 +97,9 @@ ///////////////////////////////////////////////////////////////////////////// +#define ALERT_NOTIFICATION_CID \ +{ 0x9a7b7a41, 0x0b47, 0x47f7, { 0xb6, 0x1b, 0x15, 0xa2, 0x10, 0xd6, 0xf0, 0x20 } } + // {A0CCAAF8-09DA-44D8-B250-9AC3E93C8117} #define NS_ALERTSSERVICE_CID \ { 0xa0ccaaf8, 0x9da, 0x44d8, { 0xb2, 0x50, 0x9a, 0xc3, 0xe9, 0x3c, 0x81, 0x17 } } diff --git a/toolkit/components/build/nsToolkitCompsModule.cpp b/toolkit/components/build/nsToolkitCompsModule.cpp index ecf2383ed971..20300c811b62 100644 --- a/toolkit/components/build/nsToolkitCompsModule.cpp +++ b/toolkit/components/build/nsToolkitCompsModule.cpp @@ -16,6 +16,7 @@ #include "nsParentalControlsService.h" #endif +#include "mozilla/AlertNotification.h" #include "nsAlertsService.h" #include "nsDownloadManager.h" @@ -82,6 +83,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFindService) NS_GENERIC_FACTORY_CONSTRUCTOR(nsParentalControlsService) #endif +NS_GENERIC_FACTORY_CONSTRUCTOR(AlertNotification) NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager, @@ -138,6 +140,7 @@ NS_DEFINE_NAMED_CID(NS_TOOLKIT_PERFORMANCESTATSSERVICE_CID); NS_DEFINE_NAMED_CID(NS_TOOLKIT_TERMINATOR_CID); #endif NS_DEFINE_NAMED_CID(NS_USERINFO_CID); +NS_DEFINE_NAMED_CID(ALERT_NOTIFICATION_CID); NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID); #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS) NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID); @@ -173,6 +176,7 @@ static const Module::CIDEntry kToolkitCIDs[] = { { &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID, false, nullptr, nsPerformanceStatsServiceConstructor }, #endif // defined (MOZ_HAS_PERFSTATS) { &kNS_USERINFO_CID, false, nullptr, nsUserInfoConstructor }, + { &kALERT_NOTIFICATION_CID, false, nullptr, AlertNotificationConstructor }, { &kNS_ALERTSSERVICE_CID, false, nullptr, nsAlertsServiceConstructor }, #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS) { &kNS_PARENTALCONTROLSSERVICE_CID, false, nullptr, nsParentalControlsServiceConstructor }, @@ -210,6 +214,7 @@ static const Module::ContractIDEntry kToolkitContracts[] = { { NS_TOOLKIT_PERFORMANCESTATSSERVICE_CONTRACTID, &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID }, #endif // defined (MOZ_HAS_PERFSTATS) { NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID }, + { ALERT_NOTIFICATION_CONTRACTID, &kALERT_NOTIFICATION_CID }, { NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID }, #if !defined(MOZ_DISABLE_PARENTAL_CONTROLS) { NS_PARENTALCONTROLSSERVICE_CONTRACTID, &kNS_PARENTALCONTROLSSERVICE_CID }, From 87582e390a9b072d2223e19843f94c1561bd1bb5 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Thu, 31 Dec 2015 12:04:24 -0700 Subject: [PATCH 19/25] Bug 1227300, Part 2 - Implement `showAlert`. r=MattN,wchen --HG-- extra : commitid : HrMh88lKFVK extra : rebase_source : e8a8def77f0e12152ecb48986f3c1a850d6ac9c4 --- dom/ipc/ContentParent.cpp | 23 ++--- dom/ipc/ContentParent.h | 8 +- dom/ipc/PContent.ipdl | 13 +-- toolkit/components/alerts/nsAlertsService.cpp | 90 ++++++++++++++----- .../components/alerts/nsIAlertsService.idl | 4 +- 5 files changed, 84 insertions(+), 54 deletions(-) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 078f016207c5..cfc13ea865b4 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -4432,23 +4432,24 @@ ContentParent::HasNotificationPermission(const IPC::Principal& aPrincipal) } bool -ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle, - const nsString& aText, const bool& aTextClickable, - const nsString& aCookie, const nsString& aName, - const nsString& aBidi, const nsString& aLang, - const nsString& aData, - const IPC::Principal& aPrincipal, - const bool& aInPrivateBrowsing) +ContentParent::RecvShowAlert(const AlertNotificationType& aAlert) { - if (!HasNotificationPermission(aPrincipal)) { + nsCOMPtr alert(dont_AddRef(aAlert)); + if (NS_WARN_IF(!alert)) { + return true; + } + + nsCOMPtr principal; + nsresult rv = alert->GetPrincipal(getter_AddRefs(principal)); + if (NS_WARN_IF(NS_FAILED(rv)) || + !HasNotificationPermission(IPC::Principal(principal))) { + return true; } nsCOMPtr sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID)); if (sysAlerts) { - sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable, - aCookie, this, aName, aBidi, aLang, - aData, aPrincipal, aInPrivateBrowsing); + sysAlerts->ShowAlert(alert, this); } return true; } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index d28ac058989b..775828c1210d 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -787,13 +787,7 @@ private: bool HasNotificationPermission(const IPC::Principal& aPrincipal); - virtual bool RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle, - const nsString& aText, const bool& aTextClickable, - const nsString& aCookie, const nsString& aName, - const nsString& aBidi, const nsString& aLang, - const nsString& aData, - const IPC::Principal& aPrincipal, - const bool& aInPrivateBrowsing) override; + virtual bool RecvShowAlert(const AlertNotificationType& aAlert) override; virtual bool RecvCloseAlert(const nsString& aName, const IPC::Principal& aPrincipal) override; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index d516cb777a57..ad67d477ed80 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -74,6 +74,7 @@ include ProfilerTypes; include "mozilla/dom/PContentBridgeParent.h"; using GeoPosition from "nsGeoPositionIPCSerialiser.h"; +using AlertNotificationType from "mozilla/AlertNotificationIPCSerializer.h"; using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h"; using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h"; @@ -881,17 +882,7 @@ parent: CpowEntry[] aCpows, Principal aPrincipal) returns (StructuredCloneData[] retval); - ShowAlertNotification(nsString imageUrl, - nsString title, - nsString text, - bool textClickable, - nsString cookie, - nsString name, - nsString bidi, - nsString lang, - nsString data, - Principal principal, - bool inPrivateBrowsing); + ShowAlert(AlertNotificationType alert); CloseAlert(nsString name, Principal principal); diff --git a/toolkit/components/alerts/nsAlertsService.cpp b/toolkit/components/alerts/nsAlertsService.cpp index b64fe48c9490..7506751ce22d 100644 --- a/toolkit/components/alerts/nsAlertsService.cpp +++ b/toolkit/components/alerts/nsAlertsService.cpp @@ -73,40 +73,66 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl nsIPrincipal * aPrincipal, bool aInPrivateBrowsing) { + nsCOMPtr alert = + do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID); + NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE); + nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle, + aAlertText, aAlertTextClickable, + aAlertCookie, aBidi, aLang, aData, + aPrincipal, aInPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); + return ShowAlert(alert, aAlertListener); +} + + +NS_IMETHODIMP nsAlertsService::ShowAlert(nsIAlertNotification * aAlert, + nsIObserver * aAlertListener) +{ + NS_ENSURE_ARG(aAlert); + + nsAutoString cookie; + nsresult rv = aAlert->GetCookie(cookie); + NS_ENSURE_SUCCESS(rv, rv); + if (XRE_IsContentProcess()) { ContentChild* cpc = ContentChild::GetSingleton(); if (aAlertListener) - cpc->AddRemoteAlertObserver(PromiseFlatString(aAlertCookie), aAlertListener); + cpc->AddRemoteAlertObserver(cookie, aAlertListener); - cpc->SendShowAlertNotification(PromiseFlatString(aImageUrl), - PromiseFlatString(aAlertTitle), - PromiseFlatString(aAlertText), - aAlertTextClickable, - PromiseFlatString(aAlertCookie), - PromiseFlatString(aAlertName), - PromiseFlatString(aBidi), - PromiseFlatString(aLang), - PromiseFlatString(aData), - IPC::Principal(aPrincipal), - aInPrivateBrowsing); + cpc->SendShowAlert(aAlert); return NS_OK; } + nsAutoString imageUrl; + rv = aAlert->GetImageURL(imageUrl); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString title; + rv = aAlert->GetTitle(title); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString text; + rv = aAlert->GetText(text); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString name; + rv = aAlert->GetName(name); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr principal; + rv = aAlert->GetPrincipal(getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + #ifdef MOZ_WIDGET_ANDROID - mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, - aAlertListener, aAlertName, aPrincipal); + mozilla::AndroidBridge::Bridge()->ShowAlertNotification(imageUrl, title, text, cookie, + aAlertListener, name, principal); return NS_OK; #else // Check if there is an optional service that handles system-level notifications nsCOMPtr sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID)); - nsresult rv; if (sysAlerts) { - rv = sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, - aAlertCookie, aAlertListener, aAlertName, - aBidi, aLang, aData, - IPC::Principal(aPrincipal), - aInPrivateBrowsing); + rv = sysAlerts->ShowAlert(aAlert, aAlertListener); if (NS_SUCCEEDED(rv)) return NS_OK; } @@ -114,14 +140,30 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl if (!ShouldShowAlert()) { // Do not display the alert. Instead call alertfinished and get out. if (aAlertListener) - aAlertListener->Observe(nullptr, "alertfinished", PromiseFlatString(aAlertCookie).get()); + aAlertListener->Observe(nullptr, "alertfinished", cookie.get()); return NS_OK; } + bool textClickable; + rv = aAlert->GetTextClickable(&textClickable); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString bidi; + rv = aAlert->GetDir(bidi); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString lang; + rv = aAlert->GetLang(lang); + NS_ENSURE_SUCCESS(rv, rv); + + bool inPrivateBrowsing; + rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); + // Use XUL notifications as a fallback if above methods have failed. - rv = mXULAlerts.ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, - aAlertCookie, aAlertListener, aAlertName, - aBidi, aLang, aPrincipal, aInPrivateBrowsing); + rv = mXULAlerts.ShowAlertNotification(imageUrl, title, text, textClickable, + cookie, aAlertListener, name, + bidi, lang, principal, inPrivateBrowsing); return rv; #endif // !MOZ_WIDGET_ANDROID } diff --git a/toolkit/components/alerts/nsIAlertsService.idl b/toolkit/components/alerts/nsIAlertsService.idl index e84aea2200fe..ac703d019feb 100644 --- a/toolkit/components/alerts/nsIAlertsService.idl +++ b/toolkit/components/alerts/nsIAlertsService.idl @@ -93,9 +93,11 @@ interface nsIAlertNotification : nsISupports readonly attribute boolean inPrivateBrowsing; }; -[scriptable, uuid(9d0284bf-db40-42da-8f0d-c2769dbde7aa)] +[scriptable, uuid(f7a36392-d98b-4141-a7d7-4e46642684e3)] interface nsIAlertsService : nsISupports { + void showAlert(in nsIAlertNotification alert, + [optional] in nsIObserver alertListener); /** * Displays a sliding notification window. * From e17e098be0c7a5684f6a7cd99a99a1607e718938 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Thu, 31 Dec 2015 12:08:22 -0700 Subject: [PATCH 20/25] Bug 1227300, Part 3 - Implement `showAlert` for the OS X alerts backend. r=mstange --HG-- extra : commitid : t8LugdlKXX extra : rebase_source : 936e72ffc69476f86b7c02cce9de59ec9eb6bcde --- widget/cocoa/OSXNotificationCenter.mm | 80 +++++++++++++++++++++------ 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index 39d03da51d78..2657b7a1b8ef 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -11,6 +11,7 @@ #include "nsNetUtil.h" #include "imgLoader.h" #import "nsCocoaUtils.h" +#include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsObjCExceptions.h" #include "nsString.h" @@ -240,15 +241,39 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const const nsAString & aData, nsIPrincipal * aPrincipal, bool aInPrivateBrowsing) +{ + nsCOMPtr alert = + do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID); + NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE); + nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle, + aAlertText, aAlertTextClickable, + aAlertCookie, aBidi, aLang, aData, + aPrincipal, aInPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); + return ShowAlert(alert, aAlertListener); +} + +NS_IMETHODIMP +OSXNotificationCenter::ShowAlert(nsIAlertNotification* aAlert, + nsIObserver* aAlertListener) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + NS_ENSURE_ARG(aAlert); + Class unClass = NSClassFromString(@"NSUserNotification"); id notification = [[unClass alloc] init]; - notification.title = nsCocoaUtils::ToNSString(aAlertTitle); + nsAutoString title; + nsresult rv = aAlert->GetTitle(title); + NS_ENSURE_SUCCESS(rv, rv); + notification.title = nsCocoaUtils::ToNSString(title); + + nsCOMPtr principal; + rv = aAlert->GetPrincipal(getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); nsAutoString hostPort; - nsAlertsUtils::GetSourceHostPort(aPrincipal, hostPort); + nsAlertsUtils::GetSourceHostPort(principal, hostPort); nsCOMPtr bundle; nsCOMPtr sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID); sbs->CreateBundle("chrome://alerts/locale/alert.properties", getter_AddRefs(bundle)); @@ -263,12 +288,16 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const notification.subtitle = nsCocoaUtils::ToNSString(notificationSource); } - notification.informativeText = nsCocoaUtils::ToNSString(aAlertText); + nsAutoString text; + rv = aAlert->GetText(text); + NS_ENSURE_SUCCESS(rv, rv); + notification.informativeText = nsCocoaUtils::ToNSString(text); + notification.soundName = NSUserNotificationDefaultSoundName; notification.hasActionButton = NO; // If this is not an application/extension alert, show additional actions dealing with permissions. - if (nsAlertsUtils::IsActionablePrincipal(aPrincipal)) { + if (nsAlertsUtils::IsActionablePrincipal(principal)) { if (bundle) { nsXPIDLString closeButtonTitle, actionButtonTitle, disableButtonTitle, settingsButtonTitle; bundle->GetStringFromName(MOZ_UTF16("closeButton.title"), @@ -307,24 +336,39 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const } } } - NSString *alertName = nsCocoaUtils::ToNSString(aAlertName); + nsAutoString name; + rv = aAlert->GetName(name); + NS_ENSURE_SUCCESS(rv, rv); + NSString *alertName = nsCocoaUtils::ToNSString(name); if (!alertName) { return NS_ERROR_FAILURE; } notification.userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:alertName, nil] forKeys:[NSArray arrayWithObjects:@"name", nil]]; - OSXNotificationInfo *osxni = new OSXNotificationInfo(alertName, aAlertListener, aAlertCookie); + nsAutoString cookie; + rv = aAlert->GetCookie(cookie); + NS_ENSURE_SUCCESS(rv, rv); + + OSXNotificationInfo *osxni = new OSXNotificationInfo(alertName, aAlertListener, cookie); + + nsAutoString imageUrl; + rv = aAlert->GetImageURL(imageUrl); + NS_ENSURE_SUCCESS(rv, rv); + + bool inPrivateBrowsing; + rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); // Show the notification without waiting for an image if there is no icon URL or // notification icons are not supported on this version of OS X. - if (aImageUrl.IsEmpty() || ![unClass instancesRespondToSelector:@selector(setContentImage:)]) { + if (imageUrl.IsEmpty() || ![unClass instancesRespondToSelector:@selector(setContentImage:)]) { CloseAlertCocoaString(alertName); mActiveAlerts.AppendElement(osxni); [GetNotificationCenter() deliverNotification:notification]; [notification release]; if (aAlertListener) { - aAlertListener->Observe(nullptr, "alertshow", PromiseFlatString(aAlertCookie).get()); + aAlertListener->Observe(nullptr, "alertshow", cookie.get()); } } else { mPendingAlerts.AppendElement(osxni); @@ -332,17 +376,17 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const RefPtr il = imgLoader::GetInstance(); if (il) { nsCOMPtr imageUri; - NS_NewURI(getter_AddRefs(imageUri), aImageUrl); + NS_NewURI(getter_AddRefs(imageUri), imageUrl); if (imageUri) { - nsresult rv = il->LoadImage(imageUri, nullptr, nullptr, - mozilla::net::RP_Default, - aPrincipal, nullptr, - this, nullptr, - aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS : - nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, - EmptyString(), - getter_AddRefs(osxni->mIconRequest)); + rv = il->LoadImage(imageUri, nullptr, nullptr, + mozilla::net::RP_Default, + principal, nullptr, + this, nullptr, + inPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS : + nsIRequest::LOAD_NORMAL, + nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, + EmptyString(), + getter_AddRefs(osxni->mIconRequest)); if (NS_SUCCEEDED(rv)) { // Set a timer for six seconds. If we don't have an icon by the time this // goes off then we go ahead without an icon. From 91f6d2449c4d00dd9725cd457ef3fdeaed6d2af2 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Thu, 31 Dec 2015 12:13:27 -0700 Subject: [PATCH 21/25] Bug 1227300, Part 4 - Implement `showAlert` for the libnotify alerts backend. r=karlt --HG-- extra : commitid : LTTy50oCXfw extra : rebase_source : 025b682fad77f853b72d930b0e975e2fa5cf39bc --- toolkit/system/gnome/nsAlertsIconListener.cpp | 50 ++++++++++++------- toolkit/system/gnome/nsAlertsIconListener.h | 10 ++-- .../system/gnome/nsSystemAlertsService.cpp | 20 +++++++- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/toolkit/system/gnome/nsAlertsIconListener.cpp b/toolkit/system/gnome/nsAlertsIconListener.cpp index 6f04e10e7f2c..97eca76347af 100644 --- a/toolkit/system/gnome/nsAlertsIconListener.cpp +++ b/toolkit/system/gnome/nsAlertsIconListener.cpp @@ -9,6 +9,7 @@ #include "imgIRequest.h" #include "nsNetUtil.h" #include "nsServiceManagerUtils.h" +#include "nsIAlertsService.h" #include "nsIImageToPixbuf.h" #include "nsIStringBundle.h" #include "nsIObserverService.h" @@ -186,6 +187,11 @@ nsAlertsIconListener::ShowAlert(GdkPixbuf* aPixbuf) if (!mNotification) return NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr obsServ = + do_GetService("@mozilla.org/observer-service;1"); + if (obsServ) + obsServ->AddObserver(this, "quit-application", true); + if (aPixbuf) notify_notification_set_icon_from_pixbuf(mNotification, aPixbuf); @@ -277,13 +283,8 @@ nsAlertsIconListener::Observe(nsISupports *aSubject, const char *aTopic, } nsresult -nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl, - const nsAString & aAlertTitle, - const nsAString & aAlertText, - bool aAlertTextClickable, - const nsAString & aAlertCookie, - nsIObserver * aAlertListener, - bool aInPrivateBrowsing) +nsAlertsIconListener::InitAlertAsync(nsIAlertNotification* aAlert, + nsIObserver* aAlertListener) { if (!libNotifyHandle) return NS_ERROR_FAILURE; @@ -335,27 +336,38 @@ nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl, return NS_ERROR_FAILURE; } - if (!gHasActions && aAlertTextClickable) + nsresult rv = aAlert->GetTextClickable(&mAlertHasAction); + NS_ENSURE_SUCCESS(rv, rv); + if (!gHasActions && mAlertHasAction) return NS_ERROR_FAILURE; // No good, fallback to XUL - nsCOMPtr obsServ = - do_GetService("@mozilla.org/observer-service;1"); - if (obsServ) - obsServ->AddObserver(this, "quit-application", true); - + nsAutoString title; + rv = aAlert->GetTitle(title); + NS_ENSURE_SUCCESS(rv, rv); // Workaround for a libnotify bug - blank titles aren't dealt with // properly so we use a space - if (aAlertTitle.IsEmpty()) { + if (title.IsEmpty()) { mAlertTitle = NS_LITERAL_CSTRING(" "); } else { - mAlertTitle = NS_ConvertUTF16toUTF8(aAlertTitle); + mAlertTitle = NS_ConvertUTF16toUTF8(title); } - mAlertText = NS_ConvertUTF16toUTF8(aAlertText); - mAlertHasAction = aAlertTextClickable; + nsAutoString text; + rv = aAlert->GetText(text); + NS_ENSURE_SUCCESS(rv, rv); + mAlertText = NS_ConvertUTF16toUTF8(text); mAlertListener = aAlertListener; - mAlertCookie = aAlertCookie; - return StartRequest(aImageUrl, aInPrivateBrowsing); + rv = aAlert->GetCookie(mAlertCookie); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString imageUrl; + rv = aAlert->GetImageURL(imageUrl); + NS_ENSURE_SUCCESS(rv, rv); + bool inPrivateBrowsing; + rv = aAlert->GetInPrivateBrowsing(&inPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); + + return StartRequest(imageUrl, inPrivateBrowsing); } diff --git a/toolkit/system/gnome/nsAlertsIconListener.h b/toolkit/system/gnome/nsAlertsIconListener.h index 296a50ac230d..8848f0da0f7e 100644 --- a/toolkit/system/gnome/nsAlertsIconListener.h +++ b/toolkit/system/gnome/nsAlertsIconListener.h @@ -15,6 +15,7 @@ #include class imgIRequest; +class nsIAlertNotification; struct NotifyNotification; @@ -29,13 +30,8 @@ public: nsAlertsIconListener(); - nsresult InitAlertAsync(const nsAString & aImageUrl, - const nsAString & aAlertTitle, - const nsAString & aAlertText, - bool aAlertTextClickable, - const nsAString & aAlertCookie, - nsIObserver * aAlertListener, - bool aInPrivateBrowsing); + nsresult InitAlertAsync(nsIAlertNotification* aAlert, + nsIObserver* aAlertListener); void SendCallback(); void SendClosed(); diff --git a/toolkit/system/gnome/nsSystemAlertsService.cpp b/toolkit/system/gnome/nsSystemAlertsService.cpp index fe7eca54159f..8b0bf6856fe2 100644 --- a/toolkit/system/gnome/nsSystemAlertsService.cpp +++ b/toolkit/system/gnome/nsSystemAlertsService.cpp @@ -3,6 +3,7 @@ * 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/. */ +#include "nsComponentManagerUtils.h" #include "nsXULAppAPI.h" #include "nsSystemAlertsService.h" #include "nsAlertsIconListener.h" @@ -40,12 +41,27 @@ NS_IMETHODIMP nsSystemAlertsService::ShowAlertNotification(const nsAString & aIm nsIPrincipal * aPrincipal, bool aInPrivateBrowsing) { + nsCOMPtr alert = + do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID); + NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE); + nsresult rv = alert->Init(aAlertName, aImageUrl, aAlertTitle, + aAlertText, aAlertTextClickable, + aAlertCookie, aBidi, aLang, aData, + aPrincipal, aInPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); + return ShowAlert(alert, aAlertListener); +} + +NS_IMETHODIMP nsSystemAlertsService::ShowAlert(nsIAlertNotification* aAlert, + nsIObserver* aAlertListener) +{ + NS_ENSURE_ARG(aAlert); + RefPtr alertListener = new nsAlertsIconListener(); if (!alertListener) return NS_ERROR_OUT_OF_MEMORY; - return alertListener->InitAlertAsync(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable, - aAlertCookie, aAlertListener, aInPrivateBrowsing); + return alertListener->InitAlertAsync(aAlert, aAlertListener); } NS_IMETHODIMP nsSystemAlertsService::CloseAlert(const nsAString& aAlertName, From a96af10ef8ac0b3e2f6b23ed0667cb4cc8c311d1 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Mon, 23 Nov 2015 15:01:57 -0800 Subject: [PATCH 22/25] Bug 1227300, Part 5 - Implement `showAlert` for the B2G alerts backend. r=mhenretty --HG-- extra : commitid : JMm9N0eVUYr extra : rebase_source : dfb08f757919cb1345f4447e88c7ad91a70194e3 --- b2g/components/AlertsService.js | 39 ++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/b2g/components/AlertsService.js b/b2g/components/AlertsService.js index 38cc9b8bc521..fadfb4a8603d 100644 --- a/b2g/components/AlertsService.js +++ b/b2g/components/AlertsService.js @@ -66,23 +66,36 @@ AlertsService.prototype = { }, // nsIAlertsService + showAlert: function(aAlert, aAlertListener) { + if (!aAlert) { + return; + } + cpmm.sendAsyncMessage(kMessageAlertNotificationSend, { + imageURL: aAlert.imageURL, + title: aAlert.title, + text: aAlert.text, + clickable: aAlert.textClickable, + cookie: aAlert.cookie, + listener: aAlertListener, + id: aAlert.name, + dir: aAlert.dir, + lang: aAlert.lang, + dataStr: aAlert.data, + inPrivateBrowsing: aAlert.inPrivateBrowsing + }); + }, + showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName, aBidi, aLang, aDataStr, aPrincipal, aInPrivateBrowsing) { - cpmm.sendAsyncMessage(kMessageAlertNotificationSend, { - imageURL: aImageUrl, - title: aTitle, - text: aText, - clickable: aTextClickable, - cookie: aCookie, - listener: aAlertListener, - id: aName, - dir: aBidi, - lang: aLang, - dataStr: aDataStr, - inPrivateBrowsing: aInPrivateBrowsing - }); + let alert = Cc["@mozilla.org/alert-notification;1"]. + createInstance(Ci.nsIAlertNotification); + + alert.init(aName, aImageUrl, aTitle, aText, aTextClickable, aCookie, + aBidi, aLang, aDataStr, aPrincipal, aInPrivateBrowsing); + + this.showAlert(alert, aAlertListener); }, closeAlert: function(aName) { From cc75f797d3e37e41e8a14a7d27ccf3079127b057 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Thu, 3 Dec 2015 08:27:25 -0800 Subject: [PATCH 23/25] Bug 1227300, Part 6 - Use `showAlert` to display web notifications. r=wchen --HG-- extra : commitid : 5nONFewHMrl extra : rebase_source : 229904177cc611137572b8a6056025aeffe3ddca --- dom/notification/DesktopNotification.cpp | 25 ++++++++++++++---------- dom/notification/Notification.cpp | 19 +++++++++++++----- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/dom/notification/DesktopNotification.cpp b/dom/notification/DesktopNotification.cpp index a25f1925931b..5b3c5c1c5e7a 100644 --- a/dom/notification/DesktopNotification.cpp +++ b/dom/notification/DesktopNotification.cpp @@ -7,6 +7,7 @@ #include "mozilla/dom/DesktopNotificationBinding.h" #include "mozilla/dom/AppNotificationServiceOptionsBinding.h" #include "mozilla/dom/ToJSValue.h" +#include "nsComponentManagerUtils.h" #include "nsContentPermissionHelper.h" #include "nsXULAppAPI.h" #include "mozilla/dom/PBrowserChild.h" @@ -114,16 +115,20 @@ DesktopNotification::PostDesktopNotification() nsIPrincipal* principal = doc->NodePrincipal(); nsCOMPtr loadContext = doc->GetLoadContext(); bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing(); - return alerts->ShowAlertNotification(mIconURL, mTitle, mDescription, - true, - uniqueName, - mObserver, - uniqueName, - NS_LITERAL_STRING("auto"), - EmptyString(), - EmptyString(), - principal, - inPrivateBrowsing); + nsCOMPtr alert = + do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID); + NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE); + nsresult rv = alert->Init(uniqueName, mIconURL, mTitle, + mDescription, + true, + uniqueName, + NS_LITERAL_STRING("auto"), + EmptyString(), + EmptyString(), + principal, + inPrivateBrowsing); + NS_ENSURE_SUCCESS(rv, rv); + return alerts->ShowAlert(alert, mObserver); } DesktopNotification::DesktopNotification(const nsAString & title, diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index 201c7837abc2..49e01fcf30e0 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -23,6 +23,7 @@ #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" #include "nsAlertsUtils.h" +#include "nsComponentManagerUtils.h" #include "nsContentPermissionHelper.h" #include "nsContentUtils.h" #include "nsCRTGlue.h" @@ -1787,11 +1788,19 @@ Notification::ShowInternal() nsAutoString alertName; GetAlertName(alertName); - alertService->ShowAlertNotification(iconUrl, mTitle, mBody, true, - uniqueCookie, alertObserver, alertName, - DirectionToString(mDir), mLang, - mDataAsBase64, GetPrincipal(), - inPrivateBrowsing); + nsCOMPtr alert = + do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID); + NS_ENSURE_TRUE_VOID(alert); + rv = alert->Init(alertName, iconUrl, mTitle, mBody, + true, + uniqueCookie, + DirectionToString(mDir), + mLang, + mDataAsBase64, + GetPrincipal(), + inPrivateBrowsing); + NS_ENSURE_SUCCESS_VOID(rv); + alertService->ShowAlert(alert, alertObserver); } /* static */ bool From 00c6238e015ca846c41f3518ef9ba70b2a5d1bd3 Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Mon, 23 Nov 2015 15:03:20 -0800 Subject: [PATCH 24/25] Bug 1227300, Part 7 - Update test interfaces. a=testonly --HG-- extra : commitid : BgDWJWJ8OmB extra : rebase_source : f700b49d5b0aa5f94c2d1c4f9b817d3aab8e4777 --- .../mochitest/notification/MockServices.js | 22 +++++++++++++------ .../notification_common.js | 22 ++++++++++++------- .../test_notification_tag.html | 12 ++++++---- .../test_system_principal.xul | 10 ++++++--- dom/tests/mochitest/webapps/head.js | 3 +++ 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/dom/tests/mochitest/notification/MockServices.js b/dom/tests/mochitest/notification/MockServices.js index b47194b5c60a..ff8c5da0a033 100644 --- a/dom/tests/mochitest/notification/MockServices.js +++ b/dom/tests/mochitest/notification/MockServices.js @@ -29,26 +29,34 @@ var MockServices = (function () { }); var mockAlertsService = { - showAlertNotification: function(imageUrl, title, text, textClickable, - cookie, alertListener, name) { + showAlert: function(alert, alertListener) { var listener = SpecialPowers.wrap(alertListener); - activeAlertNotifications[name] = { + activeAlertNotifications[alert.name] = { listener: listener, - cookie: cookie, - title: title + cookie: alert.cookie, + title: alert.title }; // fake async alert show event if (listener) { setTimeout(function () { - listener.observe(null, "alertshow", cookie); + listener.observe(null, "alertshow", alert.cookie); }, 100); setTimeout(function () { - listener.observe(null, "alertclickcallback", cookie); + listener.observe(null, "alertclickcallback", alert.cookie); }, 100); } }, + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name) { + this.showAlert({ + name: name, + cookie: cookie, + title: title + }, alertListener); + }, + showAppNotification: function(aImageUrl, aTitle, aText, aAlertListener, aDetails) { var listener = aAlertListener || (activeAlertNotifications[aDetails.id] ? activeAlertNotifications[aDetails.id].listener : undefined); activeAppNotifications[aDetails.id] = { diff --git a/dom/tests/mochitest/notification/desktop-notification/notification_common.js b/dom/tests/mochitest/notification/desktop-notification/notification_common.js index 47d9d22da978..3aae3cef4b91 100644 --- a/dom/tests/mochitest/notification/desktop-notification/notification_common.js +++ b/dom/tests/mochitest/notification/desktop-notification/notification_common.js @@ -8,17 +8,23 @@ var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager. QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar); var mockAlertsService = { + showAlert: function(alert, alertListener) { + // probably should do this async.... + SpecialPowers.wrap(alertListener).observe(null, "alertshow", alert.cookie); + + if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) { + SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", alert.cookie); + } + + SpecialPowers.wrap(alertListener).observe(null, "alertfinished", alert.cookie); + }, + showAlertNotification: function(imageUrl, title, text, textClickable, cookie, alertListener, name, bidi, lang, data) { - // probably should do this async.... - SpecialPowers.wrap(alertListener).observe(null, "alertshow", cookie); - - if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) { - SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", cookie); - } - - SpecialPowers.wrap(alertListener).observe(null, "alertfinished", cookie); + return this.showAlert({ + cookie: cookie + }, alertListener); }, showAppNotification: function(imageUrl, title, text, alertListener, details) { diff --git a/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html b/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html index 086ff0a7b57a..37bcb16c0299 100644 --- a/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html +++ b/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html @@ -23,15 +23,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211 const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1"; var mockAlertsService = { - showAlertNotification: function(imageUrl, title, text, textClickable, - cookie, alertListener, name, dir, - lang, data) { - notificationsCreated.push(name); + showAlert: function(alert, alertListener) { + notificationsCreated.push(alert.name); if (notificationsCreated.length == 3) { checkNotifications(); } }, + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name, dir, + lang, data) { + this.showAlert({ name: name }); + }, + QueryInterface: function(aIID) { if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) || SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) { diff --git a/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul b/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul index 52312a76635a..1690bc101bdf 100644 --- a/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul +++ b/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul @@ -23,13 +23,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=874090 const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1"; var mockAlertsService = { - showAlertNotification: function(imageUrl, title, text, textClickable, - cookie, alertListener, name, dir, lang, data) { - ok(true, "System principal was granted permission and is able to call showAlertNotification."); + showAlert: function(alert, alertListener) { + ok(true, "System principal was granted permission and is able to call showAlert."); unregisterMock(); SimpleTest.finish(); }, + showAlertNotification: function(imageUrl, title, text, textClickable, + cookie, alertListener, name, dir, lang, data) { + this.showAlert(); + }, + QueryInterface: function(aIID) { if (aIID.equals(Components.interfaces.nsISupports) || aIID.equals(Components.interfaces.nsIAlertsService)) { diff --git a/dom/tests/mochitest/webapps/head.js b/dom/tests/mochitest/webapps/head.js index 8d5e9c042ff3..ba5a995e46fd 100644 --- a/dom/tests/mochitest/webapps/head.js +++ b/dom/tests/mochitest/webapps/head.js @@ -117,6 +117,9 @@ var AlertsService = { "", ALERTS_SERVICE_CONTRACT_ID, null); }, + showAlert: function() { + }, + showAlertNotification: function() { }, }; From 418150f47e83af5c571168012ea049141da5e0ba Mon Sep 17 00:00:00 2001 From: David Critchley Date: Tue, 5 Jan 2016 19:17:54 +0000 Subject: [PATCH 25/25] Bug 1231808 - Hide Pause button in Infobar using CSS r=Standard8 --- browser/extensions/loop/bootstrap.js | 6 ++++-- browser/extensions/loop/skin/osx/platform.css | 5 +++++ browser/extensions/loop/skin/shared/loop.css | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/browser/extensions/loop/bootstrap.js b/browser/extensions/loop/bootstrap.js index f19049011912..56e925405043 100644 --- a/browser/extensions/loop/bootstrap.js +++ b/browser/extensions/loop/bootstrap.js @@ -556,7 +556,8 @@ var WindowListener = { buttonNode.accessKey = paused ? this._getString("infobar_button_resume_accesskey") : this._getString("infobar_button_pause_accesskey"); return true; - } + }, + type: "pause" }, { label: this._getString("infobar_button_stop_label"), @@ -565,7 +566,8 @@ var WindowListener = { callback: () => { this._hideBrowserSharingInfoBar(); LoopUI.MozLoopService.hangupAllChatWindows(); - } + }, + type: "stop" }] ); diff --git a/browser/extensions/loop/skin/osx/platform.css b/browser/extensions/loop/skin/osx/platform.css index 8960052547fb..def39bd465a6 100644 --- a/browser/extensions/loop/skin/osx/platform.css +++ b/browser/extensions/loop/skin/osx/platform.css @@ -21,6 +21,11 @@ border-radius: 0; } + /* Hide Pause/Resume button until the functionality is complete */ + notification[value="loop-sharing-notification"] .notification-button[type="pause"] { + display:none; + } + notification[value="loop-sharing-notification"].paused .notification-button { background: #57bd35; } diff --git a/browser/extensions/loop/skin/shared/loop.css b/browser/extensions/loop/skin/shared/loop.css index 391f33bfe996..a52e24384cba 100644 --- a/browser/extensions/loop/skin/shared/loop.css +++ b/browser/extensions/loop/skin/shared/loop.css @@ -192,6 +192,11 @@ text-shadow: none; } + /* Hide Pause/Resume button until the functionality is complete */ + notification[value="loop-sharing-notification"] .notification-button[type="pause"] { + display:none; + } + notification[value="loop-sharing-notification"].paused .notification-button { background-color: #57bd35; color: #fff;