browser/metro/base/content/ContextCommands.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * context menu command handlers
michael@0 8 */
michael@0 9
michael@0 10 var ContextCommands = {
michael@0 11 _picker: null,
michael@0 12
michael@0 13 get _ellipsis() {
michael@0 14 delete this._ellipsis;
michael@0 15 this._ellipsis = "\u2026";
michael@0 16 try {
michael@0 17 this._ellipsis = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
michael@0 18 } catch (ex) { }
michael@0 19 return this._ellipsis;
michael@0 20 },
michael@0 21
michael@0 22 get clipboard() {
michael@0 23 return Cc["@mozilla.org/widget/clipboardhelper;1"]
michael@0 24 .getService(Ci.nsIClipboardHelper);
michael@0 25 },
michael@0 26
michael@0 27 get docRef() {
michael@0 28 return Browser.selectedBrowser.contentWindow.document;
michael@0 29 },
michael@0 30
michael@0 31 /*
michael@0 32 * Context menu handlers
michael@0 33 */
michael@0 34
michael@0 35 // Text specific
michael@0 36
michael@0 37 cut: function cc_cut() {
michael@0 38 let target = ContextMenuUI.popupState.target;
michael@0 39
michael@0 40 if (!target) {
michael@0 41 return;
michael@0 42 }
michael@0 43
michael@0 44 if (target.localName === "browser") {
michael@0 45 // content
michael@0 46 if (ContextMenuUI.popupState.string) {
michael@0 47 this.sendCommand("cut");
michael@0 48
michael@0 49 SelectionHelperUI.closeEditSession(true);
michael@0 50 }
michael@0 51 } else {
michael@0 52 // chrome
michael@0 53 CommandUpdater.doCommand("cmd_cut");
michael@0 54 }
michael@0 55
michael@0 56 target.focus();
michael@0 57 },
michael@0 58
michael@0 59 copy: function cc_copy() {
michael@0 60 let target = ContextMenuUI.popupState.target;
michael@0 61
michael@0 62 if (!target) {
michael@0 63 return;
michael@0 64 }
michael@0 65
michael@0 66 if (target.localName == "browser") {
michael@0 67 // content
michael@0 68 if (ContextMenuUI.popupState.string) {
michael@0 69 this.sendCommand("copy");
michael@0 70 }
michael@0 71 } else if (ContextMenuUI.popupState.string) {
michael@0 72 this.clipboard.copyString(ContextMenuUI.popupState.string, this.docRef);
michael@0 73 } else {
michael@0 74 // chrome
michael@0 75 CommandUpdater.doCommand("cmd_copy");
michael@0 76 }
michael@0 77
michael@0 78 target.focus();
michael@0 79 },
michael@0 80
michael@0 81 paste: function cc_paste() {
michael@0 82 let target = ContextMenuUI.popupState.target;
michael@0 83
michael@0 84 if (!target) {
michael@0 85 return;
michael@0 86 }
michael@0 87
michael@0 88 if (target.localName == "browser") {
michael@0 89 // content
michael@0 90 let x = ContextMenuUI.popupState.x;
michael@0 91 let y = ContextMenuUI.popupState.y;
michael@0 92 let json = {x: x, y: y, command: "paste" };
michael@0 93 target.messageManager.sendAsyncMessage("Browser:ContextCommand", json);
michael@0 94 } else {
michael@0 95 // chrome
michael@0 96 CommandUpdater.doCommand("cmd_paste");
michael@0 97 target.focus();
michael@0 98 }
michael@0 99 SelectionHelperUI.closeEditSession();
michael@0 100 },
michael@0 101
michael@0 102 pasteAndGo: function cc_pasteAndGo() {
michael@0 103 let target = ContextMenuUI.popupState.target;
michael@0 104 target.editor.selectAll();
michael@0 105 target.editor.paste(Ci.nsIClipboard.kGlobalClipboard);
michael@0 106 BrowserUI.goToURI();
michael@0 107 },
michael@0 108
michael@0 109 select: function cc_select() {
michael@0 110 SelectionHelperUI.openEditSession(ContextMenuUI.popupState.target,
michael@0 111 ContextMenuUI.popupState.xPos,
michael@0 112 ContextMenuUI.popupState.yPos,
michael@0 113 true);
michael@0 114 },
michael@0 115
michael@0 116 selectAll: function cc_selectAll() {
michael@0 117 let target = ContextMenuUI.popupState.target;
michael@0 118 if (target.localName == "browser") {
michael@0 119 // content
michael@0 120 let x = ContextMenuUI.popupState.xPos;
michael@0 121 let y = ContextMenuUI.popupState.yPos;
michael@0 122 let json = {x: x, y: y, command: "select-all" };
michael@0 123 target.messageManager.sendAsyncMessage("Browser:ContextCommand", json);
michael@0 124 SelectionHelperUI.attachEditSession(target, x, y);
michael@0 125 } else {
michael@0 126 // chrome
michael@0 127 target.editor.selectAll();
michael@0 128 target.focus();
michael@0 129 }
michael@0 130 },
michael@0 131
michael@0 132 // called on display of the search text menu item
michael@0 133 searchTextSetup: function cc_searchTextSetup(aRichListItem, aSearchString) {
michael@0 134 let defaultURI;
michael@0 135 let defaultName;
michael@0 136 aSearchString = aSearchString.trim();
michael@0 137 try {
michael@0 138 let defaultPB = Services.prefs.getDefaultBranch(null);
michael@0 139 const nsIPLS = Ci.nsIPrefLocalizedString;
michael@0 140 defaultName = defaultPB.getComplexValue("browser.search.defaultenginename", nsIPLS).data;
michael@0 141 let defaultEngine = Services.search.getEngineByName(defaultName);
michael@0 142 defaultURI = defaultEngine.getSubmission(aSearchString).uri.spec;
michael@0 143 } catch (ex) {
michael@0 144 Cu.reportError(ex);
michael@0 145 return false;
michael@0 146 }
michael@0 147 let displayString = aSearchString;
michael@0 148 if (displayString.length > 15) {
michael@0 149 displayString = displayString.substring(0, 15) + this._ellipsis;
michael@0 150 }
michael@0 151 // label child node
michael@0 152 let label = Services.strings
michael@0 153 .createBundle("chrome://browser/locale/browser.properties")
michael@0 154 .formatStringFromName("browser.search.contextTextSearchLabel2",
michael@0 155 [defaultName, displayString], 2);
michael@0 156 aRichListItem.childNodes[0].setAttribute("value", label);
michael@0 157 aRichListItem.setAttribute("searchString", defaultURI);
michael@0 158 return true;
michael@0 159 },
michael@0 160
michael@0 161 searchText: function cc_searchText(aRichListItem) {
michael@0 162 let defaultURI = aRichListItem.getAttribute("searchString");
michael@0 163 aRichListItem.childNodes[0].setAttribute("value", "");
michael@0 164 aRichListItem.setAttribute("searchString", "");
michael@0 165 BrowserUI.addAndShowTab(defaultURI, Browser.selectedTab);
michael@0 166 },
michael@0 167
michael@0 168 // Link specific
michael@0 169
michael@0 170 openLinkInNewTab: function cc_openLinkInNewTab() {
michael@0 171 let url = ContextMenuUI.popupState.linkURL;
michael@0 172 BrowserUI.openLinkInNewTab(url, false, Browser.selectedTab);
michael@0 173 },
michael@0 174
michael@0 175 copyLink: function cc_copyLink() {
michael@0 176 this.clipboard.copyString(ContextMenuUI.popupState.linkURL,
michael@0 177 this.docRef);
michael@0 178 },
michael@0 179
michael@0 180 bookmarkLink: function cc_bookmarkLink() {
michael@0 181 let state = ContextMenuUI.popupState;
michael@0 182 let uri = Util.makeURI(state.linkURL);
michael@0 183 let title = state.linkTitle || state.linkURL;
michael@0 184
michael@0 185 try {
michael@0 186 Bookmarks.addForURI(uri, title);
michael@0 187 } catch (e) {
michael@0 188 return;
michael@0 189 }
michael@0 190 },
michael@0 191
michael@0 192 // Image specific
michael@0 193
michael@0 194 saveImageToLib: function cc_saveImageToLib() {
michael@0 195 this.saveToWinLibrary("Pict");
michael@0 196 },
michael@0 197
michael@0 198 copyImage: function cc_copyImage() {
michael@0 199 // copy to clibboard
michael@0 200 this.sendCommand("copy-image-contents");
michael@0 201 },
michael@0 202
michael@0 203 copyImageSrc: function cc_copyImageSrc() {
michael@0 204 this.clipboard.copyString(ContextMenuUI.popupState.mediaURL,
michael@0 205 this.docRef);
michael@0 206 },
michael@0 207
michael@0 208 openImageInNewTab: function cc_openImageInNewTab() {
michael@0 209 BrowserUI.addAndShowTab(ContextMenuUI.popupState.mediaURL, Browser.selectedTab);
michael@0 210 },
michael@0 211
michael@0 212 // Video specific
michael@0 213
michael@0 214 saveVideoToLib: function cc_saveVideoToLib() {
michael@0 215 this.saveToWinLibrary("Vids");
michael@0 216 },
michael@0 217
michael@0 218 copyVideoSrc: function cc_copyVideoSrc() {
michael@0 219 this.clipboard.copyString(ContextMenuUI.popupState.mediaURL,
michael@0 220 this.docRef);
michael@0 221 },
michael@0 222
michael@0 223 openVideoInNewTab: function cc_openVideoInNewTab() {
michael@0 224 BrowserUI.addAndShowTab(ContextMenuUI.popupState.mediaURL, Browser.selectedTab);
michael@0 225 },
michael@0 226
michael@0 227 // Bookmarks
michael@0 228
michael@0 229 editBookmark: function cc_editBookmark() {
michael@0 230 let target = ContextMenuUI.popupState.target;
michael@0 231 target.startEditing();
michael@0 232 },
michael@0 233
michael@0 234 removeBookmark: function cc_removeBookmark() {
michael@0 235 let target = ContextMenuUI.popupState.target;
michael@0 236 target.remove();
michael@0 237 },
michael@0 238
michael@0 239 // App bar
michael@0 240
michael@0 241 errorConsole: function cc_errorConsole() {
michael@0 242 PanelUI.show("console-container");
michael@0 243 },
michael@0 244
michael@0 245 jsShell: function cc_jsShell() {
michael@0 246 // XXX for debugging, this only works when running on the desktop.
michael@0 247 if (!Services.metro.immersive)
michael@0 248 window.openDialog("chrome://browser/content/shell.xul", "_blank",
michael@0 249 "all=no,scrollbars=yes,resizable=yes,dialog=no");
michael@0 250 },
michael@0 251
michael@0 252 findInPage: function cc_findInPage() {
michael@0 253 FindHelperUI.show();
michael@0 254 },
michael@0 255
michael@0 256 viewOnDesktop: function cc_viewOnDesktop() {
michael@0 257 Appbar.onViewOnDesktop();
michael@0 258 },
michael@0 259
michael@0 260 // Checks for MS app store specific meta data, and if present opens
michael@0 261 // the Windows Store to the appropriate app
michael@0 262 openWindowsStoreLink: function cc_openWindowsStoreLink() {
michael@0 263 let storeLink = this.getStoreLink();
michael@0 264 if (storeLink) {
michael@0 265 Browser.selectedBrowser.contentWindow.document.location = storeLink;
michael@0 266 }
michael@0 267 },
michael@0 268
michael@0 269 getStoreLink: function cc_getStoreLink() {
michael@0 270 let metaData = Browser.selectedBrowser.contentWindow.document.getElementsByTagName("meta");
michael@0 271 let msApplicationName = metaData.namedItem("msApplication-PackageFamilyName");
michael@0 272 if (msApplicationName) {
michael@0 273 return "ms-windows-store:PDP?PFN=" + msApplicationName.getAttribute("content");
michael@0 274 }
michael@0 275 return null;
michael@0 276 },
michael@0 277
michael@0 278 getPageSource: function cc_getPageSource() {
michael@0 279 let uri = Services.io.newURI(Browser.selectedBrowser.currentURI.spec, null, null);
michael@0 280 if (!uri.schemeIs("view-source")) {
michael@0 281 return "view-source:" + Browser.selectedBrowser.currentURI.spec;
michael@0 282 }
michael@0 283 return null;
michael@0 284 },
michael@0 285
michael@0 286 viewPageSource: function cc_viewPageSource() {
michael@0 287 let uri = this.getPageSource();
michael@0 288 if (uri) {
michael@0 289 BrowserUI.addAndShowTab(uri, Browser.selectedTab);
michael@0 290 }
michael@0 291 },
michael@0 292
michael@0 293 /*
michael@0 294 * Utilities
michael@0 295 */
michael@0 296
michael@0 297 saveToWinLibrary: function cc_saveToWinLibrary(aType) {
michael@0 298 let popupState = ContextMenuUI.popupState;
michael@0 299 let browser = popupState.target;
michael@0 300
michael@0 301 // ContentAreaUtils internalSave relies on various desktop related prefs,
michael@0 302 // values, and functionality. We want to be more direct by saving the
michael@0 303 // image to the users Windows Library. If users want to specify the
michael@0 304 // save location they can use the context menu option 'Save (type) To'.
michael@0 305
michael@0 306 let dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
michael@0 307 .getService(Components.interfaces.nsIProperties);
michael@0 308 let saveLocationPath = dirSvc.get(aType, Components.interfaces.nsIFile);
michael@0 309
michael@0 310 let fileInfo = new ContentAreaUtils.FileInfo();
michael@0 311 ContentAreaUtils.initFileInfo(fileInfo, popupState.mediaURL,
michael@0 312 browser.documentURI.originCharset,
michael@0 313 null, null, null);
michael@0 314 let filename =
michael@0 315 ContentAreaUtils.getNormalizedLeafName(fileInfo.fileName, fileInfo.fileExt);
michael@0 316 saveLocationPath.append(filename);
michael@0 317
michael@0 318 // Start the background save process
michael@0 319 ContentAreaUtils.internalPersist({
michael@0 320 sourceURI : fileInfo.uri,
michael@0 321 sourceDocument : null,
michael@0 322 sourceReferrer : browser.documentURI,
michael@0 323 targetContentType : popupState.contentType,
michael@0 324 targetFile : saveLocationPath,
michael@0 325 sourceCacheKey : null,
michael@0 326 sourcePostData : null,
michael@0 327 bypassCache : false,
michael@0 328 initiatingWindow : this.docRef.defaultView
michael@0 329 });
michael@0 330 },
michael@0 331
michael@0 332 sendCommand: function sendCommand(aCommand) {
michael@0 333 // Send via message manager over to ContextMenuHandler
michael@0 334 let browser = ContextMenuUI.popupState.target;
michael@0 335 browser.messageManager.sendAsyncMessage("Browser:ContextCommand", { command: aCommand });
michael@0 336 },
michael@0 337
michael@0 338 /*
michael@0 339 * isAccessibleDirectory
michael@0 340 *
michael@0 341 * Test to see if the directory exists and is writable.
michael@0 342 */
michael@0 343 isAccessibleDirectory: function isAccessibleDirectory(aDirectory) {
michael@0 344 return aDirectory && aDirectory.exists() && aDirectory.isDirectory() &&
michael@0 345 aDirectory.isWritable();
michael@0 346 },
michael@0 347
michael@0 348 /*
michael@0 349 * saveFileAs
michael@0 350 *
michael@0 351 * Browse for a location and then save a file to the local system using
michael@0 352 * standard download prefs.
michael@0 353 *
michael@0 354 * @param aFileUriString path to file
michael@0 355 */
michael@0 356 saveFileAs: function saveFileAs(aPopupState) {
michael@0 357 let srcUri = null;
michael@0 358 let mediaURL = aPopupState.mediaURL;
michael@0 359 try {
michael@0 360 srcUri = Util.makeURI(mediaURL, null, null);
michael@0 361 } catch (ex) {
michael@0 362 Util.dumpLn("could not parse:", mediaURL);
michael@0 363 return;
michael@0 364 }
michael@0 365
michael@0 366 let picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
michael@0 367 let windowTitle = Strings.browser.GetStringFromName("browserForSaveLocation");
michael@0 368
michael@0 369 picker.init(window, windowTitle, Ci.nsIFilePicker.modeSave);
michael@0 370
michael@0 371 // prefered filename
michael@0 372 let fileName = mediaURL.substring(mediaURL.lastIndexOf("/") + 1);
michael@0 373 if (fileName.length)
michael@0 374 picker.defaultString = fileName;
michael@0 375
michael@0 376 // prefered file extension
michael@0 377 let fileExtension = mediaURL.substring(mediaURL.lastIndexOf(".") + 1);
michael@0 378 if (fileExtension.length)
michael@0 379 picker.defaultExtension = fileExtension;
michael@0 380 picker.appendFilters(Ci.nsIFilePicker.filterImages);
michael@0 381
michael@0 382 // prefered save location
michael@0 383 Task.spawn(function() {
michael@0 384 let preferredDir = yield Downloads.getPreferredDownloadsDirectory();
michael@0 385 picker.displayDirectory = new FileUtils.File(preferredDir);
michael@0 386
michael@0 387 try {
michael@0 388 let lastDir = Services.prefs.getComplexValue("browser.download.lastDir", Ci.nsILocalFile);
michael@0 389 if (this.isAccessibleDirectory(lastDir))
michael@0 390 picker.displayDirectory = lastDir;
michael@0 391 }
michael@0 392 catch (e) { }
michael@0 393
michael@0 394 this._picker = picker;
michael@0 395 this._pickerUrl = mediaURL;
michael@0 396 this._pickerContentDisp = aPopupState.contentDisposition;
michael@0 397 this._contentType = aPopupState.contentType;
michael@0 398 picker.open(ContextCommands);
michael@0 399 }.bind(this));
michael@0 400 },
michael@0 401
michael@0 402 /*
michael@0 403 * Filepicker callback
michael@0 404 */
michael@0 405 done: function done(aSuccess) {
michael@0 406 let picker = this._picker;
michael@0 407 this._picker = null;
michael@0 408
michael@0 409 if (aSuccess == Ci.nsIFilePicker.returnCancel)
michael@0 410 return;
michael@0 411
michael@0 412 let file = picker.file;
michael@0 413 if (file == null)
michael@0 414 return;
michael@0 415
michael@0 416 try {
michael@0 417 if (file.exists())
michael@0 418 file.remove(false);
michael@0 419 } catch (e) {}
michael@0 420
michael@0 421 ContentAreaUtils.internalSave(this._pickerUrl, null, null,
michael@0 422 this._pickerContentDisp,
michael@0 423 this._contentType, false, "SaveImageTitle",
michael@0 424 new AutoChosen(file, Util.makeURI(this._pickerUrl, null, null)),
michael@0 425 getBrowser().documentURI, this.docRef, true, null);
michael@0 426
michael@0 427 var newDir = file.parent.QueryInterface(Ci.nsILocalFile);
michael@0 428 Services.prefs.setComplexValue("browser.download.lastDir", Ci.nsILocalFile, newDir);
michael@0 429 },
michael@0 430 };
michael@0 431
michael@0 432 function AutoChosen(aFileAutoChosen, aUriAutoChosen) {
michael@0 433 this.file = aFileAutoChosen;
michael@0 434 this.uri = aUriAutoChosen;
michael@0 435 }
michael@0 436

mercurial