[Extensions Bindings] Gracefully handle invalidated contexts in app hooks

Handle the case of a context being invalidated before accessing
chrome.app.isInstalled. This can happen in cases where the owning frame
is removed.

Add a regression test for the same.

Bug: 855853
Change-Id: Ic9e5f5a45fc2a833c5c1a45d3b7c1e8c04c71a18
Reviewed-on: https://chromium-review.googlesource.com/1119066
Reviewed-by: Istiaque Ahmed <[email protected]>
Commit-Queue: Devlin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#571355}
diff --git a/chrome/browser/extensions/chrome_app_api_browsertest.cc b/chrome/browser/extensions/chrome_app_api_browsertest.cc
index db24543b..02436f3 100644
--- a/chrome/browser/extensions/chrome_app_api_browsertest.cc
+++ b/chrome/browser/extensions/chrome_app_api_browsertest.cc
@@ -171,6 +171,34 @@
   EXPECT_EQ("true", result);
 }
 
+// Test accessing app.isInstalled when the context has been invalidated (e.g.
+// by removing the frame). Regression test for https://crbug.com/855853.
+IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, IsInstalledFromRemovedFrame) {
+  GURL app_url =
+      embedded_test_server()->GetURL("app.com", "/extensions/test_file.html");
+  const Extension* extension =
+      LoadExtension(test_data_dir_.AppendASCII("app_dot_com_app"));
+  ASSERT_TRUE(extension);
+  ui_test_utils::NavigateToURL(browser(), app_url);
+
+  constexpr char kScript[] =
+      R"(var i = document.createElement('iframe');
+         i.onload = function() {
+           var frameApp = i.contentWindow.chrome.app;
+           document.body.removeChild(i);
+           var isInstalled = frameApp.isInstalled;
+           window.domAutomationController.send(
+               isInstalled === undefined);
+         };
+         i.src = '%s';
+         document.body.appendChild(i);)";
+  bool result = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      base::StringPrintf(kScript, app_url.spec().c_str()), &result));
+  EXPECT_TRUE(result);
+}
+
 IN_PROC_BROWSER_TEST_F(ChromeAppAPITest, InstallAndRunningState) {
   GURL app_url = embedded_test_server()->GetURL(
       "app.com", "/extensions/get_app_details_for_frame.html");