1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <atomic>
#include <memory>
#include "base/environment.h"
#include "base/run_loop.h"
#include "chrome/browser/vr/test/mock_xr_device_hook_base.h"
#include "chrome/browser/vr/test/multi_class_browser_test.h"
#include "chrome/browser/vr/test/ui_utils.h"
#include "chrome/browser/vr/test/webxr_vr_browser_test.h"
namespace vr {
namespace {
class MyXRMock : public MockXRDeviceHookBase {
public:
void OnFrameSubmitted(
std::vector<device_test::mojom::ViewDataPtr> views,
device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback) final;
// The test waits for a submitted frame before returning.
void WaitForTotalFrames(int count) {
DCHECK(!wait_loop_);
wait_frame_count_ = count;
wait_loop_ = std::make_unique<base::RunLoop>(
base::RunLoop::Type::kNestableTasksAllowed);
can_signal_wait_loop_ = true;
wait_loop_->Run();
can_signal_wait_loop_ = false;
wait_loop_ = nullptr;
}
int FramesSubmitted() const { return num_frames_submitted_; }
private:
std::unique_ptr<base::RunLoop> wait_loop_ = nullptr;
// Used to track both if `wait_loop_` is valid in a thread-safe manner or if
// it has already had quit signaled on it, since `AnyQuitCalled` won't update
// until the `Quit` task has posted to the main thread.
std::atomic_bool can_signal_wait_loop_ = true;
int wait_frame_count_ = 0;
int num_frames_submitted_ = 0;
};
void MyXRMock::OnFrameSubmitted(
std::vector<device_test::mojom::ViewDataPtr> views,
device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback) {
num_frames_submitted_++;
if (num_frames_submitted_ >= wait_frame_count_ && wait_frame_count_ > 0 &&
can_signal_wait_loop_) {
wait_loop_->Quit();
can_signal_wait_loop_ = false;
}
std::move(callback).Run();
}
} // namespace
// TODO(https://crbug.com/381000093): Fix tests on Android
#if !BUILDFLAG(IS_ANDROID)
WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestNoStalledFrameLoop) {
MyXRMock my_mock;
// Load the test page, and enter presentation.
t->LoadFileAndAwaitInitialization("webxr_no_stalled_frame_loop");
t->EnterSessionWithUserGestureOrFail();
// Wait for 2 frames to be submitted back to the device, but the js frame loop
// should've only been called once.
my_mock.WaitForTotalFrames(2);
ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail("frame_count === 1"));
// Now restart the frame loop and wait for another frame to get submitted.
t->RunJavaScriptOrFail("setBaseLayer()");
t->PollJavaScriptBooleanOrFail("frame_count >= 2",
XrBrowserTestBase::kPollTimeoutMedium);
t->AssertNoJavaScriptErrors();
}
#endif // if !BUILDFLAG(IS_ANDROID)
WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestLateSetOfBaseLayer) {
MyXRMock my_mock;
// Load the test page, and enter presentation.
t->LoadFileAndAwaitInitialization("webxr_set_base_layer_late");
t->EnterSessionWithUserGestureOrFail();
// Poll and have the javascript yield for 500 ms. This should give us enough
// time for any frame requests that were going to propagate to propagate.
t->RunJavaScriptOrFail("delayMilliseconds(500)");
t->PollJavaScriptBooleanOrFail("delay_ended");
// No frames should have been submitted to either the JS or the runtime.
ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail("frame_count === 0"));
ASSERT_EQ(my_mock.FramesSubmitted(), 0);
// Now restart the frame loop and wait for a frame to get submitted.
t->RunJavaScriptOrFail("setBaseLayer()");
t->PollJavaScriptBooleanOrFail("frame_count >= 1",
XrBrowserTestBase::kPollTimeoutMedium);
t->AssertNoJavaScriptErrors();
}
} // namespace vr
|