@@ -58,6 +58,7 @@ interface IStoredWebExtension {
58
58
readonly identifier : IExtensionIdentifier ;
59
59
readonly version : string ;
60
60
readonly location : UriComponents ;
61
+ readonly manifest ?: string ;
61
62
readonly readmeUri ?: UriComponents ;
62
63
readonly changelogUri ?: UriComponents ;
63
64
// deprecated in favor of packageNLSUris & fallbackPackageNLSUri
@@ -71,6 +72,7 @@ interface IWebExtension {
71
72
identifier : IExtensionIdentifier ;
72
73
version : string ;
73
74
location : URI ;
75
+ manifest ?: IExtensionManifest ;
74
76
readmeUri ?: URI ;
75
77
changelogUri ?: URI ;
76
78
// deprecated in favor of packageNLSUris & fallbackPackageNLSUri
@@ -425,16 +427,12 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
425
427
}
426
428
427
429
async scanExtensionManifest ( extensionLocation : URI ) : Promise < IExtensionManifest | null > {
428
- const packageJSONUri = joinPath ( extensionLocation , 'package.json' ) ;
429
430
try {
430
- const content = await this . extensionResourceLoaderService . readExtensionResource ( packageJSONUri ) ;
431
- if ( content ) {
432
- return JSON . parse ( content ) ;
433
- }
431
+ return await this . getExtensionManifest ( extensionLocation ) ;
434
432
} catch ( error ) {
435
- this . logService . warn ( `Error while fetching package.json from ${ packageJSONUri . toString ( ) } ` , getErrorMessage ( error ) ) ;
433
+ this . logService . warn ( `Error while fetching manifest from ${ extensionLocation . toString ( ) } ` , getErrorMessage ( error ) ) ;
434
+ return null ;
436
435
}
437
- return null ;
438
436
}
439
437
440
438
async addExtensionFromGallery ( galleryExtension : IGalleryExtension , metadata : Metadata , profileLocation : URI ) : Promise < IScannedExtension > {
@@ -593,18 +591,13 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
593
591
}
594
592
595
593
private async toWebExtension ( extensionLocation : URI , identifier ?: IExtensionIdentifier , packageNLSUris ?: Map < string , URI > , bundleNLSUris ?: Map < string , URI > , fallbackPackageNLSUri ?: URI | null , readmeUri ?: URI , changelogUri ?: URI , metadata ?: Metadata ) : Promise < IWebExtension > {
596
- let packageJSONContent ;
594
+ let manifest : IExtensionManifest ;
597
595
try {
598
- packageJSONContent = await this . extensionResourceLoaderService . readExtensionResource ( joinPath ( extensionLocation , 'package.json' ) ) ;
596
+ manifest = await this . getExtensionManifest ( extensionLocation ) ;
599
597
} catch ( error ) {
600
- throw new Error ( `Cannot find the package.json from the location '${ extensionLocation . toString ( ) } '. ${ getErrorMessage ( error ) } ` ) ;
598
+ throw new Error ( `Error while fetching manifest from the location '${ extensionLocation . toString ( ) } '. ${ getErrorMessage ( error ) } ` ) ;
601
599
}
602
600
603
- if ( ! packageJSONContent ) {
604
- throw new Error ( `Error while fetching package.json for extension '${ extensionLocation . toString ( ) } '. Server returned no content` ) ;
605
- }
606
-
607
- const manifest = JSON . parse ( packageJSONContent ) ;
608
601
if ( ! this . extensionManifestPropertiesService . canExecuteOnWeb ( manifest ) ) {
609
602
throw new Error ( localize ( 'not a web extension' , "Cannot add '{0}' because this extension is not a web extension." , manifest . displayName || manifest . name ) ) ;
610
603
}
@@ -618,7 +611,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
618
611
}
619
612
}
620
613
621
- if ( bundleNLSUris === undefined ) {
614
+ if ( bundleNLSUris === undefined && manifest . browser ) {
622
615
const englishStringsUri = joinPath (
623
616
this . uriIdentityService . extUri . dirname ( joinPath ( extensionLocation , manifest . browser ) ) ,
624
617
'nls.metadata.json'
@@ -637,6 +630,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
637
630
identifier : { id : getGalleryExtensionId ( manifest . publisher , manifest . name ) , uuid : identifier ?. uuid } ,
638
631
version : manifest . version ,
639
632
location : extensionLocation ,
633
+ manifest,
640
634
readmeUri,
641
635
changelogUri,
642
636
packageNLSUris,
@@ -647,25 +641,14 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
647
641
}
648
642
649
643
private async toScannedExtension ( webExtension : IWebExtension , isBuiltin : boolean , type : ExtensionType = ExtensionType . User ) : Promise < IScannedExtension > {
650
- const url = joinPath ( webExtension . location , 'package.json' ) ;
651
-
652
644
const validations : [ Severity , string ] [ ] = [ ] ;
653
- let content : string | undefined ;
654
- try {
655
- content = await this . extensionResourceLoaderService . readExtensionResource ( url ) ;
656
- if ( ! content ) {
657
- validations . push ( [ Severity . Error , `Error while fetching package.json from the location '${ url } '. Server returned no content` ] ) ;
658
- }
659
- } catch ( error ) {
660
- validations . push ( [ Severity . Error , `Error while fetching package.json from the location '${ url } '. ${ getErrorMessage ( error ) } ` ] ) ;
661
- }
645
+ let manifest : IExtensionManifest | undefined = webExtension . manifest ;
662
646
663
- let manifest : IExtensionManifest | null = null ;
664
- if ( content ) {
647
+ if ( ! manifest ) {
665
648
try {
666
- manifest = JSON . parse ( content ) ;
649
+ manifest = await this . getExtensionManifest ( webExtension . location ) ;
667
650
} catch ( error ) {
668
- validations . push ( [ Severity . Error , `Error while parsing package.json . ${ getErrorMessage ( error ) } ` ] ) ;
651
+ validations . push ( [ Severity . Error , `Error while fetching manifest from the location ' ${ webExtension . location } ' . ${ getErrorMessage ( error ) } ` ] ) ;
669
652
}
670
653
}
671
654
@@ -764,6 +747,12 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
764
747
return this . _migratePackageNLSUrisPromise ;
765
748
}
766
749
750
+ private async getExtensionManifest ( location : URI ) : Promise < IExtensionManifest > {
751
+ const url = joinPath ( location , 'package.json' ) ;
752
+ const content = await this . extensionResourceLoaderService . readExtensionResource ( url ) ;
753
+ return JSON . parse ( content ) ;
754
+ }
755
+
767
756
private async readInstalledExtensions ( profileLocation : URI ) : Promise < IWebExtension [ ] > {
768
757
if ( this . uriIdentityService . extUri . isEqual ( profileLocation , this . userDataProfilesService . defaultProfile . extensionsResource ) ) {
769
758
await this . migratePackageNLSUris ( ) ;
@@ -817,6 +806,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
817
806
identifier : e . identifier ,
818
807
version : e . version ,
819
808
location : URI . revive ( e . location ) ,
809
+ manifest : e . manifest ? JSON . parse ( e . manifest ) : undefined ,
820
810
readmeUri : URI . revive ( e . readmeUri ) ,
821
811
changelogUri : URI . revive ( e . changelogUri ) ,
822
812
packageNLSUris,
@@ -825,6 +815,13 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
825
815
metadata : e . metadata ,
826
816
} ) ;
827
817
}
818
+
819
+ try {
820
+ webExtensions = await this . migrateWebExtensions ( webExtensions , file ) ;
821
+ } catch ( error ) {
822
+ this . logService . error ( `Error while migrating scanned extensions in ${ file . toString ( ) } ` , getErrorMessage ( error ) ) ;
823
+ }
824
+
828
825
} catch ( error ) {
829
826
/* Ignore */
830
827
if ( ( < FileOperationError > error ) . fileOperationResult !== FileOperationResult . FILE_NOT_FOUND ) {
@@ -834,37 +831,59 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
834
831
835
832
// Update
836
833
if ( updateFn ) {
837
- webExtensions = updateFn ( webExtensions ) ;
838
- function toStringDictionary ( dictionary : Map < string , URI > | undefined ) : IStringDictionary < UriComponents > | undefined {
839
- if ( ! dictionary ) {
840
- return undefined ;
841
- }
842
- const result : IStringDictionary < UriComponents > = Object . create ( null ) ;
843
- dictionary . forEach ( ( value , key ) => result [ key ] = value . toJSON ( ) ) ;
844
- return result ;
845
- }
846
- const storedWebExtensions : IStoredWebExtension [ ] = webExtensions . map ( e => ( {
847
- identifier : e . identifier ,
848
- version : e . version ,
849
- location : e . location . toJSON ( ) ,
850
- readmeUri : e . readmeUri ?. toJSON ( ) ,
851
- changelogUri : e . changelogUri ?. toJSON ( ) ,
852
- packageNLSUris : toStringDictionary ( e . packageNLSUris ) ,
853
- fallbackPackageNLSUri : e . fallbackPackageNLSUri ?. toJSON ( ) ,
854
- metadata : e . metadata
855
- } ) ) ;
856
- await this . fileService . writeFile ( file , VSBuffer . fromString ( JSON . stringify ( storedWebExtensions ) ) ) ;
834
+ await this . storeWebExtensions ( webExtensions = updateFn ( webExtensions ) , file ) ;
857
835
}
858
836
859
837
return webExtensions ;
860
838
} ) ;
861
839
}
862
840
841
+ private async migrateWebExtensions ( webExtensions : IWebExtension [ ] , file : URI ) : Promise < IWebExtension [ ] > {
842
+ let update = false ;
843
+ webExtensions = await Promise . all ( webExtensions . map ( async webExtension => {
844
+ if ( ! webExtension . manifest ) {
845
+ try {
846
+ webExtension . manifest = await this . getExtensionManifest ( webExtension . location ) ;
847
+ update = true ;
848
+ } catch ( error ) {
849
+ this . logService . error ( `Error while updating manifest of an extension in ${ file . toString ( ) } ` , webExtension . identifier . id , getErrorMessage ( error ) ) ;
850
+ }
851
+ }
852
+ return webExtension ;
853
+ } ) ) ;
854
+ if ( update ) {
855
+ await this . storeWebExtensions ( webExtensions , file ) ;
856
+ }
857
+ return webExtensions ;
858
+ }
859
+
860
+ private async storeWebExtensions ( webExtensions : IWebExtension [ ] , file : URI ) : Promise < void > {
861
+ function toStringDictionary ( dictionary : Map < string , URI > | undefined ) : IStringDictionary < UriComponents > | undefined {
862
+ if ( ! dictionary ) {
863
+ return undefined ;
864
+ }
865
+ const result : IStringDictionary < UriComponents > = Object . create ( null ) ;
866
+ dictionary . forEach ( ( value , key ) => result [ key ] = value . toJSON ( ) ) ;
867
+ return result ;
868
+ }
869
+ const storedWebExtensions : IStoredWebExtension [ ] = webExtensions . map ( e => ( {
870
+ identifier : e . identifier ,
871
+ version : e . version ,
872
+ manifest : e . manifest ? JSON . stringify ( e . manifest ) : undefined ,
873
+ location : e . location . toJSON ( ) ,
874
+ readmeUri : e . readmeUri ?. toJSON ( ) ,
875
+ changelogUri : e . changelogUri ?. toJSON ( ) ,
876
+ packageNLSUris : toStringDictionary ( e . packageNLSUris ) ,
877
+ fallbackPackageNLSUri : e . fallbackPackageNLSUri ?. toJSON ( ) ,
878
+ metadata : e . metadata
879
+ } ) ) ;
880
+ await this . fileService . writeFile ( file , VSBuffer . fromString ( JSON . stringify ( storedWebExtensions ) ) ) ;
881
+ }
882
+
863
883
private getResourceAccessQueue ( file : URI ) : Queue < IWebExtension [ ] > {
864
884
let resourceQueue = this . resourcesAccessQueueMap . get ( file ) ;
865
885
if ( ! resourceQueue ) {
866
- resourceQueue = new Queue < IWebExtension [ ] > ( ) ;
867
- this . resourcesAccessQueueMap . set ( file , resourceQueue ) ;
886
+ this . resourcesAccessQueueMap . set ( file , resourceQueue = new Queue < IWebExtension [ ] > ( ) ) ;
868
887
}
869
888
return resourceQueue ;
870
889
}
0 commit comments