browser/base/content/socialmarks.xml

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 <?xml version="1.0"?>
     3 <bindings id="socialMarkBindings"
     4     xmlns="http://www.mozilla.org/xbl"
     5     xmlns:xbl="http://www.mozilla.org/xbl"
     6     xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
     9   <binding id="toolbarbutton-marks" display="xul:button"
    10            extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
    11     <content disabled="true">
    12       <xul:panel anonid="panel" hidden="true" type="arrow" class="social-panel"/>
    13       <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/>
    14       <xul:label class="toolbarbutton-text" crop="right" flex="1"
    15                  xbl:inherits="value=label,accesskey,crop,wrap"/>
    16       <xul:label class="toolbarbutton-multiline-text" flex="1"
    17                  xbl:inherits="xbl:text=label,accesskey,wrap"/>
    18     </content>
    19     <implementation implements="nsIDOMEventListener, nsIObserver">
    20       <field name="inMenuPanel">false</field>
    22       <property name="panel">
    23         <getter>
    24           let widgetGroup = CustomizableUI.getWidget(this.getAttribute("id"));
    25           let widget = widgetGroup.forWindow(window);
    26           this.inMenuPanel = widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL;
    27           if (this.inMenuPanel) {
    28             widget.node.setAttribute("closemenu", "none");
    29             return document.getElementById("PanelUI-socialapi");
    30           }
    31           return document.getAnonymousElementByAttribute(this, "anonid", "panel");
    32         </getter>
    33       </property>
    35       <property name="content">
    36         <getter><![CDATA[
    37           if (this._frame)
    38             return this._frame;
    39           let notificationFrameId = "social-mark-frame-" + this.getAttribute("origin");
    40           this._frame = SharedFrame.createFrame(
    41             notificationFrameId, /* frame name */
    42             this.panel, /* parent */
    43             {
    44               "type": "content",
    45               "mozbrowser": "true",
    46               "class": "social-panel-frame",
    47               "id": notificationFrameId,
    48               "tooltip": "aHTMLTooltip",
    49               "flex": "1",
    50               "context": "contentAreaContextMenu",
    51               "origin": this.getAttribute("origin"),
    52               "src": "about:blank"
    53             }
    54           );
    55           this._frame.addEventListener("DOMLinkAdded", this);
    56           this.setAttribute("notificationFrameId", notificationFrameId);
    57           return this._frame;
    58         ]]></getter>
    59       </property>
    61       <property name="contentWindow">
    62         <getter>
    63           return this.content.contentWindow;
    64         </getter>
    65       </property>
    67       <property name="contentDocument">
    68         <getter>
    69           return this.content.contentDocument;
    70         </getter>
    71       </property>
    73       <property name="provider">
    74         <getter>
    75           return Social._getProviderFromOrigin(this.getAttribute("origin"));
    76         </getter>
    77       </property>
    79       <property name="isMarked">
    80         <setter><![CDATA[
    81           this._isMarked = val;
    82           let provider = this.provider;
    83           // we cannot size the image when we apply it via listStyleImage, so
    84           // use the toolbar image
    85           let place = CustomizableUI.getPlaceForItem(this);
    86           val = val && place != "palette";
    87           let icon = val ? provider.markedIcon : provider.unmarkedIcon;
    88           let iconURL = icon || provider.icon32URL || provider.iconURL;
    89           this.setAttribute("image", iconURL);
    90         ]]></setter>
    91         <getter>
    92           return this._isMarked;
    93         </getter>
    94       </property>
    96       <method name="update">
    97         <body><![CDATA[
    98         // update the button for use with the current tab
    99         let provider = this.provider;
   100         if (this._dynamicResizer) {
   101           this._dynamicResizer.stop();
   102           this._dynamicResizer = null;
   103         }
   104         this.content.setAttribute("src", "about:blank");
   106         // do we have a savable page loaded?
   107         let aURI = gBrowser.currentURI;
   108         this.disabled = !aURI || !(aURI.schemeIs('http') || aURI.schemeIs('https'));
   109         if (this.disabled) {
   110           this.isMarked = false;
   111         } else {
   112           Social.isURIMarked(provider.origin, aURI, (isMarked) => {
   113             this.isMarked = isMarked;
   114           });
   115         }
   117         this.content.setAttribute("origin", provider.origin);
   118         if (!this.inMenuPanel) {
   119           let panel = this.panel;
   120           // if customization is currently happening, we may not have a panel
   121           // that we can hide
   122           if (panel.hidePopup) {
   123             panel.hidePopup();
   124             panel.hidden = true;
   125           }
   126         }
   127         this.pageData = null;
   128         ]]></body>
   129       </method>
   131       <method name="loadPanel">
   132         <parameter name="pageData"/>
   133         <body><![CDATA[
   134         let provider = this.provider;
   135         let panel = this.panel;
   136         panel.hidden = false;
   138         // reparent the iframe if we've been customized to a new location
   139         if (this.content.parentNode != panel)
   140           panel.appendChild(this.content);
   142         let URLTemplate = provider.markURL;
   143         this.pageData = pageData || OpenGraphBuilder.getData(gBrowser);
   144         let endpoint = OpenGraphBuilder.generateEndpointURL(URLTemplate, this.pageData);
   146         // setup listeners
   147         let DOMContentLoaded = (event) => {
   148           if (event.target != this.contentDocument)
   149             return;
   150           this._loading = false;
   151           this.content.removeEventListener("DOMContentLoaded", DOMContentLoaded, true);
   152           // add our resizer after the dom is ready
   153           if (!this.inMenuPanel) {
   154             let DynamicResizeWatcher = Cu.import("resource:///modules/Social.jsm", {}).DynamicResizeWatcher;
   155             this._dynamicResizer = new DynamicResizeWatcher();
   156             this._dynamicResizer.start(this.panel, this.content);
   157           } else if (this._dynamicResizer) {
   158             this._dynamicResizer.stop();
   159             this._dynamicResizer = null;
   160           }
   161           // send the opengraph data
   162           let evt = this.contentDocument.createEvent("CustomEvent");
   163           evt.initCustomEvent("OpenGraphData", true, true, JSON.stringify(this.pageData));
   164           this.contentDocument.documentElement.dispatchEvent(evt);
   166           let contentWindow = this.contentWindow;
   167           let markUpdate = function(event) {
   168             // update the annotation based on this event, then update the
   169             // icon as well
   170             this.isMarked = JSON.parse(event.detail).marked;
   171             let uri = Services.io.newURI(this.pageData.url, null, null);
   172             if (this.isMarked) {
   173               Social.markURI(provider.origin, uri);
   174             } else {
   175               Social.unmarkURI(provider.origin, uri, () => {
   176                 this.update();
   177               });
   178             }
   179           }.bind(this);
   180           contentWindow.addEventListener("socialMarkUpdate", markUpdate);
   181           contentWindow.addEventListener("unload", function unload() {
   182             contentWindow.removeEventListener("unload", unload);
   183             contentWindow.removeEventListener("socialMarkUpdate", markUpdate);
   184           });
   185         }
   186         this.content.addEventListener("DOMContentLoaded", DOMContentLoaded, true);
   187         this._loading = true;
   188         this.content.setAttribute("src", endpoint);
   189         ]]></body>
   190       </method>
   192       <method name="openPanel">
   193         <parameter name="aResetOnClose"/>
   194         <body><![CDATA[
   195         let panel = this.panel;
   196         let frameId = this.getAttribute("notificationFrameId");
   198         let wasAlive = SharedFrame.isGroupAlive(frameId);
   199         SharedFrame.setOwner(frameId, this.content);
   201         // Clear dimensions on all browsers so the panel size will
   202         // only use the selected browser.
   203         let frameIter = panel.firstElementChild;
   204         while (frameIter) {
   205           frameIter.collapsed = (frameIter != this.content);
   206           frameIter = frameIter.nextElementSibling;
   207         }
   209         // if we're a slice in the hambuger, use that panel instead
   210         let widgetGroup = CustomizableUI.getWidget(this.getAttribute("id"));
   211         let widget = widgetGroup.forWindow(window);
   212         let inMenuPanel = widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL;
   213         if (inMenuPanel) {
   214           PanelUI.showSubView("PanelUI-socialapi", widget.node,
   215                               CustomizableUI.AREA_PANEL);
   216         } else {
   217           let anchor = document.getAnonymousElementByAttribute(this, "class", "toolbarbutton-icon");
   218           panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
   219           this.setAttribute("open", "true");
   220         }
   221         if (aResetOnClose) {
   222           let evName = inMenuPanel ? "ViewHiding": "popuphidden";
   223           let _hidden = () => {
   224             panel.removeEventListener(evName, _hidden);
   225             this.update();
   226           };
   227           panel.addEventListener(evName, _hidden, false);
   228         }
   229          ]]></body>
   230        </method>
   232       <method name="markCurrentPage">
   233         <parameter name="aOpenPanel"/>
   234         <body><![CDATA[
   235         // we always set the src on click if it has not been set for this tab,
   236         // but we only want to open the panel if it was previously annotated.
   237         let openPanel = this.isMarked || aOpenPanel ||
   238                         this.inMenuPanel || !this.provider.haveLoggedInUser();
   239         let src = this.content.getAttribute("src");
   240         if (!src || src == "about:blank") {
   241           this.loadPanel();
   242         }
   243         if (openPanel)
   244           this.openPanel();
   245         ]]></body>
   246       </method>
   248       <method name="markLink">
   249         <parameter name="aUrl"/>
   250         <body><![CDATA[
   251         if (!aUrl) {
   252           this.markCurrentPage(true);
   253           return;
   254         }
   255         // initiated form an external source, such as gContextMenu, where
   256         // pageData is passed into us. In this case, we always load the iframe
   257         // and show it since the url may not be the browser tab, but an image,
   258         // link, etc. inside the page. We also "update" the iframe to the
   259         // previous url when it is closed.
   260         this.content.setAttribute("src", "about:blank");
   261         this.loadPanel({ url: aUrl });
   262         this.openPanel(true);
   263         ]]></body>
   264       </method>
   266       <method name="dispatchPanelEvent">
   267         <parameter name="name"/>
   268         <body><![CDATA[
   269         let evt = this.contentDocument.createEvent("CustomEvent");
   270         evt.initCustomEvent(name, true, true, {});
   271         this.contentDocument.documentElement.dispatchEvent(evt);
   272         ]]></body>
   273       </method>
   275       <method name="onShown">
   276         <body><![CDATA[
   277         // because the panel may be preloaded, we need to size the panel when
   278         // showing as well as after load
   279         let sizeSocialPanelToContent = Cu.import("resource:///modules/Social.jsm", {}).sizeSocialPanelToContent;
   280         if (!this._loading && this.contentDocument &&
   281             this.contentDocument.readyState == "complete") {
   282           this.dispatchPanelEvent("socialFrameShow");
   283           if (!this.inMenuPanel)
   284             sizeSocialPanelToContent(this.panel, this.content);
   285         } else {
   286           let panelBrowserOnload = (e) => {
   287             this.content.removeEventListener("load", panelBrowserOnload, true);
   288             this.dispatchPanelEvent("socialFrameShow");
   289             if (!this.inMenuPanel)
   290               sizeSocialPanelToContent(this.panel, this.content);
   291           };
   292           this.content.addEventListener("load", panelBrowserOnload, true);
   293         }
   294         ]]></body>
   295       </method>
   297       <method name="handleEvent">
   298         <parameter name="aEvent"/>
   299         <body><![CDATA[
   300         if (aEvent.eventPhase != aEvent.BUBBLING_PHASE)
   301           return;
   302         switch(aEvent.type) {
   303           case "DOMLinkAdded": {
   304             // much of this logic is from DOMLinkHandler in browser.js, this sets
   305             // the presence icon for a chat user, we simply use favicon style
   306             // updating
   307             let link = aEvent.originalTarget;
   308             let rel = link.rel && link.rel.toLowerCase();
   309             if (!link || !link.ownerDocument || !rel || !link.href)
   310               return;
   311             if (link.rel.indexOf("icon") < 0)
   312               return;
   314             let ContentLinkHandler = Cu.import("resource:///modules/ContentLinkHandler.jsm", {}).ContentLinkHandler;
   315             let uri = ContentLinkHandler.getLinkIconURI(link);
   316             if (!uri)
   317               return;
   319             // we cannot size the image when we apply it via listStyleImage, so
   320             // use the toolbar image
   321             this.setAttribute("image", uri.spec);
   322             }
   323             break;
   324           case "ViewShowing":
   325             this.onShown();
   326             break;
   327           case "ViewHiding":
   328             this.dispatchPanelEvent("socialFrameHide");
   329             break;
   330         }
   331         ]]></body>
   332       </method>
   334     </implementation>
   335     <handlers>
   336       <handler event="popupshown"><![CDATA[
   337         this.onShown();
   338       ]]></handler>
   339       <handler event="popuphidden"><![CDATA[
   340         this.dispatchPanelEvent("socialFrameHide");
   341         this.removeAttribute("open");
   342       ]]></handler>
   343       <handler event="command"><![CDATA[
   344         this.markCurrentPage();
   345       ]]></handler>
   346     </handlers>
   347   </binding>
   349 </bindings>

mercurial