@@ -8,7 +8,7 @@ export const BACKGROUND_COLOR_START = 'rgba(85, 127, 243, 0.10)';
88export const BACKGROUND_COLOR_END = 'rgba(85, 127, 243, 0.25)' ;
99export const OVERLAY_ID = 'ddg-password-import-overlay' ;
1010export const DELAY_BEFORE_ANIMATION = 300 ;
11- const TAKEOUT_DOWNLOAD_URL_BASE = '/takeout/download ' ;
11+ const MANAGE_ARCHIVE_DEFAULT_BASE = '/manage/archive ' ;
1212
1313/**
1414 * @typedef ButtonAnimationStyle
@@ -55,8 +55,6 @@ export default class AutofillImport extends ActionExecutorBase {
5555
5656 #domLoaded;
5757
58- #exportId;
59-
6058 #processingBookmark;
6159
6260 #isBookmarkModalVisible = false ;
@@ -589,22 +587,23 @@ export default class AutofillImport extends ActionExecutorBase {
589587 }
590588
591589 /** Bookmark import code */
590+ get defaultRetrySettings ( ) {
591+ return {
592+ maxAttempts : this . getFeatureSetting ( 'downloadRetryLimit' ) ?? Infinity ,
593+ interval : this . getFeatureSetting ( 'downloadRetryInterval' ) ?? 1000 ,
594+ } ;
595+ }
596+
592597 async downloadData ( ) {
593598 // Run with retry forever until the download link is available,
594599 // Android is the one that timesout anyway and closes the whole tab if this doesn't complete
595- const downloadRetryLimit = this . getFeatureSetting ( 'downloadRetryLimit' ) ?? Infinity ;
596- const downloadRetryInterval = this . getFeatureSetting ( 'downloadRetryInterval' ) ?? 1000 ;
597-
598- const userIdElement = await this . runWithRetry (
599- ( ) => document . querySelector ( this . bookmarkImportSelectorSettings . userIdLink ) ,
600- downloadRetryLimit ,
601- downloadRetryInterval ,
602- 'linear' ,
603- ) ;
604- const userIdLink = userIdElement ?. getAttribute ( 'href' ) ;
605- const userId = userIdLink ? new URL ( userIdLink , window . location . origin ) . searchParams . get ( 'user' ) : null ;
606600
607- if ( ! userId || ! this . #exportId) {
601+ const exportId = window . location . pathname
602+ . split ( '/' )
603+ . filter ( ( segment ) => segment )
604+ . pop ( ) ;
605+
606+ if ( ! exportId ) {
608607 this . postBookmarkImportMessage ( 'actionCompleted' , {
609608 result : new ErrorResponse ( {
610609 actionID : 'download-data' ,
@@ -614,30 +613,28 @@ export default class AutofillImport extends ActionExecutorBase {
614613 return ;
615614 }
616615
617- await this . runWithRetry (
618- ( ) => document . querySelector ( `a[href="./manage/archive/${ this . #exportId} "]` ) ,
619- downloadRetryLimit ,
620- downloadRetryInterval ,
621- 'linear' ,
616+ const downloadLinkSelector = this . bookmarkImportSelectorSettings . downloadLink ?? `a[href*="&i=0&user="]` ;
617+ const downloadButton = /** @type {HTMLAnchorElement|null } */ (
618+ await this . runWithRetry ( ( ) => document . querySelector ( downloadLinkSelector ) , 5 , 1000 , 'linear' )
622619 ) ;
620+ if ( downloadButton == null ) {
621+ // If there was no download link, it was likely a 404
622+ // so we reload the page to try again
623+ window . location . reload ( ) ;
624+ }
623625
624- const downloadURL = `${ TAKEOUT_DOWNLOAD_URL_BASE } ?j=${ this . #exportId} &i=0&user=${ userId } ` ;
625-
626- // Sleep before downloading to ensure the download link is available
627- const downloadNavigationDelayMs = this . getFeatureSetting ( 'downloadNavigationDelayMs' ) ?? 2000 ;
628- await new Promise ( ( resolve ) => setTimeout ( resolve , downloadNavigationDelayMs ) ) ;
629-
630- window . location . href = downloadURL ;
626+ downloadButton ?. click ( ) ;
631627 }
632628
633629 /**
634630 * Here we ignore the action and return a default retry config
635631 * as for now the retry doesn't need to be per action.
636632 */
637633 retryConfigFor ( _ ) {
634+ const { interval, maxAttempts } = this . defaultRetrySettings ;
638635 return {
639- interval : { ms : 1000 } ,
640- maxAttempts : 30 ,
636+ interval : { ms : interval } ,
637+ maxAttempts,
641638 } ;
642639 }
643640
@@ -660,14 +657,17 @@ export default class AutofillImport extends ActionExecutorBase {
660657 async handleBookmarkImportPath ( pathname ) {
661658 if ( pathname === '/' && ! this . #isBookmarkModalVisible) {
662659 for ( const action of this . bookmarkImportActionSettings ) {
663- // Before clicking on the manage button, we need to store the export id
664- if ( action . id === 'manage-button-click' ) {
665- await this . storeExportId ( ) ;
666- }
667-
668660 await this . patchMessagingAndProcessAction ( action ) ;
669661 }
662+
663+ // Parse the export id from the page and then navigate to the 'manage' page
664+ const exportId = await this . getExportId ( ) ;
665+ window . location . href = `${ MANAGE_ARCHIVE_DEFAULT_BASE } /${ exportId } ` ;
666+ } else if ( pathname . startsWith ( MANAGE_ARCHIVE_DEFAULT_BASE ) ) {
667+ // If we're on the 'manage' page, we can download the data
670668 await this . downloadData ( ) ;
669+ } else {
670+ // Unhandled path, we bail out
671671 }
672672 }
673673
@@ -681,11 +681,13 @@ export default class AutofillImport extends ActionExecutorBase {
681681 findExportId ( ) {
682682 const panels = document . querySelectorAll ( this . bookmarkImportSelectorSettings . tabPanel ) ;
683683 const exportPanel = panels [ panels . length - 1 ] ;
684- return exportPanel . querySelector ( 'div[data-archive-id]' ) ?. getAttribute ( 'data-archive-id' ) ;
684+ const dataArchiveIdSelector = this . bookmarkImportSelectorSettings . dataArchiveId ?? `div[data-archive-id]` ;
685+ return exportPanel . querySelector ( dataArchiveIdSelector ) ?. getAttribute ( 'data-archive-id' ) ;
685686 }
686687
687- async storeExportId ( ) {
688- this . #exportId = await this . runWithRetry ( ( ) => this . findExportId ( ) , 30 , 1000 , 'linear' ) ;
688+ async getExportId ( ) {
689+ const { maxAttempts, interval } = this . defaultRetrySettings ;
690+ return await this . runWithRetry ( ( ) => this . findExportId ( ) , maxAttempts , interval , 'linear' ) ;
689691 }
690692
691693 urlChanged ( ) {
0 commit comments