Bug 867089 - Validate the playbackRate before using it. r=ehsan
[gecko.git] / webapprt / content / webapp.js
blob75fd31f799e25c2dd1ced32a3ba8bfda0ae2b62a
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 const Cc = Components.classes;
6 const Ci = Components.interfaces;
7 const Cu = Components.utils;
9 Cu.import("resource://webapprt/modules/Startup.jsm");
10 Cu.import("resource://webapprt/modules/WebappRT.jsm");
11 Cu.import("resource://gre/modules/Services.jsm");
12 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
14 XPCOMUtils.defineLazyGetter(this, "gAppBrowser",
15                             function() document.getElementById("content"));
17 #ifdef MOZ_CRASHREPORTER
18 XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
19                                    "@mozilla.org/toolkit/crash-reporter;1",
20                                    "nsICrashReporter");
21 #endif
23 let progressListener = {
24   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
25                                          Ci.nsISupportsWeakReference]),
26   onLocationChange: function onLocationChange(progress, request, location,
27                                               flags) {
28     // Set the title of the window to the name of the webapp, adding the origin
29     // of the page being loaded if it's from a different origin than the app
30     // (per security bug 741955, which specifies that other-origin pages loaded
31     // in runtime windows must be identified in chrome).
32     let title = WebappRT.config.app.manifest.name;
33     let origin = location.prePath;
34     if (origin != WebappRT.config.app.origin) {
35       title = origin + " - " + title;
36     }
37     document.documentElement.setAttribute("title", title);
38   },
40   onStateChange: function onStateChange(aProgress, aRequest, aFlags, aStatus) {
41     if (aRequest instanceof Ci.nsIChannel &&
42         aFlags & Ci.nsIWebProgressListener.STATE_START &&
43         aFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {
44       updateCrashReportURL(aRequest.URI);
45     }
46   }
49 function onLoad() {
50   window.removeEventListener("load", onLoad, false);
52   let args = window.arguments && window.arguments[0] ?
53              window.arguments[0].QueryInterface(Ci.nsIPropertyBag2) :
54              null;
56   gAppBrowser.addProgressListener(progressListener,
57                                   Ci.nsIWebProgress.NOTIFY_LOCATION |
58                                   Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
60   updateMenuItems();
62   // Listen for clicks to redirect <a target="_blank"> to the browser.
63   // This doesn't capture clicks so content can capture them itself and do
64   // something different if it doesn't want the default behavior.
65   gAppBrowser.addEventListener("click", onContentClick, false, true);
67   // This is not the only way that a URL gets loaded in the app browser.
68   // When content calls openWindow(), there are no window.arguments,
69   // but something in the platform loads the URL specified by the content.
70   if (args && args.hasKey("url")) {
71     gAppBrowser.setAttribute("src", args.get("url"));
72   }
75 window.addEventListener("load", onLoad, false);
77 function onUnload() {
78   gAppBrowser.removeProgressListener(progressListener);
80 window.addEventListener("unload", onUnload, false);
82 /**
83  * Direct a click on <a target="_blank"> to the user's default browser.
84  *
85  * In the long run, it might be cleaner to move this to an extension of
86  * nsIWebBrowserChrome3::onBeforeLinkTraversal.
87  *
88  * @param {DOMEvent} event the DOM event
89  **/
90 function onContentClick(event) {
91   let target = event.target;
93   if (!(target instanceof HTMLAnchorElement) ||
94       target.getAttribute("target") != "_blank") {
95     return;
96   }
98   let uri = Services.io.newURI(target.href,
99                                target.ownerDocument.characterSet,
100                                null);
102   // Direct the URL to the browser.
103   Cc["@mozilla.org/uriloader/external-protocol-service;1"].
104     getService(Ci.nsIExternalProtocolService).
105     getProtocolHandlerInfo(uri.scheme).
106     launchWithURI(uri);
108   // Prevent the runtime from loading the URL.  We do this after directing it
109   // to the browser to give the runtime a shot at handling the URL if we fail
110   // to direct it to the browser for some reason.
111   event.preventDefault();
114 // On Mac, we dynamically create the label for the Quit menuitem, using
115 // a string property to inject the name of the webapp into it.
116 function updateMenuItems() {
117 #ifdef XP_MACOSX
118   let installRecord = WebappRT.config.app;
119   let manifest = WebappRT.config.app.manifest;
120   let bundle =
121     Services.strings.createBundle("chrome://webapprt/locale/webapp.properties");
122   let quitLabel = bundle.formatStringFromName("quitApplicationCmdMac.label",
123                                               [manifest.name], 1);
124   let hideLabel = bundle.formatStringFromName("hideApplicationCmdMac.label",
125                                               [manifest.name], 1);
126   document.getElementById("menu_FileQuitItem").setAttribute("label", quitLabel);
127   document.getElementById("menu_mac_hide_app").setAttribute("label", hideLabel);
128 #endif
131 function updateEditUIVisibility() {
132 #ifndef XP_MACOSX
133   let editMenuPopupState = document.getElementById("menu_EditPopup").state;
135   // The UI is visible if the Edit menu is opening or open, if the context menu
136   // is open, or if the toolbar has been customized to include the Cut, Copy,
137   // or Paste toolbar buttons.
138   gEditUIVisible = editMenuPopupState == "showing" ||
139                    editMenuPopupState == "open";
141   // If UI is visible, update the edit commands' enabled state to reflect
142   // whether or not they are actually enabled for the current focus/selection.
143   if (gEditUIVisible) {
144     goUpdateGlobalEditMenuItems();
145   }
147   // Otherwise, enable all commands, so that keyboard shortcuts still work,
148   // then lazily determine their actual enabled state when the user presses
149   // a keyboard shortcut.
150   else {
151     goSetCommandEnabled("cmd_undo", true);
152     goSetCommandEnabled("cmd_redo", true);
153     goSetCommandEnabled("cmd_cut", true);
154     goSetCommandEnabled("cmd_copy", true);
155     goSetCommandEnabled("cmd_paste", true);
156     goSetCommandEnabled("cmd_selectAll", true);
157     goSetCommandEnabled("cmd_delete", true);
158     goSetCommandEnabled("cmd_switchTextDirection", true);
159   }
160 #endif
163 function updateCrashReportURL(aURI) {
164 #ifdef MOZ_CRASHREPORTER
165   if (!gCrashReporter.enabled)
166     return;
168   let uri = aURI.clone();
169   // uri.userPass throws on protocols without the concept of authentication,
170   // like about:, which tests can load, so we catch and ignore an exception.
171   try {
172     if (uri.userPass != "") {
173       uri.userPass = "";
174     }
175   } catch (e) {}
177   gCrashReporter.annotateCrashReport("URL", uri.spec);
178 #endif