summaryrefslogtreecommitdiffstats
path: root/src/core/renderer/user_resource_controller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/renderer/user_resource_controller.cpp')
-rw-r--r--src/core/renderer/user_resource_controller.cpp325
1 files changed, 142 insertions, 183 deletions
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index 3c1ad0477..eff304981 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -1,60 +1,20 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "user_resource_controller.h"
#include "base/memory/weak_ptr.h"
-#include "base/pending_task.h"
#include "base/strings/pattern.h"
+#include "base/task/single_thread_task_runner.h"
#include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_view.h"
#include "content/public/renderer/render_frame_observer.h"
-#include "content/public/renderer/render_view_observer.h"
#include "extensions/common/url_pattern.h"
-#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_script_source.h"
-#include "third_party/blink/public/web/web_view.h"
-#include "v8/include/v8.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
-#include "common/qt_messages.h"
-#include "common/user_script_data.h"
+#include "qtwebengine/userscript/user_script_data.h"
#include "type_conversion.h"
#include "user_script.h"
@@ -62,9 +22,9 @@
#include <bitset>
-Q_GLOBAL_STATIC(UserResourceController, qt_webengine_userResourceController)
+namespace QtWebEngineCore {
-static content::RenderView *const globalScriptsIndex = nullptr;
+static content::RenderFrame *const globalScriptsIndex = nullptr;
// Scripts meant to run after the load event will be run 500ms after DOMContentLoaded if the load event doesn't come within that delay.
static const int afterLoadTimeout = 500;
@@ -97,7 +57,7 @@ static bool includeRuleMatchesURL(const std::string &pat, const GURL &url)
return false;
}
-static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url)
+static bool scriptMatchesURL(const QtWebEngineCore::UserScriptData &scriptData, const GURL &url)
{
// Logic taken from Chromium (extensions/common/user_script.cc)
bool matchFound;
@@ -132,26 +92,34 @@ static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url)
return true;
}
-class UserResourceController::RenderFrameObserverHelper : public content::RenderFrameObserver
+// using UserScriptDataPtr = mojo::StructPtr<qtwebengine::mojom::UserScriptData>;
+
+class UserResourceController::RenderFrameObserverHelper
+ : public content::RenderFrameObserver,
+ public qtwebengine::mojom::UserResourceControllerRenderFrame
{
public:
- RenderFrameObserverHelper(content::RenderFrame *render_frame);
+ RenderFrameObserverHelper(content::RenderFrame *render_frame,
+ UserResourceController *controller);
+ void BindReceiver(
+ mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceControllerRenderFrame>
+ receiver);
private:
// RenderFrameObserver implementation.
- void DidCommitProvisionalLoad(bool is_same_document_navigation, ui::PageTransition transition) override;
- void DidFinishDocumentLoad() override;
+ void DidCommitProvisionalLoad(ui::PageTransition transition) override;
+ void DidDispatchDOMContentLoadedEvent() override;
void DidFinishLoad() override;
- void FrameDetached() override;
+ void WillDetach() override;
void OnDestruct() override;
- bool OnMessageReceived(const IPC::Message &message) override;
-
- void onUserScriptAdded(const UserScriptData &);
- void onUserScriptRemoved(const UserScriptData &);
- void onScriptsCleared();
+ void AddScript(const QtWebEngineCore::UserScriptData &data) override;
+ void RemoveScript(const QtWebEngineCore::UserScriptData &data) override;
+ void ClearScripts() override;
class Runner;
QScopedPointer<Runner> m_runner;
+ mojo::AssociatedReceiver<qtwebengine::mojom::UserResourceControllerRenderFrame> m_binding;
+ UserResourceController *m_userResourceController;
};
// Helper class to create WeakPtrs so the AfterLoad tasks can be canceled and to
@@ -159,13 +127,16 @@ private:
class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr<Runner>
{
public:
- explicit Runner(blink::WebLocalFrame *frame) : m_frame(frame) {}
+ explicit Runner(blink::WebLocalFrame *frame, UserResourceController *controller)
+ : m_frame(frame), m_userResourceController(controller)
+ {
+ }
- void run(UserScriptData::InjectionPoint p)
+ void run(QtWebEngineCore::UserScriptData::InjectionPoint p)
{
DCHECK_LT(p, m_ran.size());
if (!m_ran[p]) {
- UserResourceController::instance()->runScripts(p, m_frame);
+ m_userResourceController->runScripts(p, m_frame);
m_ran[p] = true;
}
}
@@ -173,42 +144,29 @@ public:
private:
blink::WebLocalFrame *m_frame;
std::bitset<3> m_ran;
+ UserResourceController *m_userResourceController;
};
-// Used only for script cleanup on RenderView destruction.
-class UserResourceController::RenderViewObserverHelper : public content::RenderViewObserver
-{
-public:
- RenderViewObserverHelper(content::RenderView *render_view);
-
-private:
- // RenderViewObserver implementation.
- void OnDestruct() override;
-};
-
-void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame)
+void UserResourceController::runScripts(QtWebEngineCore::UserScriptData::InjectionPoint p,
+ blink::WebLocalFrame *frame)
{
content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame);
if (!renderFrame)
return;
const bool isMainFrame = renderFrame->IsMainFrame();
- content::RenderView *renderView = renderFrame->GetRenderView();
- if (!renderView)
- return;
-
- QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(0).values();
- scriptsToRun.append(m_viewUserScriptMap.value(renderView).values());
+ QList<uint64_t> scriptsToRun = m_frameUserScriptMap.value(globalScriptsIndex);
+ scriptsToRun.append(m_frameUserScriptMap.value(renderFrame));
- for (uint64_t id : qAsConst(scriptsToRun)) {
- const UserScriptData &script = m_scripts.value(id);
+ for (uint64_t id : std::as_const(scriptsToRun)) {
+ const QtWebEngineCore::UserScriptData &script = m_scripts.value(id);
if (script.injectionPoint != p || (!script.injectForSubframes && !isMainFrame))
continue;
if (!scriptMatchesURL(script, frame->GetDocument().Url()))
continue;
blink::WebScriptSource source(blink::WebString::FromUTF8(script.source), script.url);
if (script.worldId)
- frame->ExecuteScriptInIsolatedWorld(script.worldId, source);
+ frame->ExecuteScriptInIsolatedWorld(script.worldId, source, blink::BackForwardCacheAware::kAllow); // FIXME, check
else
frame->ExecuteScript(source);
}
@@ -216,119 +174,103 @@ void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink:
void UserResourceController::RunScriptsAtDocumentEnd(content::RenderFrame *render_frame)
{
- runScripts(UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame());
+ runScripts(QtWebEngineCore::UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame());
}
-UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper(content::RenderFrame *render_frame)
+UserResourceController::RenderFrameObserverHelper::RenderFrameObserverHelper(
+ content::RenderFrame *render_frame, UserResourceController *controller)
: content::RenderFrameObserver(render_frame)
-{}
+ , m_binding(this)
+ , m_userResourceController(controller)
+{
+ render_frame->GetAssociatedInterfaceRegistry()->AddInterface<qtwebengine::mojom::UserResourceControllerRenderFrame>(
+ base::BindRepeating(&UserResourceController::RenderFrameObserverHelper::BindReceiver,
+ base::Unretained(this)));
+}
-UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *render_view)
- : content::RenderViewObserver(render_view)
-{}
-void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(bool is_same_document_navigation,
- ui::PageTransition /*transitionbool*/)
+void UserResourceController::RenderFrameObserverHelper::BindReceiver(
+ mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceControllerRenderFrame>
+ receiver)
{
- if (is_same_document_navigation)
- return;
+ m_binding.Bind(std::move(receiver));
+}
+void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(ui::PageTransition /*transition*/)
+{
// We are almost ready to run scripts. We still have to wait until the host
// process has been notified of the DidCommitProvisionalLoad event to ensure
// that the WebChannelTransportHost is ready to receive messages.
- m_runner.reset(new Runner(render_frame()->GetWebFrame()));
+ m_runner.reset(new Runner(render_frame()->GetWebFrame(), m_userResourceController));
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::DocumentElementCreation));
+ base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&Runner::run, m_runner->AsWeakPtr(),
+ QtWebEngineCore::UserScriptData::DocumentElementCreation));
}
-void UserResourceController::RenderFrameObserverHelper::DidFinishDocumentLoad()
+void UserResourceController::RenderFrameObserverHelper::DidDispatchDOMContentLoadedEvent()
{
// Don't run scripts if provisional load failed (DidFailProvisionalLoad
// called instead of DidCommitProvisionalLoad).
if (m_runner)
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad),
- base::TimeDelta::FromMilliseconds(afterLoadTimeout));
+ base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&Runner::run, m_runner->AsWeakPtr(),
+ QtWebEngineCore::UserScriptData::AfterLoad),
+ base::Milliseconds(afterLoadTimeout));
}
void UserResourceController::RenderFrameObserverHelper::DidFinishLoad()
{
if (m_runner)
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&Runner::run, m_runner->AsWeakPtr(), UserScriptData::AfterLoad));
+ base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&Runner::run, m_runner->AsWeakPtr(),
+ QtWebEngineCore::UserScriptData::AfterLoad));
}
-void UserResourceController::RenderFrameObserverHelper::FrameDetached()
+void UserResourceController::RenderFrameObserverHelper::WillDetach()
{
m_runner.reset();
}
void UserResourceController::RenderFrameObserverHelper::OnDestruct()
{
+ if (content::RenderFrame *frame = render_frame()) {
+ m_userResourceController->renderFrameDestroyed(frame);
+ }
delete this;
}
-void UserResourceController::RenderViewObserverHelper::OnDestruct()
-{
- // Remove all scripts associated with the render view.
- if (content::RenderView *view = render_view())
- UserResourceController::instance()->renderViewDestroyed(view);
- delete this;
-}
-
-bool UserResourceController::RenderFrameObserverHelper::OnMessageReceived(const IPC::Message &message)
-{
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(UserResourceController::RenderFrameObserverHelper, message)
- IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_AddScript, onUserScriptAdded)
- IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_RemoveScript, onUserScriptRemoved)
- IPC_MESSAGE_HANDLER(RenderFrameObserverHelper_ClearScripts, onScriptsCleared)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void UserResourceController::RenderFrameObserverHelper::onUserScriptAdded(const UserScriptData &script)
+void UserResourceController::RenderFrameObserverHelper::AddScript(
+ const QtWebEngineCore::UserScriptData &script)
{
if (content::RenderFrame *frame = render_frame())
- if (content::RenderView *view = frame->GetRenderView())
- UserResourceController::instance()->addScriptForView(script, view);
+ m_userResourceController->addScriptForFrame(script, frame);
}
-void UserResourceController::RenderFrameObserverHelper::onUserScriptRemoved(const UserScriptData &script)
+void UserResourceController::RenderFrameObserverHelper::RemoveScript(
+ const QtWebEngineCore::UserScriptData &script)
{
if (content::RenderFrame *frame = render_frame())
- if (content::RenderView *view = frame->GetRenderView())
- UserResourceController::instance()->removeScriptForView(script, view);
+ m_userResourceController->removeScriptForFrame(script, frame);
}
-void UserResourceController::RenderFrameObserverHelper::onScriptsCleared()
+void UserResourceController::RenderFrameObserverHelper::ClearScripts()
{
if (content::RenderFrame *frame = render_frame())
- if (content::RenderView *view = frame->GetRenderView())
- UserResourceController::instance()->clearScriptsForView(view);
+ m_userResourceController->clearScriptsForFrame(frame);
}
-UserResourceController *UserResourceController::instance()
+void UserResourceController::BindReceiver(
+ mojo::PendingAssociatedReceiver<qtwebengine::mojom::UserResourceController> receiver)
{
- return qt_webengine_userResourceController();
+ m_binding.Bind(std::move(receiver));
}
-bool UserResourceController::OnControlMessageReceived(const IPC::Message &message)
-{
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(UserResourceController, message)
- IPC_MESSAGE_HANDLER(UserResourceController_AddScript, onAddScript)
- IPC_MESSAGE_HANDLER(UserResourceController_RemoveScript, onRemoveScript)
- IPC_MESSAGE_HANDLER(UserResourceController_ClearScripts, onClearScripts)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-UserResourceController::UserResourceController()
+UserResourceController::UserResourceController() : m_binding(this)
{
#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS)
static bool onlyCalledOnce = true;
@@ -340,68 +282,85 @@ UserResourceController::UserResourceController()
void UserResourceController::renderFrameCreated(content::RenderFrame *renderFrame)
{
// Will destroy itself when the RenderFrame is destroyed.
- new RenderFrameObserverHelper(renderFrame);
+ new RenderFrameObserverHelper(renderFrame, this);
}
-void UserResourceController::renderViewCreated(content::RenderView *renderView)
+void UserResourceController::renderFrameDestroyed(content::RenderFrame *renderFrame)
{
- // Will destroy itself when the RenderView is destroyed.
- new RenderViewObserverHelper(renderView);
+ FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(renderFrame);
+ if (it == m_frameUserScriptMap.end()) // ASSERT maybe?
+ return;
+ if (renderFrame->IsMainFrame()) {
+ for (uint64_t id : std::as_const(it.value()))
+ m_scripts.remove(id);
+ }
+ m_frameUserScriptMap.erase(it);
}
-void UserResourceController::renderViewDestroyed(content::RenderView *renderView)
+void UserResourceController::addScriptForFrame(const QtWebEngineCore::UserScriptData &script,
+ content::RenderFrame *frame)
{
- ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(renderView);
- if (it == m_viewUserScriptMap.end()) // ASSERT maybe?
- return;
- for (uint64_t id : qAsConst(it.value())) {
- m_scripts.remove(id);
- }
- m_viewUserScriptMap.remove(renderView);
+ FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(frame);
+ if (it == m_frameUserScriptMap.end())
+ it = m_frameUserScriptMap.insert(frame, UserScriptList());
+
+ if (!(*it).contains(script.scriptId))
+ (*it).append(script.scriptId);
+ if (!frame || frame->IsMainFrame())
+ m_scripts.insert(script.scriptId, script);
}
-void UserResourceController::addScriptForView(const UserScriptData &script, content::RenderView *view)
+void UserResourceController::removeScriptForFrame(const QtWebEngineCore::UserScriptData &script,
+ content::RenderFrame *frame)
{
- ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view);
- if (it == m_viewUserScriptMap.end())
- it = m_viewUserScriptMap.insert(view, UserScriptSet());
+ FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(frame);
+ if (it == m_frameUserScriptMap.end())
+ return;
- (*it).insert(script.scriptId);
- m_scripts.insert(script.scriptId, script);
+ (*it).removeOne(script.scriptId);
+ if (!frame || frame->IsMainFrame())
+ m_scripts.remove(script.scriptId);
}
-void UserResourceController::removeScriptForView(const UserScriptData &script, content::RenderView *view)
+void UserResourceController::clearScriptsForFrame(content::RenderFrame *frame)
{
- ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view);
- if (it == m_viewUserScriptMap.end())
+ FrameUserScriptMap::iterator it = m_frameUserScriptMap.find(frame);
+ if (it == m_frameUserScriptMap.end())
return;
+ if (!frame || frame->IsMainFrame()) {
+ for (uint64_t id : std::as_const(it.value()))
+ m_scripts.remove(id);
+ }
- (*it).remove(script.scriptId);
- m_scripts.remove(script.scriptId);
+ m_frameUserScriptMap.remove(frame);
}
-void UserResourceController::clearScriptsForView(content::RenderView *view)
+void UserResourceController::AddScript(const QtWebEngineCore::UserScriptData &script)
{
- ViewUserScriptMap::iterator it = m_viewUserScriptMap.find(view);
- if (it == m_viewUserScriptMap.end())
- return;
- for (uint64_t id : qAsConst(it.value()))
- m_scripts.remove(id);
+ addScriptForFrame(script, globalScriptsIndex);
+}
- m_viewUserScriptMap.remove(view);
+void UserResourceController::RemoveScript(const QtWebEngineCore::UserScriptData &script)
+{
+ removeScriptForFrame(script, globalScriptsIndex);
}
-void UserResourceController::onAddScript(const UserScriptData &script)
+void UserResourceController::ClearScripts()
{
- addScriptForView(script, globalScriptsIndex);
+ clearScriptsForFrame(globalScriptsIndex);
}
-void UserResourceController::onRemoveScript(const UserScriptData &script)
+void UserResourceController::RegisterMojoInterfaces(
+ blink::AssociatedInterfaceRegistry *associated_interfaces)
{
- removeScriptForView(script, globalScriptsIndex);
+ associated_interfaces->AddInterface<qtwebengine::mojom::UserResourceController>(
+ base::BindRepeating(&UserResourceController::BindReceiver, base::Unretained(this)));
}
-void UserResourceController::onClearScripts()
+void UserResourceController::UnregisterMojoInterfaces(
+ blink::AssociatedInterfaceRegistry *associated_interfaces)
{
- clearScriptsForView(globalScriptsIndex);
+ associated_interfaces->RemoveInterface(qtwebengine::mojom::UserResourceController::Name_);
}
+
+} // namespace