@@ -29,6 +29,7 @@ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
29
29
const lazy = { } ;
30
30
31
31
ChromeUtils . defineESModuleGetters ( lazy , {
32
+ AddonManagerPrivate : "resource://gre/modules/AddonManager.sys.mjs" ,
32
33
BasePromiseWorker : "resource://gre/modules/PromiseWorker.sys.mjs" ,
33
34
} ) ;
34
35
@@ -60,6 +61,8 @@ const PREF_SEPARATE_PRIVILEGEDABOUT_CONTENT_PROCESS =
60
61
"browser.tabs.remote.separatePrivilegedContentProcess" ;
61
62
const PREF_ACTIVITY_STREAM_DEBUG = "browser.newtabpage.activity-stream.debug" ;
62
63
64
+ const BUILTIN_ADDON_ID = "newtab@mozilla.org" ;
65
+
63
66
/**
64
67
* The AboutHomeStartupCacheChild is responsible for connecting the
65
68
* AboutNewTabRedirectorChild with a cached document and script for about:home
@@ -462,6 +465,9 @@ class BaseAboutNewTabRedirector {
462
465
* before the AboutNewTabRedirectorChild has a chance to handle the request).
463
466
*/
464
467
export class AboutNewTabRedirectorParent extends BaseAboutNewTabRedirector {
468
+ #addonInitialized = false ;
469
+ #suspendedChannels = [ ] ;
470
+
465
471
constructor ( ) {
466
472
super ( ) ;
467
473
@@ -489,6 +495,36 @@ export class AboutNewTabRedirectorParent extends BaseAboutNewTabRedirector {
489
495
matches : [ "about:home*" , "about:newtab*" ] ,
490
496
remoteTypes : [ "privilegedabout" ] ,
491
497
} ) ;
498
+
499
+ if ( AppConstants . BROWSER_NEWTAB_AS_ADDON ) {
500
+ this . #waitForBuiltInAddonInitialized( ) ;
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Waits for the AddonManager to be fully initialized, and for the built-in
506
+ * addon to be ready. Once that's done, it tterates any suspended channels and
507
+ * resumes them, now that the built-in addon has been set up.
508
+ *
509
+ * @returns {Promise<undefined> }
510
+ * Resolves when the built-in addon has initialized and all suspended
511
+ * channels are resumed.
512
+ */
513
+ async #waitForBuiltInAddonInitialized( ) {
514
+ let addon = WebExtensionPolicy . getByID ( BUILTIN_ADDON_ID ) ;
515
+ if ( ! addon ?. readyPromise ) {
516
+ await lazy . AddonManagerPrivate . databaseReady ;
517
+ addon = WebExtensionPolicy . getByID ( BUILTIN_ADDON_ID ) ;
518
+ }
519
+
520
+ await addon . readyPromise ;
521
+
522
+ this . #addonInitialized = true ;
523
+
524
+ for ( let suspendedChannel of this . #suspendedChannels) {
525
+ suspendedChannel . resume ( ) ;
526
+ }
527
+ this . #suspendedChannels = [ ] ;
492
528
}
493
529
494
530
newChannel ( uri , loadInfo ) {
@@ -506,8 +542,31 @@ export class AboutNewTabRedirectorParent extends BaseAboutNewTabRedirector {
506
542
loadInfo
507
543
) ;
508
544
resultChannel . originalURI = uri ;
545
+
546
+ if ( AppConstants . BROWSER_NEWTAB_AS_ADDON && ! this . #addonInitialized) {
547
+ return this . #getSuspendedChannel( resultChannel ) ;
548
+ }
549
+
509
550
return resultChannel ;
510
551
}
552
+
553
+ /**
554
+ * Wraps an nsIChannel with an nsISuspendableChannelWrapper, suspends that
555
+ * wrapper, and then stores the wrapper in #suspendedChannels so that it can
556
+ * be resumed with a call to #notifyBuildInAddonInitialized.
557
+ *
558
+ * @param {nsIChannel } innerChannel
559
+ * The channel to wrap and suspend.
560
+ * @returns {nsISuspendableChannelWrapper }
561
+ */
562
+ #getSuspendedChannel( innerChannel ) {
563
+ let suspendedChannel =
564
+ Services . io . newSuspendableChannelWrapper ( innerChannel ) ;
565
+ suspendedChannel . suspend ( ) ;
566
+
567
+ this . #suspendedChannels. push ( suspendedChannel ) ;
568
+ return suspendedChannel ;
569
+ }
511
570
}
512
571
513
572
/**
0 commit comments