DevTools: implement Target.createBrowserContext for non-headless mode

This patch uses OffTheRecord profiles to implement
|Target.createBrowserContext| and |Target.diposeBrowserContext| methods
for non-headless mode.

R=dgozman
BUG=836272

Change-Id: Ibd8b33bd9c804b69f17ef9cf1283b8c4bfc405ac
Reviewed-on: https://chromium-review.googlesource.com/1023591
Commit-Queue: Andrey Lushnikov <[email protected]>
Reviewed-by: Stefan Kuhne <[email protected]>
Reviewed-by: Dmitry Gozman <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#553323}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 933b81ec9520463c18329bc185b0dab3bc40bc80
diff --git a/front_end/Tests.js b/front_end/Tests.js
index d66f75a..add9616 100644
--- a/front_end/Tests.js
+++ b/front_end/Tests.js
@@ -1110,6 +1110,66 @@
     this.releaseControl();
   };
 
+  TestSuite.prototype.testCreateBrowserContext = async function(url) {
+    this.takeControl();
+    const browserContextIds = [];
+
+    const target1 = await createIsolatedTarget(url);
+    const target2 = await createIsolatedTarget(url);
+
+    await evalCode(target1, 'localStorage.setItem("page1", "page1")');
+    await evalCode(target2, 'localStorage.setItem("page2", "page2")');
+
+    this.assertEquals(await evalCode(target1, 'localStorage.getItem("page1")'), 'page1');
+    this.assertEquals(await evalCode(target1, 'localStorage.getItem("page2")'), null);
+    this.assertEquals(await evalCode(target2, 'localStorage.getItem("page1")'), null);
+    this.assertEquals(await evalCode(target2, 'localStorage.getItem("page2")'), 'page2');
+
+    this.assertEquals(await disposeBrowserContext(browserContextIds[0]), false);
+    this.assertEquals(await disposeBrowserContext(browserContextIds[1]), false);
+
+    await closeTarget(target1);
+    await closeTarget(target2);
+    this.assertEquals(await disposeBrowserContext(browserContextIds[0]), true);
+    this.assertEquals(await disposeBrowserContext(browserContextIds[1]), true);
+
+    this.releaseControl();
+
+    /**
+     * @param {string} url
+     * @return {!Promise<!SDK.Target>}
+     */
+    async function createIsolatedTarget(url) {
+      const targetAgent = SDK.targetManager.mainTarget().targetAgent();
+      const {browserContextId} = await targetAgent.invoke_createBrowserContext();
+      browserContextIds.push(browserContextId);
+
+      const {targetId} = await targetAgent.invoke_createTarget({url: 'about:blank', browserContextId});
+      await targetAgent.invoke_attachToTarget({targetId});
+
+      const target = SDK.targetManager.targets().find(target => target.id() === targetId);
+      const pageAgent = target.pageAgent();
+      await pageAgent.invoke_enable();
+      await pageAgent.invoke_navigate({url});
+      return target;
+    }
+
+    async function closeTarget(target) {
+      const targetAgent = SDK.targetManager.mainTarget().targetAgent();
+      await targetAgent.invoke_closeTarget({targetId: target.id()});
+    }
+
+    async function disposeBrowserContext(browserContextId) {
+      const targetAgent = SDK.targetManager.mainTarget().targetAgent();
+      const {success} = await targetAgent.invoke_disposeBrowserContext({browserContextId});
+      return success;
+    }
+
+    async function evalCode(target, code) {
+      return (await target.runtimeAgent().invoke_evaluate({expression: code})).result.value;
+    }
+  };
+
   TestSuite.prototype.testInputDispatchEventsToOOPIF = async function() {
     this.takeControl();