Type path in createFile as EncodedPathString

Bug: 1253323
Change-Id: Icc520f383e032a8a6be8cbaffded2d2896ac4d37
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3470238
Reviewed-by: Jack Franklin <[email protected]>
Reviewed-by: Eric Leese <[email protected]>
Commit-Queue: Kateryna Prokopenko <[email protected]>
diff --git a/front_end/core/common/ParsedURL.ts b/front_end/core/common/ParsedURL.ts
index 84017c4d..ecc6ecb 100644
--- a/front_end/core/common/ParsedURL.ts
+++ b/front_end/core/common/ParsedURL.ts
@@ -240,6 +240,11 @@
     return devToolsPath.substring(start, end) as DevToolsPathType;
   }
 
+  static prepend<DevToolsPathType extends BrandedPathString>(prefix: string, devToolsPath: DevToolsPathType):
+      DevToolsPathType {
+    return prefix + devToolsPath as DevToolsPathType;
+  }
+
   static concatenate<DevToolsPathType extends BrandedPathString>(
       devToolsPath: DevToolsPathType, ...appendage: string[]): DevToolsPathType {
     return devToolsPath.concat(...appendage) as DevToolsPathType;
@@ -249,6 +254,12 @@
     return devToolsPath.trim() as DevToolsPathType;
   }
 
+  static join<DevToolsPathType extends Platform.DevToolsPath.UrlString|Platform.DevToolsPath.RawPathString|
+                                       Platform.DevToolsPath.EncodedPathString>(
+      devToolsPaths: DevToolsPathType[], separator?: string): DevToolsPathType {
+    return devToolsPaths.join(separator) as DevToolsPathType;
+  }
+
   static urlWithoutHash(url: string): string {
     const hashIndex = url.indexOf('#');
     if (hashIndex !== -1) {
diff --git a/front_end/core/platform/DevToolsPath.ts b/front_end/core/platform/DevToolsPath.ts
index 412b29c..44e69b2 100644
--- a/front_end/core/platform/DevToolsPath.ts
+++ b/front_end/core/platform/DevToolsPath.ts
@@ -11,6 +11,7 @@
  * “file:///Hello%20World/file/js”
  */
 export type UrlString = string&UrlStringTag;
+export const EmptyUrlString = '' as UrlString;
 
 class RawPathStringTag {
   private rawPathTag: (string|undefined);
@@ -22,6 +23,7 @@
  * “/Hello World/file.js”
  */
 export type RawPathString = string&RawPathStringTag;
+export const EmptyRawPathString = '' as RawPathString;
 
 class EncodedPathStringTag {
   private encodedPathTag: (string|undefined);
@@ -32,3 +34,4 @@
  * “/Hello%20World/file.js”
  */
 export type EncodedPathString = string&EncodedPathStringTag;
+export const EmptyEncodedPathString = '' as EncodedPathString;
diff --git a/front_end/core/sdk/CSSRule.ts b/front_end/core/sdk/CSSRule.ts
index 2318cc7..fcb6ba2 100644
--- a/front_end/core/sdk/CSSRule.ts
+++ b/front_end/core/sdk/CSSRule.ts
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import type * as Platform from '../platform/platform.js';
 import * as Protocol from '../../generated/protocol.js';
 import * as TextUtils from '../../models/text_utils/text_utils.js';
+import * as Platform from '../platform/platform.js';
 
 import {CSSContainerQuery} from './CSSContainerQuery.js';
 import {CSSLayer} from './CSSLayer.js';
@@ -47,7 +47,7 @@
 
   resourceURL(): Platform.DevToolsPath.UrlString {
     if (!this.styleSheetId) {
-      return '' as Platform.DevToolsPath.UrlString;
+      return Platform.DevToolsPath.EmptyUrlString;
     }
     const styleSheetHeader = this.getStyleSheetHeader(this.styleSheetId);
     return styleSheetHeader.resourceURL();
diff --git a/front_end/core/sdk/DOMDebuggerModel.ts b/front_end/core/sdk/DOMDebuggerModel.ts
index e6fd8e1..dc6e5fa 100644
--- a/front_end/core/sdk/DOMDebuggerModel.ts
+++ b/front_end/core/sdk/DOMDebuggerModel.ts
@@ -4,7 +4,7 @@
 
 import * as Common from '../common/common.js';
 import * as i18n from '../i18n/i18n.js';
-import type * as Platform from '../platform/platform.js';
+import * as Platform from '../platform/platform.js';
 import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
 import * as Protocol from '../../generated/protocol.js';
 
@@ -534,7 +534,7 @@
     this.#originalHandlerInternal = originalHandler || handler;
     this.#locationInternal = location;
     const script = location.script();
-    this.#sourceURLInternal = script ? script.contentURL() : '' as Platform.DevToolsPath.UrlString;
+    this.#sourceURLInternal = script ? script.contentURL() : Platform.DevToolsPath.EmptyUrlString;
     this.#customRemoveFunction = customRemoveFunction;
     this.#originInternal = origin || EventListener.Origin.Raw;
   }
diff --git a/front_end/core/sdk/NetworkRequest.ts b/front_end/core/sdk/NetworkRequest.ts
index e8594de..b64ffae 100644
--- a/front_end/core/sdk/NetworkRequest.ts
+++ b/front_end/core/sdk/NetworkRequest.ts
@@ -379,7 +379,7 @@
       backendRequestId: Protocol.Network.RequestId, requestURL: Platform.DevToolsPath.UrlString,
       initiator?: Protocol.Network.Initiator): NetworkRequest {
     return new NetworkRequest(
-        backendRequestId, backendRequestId, requestURL, '' as Platform.DevToolsPath.UrlString, null, null,
+        backendRequestId, backendRequestId, requestURL, Platform.DevToolsPath.EmptyUrlString, null, null,
         initiator || null);
   }
 
diff --git a/front_end/core/sdk/SourceMap.ts b/front_end/core/sdk/SourceMap.ts
index 2ecb44b..8c00df2 100644
--- a/front_end/core/sdk/SourceMap.ts
+++ b/front_end/core/sdk/SourceMap.ts
@@ -360,7 +360,7 @@
 
   private parseSources(sourceMap: SourceMapV3): void {
     const sourcesList = [];
-    let sourceRoot = sourceMap.sourceRoot || '' as Platform.DevToolsPath.UrlString;
+    let sourceRoot = sourceMap.sourceRoot || Platform.DevToolsPath.EmptyUrlString;
     if (sourceRoot && !sourceRoot.endsWith('/')) {
       sourceRoot = Common.ParsedURL.ParsedURL.concatenate(sourceRoot, '/');
     }
diff --git a/front_end/core/sdk/Target.ts b/front_end/core/sdk/Target.ts
index 0879422..e380cef 100644
--- a/front_end/core/sdk/Target.ts
+++ b/front_end/core/sdk/Target.ts
@@ -4,7 +4,7 @@
 
 import * as Common from '../common/common.js';
 import * as Host from '../host/host.js';
-import type * as Platform from '../platform/platform.js';
+import * as Platform from '../platform/platform.js';
 import * as ProtocolClient from '../protocol_client/protocol_client.js';
 import type * as Protocol from '../../generated/protocol.js';
 import type {TargetManager} from './TargetManager.js';
@@ -32,7 +32,7 @@
     super(needsNodeJSPatching, parentTarget, sessionId, connection);
     this.#targetManagerInternal = targetManager;
     this.#nameInternal = name;
-    this.#inspectedURLInternal = '' as Platform.DevToolsPath.UrlString;
+    this.#inspectedURLInternal = Platform.DevToolsPath.EmptyUrlString;
     this.#inspectedURLName = '';
     this.#capabilitiesMask = 0;
     switch (type) {
diff --git a/front_end/models/bindings/ContentProviderBasedProject.ts b/front_end/models/bindings/ContentProviderBasedProject.ts
index 3374086..7452456 100644
--- a/front_end/models/bindings/ContentProviderBasedProject.ts
+++ b/front_end/models/bindings/ContentProviderBasedProject.ts
@@ -140,12 +140,13 @@
   excludeFolder(_path: string): void {
   }
 
-  canExcludeFolder(_path: string): boolean {
+  canExcludeFolder(_path: Platform.DevToolsPath.EncodedPathString): boolean {
     return false;
   }
 
-  async createFile(_path: string, _name: string|null, _content: string, _isBase64?: boolean):
-      Promise<Workspace.UISourceCode.UISourceCode|null> {
+  async createFile(
+      _path: Platform.DevToolsPath.EncodedPathString, _name: string|null, _content: string,
+      _isBase64?: boolean): Promise<Workspace.UISourceCode.UISourceCode|null> {
     return null;
   }
 
diff --git a/front_end/models/persistence/EditFileSystemView.ts b/front_end/models/persistence/EditFileSystemView.ts
index 38da676..f8c9718 100644
--- a/front_end/models/persistence/EditFileSystemView.ts
+++ b/front_end/models/persistence/EditFileSystemView.ts
@@ -30,6 +30,7 @@
 
 import * as Common from '../../core/common/common.js';
 import * as i18n from '../../core/i18n/i18n.js';
+import type * as Platform from '../../core/platform/platform.js';
 import * as UI from '../../ui/legacy/legacy.js';
 
 import editFileSystemViewStyles from './editFileSystemView.css.js';
@@ -152,7 +153,8 @@
     if (!isNew) {
       this.getFileSystem().removeExcludedFolder(item);
     }
-    this.getFileSystem().addExcludedFolder(this.normalizePrefix(editor.control('pathPrefix').value));
+    this.getFileSystem().addExcludedFolder(
+        this.normalizePrefix(editor.control('pathPrefix').value) as Platform.DevToolsPath.EncodedPathString);
     this.muteUpdate = false;
     this.update();
   }
diff --git a/front_end/models/persistence/FileSystemWorkspaceBinding.ts b/front_end/models/persistence/FileSystemWorkspaceBinding.ts
index f07dcf5..009b123 100644
--- a/front_end/models/persistence/FileSystemWorkspaceBinding.ts
+++ b/front_end/models/persistence/FileSystemWorkspaceBinding.ts
@@ -28,6 +28,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// TODO(crbug.com/1253323): Cast to Branded Types will be removed from this file when migration to branded types is complete.
+
 import * as Common from '../../core/common/common.js';
 import * as Platform from '../../core/platform/platform.js';
 import * as TextUtils from '../text_utils/text_utils.js';
@@ -200,7 +202,8 @@
 
   private filePathForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode):
       Platform.DevToolsPath.EncodedPathString {
-    return uiSourceCode.url().substring(this.fileSystemPathInternal.length) as Platform.DevToolsPath.EncodedPathString;
+    return Common.ParsedURL.ParsedURL.sliceUrlToEncodedPathString(
+        uiSourceCode.url(), this.fileSystemPathInternal.length);
   }
 
   isServiceProject(): boolean {
@@ -339,12 +342,13 @@
   }
 
   excludeFolder(url: string): void {
-    let relativeFolder = url.substring(this.fileSystemBaseURL.length);
+    let relativeFolder = Common.ParsedURL.ParsedURL.sliceUrlToEncodedPathString(
+        url as Platform.DevToolsPath.UrlString, this.fileSystemBaseURL.length);
     if (!relativeFolder.startsWith('/')) {
-      relativeFolder = '/' + relativeFolder;
+      relativeFolder = Common.ParsedURL.ParsedURL.prepend('/', relativeFolder);
     }
     if (!relativeFolder.endsWith('/')) {
-      relativeFolder += '/';
+      relativeFolder = Common.ParsedURL.ParsedURL.concatenate(relativeFolder, '/');
     }
     this.fileSystemInternal.addExcludedFolder(relativeFolder);
 
@@ -357,7 +361,7 @@
     }
   }
 
-  canExcludeFolder(path: string): boolean {
+  canExcludeFolder(path: Platform.DevToolsPath.EncodedPathString): boolean {
     return this.fileSystemInternal.canExcludeFolder(path);
   }
 
@@ -365,8 +369,9 @@
     return true;
   }
 
-  async createFile(path: string, name: Platform.DevToolsPath.RawPathString|null, content: string, isBase64?: boolean):
-      Promise<Workspace.UISourceCode.UISourceCode|null> {
+  async createFile(
+      path: Platform.DevToolsPath.EncodedPathString, name: Platform.DevToolsPath.RawPathString|null, content: string,
+      isBase64?: boolean): Promise<Workspace.UISourceCode.UISourceCode|null> {
     const guardFileName = this.fileSystemPathInternal + path + (!path.endsWith('/') ? '/' : '') + name;
     this.creatingFilesGuard.add(guardFileName);
     const filePath = await this.fileSystemInternal.createFile(path, name);
@@ -392,7 +397,7 @@
     this.fileSystemWorkspaceBinding.isolatedFileSystemManager.removeFileSystem(this.fileSystemInternal);
   }
 
-  private addFile(filePath: string): Workspace.UISourceCode.UISourceCode {
+  private addFile(filePath: Platform.DevToolsPath.EncodedPathString): Workspace.UISourceCode.UISourceCode {
     const contentType = this.fileSystemInternal.contentType(filePath);
     const uiSourceCode = this.createUISourceCode(this.fileSystemBaseURL + filePath, contentType);
     this.addUISourceCode(uiSourceCode);
diff --git a/front_end/models/persistence/IsolatedFileSystem.ts b/front_end/models/persistence/IsolatedFileSystem.ts
index 2388d7e..c449d69 100644
--- a/front_end/models/persistence/IsolatedFileSystem.ts
+++ b/front_end/models/persistence/IsolatedFileSystem.ts
@@ -70,17 +70,19 @@
 const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
 export class IsolatedFileSystem extends PlatformFileSystem {
   private readonly manager: IsolatedFileSystemManager;
-  private readonly embedderPathInternal: string;
+  private readonly embedderPathInternal: Platform.DevToolsPath.RawPathString;
   private readonly domFileSystem: FileSystem;
-  private readonly excludedFoldersSetting: Common.Settings.Setting<{[path: string]: string[]}>;
-  private excludedFoldersInternal: Set<string>;
-  private readonly excludedEmbedderFolders: string[];
+  private readonly excludedFoldersSetting:
+      Common.Settings.Setting<{[path: Platform.DevToolsPath.UrlString]: Platform.DevToolsPath.EncodedPathString[]}>;
+  private excludedFoldersInternal: Set<Platform.DevToolsPath.EncodedPathString>;
+  private readonly excludedEmbedderFolders: Platform.DevToolsPath.RawPathString[];
   private readonly initialFilePathsInternal: Set<Platform.DevToolsPath.EncodedPathString>;
   private readonly initialGitFoldersInternal: Set<Platform.DevToolsPath.EncodedPathString>;
-  private readonly fileLocks: Map<string, Promise<void>>;
+  private readonly fileLocks: Map<Platform.DevToolsPath.EncodedPathString, Promise<void>>;
 
   constructor(
-      manager: IsolatedFileSystemManager, path: string, embedderPath: string, domFileSystem: FileSystem, type: string) {
+      manager: IsolatedFileSystemManager, path: Platform.DevToolsPath.UrlString,
+      embedderPath: Platform.DevToolsPath.RawPathString, domFileSystem: FileSystem, type: string) {
     super(path, type);
     this.manager = manager;
     this.embedderPathInternal = embedderPath;
@@ -96,7 +98,8 @@
   }
 
   static async create(
-      manager: IsolatedFileSystemManager, path: string, embedderPath: string, type: string, name: string,
+      manager: IsolatedFileSystemManager, path: Platform.DevToolsPath.UrlString,
+      embedderPath: Platform.DevToolsPath.RawPathString, type: string, name: string,
       rootURL: string): Promise<IsolatedFileSystem|null> {
     const domFileSystem = Host.InspectorFrontendHost.InspectorFrontendHostInstance.isolatedFileSystem(name, rootURL);
     if (!domFileSystem) {
@@ -115,18 +118,20 @@
     return i18nString(UIStrings.fileSystemErrorS, {PH1: error.message});
   }
 
-  private serializedFileOperation<T>(path: string, operation: () => Promise<T>): Promise<T> {
+  private serializedFileOperation<T>(path: Platform.DevToolsPath.EncodedPathString, operation: () => Promise<T>):
+      Promise<T> {
     const promise = Promise.resolve(this.fileLocks.get(path)).then(() => operation.call(null));
     this.fileLocks.set(path, promise as unknown as Promise<void>);
     return promise;
   }
 
-  getMetadata(path: string): Promise<Metadata|null> {
+  getMetadata(path: Platform.DevToolsPath.EncodedPathString): Promise<Metadata|null> {
     let fulfill: (arg0: Metadata|null) => void;
     const promise = new Promise<Metadata|null>(f => {
       fulfill = f;
     });
-    this.domFileSystem.root.getFile(decodeURIComponent(path), undefined, fileEntryLoaded, errorHandler);
+    this.domFileSystem.root.getFile(
+        Common.ParsedURL.ParsedURL.encodedPathToRawPathString(path), undefined, fileEntryLoaded, errorHandler);
     return promise;
 
     function fileEntryLoaded(entry: FileEntry): void {
@@ -148,7 +153,7 @@
     return [...this.initialGitFoldersInternal];
   }
 
-  embedderPath(): string {
+  embedderPath(): Platform.DevToolsPath.RawPathString {
     return this.embedderPathInternal;
   }
 
@@ -156,13 +161,14 @@
     return new Promise(fulfill => {
       let pendingRequests = 1;
       const boundInnerCallback = innerCallback.bind(this);
-      this.requestEntries('', boundInnerCallback);
+      this.requestEntries(Platform.DevToolsPath.EmptyRawPathString, boundInnerCallback);
 
       function innerCallback(this: IsolatedFileSystem, entries: FileEntry[]): void {
         for (let i = 0; i < entries.length; ++i) {
           const entry = entries[i];
           if (!entry.isDirectory) {
-            if (this.isFileExcluded(entry.fullPath)) {
+            if (this.isFileExcluded(Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(
+                    entry.fullPath as Platform.DevToolsPath.RawPathString))) {
               continue;
             }
             this.initialFilePathsInternal.add(Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(
@@ -174,14 +180,20 @@
                   entry.fullPath as Platform.DevToolsPath.RawPathString, 1, lastSlash);
               this.initialGitFoldersInternal.add(Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(parentFolder));
             }
-            if (this.isFileExcluded(entry.fullPath + '/')) {
-              const url = Common.ParsedURL.ParsedURL.concatenate(this.path(), entry.fullPath);
+            if (this.isFileExcluded(Common.ParsedURL.ParsedURL.concatenate(
+                    Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(
+                        entry.fullPath as Platform.DevToolsPath.RawPathString),
+                    '/'))) {
+              const url = Common.ParsedURL.ParsedURL.concatenate(
+                  this.path(),
+                  Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(
+                      entry.fullPath as Platform.DevToolsPath.RawPathString));
               this.excludedEmbedderFolders.push(
                   Common.ParsedURL.ParsedURL.urlToRawPathString(url, Host.Platform.isWin()));
               continue;
             }
             ++pendingRequests;
-            this.requestEntries(entry.fullPath, boundInnerCallback);
+            this.requestEntries(entry.fullPath as Platform.DevToolsPath.RawPathString, boundInnerCallback);
           }
         }
         if ((--pendingRequests === 0)) {
@@ -191,7 +203,7 @@
     });
   }
 
-  private async createFoldersIfNotExist(folderPath: string): Promise<DirectoryEntry|null> {
+  private async createFoldersIfNotExist(folderPath: Platform.DevToolsPath.RawPathString): Promise<DirectoryEntry|null> {
     // Fast-path. If parent directory already exists we return it immidiatly.
     let dirEntry = await new Promise<DirectoryEntry|null>(
         resolve => this.domFileSystem.root.getDirectory(folderPath, undefined, resolve, () => resolve(null)));
@@ -220,8 +232,9 @@
     });
   }
 
-  async createFile(path: string, name: Platform.DevToolsPath.RawPathString|null): Promise<string|null> {
-    const dirEntry = await this.createFoldersIfNotExist(decodeURIComponent(path));
+  async createFile(path: Platform.DevToolsPath.EncodedPathString, name: Platform.DevToolsPath.RawPathString|null):
+      Promise<Platform.DevToolsPath.EncodedPathString|null> {
+    const dirEntry = await this.createFoldersIfNotExist(Common.ParsedURL.ParsedURL.encodedPathToRawPathString(path));
     if (!dirEntry) {
       return null;
     }
@@ -262,7 +275,8 @@
       resolveCallback = resolve;
     });
     this.domFileSystem.root.getFile(
-        decodeURIComponent(path), undefined, fileEntryLoaded.bind(this), errorHandler.bind(this));
+        Common.ParsedURL.ParsedURL.encodedPathToRawPathString(path), undefined, fileEntryLoaded.bind(this),
+        errorHandler.bind(this));
     return promise;
 
     function fileEntryLoaded(this: IsolatedFileSystem, fileEntry: FileEntry): void {
@@ -285,7 +299,7 @@
 
   requestFileBlob(path: Platform.DevToolsPath.EncodedPathString): Promise<Blob|null> {
     return new Promise(resolve => {
-      this.domFileSystem.root.getFile(decodeURIComponent(path), undefined, entry => {
+      this.domFileSystem.root.getFile(Common.ParsedURL.ParsedURL.encodedPathToRawPathString(path), undefined, entry => {
         entry.file(resolve, errorHandler.bind(this));
       }, errorHandler.bind(this));
 
@@ -357,7 +371,8 @@
         callback = x;
       });
       this.domFileSystem.root.getFile(
-          decodeURIComponent(path), {create: true}, fileEntryLoaded.bind(this), errorHandler.bind(this));
+          Common.ParsedURL.ParsedURL.encodedPathToRawPathString(path), {create: true}, fileEntryLoaded.bind(this),
+          errorHandler.bind(this));
       return promise;
     };
 
@@ -395,7 +410,7 @@
   renameFile(
       path: Platform.DevToolsPath.EncodedPathString, newName: Platform.DevToolsPath.RawPathString,
       callback: (arg0: boolean, arg1?: string|undefined) => void): void {
-    newName = newName ? newName.trim() as Platform.DevToolsPath.RawPathString : newName;
+    newName = newName ? Common.ParsedURL.ParsedURL.trim(newName) : newName;
     if (!newName || newName.indexOf('/') !== -1) {
       callback(false);
       return;
@@ -404,7 +419,8 @@
     let dirEntry: DirectoryEntry;
 
     this.domFileSystem.root.getFile(
-        decodeURIComponent(path), undefined, fileEntryLoaded.bind(this), errorHandler.bind(this));
+        Common.ParsedURL.ParsedURL.encodedPathToRawPathString(path), undefined, fileEntryLoaded.bind(this),
+        errorHandler.bind(this));
 
     function fileEntryLoaded(this: IsolatedFileSystem, entry: FileEntry): void {
       if (entry.name === newName) {
@@ -470,8 +486,8 @@
     }
   }
 
-  private requestEntries(path: string, callback: (arg0: Array<FileEntry>) => void): void {
-    this.domFileSystem.root.getDirectory(decodeURIComponent(path), undefined, innerCallback.bind(this), errorHandler);
+  private requestEntries(path: Platform.DevToolsPath.RawPathString, callback: (arg0: Array<FileEntry>) => void): void {
+    this.domFileSystem.root.getDirectory(path, undefined, innerCallback.bind(this), errorHandler);
 
     function innerCallback(this: IsolatedFileSystem, dirEntry: DirectoryEntry): void {
       this.readDirectory(dirEntry, callback);
@@ -490,13 +506,13 @@
     this.excludedFoldersSetting.set(settingValue);
   }
 
-  addExcludedFolder(path: string): void {
+  addExcludedFolder(path: Platform.DevToolsPath.EncodedPathString): void {
     this.excludedFoldersInternal.add(path);
     this.saveExcludedFolders();
     this.manager.dispatchEventToListeners(Events.ExcludedFolderAdded, path);
   }
 
-  removeExcludedFolder(path: string): void {
+  removeExcludedFolder(path: Platform.DevToolsPath.EncodedPathString): void {
     this.excludedFoldersInternal.delete(path);
     this.saveExcludedFolders();
     this.manager.dispatchEventToListeners(Events.ExcludedFolderRemoved, path);
@@ -508,12 +524,12 @@
     this.excludedFoldersSetting.set(settingValue);
   }
 
-  isFileExcluded(folderPath: string): boolean {
+  isFileExcluded(folderPath: Platform.DevToolsPath.EncodedPathString): boolean {
     if (this.excludedFoldersInternal.has(folderPath)) {
       return true;
     }
     const regex = (this.manager.workspaceFolderExcludePatternSetting() as Common.Settings.RegExpSetting).asRegExp();
-    return Boolean(regex && regex.test(folderPath));
+    return Boolean(regex && regex.test(Common.ParsedURL.ParsedURL.encodedPathToRawPathString(folderPath)));
   }
 
   excludedFolders(): Set<string> {
@@ -544,10 +560,11 @@
     return Common.ResourceType.ResourceType.mimeFromURL(path) || 'text/plain';
   }
 
-  canExcludeFolder(path: string): boolean {
+  canExcludeFolder(path: Platform.DevToolsPath.EncodedPathString): boolean {
     return Boolean(path) && this.type() !== 'overrides';
   }
 
+  // path not typed as Branded Types as here we are interested in extention only
   contentType(path: string): Common.ResourceType.ResourceType {
     const extension = Common.ParsedURL.ParsedURL.extractExtension(path);
     if (STYLE_SHEET_EXTENSIONS.has(extension)) {
diff --git a/front_end/models/persistence/IsolatedFileSystemManager.ts b/front_end/models/persistence/IsolatedFileSystemManager.ts
index 92738b4..c04298a 100644
--- a/front_end/models/persistence/IsolatedFileSystemManager.ts
+++ b/front_end/models/persistence/IsolatedFileSystemManager.ts
@@ -248,7 +248,8 @@
         const filePath = Common.ParsedURL.ParsedURL.rawPathToUrlString(embedderPath);
         for (const fileSystemPath of this.fileSystemsInternal.keys()) {
           const fileSystem = this.fileSystemsInternal.get(fileSystemPath);
-          if (fileSystem && fileSystem.isFileExcluded(embedderPath)) {
+          if (fileSystem &&
+              fileSystem.isFileExcluded(Common.ParsedURL.ParsedURL.rawPathToEncodedPathString(embedderPath))) {
             continue;
           }
           const pathPrefix = fileSystemPath.endsWith('/') ? fileSystemPath : fileSystemPath + '/';
@@ -348,8 +349,8 @@
   [Events.FileSystemAdded]: PlatformFileSystem,
   [Events.FileSystemRemoved]: PlatformFileSystem,
   [Events.FileSystemFilesChanged]: FilesChangedData,
-  [Events.ExcludedFolderAdded]: string,
-  [Events.ExcludedFolderRemoved]: string,
+  [Events.ExcludedFolderAdded]: Platform.DevToolsPath.EncodedPathString,
+  [Events.ExcludedFolderRemoved]: Platform.DevToolsPath.EncodedPathString,
 };
 
 let lastRequestId = 0;
diff --git a/front_end/models/persistence/NetworkPersistenceManager.ts b/front_end/models/persistence/NetworkPersistenceManager.ts
index e50817f..08f3a95 100644
--- a/front_end/models/persistence/NetworkPersistenceManager.ts
+++ b/front_end/models/persistence/NetworkPersistenceManager.ts
@@ -185,9 +185,9 @@
     PersistenceImpl.instance().refreshAutomapping();
   }
 
-  private encodedPathFromUrl(url: string): string {
+  private encodedPathFromUrl(url: Platform.DevToolsPath.UrlString): Platform.DevToolsPath.EncodedPathString {
     if (!this.activeInternal || !this.projectInternal) {
-      return '';
+      return Platform.DevToolsPath.EmptyEncodedPathString;
     }
     let urlPath = Common.ParsedURL.ParsedURL.urlWithoutHash(url.replace(/^https?:\/\//, ''));
     if (urlPath.endsWith('/') && urlPath.indexOf('?') === -1) {
@@ -208,7 +208,7 @@
         shortFileName + Platform.StringUtilities.hashCode(encodedPath).toString(16) + extensionPart,
       ];
     }
-    return encodedPathParts.join('/');
+    return Common.ParsedURL.ParsedURL.join(encodedPathParts as Platform.DevToolsPath.EncodedPathString[], '/');
 
     function encodeUrlPathToLocalPathParts(urlPath: string): string[] {
       const encodedParts = [];
@@ -310,7 +310,7 @@
     const encoded = await uiSourceCode.contentEncoded();
     const lastIndexOfSlash = encodedPath.lastIndexOf('/');
     const encodedFileName = encodedPath.substr(lastIndexOfSlash + 1);
-    encodedPath = encodedPath.substr(0, lastIndexOfSlash);
+    encodedPath = Common.ParsedURL.ParsedURL.substr(encodedPath, 0, lastIndexOfSlash);
     if (this.projectInternal) {
       await this.projectInternal.createFile(encodedPath, encodedFileName, content, encoded);
     }
@@ -555,7 +555,8 @@
 
   handleHeaderInterception(interceptedRequest: SDK.NetworkManager.InterceptedRequest): Protocol.Fetch.HeaderEntry[] {
     let result: Protocol.Fetch.HeaderEntry[] = interceptedRequest.responseHeaders || [];
-    const urlSegments = this.encodedPathFromUrl(interceptedRequest.request.url).split('/');
+    const urlSegments =
+        this.encodedPathFromUrl(interceptedRequest.request.url as Platform.DevToolsPath.UrlString).split('/');
     // Traverse the hierarchy of overrides from the most general to the most
     // specific. Check with empty string first to match overrides applying to
     // all domains.
diff --git a/front_end/models/persistence/PlatformFileSystem.ts b/front_end/models/persistence/PlatformFileSystem.ts
index 79c12c3..24fea4d 100644
--- a/front_end/models/persistence/PlatformFileSystem.ts
+++ b/front_end/models/persistence/PlatformFileSystem.ts
@@ -23,7 +23,7 @@
     this.typeInternal = type;
   }
 
-  getMetadata(_path: string): Promise<{modificationTime: Date, size: number}|null> {
+  getMetadata(_path: Platform.DevToolsPath.EncodedPathString): Promise<{modificationTime: Date, size: number}|null> {
     return Promise.resolve(null);
   }
 
@@ -49,7 +49,8 @@
     return this.typeInternal;
   }
 
-  async createFile(_path: string, _name: Platform.DevToolsPath.RawPathString|null): Promise<string|null> {
+  async createFile(_path: Platform.DevToolsPath.EncodedPathString, _name: Platform.DevToolsPath.RawPathString|null):
+      Promise<Platform.DevToolsPath.EncodedPathString|null> {
     return Promise.resolve(null);
   }
 
@@ -76,7 +77,7 @@
     callback(false);
   }
 
-  addExcludedFolder(_path: string): void {
+  addExcludedFolder(_path: Platform.DevToolsPath.EncodedPathString): void {
   }
 
   removeExcludedFolder(_path: string): void {
@@ -85,7 +86,7 @@
   fileSystemRemoved(): void {
   }
 
-  isFileExcluded(_folderPath: string): boolean {
+  isFileExcluded(_folderPath: Platform.DevToolsPath.EncodedPathString): boolean {
     return false;
   }
 
@@ -107,7 +108,7 @@
     throw new Error('Not implemented');
   }
 
-  canExcludeFolder(_path: string): boolean {
+  canExcludeFolder(_path: Platform.DevToolsPath.EncodedPathString): boolean {
     return false;
   }
 
diff --git a/front_end/models/workspace/UISourceCode.ts b/front_end/models/workspace/UISourceCode.ts
index 3e88e7c..d0ddfde 100644
--- a/front_end/models/workspace/UISourceCode.ts
+++ b/front_end/models/workspace/UISourceCode.ts
@@ -94,7 +94,7 @@
       }
     } else {
       this.originInternal = '';
-      this.parentURLInternal = '' as Platform.DevToolsPath.UrlString;
+      this.parentURLInternal = Platform.DevToolsPath.EmptyUrlString;
       this.nameInternal = url;
     }
 
diff --git a/front_end/models/workspace/WorkspaceImpl.ts b/front_end/models/workspace/WorkspaceImpl.ts
index cfde3d8..befec41 100644
--- a/front_end/models/workspace/WorkspaceImpl.ts
+++ b/front_end/models/workspace/WorkspaceImpl.ts
@@ -60,8 +60,9 @@
       uiSourceCode: UISourceCode, newName: Platform.DevToolsPath.RawPathString,
       callback: (arg0: boolean, arg1?: string, arg2?: string, arg3?: Common.ResourceType.ResourceType) => void): void;
   excludeFolder(path: string): void;
-  canExcludeFolder(path: string): boolean;
-  createFile(path: string, name: string|null, content: string, isBase64?: boolean): Promise<UISourceCode|null>;
+  canExcludeFolder(path: Platform.DevToolsPath.EncodedPathString): boolean;
+  createFile(path: Platform.DevToolsPath.EncodedPathString, name: string|null, content: string, isBase64?: boolean):
+      Promise<UISourceCode|null>;
   canCreateFile(): boolean;
   deleteFile(uiSourceCode: UISourceCode): void;
   remove(): void;
@@ -210,8 +211,10 @@
   abstract fullDisplayName(uiSourceCode: UISourceCode): string;
   abstract mimeType(uiSourceCode: UISourceCode): string;
   abstract canRename(): boolean;
-  abstract canExcludeFolder(path: string): boolean;
-  abstract createFile(path: string, name: string|null, content: string, isBase64?: boolean): Promise<UISourceCode|null>;
+  abstract canExcludeFolder(path: Platform.DevToolsPath.EncodedPathString): boolean;
+  abstract createFile(
+      path: Platform.DevToolsPath.EncodedPathString, name: string|null, content: string,
+      isBase64?: boolean): Promise<UISourceCode|null>;
   abstract canCreateFile(): boolean;
   abstract searchInFileContent(uiSourceCode: UISourceCode, query: string, caseSensitive: boolean, isRegex: boolean):
       Promise<TextUtils.ContentProvider.SearchMatch[]>;
diff --git a/front_end/panels/application/ServiceWorkerCacheViews.ts b/front_end/panels/application/ServiceWorkerCacheViews.ts
index 0b25307..9c5f6e2 100644
--- a/front_end/panels/application/ServiceWorkerCacheViews.ts
+++ b/front_end/panels/application/ServiceWorkerCacheViews.ts
@@ -382,7 +382,7 @@
   private createRequest(entry: Protocol.CacheStorage.DataEntry): SDK.NetworkRequest.NetworkRequest {
     const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest(
         'cache-storage-' + entry.requestURL, entry.requestURL as Platform.DevToolsPath.UrlString,
-        '' as Platform.DevToolsPath.UrlString, null);
+        Platform.DevToolsPath.EmptyUrlString, null);
     request.requestMethod = entry.requestMethod;
     request.setRequestHeaders(entry.requestHeaders);
     request.statusCode = entry.responseStatus;
diff --git a/front_end/panels/network/ResourceWebSocketFrameView.ts b/front_end/panels/network/ResourceWebSocketFrameView.ts
index 3d5ae0a..b88e455 100644
--- a/front_end/panels/network/ResourceWebSocketFrameView.ts
+++ b/front_end/panels/network/ResourceWebSocketFrameView.ts
@@ -462,8 +462,7 @@
     if (!this.binaryViewInternal) {
       if (this.dataTextInternal.length > 0) {
         this.binaryViewInternal = new BinaryResourceView(
-            this.dataTextInternal, /* url */ '' as Platform.DevToolsPath.UrlString,
-            Common.ResourceType.resourceTypes.WebSocket);
+            this.dataTextInternal, Platform.DevToolsPath.EmptyUrlString, Common.ResourceType.resourceTypes.WebSocket);
       }
     }
     return this.binaryViewInternal;
diff --git a/front_end/panels/snippets/ScriptSnippetFileSystem.ts b/front_end/panels/snippets/ScriptSnippetFileSystem.ts
index 7f8d400..46be0a6 100644
--- a/front_end/panels/snippets/ScriptSnippetFileSystem.ts
+++ b/front_end/panels/snippets/ScriptSnippetFileSystem.ts
@@ -51,7 +51,8 @@
     return savedSnippets.map(snippet => escapeSnippetName(snippet.name));
   }
 
-  async createFile(_path: string, _name: Platform.DevToolsPath.RawPathString|null): Promise<string|null> {
+  async createFile(_path: Platform.DevToolsPath.EncodedPathString, _name: Platform.DevToolsPath.RawPathString|null):
+      Promise<Platform.DevToolsPath.EncodedPathString|null> {
     const nextId = this.lastSnippetIdentifierSetting.get() + 1;
     this.lastSnippetIdentifierSetting.set(nextId);
 
diff --git a/front_end/panels/sources/NavigatorView.ts b/front_end/panels/sources/NavigatorView.ts
index e39ecd2..3155183 100644
--- a/front_end/panels/sources/NavigatorView.ts
+++ b/front_end/panels/sources/NavigatorView.ts
@@ -28,6 +28,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// TODO(crbug.com/1253323): Casts to Branded Types will be removed from this file when migration to branded types is complete.
+
 import * as Common from '../../core/common/common.js';
 import * as Host from '../../core/host/host.js';
 import * as i18n from '../../core/i18n/i18n.js';
@@ -843,7 +845,7 @@
   }
 
   handleFolderContextMenu(event: Event, node: NavigatorTreeNode): void {
-    const path = (node as NavigatorFolderTreeNode).folderPath || '';
+    const path = (node as NavigatorFolderTreeNode).folderPath || Platform.DevToolsPath.EmptyEncodedPathString;
     const project = (node as NavigatorFolderTreeNode).project || null;
 
     const contextMenu = new UI.ContextMenu.ContextMenu(event);
@@ -914,7 +916,7 @@
     if (uiSourceCodeToCopy) {
       content = (await uiSourceCodeToCopy.requestContent()).content || '';
     }
-    const uiSourceCode = await project.createFile(path, null, content);
+    const uiSourceCode = await project.createFile(path as Platform.DevToolsPath.EncodedPathString, null, content);
     if (!uiSourceCode) {
       return;
     }
@@ -1455,7 +1457,7 @@
 
 export class NavigatorFolderTreeNode extends NavigatorTreeNode {
   project: Workspace.Workspace.Project|null;
-  readonly folderPath: string;
+  readonly folderPath: Platform.DevToolsPath.EncodedPathString;
   title: string;
   treeElement!: NavigatorFolderTreeElement|null;
   constructor(
@@ -1463,7 +1465,7 @@
       folderPath: string, title: string) {
     super(navigatorView, id, type);
     this.project = project;
-    this.folderPath = folderPath;
+    this.folderPath = folderPath as Platform.DevToolsPath.EncodedPathString;
     this.title = title;
   }
 
diff --git a/front_end/panels/sources/SourcesNavigator.ts b/front_end/panels/sources/SourcesNavigator.ts
index 842d76c..ecf4d17 100644
--- a/front_end/panels/sources/SourcesNavigator.ts
+++ b/front_end/panels/sources/SourcesNavigator.ts
@@ -31,9 +31,9 @@
 import * as Common from '../../core/common/common.js';
 import * as Host from '../../core/host/host.js';
 import * as i18n from '../../core/i18n/i18n.js';
+import * as Platform from '../../core/platform/platform.js';
 import * as SDK from '../../core/sdk/sdk.js';
 import * as Persistence from '../../models/persistence/persistence.js';
-import type * as Platform from '../../core/platform/platform.js';
 import * as Workspace from '../../models/workspace/workspace.js';
 import * as UI from '../../ui/legacy/legacy.js';
 import * as Snippets from '../snippets/snippets.js';
@@ -406,7 +406,7 @@
     switch (actionId) {
       case 'sources.create-snippet':
         void Snippets.ScriptSnippetFileSystem.findSnippetsProject()
-            .createFile('', null, '')
+            .createFile(Platform.DevToolsPath.EmptyEncodedPathString, null, '')
             .then(uiSourceCode => Common.Revealer.reveal(uiSourceCode));
         return true;
       case 'sources.add-folder-to-workspace':
diff --git a/test/unittests/front_end/core/sdk/SourceMap_test.ts b/test/unittests/front_end/core/sdk/SourceMap_test.ts
index 41bc716..53824f6 100644
--- a/test/unittests/front_end/core/sdk/SourceMap_test.ts
+++ b/test/unittests/front_end/core/sdk/SourceMap_test.ts
@@ -5,7 +5,7 @@
 const {assert} = chai;
 
 import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
-import type * as Platform from '../../../../../front_end/core/platform/platform.js';
+import * as Platform from '../../../../../front_end/core/platform/platform.js';
 import {assertNotNullOrUndefined} from '../../../../../front_end/core/platform/platform.js';
 import {encodeSourceMap} from '../../helpers/SourceMapEncoder.js';
 import type * as Protocol from '../../../../../front_end/generated/protocol.js';
@@ -339,7 +339,7 @@
   });
 
   describe('source URL resolution', () => {
-    const noSourceRoot = '' as Platform.DevToolsPath.UrlString;
+    const noSourceRoot = Platform.DevToolsPath.EmptyUrlString;
     const absoluteSourceRootExample = 'http://example.com/src' as Platform.DevToolsPath.UrlString;
     const absoluteSourceRootFoo = 'http://foo.com/src' as Platform.DevToolsPath.UrlString;
     const relativeSourceRootSrc = 'src' as Platform.DevToolsPath.UrlString;
diff --git a/test/unittests/front_end/models/har/HARLog_test.ts b/test/unittests/front_end/models/har/HARLog_test.ts
index b91ba6d..e426306 100644
--- a/test/unittests/front_end/models/har/HARLog_test.ts
+++ b/test/unittests/front_end/models/har/HARLog_test.ts
@@ -5,7 +5,7 @@
 const {assert} = chai;
 
 import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
-import type * as Platform from '../../../../../front_end/core/platform/platform.js';
+import * as Platform from '../../../../../front_end/core/platform/platform.js';
 import type * as Protocol from '../../../../../front_end/generated/protocol.js';
 import * as HAR from '../../../../../front_end/models/har/har.js';
 
@@ -13,8 +13,7 @@
   it('blocked time when no response received is returned in milliseconds (crbug.com/1145177)', async () => {
     const requestId = 'r0' as Protocol.Network.RequestId;
     const request = SDK.NetworkRequest.NetworkRequest.create(
-        requestId, 'p0.com' as Platform.DevToolsPath.UrlString, '' as Platform.DevToolsPath.UrlString, null, null,
-        null);
+        requestId, 'p0.com' as Platform.DevToolsPath.UrlString, Platform.DevToolsPath.EmptyUrlString, null, null, null);
     const issueTime = new Date(2020, 1, 3).getTime() / 1000;
     request.setIssueTime(issueTime, issueTime);
     request.endTime = issueTime + 5;
diff --git a/test/unittests/front_end/models/har/HARWriter_test.ts b/test/unittests/front_end/models/har/HARWriter_test.ts
index 30dc482..fe9d881 100644
--- a/test/unittests/front_end/models/har/HARWriter_test.ts
+++ b/test/unittests/front_end/models/har/HARWriter_test.ts
@@ -8,13 +8,13 @@
 import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
 import * as UI from '../../../../../front_end/ui/legacy/legacy.js';
 import * as HAR from '../../../../../front_end/models/har/har.js';
-import type * as Platform from '../../../../../front_end/core/platform/platform.js';
+import * as Platform from '../../../../../front_end/core/platform/platform.js';
 import type * as Protocol from '../../../../../front_end/generated/protocol.js';
 
 const simulateRequestWithStartTime = (startTime: number): SDK.NetworkRequest.NetworkRequest => {
   const requestId = 'r0' as Protocol.Network.RequestId;
   const request = SDK.NetworkRequest.NetworkRequest.create(
-      requestId, 'p0.com' as Platform.DevToolsPath.UrlString, '' as Platform.DevToolsPath.UrlString, null, null, null);
+      requestId, 'p0.com' as Platform.DevToolsPath.UrlString, Platform.DevToolsPath.EmptyUrlString, null, null, null);
   request.setIssueTime(startTime, startTime);
   request.setContentDataProvider(() => Promise.resolve({error: null, content: '', encoded: false}));
   return request;
diff --git a/test/unittests/front_end/models/issues_manager/RelatedIssue_test.ts b/test/unittests/front_end/models/issues_manager/RelatedIssue_test.ts
index c89ab01..121aeb0 100644
--- a/test/unittests/front_end/models/issues_manager/RelatedIssue_test.ts
+++ b/test/unittests/front_end/models/issues_manager/RelatedIssue_test.ts
@@ -5,7 +5,7 @@
 const {assert} = chai;
 
 import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
-import type * as Platform from '../../../../../front_end/core/platform/platform.js';
+import * as Platform from '../../../../../front_end/core/platform/platform.js';
 import type * as Protocol from '../../../../../front_end/generated/protocol.js';
 import * as IssuesManager from '../../../../../front_end/models/issues_manager/issues_manager.js';
 import {StubIssue} from './StubIssue.js';
@@ -16,14 +16,14 @@
 
   it('should return no issues if no issues exist', () => {
     const request = SDK.NetworkRequest.NetworkRequest.create(
-        requestId1, '' as Platform.DevToolsPath.UrlString, '' as Platform.DevToolsPath.UrlString, null, null, null);
+        requestId1, Platform.DevToolsPath.EmptyUrlString, Platform.DevToolsPath.EmptyUrlString, null, null, null);
     assert.strictEqual(IssuesManager.RelatedIssue.issuesAssociatedWith([], request).length, 0);
   });
 
   it('should return no issues if issues dont affect any resources', () => {
     const issue = new StubIssue('code', [], []);
     const request = SDK.NetworkRequest.NetworkRequest.create(
-        requestId1, '' as Platform.DevToolsPath.UrlString, '' as Platform.DevToolsPath.UrlString, null, null, null);
+        requestId1, Platform.DevToolsPath.EmptyUrlString, Platform.DevToolsPath.EmptyUrlString, null, null, null);
 
     assert.strictEqual(IssuesManager.RelatedIssue.issuesAssociatedWith([issue], request).length, 0);
   });
@@ -34,9 +34,9 @@
     const issues = [issue1, issue2];
 
     const request1 = SDK.NetworkRequest.NetworkRequest.create(
-        requestId1, '' as Platform.DevToolsPath.UrlString, '' as Platform.DevToolsPath.UrlString, null, null, null);
+        requestId1, Platform.DevToolsPath.EmptyUrlString, Platform.DevToolsPath.EmptyUrlString, null, null, null);
     const request2 = SDK.NetworkRequest.NetworkRequest.create(
-        requestId2, '' as Platform.DevToolsPath.UrlString, '' as Platform.DevToolsPath.UrlString, null, null, null);
+        requestId2, Platform.DevToolsPath.EmptyUrlString, Platform.DevToolsPath.EmptyUrlString, null, null, null);
 
     assert.deepStrictEqual(IssuesManager.RelatedIssue.issuesAssociatedWith(issues, request1), issues);
     assert.deepStrictEqual(IssuesManager.RelatedIssue.issuesAssociatedWith(issues, request2), [issue1]);