| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/web/public/test/task_observer_util.h" |
| |
| #import "base/pending_task.h" |
| #import "base/run_loop.h" |
| #import "base/task/current_thread.h" |
| #import "base/test/ios/wait_util.h" |
| #import "ios/web/public/web_state.h" |
| |
| using base::test::ios::kWaitForPageLoadTimeout; |
| using base::test::ios::WaitUntilConditionOrTimeout; |
| |
| namespace { |
| class WaitForBackgroundTasksTaskObserver : public base::TaskObserver { |
| public: |
| // base::TaskObserver overide |
| void WillProcessTask(const base::PendingTask&, bool) override { |
| // Nothing to do. |
| } |
| void DidProcessTask(const base::PendingTask&) override { |
| processed_a_task_ = true; |
| } |
| |
| // An accessor method that returns whether the task |
| // has been processed. |
| bool has_processed_task() const { return processed_a_task_; } |
| |
| void clear_has_processed_task() { processed_a_task_ = false; } |
| |
| protected: |
| // is true if a task has been processed. |
| bool processed_a_task_ = false; |
| }; |
| } // namespace |
| |
| namespace web { |
| namespace test { |
| |
| void WaitForBackgroundTasks() { |
| // Because tasks can add new tasks to either queue, the loop continues until |
| // the first pass where no activity is seen from either queue. |
| WaitForBackgroundTasksTaskObserver observer; |
| bool activity_seen = false; |
| base::CurrentThread message_loop = base::CurrentThread::Get(); |
| message_loop->AddTaskObserver(&observer); |
| |
| do { |
| activity_seen = false; |
| |
| // Yield to the iOS message queue, e.g. [NSObject performSelector:] |
| // events. |
| if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == |
| kCFRunLoopRunHandledSource) { |
| activity_seen = true; |
| } |
| |
| // Yield to the Chromium message queue, e.g. WebThread::PostTask() |
| // events. |
| observer.clear_has_processed_task(); |
| base::RunLoop().RunUntilIdle(); |
| if (observer.has_processed_task()) { |
| activity_seen = true; |
| } |
| |
| } while (activity_seen); |
| message_loop->RemoveTaskObserver(&observer); |
| } |
| |
| bool WaitUntilLoaded(WebState* web_state) { |
| return WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{ |
| WaitForBackgroundTasks(); |
| return !web_state->IsLoading(); |
| }); |
| } |
| |
| } // namespace test |
| } // namespace web |