فهرست منبع

LibWeb: Invent a method to stop an in-progress fetch without errors

The HTMLMediaElement will need to stop fetching processes when its load
algorithm is invoked while a fetch is ongoing. We don't have a way to
really stop the process, due to the way it runs on nested deferred task
invocations. So for now, this swaps the fetch callbacks (e.g. to process
a fetch response) with empty callbacks.
Timothy Flynn 2 سال پیش
والد
کامیت
8d4d01d99a

+ 17 - 0
Userland/Libraries/LibWeb/Fetch/Infrastructure/FetchController.cpp

@@ -6,7 +6,9 @@
 
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Runtime/VM.h>
+#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
 #include <LibWeb/Fetch/Infrastructure/FetchController.h>
+#include <LibWeb/Fetch/Infrastructure/FetchParams.h>
 #include <LibWeb/WebIDL/DOMException.h>
 
 namespace Web::Fetch::Infrastructure {
@@ -22,6 +24,7 @@ void FetchController::visit_edges(JS::Cell::Visitor& visitor)
 {
     Base::visit_edges(visitor);
     visitor.visit(m_full_timing_info);
+    visitor.visit(m_fetch_params);
 }
 
 // https://fetch.spec.whatwg.org/#finalize-and-report-timing
@@ -81,4 +84,18 @@ void FetchController::terminate()
     m_state = State::Terminated;
 }
 
+void FetchController::stop_fetch()
+{
+    auto& vm = this->vm();
+
+    // AD-HOC: Some HTML elements need to stop an ongoing fetching process without causing any network error to be raised
+    //         (which abort() and terminate() will both do). This is tricky because the fetch process runs across several
+    //         nested Platform::EventLoopPlugin::deferred_invoke() invocations. For now, we "stop" the fetch process by
+    //         ignoring any callbacks.
+    if (m_fetch_params) {
+        auto fetch_algorithms = FetchAlgorithms::create(vm, {});
+        m_fetch_params->set_algorithms(fetch_algorithms);
+    }
+}
+
 }

+ 8 - 0
Userland/Libraries/LibWeb/Fetch/Infrastructure/FetchController.h

@@ -6,11 +6,13 @@
 
 #pragma once
 
+#include <AK/Badge.h>
 #include <LibJS/Forward.h>
 #include <LibJS/Heap/Cell.h>
 #include <LibJS/Heap/GCPtr.h>
 #include <LibJS/SafeFunction.h>
 #include <LibWeb/Fetch/Infrastructure/FetchTimingInfo.h>
+#include <LibWeb/Forward.h>
 
 namespace Web::Fetch::Infrastructure {
 
@@ -39,6 +41,10 @@ public:
     void abort(JS::Realm&, Optional<JS::Value>);
     void terminate();
 
+    void set_fetch_params(Badge<FetchParams>, JS::NonnullGCPtr<FetchParams> fetch_params) { m_fetch_params = fetch_params; }
+
+    void stop_fetch();
+
 private:
     FetchController();
 
@@ -67,6 +73,8 @@ private:
     // next manual redirect steps (default null)
     //     Null or an algorithm accepting nothing.
     Optional<JS::SafeFunction<void()>> m_next_manual_redirect_steps;
+
+    JS::GCPtr<FetchParams> m_fetch_params;
 };
 
 }

+ 1 - 0
Userland/Libraries/LibWeb/Fetch/Infrastructure/FetchParams.cpp

@@ -17,6 +17,7 @@ FetchParams::FetchParams(JS::NonnullGCPtr<Request> request, JS::NonnullGCPtr<Fet
     , m_controller(controller)
     , m_timing_info(timing_info)
 {
+    m_controller->set_fetch_params({}, *this);
 }
 
 JS::NonnullGCPtr<FetchParams> FetchParams::create(JS::VM& vm, JS::NonnullGCPtr<Request> request, JS::NonnullGCPtr<FetchTimingInfo> timing_info)