Index: content/browser/site_per_process_browsertest.cc |
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc |
index e825d067482393c12039f9ac8df843caec52d7b0..affe25adac31bd121e2d18cd7709c14f8e7ae97c 100644 |
--- a/content/browser/site_per_process_browsertest.cc |
+++ b/content/browser/site_per_process_browsertest.cc |
@@ -590,6 +590,21 @@ class SitePerProcessIgnoreCertErrorsBrowserTest |
} |
}; |
+// |
+// SitePerProcessWebVRBrowserTest |
+// |
+ |
+class SitePerProcessWebVRBrowserTest : public SitePerProcessBrowserTest { |
+ public: |
+ SitePerProcessWebVRBrowserTest() {} |
+ |
+ protected: |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ SitePerProcessBrowserTest::SetUpCommandLine(command_line); |
+ command_line->AppendSwitch(switches::kEnableWebVR); |
+ } |
+}; |
+ |
double GetFrameDeviceScaleFactor(const ToRenderFrameHost& adapter) { |
double device_scale_factor; |
const char kGetFrameDeviceScaleFactor[] = |
@@ -7468,6 +7483,99 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, AllowFullscreen) { |
EXPECT_TRUE(is_fullscreen_allowed(root->child_at(0)->child_at(0))); |
} |
+// Check that out-of-process frames correctly calculate their ability to enter |
+// VR. A frame is allowed enter VR if the allowVR attribute is present in all of |
+// its ancestor <iframe> elements. For OOPIF, when a parent frame changes this |
+// attribute, the change is replicated to the child frame and its proxies. |
+// |
+// The test checks the following cases: |
+// |
+// 1. Static attribute (<iframe allowvr>) |
+// 2. Attribute injected dynamically via JavaScript |
+// 3. Multiple levels of nesting (A-embed-B-embed-C) |
+// 4. Cross-site subframe navigation |
+IN_PROC_BROWSER_TEST_F(SitePerProcessWebVRBrowserTest, AllowVR) { |
+ // Load a page with a cross-site <iframe allowvr>. |
+ GURL url_1(embedded_test_server()->GetURL( |
+ "a.com", "/page_with_allowvr_frame.html")); |
+ EXPECT_TRUE(NavigateToURL(shell(), url_1)); |
+ |
+ WebContentsImpl* contents = web_contents(); |
+ FrameTreeNode* root = contents->GetFrameTree()->root(); |
+ |
+ // Helper to check if a frame is allowed to go VR on the renderer |
+ // side. |
+ auto is_vr_allowed = [](FrameTreeNode* ftn) { |
+ bool vr_allowed = false; |
+ EXPECT_TRUE(ExecuteScriptAndExtractBool( |
+ ftn, |
+ "window.domAutomationController.send(navigator.vrEnabled)", |
+ &vr_allowed)); |
+ return vr_allowed; |
+ }; |
+ |
+ EXPECT_TRUE(is_vr_allowed(root)); |
+ EXPECT_TRUE(is_vr_allowed(root->child_at(0))); |
+ EXPECT_TRUE(root->child_at(0)->frame_owner_properties().allow_vr); |
+ |
+ // Now navigate to a page with two <iframe>'s, both without allowvr. |
+ GURL url_2(embedded_test_server()->GetURL( |
+ "a.com", "/cross_site_iframe_factory.html?a(b,c)")); |
+ EXPECT_TRUE(NavigateToURL(shell(), url_2)); |
+ EXPECT_FALSE(root->child_at(0)->frame_owner_properties().allow_vr); |
+ EXPECT_FALSE(root->child_at(1)->frame_owner_properties().allow_vr); |
+ |
+ EXPECT_TRUE(is_vr_allowed(root)); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(0))); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(1))); |
+ |
+ // Dynamically enable VR for first subframe and check that the |
+ // VR property was updated on the FrameTreeNode. |
+ EXPECT_TRUE(ExecuteScript( |
+ root, "document.getElementById('child-0').allowVR='true'")); |
+ EXPECT_TRUE(root->child_at(0)->frame_owner_properties().allow_vr); |
+ |
+ // Check that the first subframe is now allowed to go VR. Other |
+ // frames shouldn't be affected. |
+ EXPECT_TRUE(is_vr_allowed(root)); |
+ EXPECT_TRUE(is_vr_allowed(root->child_at(0))); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(1))); |
+ |
+ // Now navigate to a page with two levels of nesting. |
+ GURL url_3(embedded_test_server()->GetURL( |
+ "a.com", "/cross_site_iframe_factory.html?a(b(c))")); |
+ EXPECT_TRUE(NavigateToURL(shell(), url_3)); |
+ |
+ EXPECT_TRUE(is_vr_allowed(root)); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(0))); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(0)->child_at(0))); |
+ |
+ // Dynamically enable vr for bottom subframe. |
+ EXPECT_TRUE(ExecuteScript( |
+ root->child_at(0), |
+ "document.getElementById('child-0').allowVR='true'")); |
+ |
+ // This still shouldn't allow the bottom child to go VR, since the |
+ // top frame hasn't allowed VR for the middle frame. |
+ EXPECT_TRUE(is_vr_allowed(root)); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(0))); |
+ EXPECT_FALSE(is_vr_allowed(root->child_at(0)->child_at(0))); |
+ |
+ // Now allow vr for the middle frame. |
+ EXPECT_TRUE(ExecuteScript( |
+ root, "document.getElementById('child-0').allowVR='true'")); |
+ |
+ // All frames should be allowed to go VR now. |
+ EXPECT_TRUE(is_vr_allowed(root)); |
+ EXPECT_TRUE(is_vr_allowed(root->child_at(0))); |
+ EXPECT_TRUE(is_vr_allowed(root->child_at(0)->child_at(0))); |
+ |
+ // Cross-site navigation should preserve the VR flags. |
+ NavigateFrameToURL(root->child_at(0)->child_at(0), |
+ embedded_test_server()->GetURL("d.com", "/title1.html")); |
+ EXPECT_TRUE(is_vr_allowed(root->child_at(0)->child_at(0))); |
+} |
+ |
// Test for https://crbug.com/615575. It ensures that file chooser triggered |
// by a document in an out-of-process subframe works properly. |
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, FileChooserInSubframe) { |