@@ -2,10 +2,20 @@ import { AppConstants } from 'resource://gre/modules/AppConstants.sys.mjs';
2
2
import { NetUtil } from 'resource://gre/modules/NetUtil.sys.mjs' ;
3
3
import { nsContentDispatchChooser } from 'resource://gre/modules/ContentDispatchChooser.sys.mjs' ;
4
4
import { nsDefaultCommandLineHandler , nsBrowserContentHandler } from 'resource:///modules/BrowserContentHandler.sys.mjs' ;
5
+ import { BrowserGlue } from 'resource:///modules/BrowserGlue.sys.mjs' ;
5
6
import { BrowserWindowTracker } from 'resource:///modules/BrowserWindowTracker.sys.mjs' ;
7
+ import { WebProtocolHandlerRegistrar } from 'resource:///modules/WebProtocolHandlerRegistrar.sys.mjs' ;
8
+ import { OnboardingMessageProvider } from 'resource:///modules/asrouter/OnboardingMessageProvider.sys.mjs' ;
6
9
7
10
import { applySystemIntegration } from 'resource://pwa/utils/systemIntegration.sys.mjs' ;
8
11
12
+ const lazy = { } ;
13
+
14
+ ChromeUtils . defineESModuleGetters ( lazy , {
15
+ sendNativeMessage : 'resource://pwa/utils/nativeMessaging.sys.mjs' ,
16
+ sanitizeString : 'resource://pwa/utils/common.sys.mjs' ,
17
+ } ) ;
18
+
9
19
/**
10
20
* Reads the PWAsForFirefox config file and parses it as JSON.
11
21
*
@@ -117,9 +127,18 @@ Services.prefs.getDefaultBranch(null).setBoolPref('browser.sessionstore.resume_f
117
127
Services . prefs . getDefaultBranch ( null ) . setIntPref ( 'browser.sessionstore.max_resumed_crashes' , 0 ) ;
118
128
Services . prefs . getDefaultBranch ( null ) . setIntPref ( 'browser.sessionstore.max_tabs_undo' , 0 ) ;
119
129
Services . prefs . getDefaultBranch ( null ) . setIntPref ( 'browser.sessionstore.max_windows_undo' , 0 ) ;
130
+ Services . prefs . getDefaultBranch ( null ) . setBoolPref ( 'browser.shell.checkDefaultBrowser' , false ) ;
131
+ Services . prefs . getDefaultBranch ( null ) . setBoolPref ( 'browser.startup.upgradeDialog.enabled' , false ) ;
120
132
Services . prefs . getDefaultBranch ( null ) . setBoolPref ( 'browser.privateWindowSeparation.enabled' , false ) ;
121
133
Services . prefs . getDefaultBranch ( null ) . setBoolPref ( 'browser.privacySegmentation.createdShortcut' , true ) ;
122
134
135
+ // Disable default browser prompt
136
+ BrowserGlue . prototype . _maybeShowDefaultBrowserPrompt = async ( ) => null ;
137
+
138
+ // Disable onboarding messages
139
+ OnboardingMessageProvider . getMessages = async ( ) => [ ] ;
140
+ OnboardingMessageProvider . getUntranslatedMessages = async ( ) => [ ] ;
141
+
123
142
// Override command line helper to intercept PWAsForFirefox arguments and start loading the site
124
143
nsDefaultCommandLineHandler . prototype . _handle = nsDefaultCommandLineHandler . prototype . handle ;
125
144
nsDefaultCommandLineHandler . prototype . handle = function ( cmdLine ) {
@@ -196,6 +215,118 @@ nsContentDispatchChooser.prototype._hasProtocolHandlerPermission = function(sche
196
215
return this . _hasProtocolHandlerPermissionOriginal ( scheme , principal , triggeredExternally ) ;
197
216
} ;
198
217
218
+ // Handle opening new window from keyboard shortcuts
219
+ BrowserWindowTracker . _openWindow = BrowserWindowTracker . openWindow ;
220
+ BrowserWindowTracker . openWindow = function ( options ) {
221
+ if ( options . openerWindow && options . openerWindow . gFFPWASiteConfig && ! options . args ) {
222
+ options . args = Cc [ '@mozilla.org/supports-string;1' ] . createInstance ( Ci . nsISupportsString ) ;
223
+ options . args . data = options . openerWindow . HomePage . get ( options . openerWindow ) ;
224
+ }
225
+ return BrowserWindowTracker . _openWindow ( options ) ;
226
+ } ;
227
+
228
+ // Some checks for protocol handlers are directly based on the Firefox code, licensed under MPL 2.0
229
+ // Original source: https://github.com/mozilla/gecko-dev/blob/a62618baa72cd0ba6c0a5f5fc0b1d63f2866b7c6/browser/components/protocolhandler/WebProtocolHandlerRegistrar.jsm
230
+
231
+ // Handle registering custom protocol handlers
232
+ WebProtocolHandlerRegistrar . prototype . registerProtocolHandler = function ( protocol , url , title , documentURI , browserOrWindow ) {
233
+ protocol = ( protocol || '' ) . toLowerCase ( ) ;
234
+ if ( ! url || ! documentURI ) return ;
235
+
236
+ // Some special handling for e10s and non-e10s
237
+ let browser = browserOrWindow ;
238
+ if ( browserOrWindow instanceof Ci . nsIDOMWindow ) {
239
+ let rootDocShell = browserOrWindow . docShell . sameTypeRootTreeItem ;
240
+ browser = rootDocShell . QueryInterface ( Ci . nsIDocShell ) . chromeEventHandler ;
241
+ }
242
+
243
+ // Get the browser window
244
+ let browserWindow = browser . ownerGlobal ;
245
+
246
+ // Check if protocol handler is allowed
247
+ try { browser . ownerGlobal . navigator . checkProtocolHandlerAllowed ( protocol , url , documentURI ) }
248
+ catch ( _ ) { return }
249
+
250
+ // If the protocol handler is already registered, just return early
251
+ // We only allow one handler (either manifest or custom) per protocol scheme
252
+ const existingHandlers = new Set ( [
253
+ ...browserWindow . gFFPWASiteConfig . config . custom_protocol_handlers ,
254
+ ...browserWindow . gFFPWASiteConfig . manifest . protocol_handlers
255
+ ] . map ( handler => lazy . sanitizeString ( handler . protocol ) ) . filter ( handler => handler ) . sort ( ) ) ;
256
+ if ( existingHandlers . has ( protocol ) ) return ;
257
+
258
+ // Now ask the user and provide the proper callback
259
+ const message = this . _getFormattedString ( 'addProtocolHandlerMessage' , [ url . host , protocol , ] ) ;
260
+
261
+ const notificationBox = browser . getTabBrowser ( ) . getNotificationBox ( browser ) ;
262
+ const notificationIcon = url . prePath + '/favicon.ico' ;
263
+ const notificationValue = 'Protocol Registration: ' + protocol ;
264
+
265
+ const addButton = {
266
+ label : this . _getString ( 'addProtocolHandlerAddButton' ) ,
267
+ accessKey : this . _getString ( 'addProtocolHandlerAddButtonAccesskey' ) ,
268
+ protocolInfo : { site : browserWindow . gFFPWASiteConfig . ulid , protocol : protocol , url : url . spec } ,
269
+
270
+ async callback ( notification , buttonInfo ) {
271
+ // Send a request to the native program to register the handler
272
+ const response = await lazy . sendNativeMessage ( {
273
+ cmd : 'RegisterProtocolHandler' ,
274
+ params : {
275
+ site : buttonInfo . protocolInfo . site ,
276
+ protocol : buttonInfo . protocolInfo . protocol ,
277
+ url : buttonInfo . protocolInfo . url ,
278
+ }
279
+ } ) ;
280
+ if ( response . type === 'Error' ) throw new Error ( response . data ) ;
281
+ if ( response . type !== 'ProtocolHandlerRegistered' ) throw new Error ( `Received invalid response type: ${ response . type } ` ) ;
282
+
283
+ // Reset the handlerInfo to ask before the next use
284
+ const eps = Cc [ '@mozilla.org/uriloader/external-protocol-service;1' ] . getService ( Ci . nsIExternalProtocolService ) ;
285
+ const handlerInfo = eps . getProtocolHandlerInfo ( buttonInfo . protocolInfo . protocol ) ;
286
+ handlerInfo . alwaysAskBeforeHandling = true ;
287
+
288
+ const hs = Cc [ '@mozilla.org/uriloader/handler-service;1' ] . getService ( Ci . nsIHandlerService ) ;
289
+ hs . store ( handlerInfo ) ;
290
+
291
+ // Hide the notification
292
+ notificationBox . currentNotification . close ( ) ;
293
+ } ,
294
+ } ;
295
+
296
+ notificationBox . appendNotification (
297
+ notificationValue ,
298
+ {
299
+ label : message ,
300
+ image : notificationIcon ,
301
+ priority : notificationBox . PRIORITY_INFO_LOW
302
+ } ,
303
+ [ addButton ]
304
+ ) ;
305
+ } ;
306
+
307
+ // Handle unregistering custom protocol handlers
308
+ // Disabled for now until we figure out how to access window from here
309
+ // WebProtocolHandlerRegistrar.prototype.removeProtocolHandler = function (protocol, url) {
310
+ // (async () => {
311
+ // // Send a request to the native program to unregister the handler
312
+ // const response = await lazy.sendNativeMessage({
313
+ // cmd: 'UnregisterProtocolHandler',
314
+ // params: {
315
+ // site: window.gFFPWASiteConfig.ulid,
316
+ // protocol,
317
+ // url,
318
+ // }
319
+ // });
320
+ // if (response.type === 'Error') throw new Error(response.data);
321
+ // if (response.type !== 'ProtocolHandlerUnregistered') throw new Error(`Received invalid response type: ${response.type}`);
322
+ //
323
+ // // Reset the handlerInfo to ask before the next use
324
+ // const eps = Cc['@mozilla.org/uriloader/external-protocol-service;1'].getService(Ci.nsIExternalProtocolService);
325
+ // const handlerInfo = eps.getProtocolHandlerInfo(protocol);
326
+ // handlerInfo.alwaysAskBeforeHandling = true;
327
+ // })()
328
+ // };
329
+
199
330
// Register a localization source for the packaged locales
200
331
Services . obs . addObserver ( async ( ) => {
201
332
const languages = Services . locale . packagedLocales ;
0 commit comments