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