diff --git a/src/core/browser_message_filter_qt.cpp b/src/core/browser_message_filter_qt.cpp index 72b38e1bbfded442df1aad373707408fc7d264f5..330bba3a954f7b6066bf610de1c69b4e0ab6bc71 100644 --- a/src/core/browser_message_filter_qt.cpp +++ b/src/core/browser_message_filter_qt.cpp @@ -39,14 +39,20 @@ #include "browser_message_filter_qt.h" +#include "chrome/browser/profiles/profile.h" #include "common/qt_messages.h" #include "content/public/browser/plugin_service.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" #include "type_conversion.h" +#include "net/network_delegate_qt.h" + namespace QtWebEngineCore { -BrowserMessageFilterQt::BrowserMessageFilterQt(int /*render_process_id*/) +BrowserMessageFilterQt::BrowserMessageFilterQt(int /*render_process_id*/, Profile *profile) : BrowserMessageFilter(QtMsgStart) + , m_profile(profile) { } @@ -58,6 +64,13 @@ BrowserMessageFilterQt::BrowserMessageFilterQt(int /*render_process_id*/) bool BrowserMessageFilterQt::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(BrowserMessageFilterQt, message) + IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowDatabase, OnAllowDatabase) + IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowDOMStorage, OnAllowDOMStorage) + IPC_MESSAGE_HANDLER_DELAY_REPLY(QtWebEngineHostMsg_RequestFileSystemAccessSync, + OnRequestFileSystemAccessSync) + IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_RequestFileSystemAccessAsync, + OnRequestFileSystemAccessAsync) + IPC_MESSAGE_HANDLER(QtWebEngineHostMsg_AllowIndexedDB, OnAllowIndexedDB) #if BUILDFLAG(ENABLE_LIBRARY_CDMS) IPC_MESSAGE_HANDLER( QtWebEngineHostMsg_IsInternalPluginAvailableForMimeType, @@ -90,4 +103,92 @@ void BrowserMessageFilterQt::OnIsInternalPluginAvailableForMimeType( #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + +void BrowserMessageFilterQt::OnAllowDatabase(int /*render_frame_id*/, + const GURL &origin_url, + const GURL &top_origin_url, + const base::string16 &/*name*/, + const base::string16 &/*display_name*/, + bool* allowed) +{ + NetworkDelegateQt *networkDelegate = static_cast<NetworkDelegateQt *>(m_profile->GetRequestContext()->GetURLRequestContext()->network_delegate()); + *allowed = networkDelegate->canGetCookies(top_origin_url, origin_url); +} + +void BrowserMessageFilterQt::OnAllowDOMStorage(int /*render_frame_id*/, + const GURL &origin_url, + const GURL &top_origin_url, + bool /*local*/, + bool *allowed) +{ + NetworkDelegateQt *networkDelegate = static_cast<NetworkDelegateQt *>(m_profile->GetRequestContext()->GetURLRequestContext()->network_delegate()); + *allowed = networkDelegate->canGetCookies(top_origin_url, origin_url); +} + +void BrowserMessageFilterQt::OnAllowIndexedDB(int /*render_frame_id*/, + const GURL &origin_url, + const GURL &top_origin_url, + const base::string16 &/*name*/, + bool *allowed) +{ + NetworkDelegateQt *networkDelegate = static_cast<NetworkDelegateQt *>(m_profile->GetRequestContext()->GetURLRequestContext()->network_delegate()); + *allowed = networkDelegate->canGetCookies(top_origin_url, origin_url); +} + +void BrowserMessageFilterQt::OnRequestFileSystemAccessSync(int render_frame_id, + const GURL& origin_url, + const GURL& top_origin_url, + IPC::Message* reply_msg) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + base::Callback<void(bool)> callback = base::Bind( + &BrowserMessageFilterQt::OnRequestFileSystemAccessSyncResponse, + base::WrapRefCounted(this), reply_msg); + OnRequestFileSystemAccess(render_frame_id, + origin_url, + top_origin_url, + callback); +} + +void BrowserMessageFilterQt::OnRequestFileSystemAccessSyncResponse(IPC::Message *reply_msg, bool allowed) +{ + QtWebEngineHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg, allowed); + Send(reply_msg); +} + +void BrowserMessageFilterQt::OnRequestFileSystemAccessAsync(int render_frame_id, + int request_id, + const GURL& origin_url, + const GURL& top_origin_url) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + base::Callback<void(bool)> callback = base::Bind( + &BrowserMessageFilterQt::OnRequestFileSystemAccessAsyncResponse, + base::WrapRefCounted(this), render_frame_id, request_id); + OnRequestFileSystemAccess(render_frame_id, + origin_url, + top_origin_url, + callback); +} + +void BrowserMessageFilterQt::OnRequestFileSystemAccessAsyncResponse(int render_frame_id, + int request_id, + bool allowed) +{ + Send(new QtWebEngineMsg_RequestFileSystemAccessAsyncResponse(render_frame_id, request_id, allowed)); +} + +void BrowserMessageFilterQt::OnRequestFileSystemAccess(int /*render_frame_id*/, + const GURL &origin_url, + const GURL &top_origin_url, + base::Callback<void(bool)> callback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + NetworkDelegateQt *networkDelegate = static_cast<NetworkDelegateQt *>(m_profile->GetRequestContext()->GetURLRequestContext()->network_delegate()); + bool allowed = networkDelegate->canGetCookies(top_origin_url, origin_url); + + callback.Run(allowed); +} + } // namespace QtWebEngineCore diff --git a/src/core/browser_message_filter_qt.h b/src/core/browser_message_filter_qt.h index 9ad9a0e6ed6a65e7df6e0a28cd29caaa5f09eed3..c05da794409b0510a1ecf7c750986074c14a7cc2 100644 --- a/src/core/browser_message_filter_qt.h +++ b/src/core/browser_message_filter_qt.h @@ -40,16 +40,20 @@ #ifndef BROWSER_MESSAGE_FILTER_QT_H #define BROWSER_MESSAGE_FILTER_QT_H +#include "base/callback.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/common/webplugininfo.h" #include "media/media_features.h" +class GURL; +class Profile; + namespace QtWebEngineCore { class BrowserMessageFilterQt : public content::BrowserMessageFilter { public: - BrowserMessageFilterQt(int render_process_id); + BrowserMessageFilterQt(int render_process_id, Profile *profile); private: bool OnMessageReceived(const IPC::Message& message) override; @@ -65,6 +69,45 @@ private: const std::string& mime_type, base::Optional<std::vector<content::WebPluginMimeType::Param>> *opt_additional_params); #endif + + void OnAllowDatabase(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + const base::string16& name, + const base::string16& display_name, + bool *allowed); + + void OnAllowDOMStorage(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + bool local, + bool *allowed); + + void OnAllowIndexedDB(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + const base::string16 &name, + bool *allowed); + + void OnRequestFileSystemAccessSync(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + IPC::Message *message); + void OnRequestFileSystemAccessAsync(int render_frame_id, + int request_id, + const GURL &origin_url, + const GURL &top_origin_url); + void OnRequestFileSystemAccessSyncResponse(IPC::Message *reply_msg, + bool allowed); + void OnRequestFileSystemAccessAsyncResponse(int render_frame_id, + int request_id, + bool allowed); + void OnRequestFileSystemAccess(int render_frame_id, + const GURL &origin_url, + const GURL &top_origin_url, + base::Callback<void(bool)> callback); + + Profile *m_profile; }; } // namespace QtWebEngineCore diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index 411d06bc85d69c23ddca49a515e55270ff9ceec8..c5caa0fff1831bb72dea53e1645c112f40b61d79 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -54,6 +54,12 @@ IPC_MESSAGE_CONTROL1(UserResourceController_AddScript, UserScriptData /* scriptC IPC_MESSAGE_CONTROL1(UserResourceController_RemoveScript, UserScriptData /* scriptContents */) IPC_MESSAGE_CONTROL0(UserResourceController_ClearScripts) +// Tells the renderer whether or not a file system access has been allowed. +IPC_MESSAGE_ROUTED2(QtWebEngineMsg_RequestFileSystemAccessAsyncResponse, + int /* request_id */, + bool /* allowed */) + + //----------------------------------------------------------------------------- // WebContents messages // These are messages sent from the renderer back to the browser process. @@ -85,3 +91,47 @@ IPC_SYNC_MESSAGE_CONTROL1_1(QtWebEngineHostMsg_IsInternalPluginAvailableForMimeT std::string /* mime_type */, base::Optional<std::vector<content::WebPluginMimeType::Param>>) #endif + +// Sent by the renderer process to check whether access to web databases is +// granted by content settings. +IPC_SYNC_MESSAGE_CONTROL5_1(QtWebEngineHostMsg_AllowDatabase, + int /* render_frame_id */, + GURL /* origin_url */, + GURL /* top origin url */, + base::string16 /* database name */, + base::string16 /* database display name */, + bool /* allowed */) + +// Sent by the renderer process to check whether access to DOM Storage is +// granted by content settings. +IPC_SYNC_MESSAGE_CONTROL4_1(QtWebEngineHostMsg_AllowDOMStorage, + int /* render_frame_id */, + GURL /* origin_url */, + GURL /* top origin url */, + bool /* if true local storage, otherwise session */, + bool /* allowed */) + +// Sent by the renderer process to check whether access to FileSystem is +// granted by content settings. +IPC_SYNC_MESSAGE_CONTROL3_1(QtWebEngineHostMsg_RequestFileSystemAccessSync, + int /* render_frame_id */, + GURL /* origin_url */, + GURL /* top origin url */, + bool /* allowed */) + +// Sent by the renderer process to check whether access to FileSystem is +// granted by content settings. +IPC_MESSAGE_CONTROL4(QtWebEngineHostMsg_RequestFileSystemAccessAsync, + int /* render_frame_id */, + int /* request_id */, + GURL /* origin_url */, + GURL /* top origin url */) + +// Sent by the renderer process to check whether access to Indexed DB is +// granted by content settings. +IPC_SYNC_MESSAGE_CONTROL4_1(QtWebEngineHostMsg_AllowIndexedDB, + int /* render_frame_id */, + GURL /* origin_url */, + GURL /* top origin url */, + base::string16 /* database name */, + bool /* allowed */) diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 3e620bd1f67e7d7329d5592fad5fcbec403a63c5..60d7e3fdf5abbe389c34eb1cbf45c93aa7621998 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -390,13 +390,12 @@ content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* host) { - // FIXME: Add a settings variable to enable/disable the file scheme. const int id = host->GetID(); + Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext()); + // FIXME: Add a settings variable to enable/disable the file scheme. content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(id, url::kFileScheme); static_cast<BrowserContextQt*>(host->GetBrowserContext())->m_adapter->userResourceController()->renderProcessStartedWithHost(host); -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) - host->AddFilter(new BrowserMessageFilterQt(id)); -#endif + host->AddFilter(new BrowserMessageFilterQt(id, profile)); #if defined(Q_OS_MACOS) && BUILDFLAG(ENABLE_SPELLCHECK) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) host->AddFilter(new SpellCheckMessageFilterPlatform(id)); #endif diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index 84866c6cf98af4193f8aab984edbdde546d0dfc8..adc0e1fe06adb969e6cfb0fe999d996b42f2fc49 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -96,6 +96,7 @@ SOURCES = \ render_view_observer_host_qt.cpp \ render_widget_host_view_qt.cpp \ renderer/content_renderer_client_qt.cpp \ + renderer/content_settings_observer_qt.cpp \ renderer/render_frame_observer_qt.cpp \ renderer/render_view_observer_qt.cpp \ renderer/user_resource_controller.cpp \ @@ -187,6 +188,7 @@ HEADERS = \ render_widget_host_view_qt.h \ render_widget_host_view_qt_delegate.h \ renderer/content_renderer_client_qt.h \ + renderer/content_settings_observer_qt.h \ renderer/render_frame_observer_qt.h \ renderer/render_view_observer_qt.h \ renderer/user_resource_controller.h \ diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 74edc43693dea66ede8444d03b0925c329082534..db3ab5745e2879af3f88a6c27164afdba7c0572e 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -41,6 +41,7 @@ #include "common/qt_messages.h" #include "printing/features/features.h" +#include "renderer/content_settings_observer_qt.h" #include "base/strings/string_split.h" #if BUILDFLAG(ENABLE_SPELLCHECK) @@ -133,6 +134,8 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_fr new WebChannelIPCTransport(render_frame); UserResourceController::instance()->renderFrameCreated(render_frame); + new QtWebEngineCore::ContentSettingsObserverQt(render_frame); + #if BUILDFLAG(ENABLE_SPELLCHECK) new SpellCheckProvider(render_frame, m_spellCheck.data(), this); #endif diff --git a/src/core/renderer/content_settings_observer_qt.cpp b/src/core/renderer/content_settings_observer_qt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bfd0c96f88c385bc2913847c809c5d79a02348a6 --- /dev/null +++ b/src/core/renderer/content_settings_observer_qt.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +// Based on chrome/renderer/content_settings_observer.cc: +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content_settings_observer_qt.h" + +#include "content/public/renderer/render_frame.h" +#include "third_party/WebKit/public/platform/WebContentSettingCallbacks.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "url/origin.h" + +#include "common/qt_messages.h" + +using blink::WebContentSettingCallbacks; +using blink::WebSecurityOrigin; +using blink::WebString; + +namespace { + +bool IsUniqueFrame(blink::WebFrame *frame) +{ + return frame->GetSecurityOrigin().IsUnique() || + frame->Top()->GetSecurityOrigin().IsUnique(); +} + +} // namespace + +namespace QtWebEngineCore { + +ContentSettingsObserverQt::ContentSettingsObserverQt(content::RenderFrame *render_frame) + : content::RenderFrameObserver(render_frame) + , content::RenderFrameObserverTracker<ContentSettingsObserverQt>(render_frame) + , m_currentRequestId(0) +{ + ClearBlockedContentSettings(); + render_frame->GetWebFrame()->SetContentSettingsClient(this); +} + +ContentSettingsObserverQt::~ContentSettingsObserverQt() { +} + +bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message& message) +{ + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserverQt, message) + IPC_MESSAGE_HANDLER(QtWebEngineMsg_RequestFileSystemAccessAsyncResponse, + OnRequestFileSystemAccessAsyncResponse) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; +} + +void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool /*is_new_navigation*/, + bool is_same_document_navigation) +{ + blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); + if (frame->Parent()) + return; // Not a top-level navigation. + + if (!is_same_document_navigation) + ClearBlockedContentSettings(); + + GURL url = frame->GetDocument().Url(); + // If we start failing this DCHECK, please makes sure we don't regress + // this bug: http://code.google.com/p/chromium/issues/detail?id=79304 + DCHECK(frame->GetDocument().GetSecurityOrigin().ToString() == "null" || + !url.SchemeIs(url::kDataScheme)); +} + +void ContentSettingsObserverQt::OnDestruct() +{ + delete this; +} + +bool ContentSettingsObserverQt::AllowDatabase(const WebString &name, + const WebString &display_name, + unsigned /*estimated_size*/) +{ + blink::WebFrame *frame = render_frame()->GetWebFrame(); + if (IsUniqueFrame(frame)) + return false; + + bool result = false; + Send(new QtWebEngineHostMsg_AllowDatabase( + routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), name.Utf16(), + display_name.Utf16(), &result)); + return result; +} + +void ContentSettingsObserverQt::RequestFileSystemAccessAsync(const WebContentSettingCallbacks &callbacks) +{ + blink::WebFrame *frame = render_frame()->GetWebFrame(); + if (IsUniqueFrame(frame)) { + WebContentSettingCallbacks permissionCallbacks(callbacks); + permissionCallbacks.DoDeny(); + return; + } + ++m_currentRequestId; + bool inserted = m_permissionRequests.insert(std::make_pair(m_currentRequestId, callbacks)).second; + + // Verify there are no duplicate insertions. + DCHECK(inserted); + + Send(new QtWebEngineHostMsg_RequestFileSystemAccessAsync( + routing_id(), m_currentRequestId, + url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL())); +} + +bool ContentSettingsObserverQt::AllowIndexedDB(const WebString &name, + const WebSecurityOrigin &/*origin*/) +{ + blink::WebFrame *frame = render_frame()->GetWebFrame(); + if (IsUniqueFrame(frame)) + return false; + + bool result = false; + Send(new QtWebEngineHostMsg_AllowIndexedDB( + routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), name.Utf16(), + &result)); + return result; +} + +bool ContentSettingsObserverQt::AllowStorage(bool local) +{ + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); + if (IsUniqueFrame(frame)) + return false; + + StoragePermissionsKey key(url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL(), local); + const auto permissions = m_cachedStoragePermissions.find(key); + if (permissions != m_cachedStoragePermissions.end()) + return permissions->second; + + bool result = false; + Send(new QtWebEngineHostMsg_AllowDOMStorage( + routing_id(), url::Origin(frame->GetSecurityOrigin()).GetURL(), + url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(), local, &result)); + m_cachedStoragePermissions[key] = result; + return result; +} + +void ContentSettingsObserverQt::OnRequestFileSystemAccessAsyncResponse(int request_id, bool allowed) +{ + auto it = m_permissionRequests.find(request_id); + if (it == m_permissionRequests.end()) + return; + + WebContentSettingCallbacks callbacks = it->second; + m_permissionRequests.erase(it); + + if (allowed) { + callbacks.DoAllow(); + return; + } + callbacks.DoDeny(); +} + +void ContentSettingsObserverQt::ClearBlockedContentSettings() +{ + m_cachedStoragePermissions.clear(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/renderer/content_settings_observer_qt.h b/src/core/renderer/content_settings_observer_qt.h new file mode 100644 index 0000000000000000000000000000000000000000..07dcbe350521ee498da3867d0204e2c1190f1425 --- /dev/null +++ b/src/core/renderer/content_settings_observer_qt.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_SETTINGS_OBSERVER_QT_H +#define CONTENT_SETTINGS_OBSERVER_QT_H + +#include "base/containers/flat_map.h" +#include "content/public/renderer/render_frame_observer.h" +#include "content/public/renderer/render_frame_observer_tracker.h" +#include "third_party/WebKit/public/platform/WebContentSettingsClient.h" +#include "url/gurl.h" + +namespace blink { +class WebContentSettingCallbacks; +class WebSecurityOrigin; +} + +namespace QtWebEngineCore { + +// Handles blocking content per content settings for each RenderFrame. +class ContentSettingsObserverQt + : public content::RenderFrameObserver + , public content::RenderFrameObserverTracker<ContentSettingsObserverQt> + , public blink::WebContentSettingsClient +{ +public: + ContentSettingsObserverQt(content::RenderFrame *render_frame); + ~ContentSettingsObserverQt() override; + + // blink::WebContentSettingsClient: + bool AllowDatabase(const blink::WebString &name, + const blink::WebString &display_name, + unsigned estimated_size) override; + void RequestFileSystemAccessAsync(const blink::WebContentSettingCallbacks &callbacks) override; + bool AllowIndexedDB(const blink::WebString &name, + const blink::WebSecurityOrigin &origin) override; + bool AllowStorage(bool local) override; + +private: + + // RenderFrameObserver implementation: + bool OnMessageReceived(const IPC::Message &message) override; + void DidCommitProvisionalLoad(bool is_new_navigation, + bool is_same_document_navigation) override; + void OnDestruct() override; + + // Message handlers. + void OnRequestFileSystemAccessAsyncResponse(int request_id, bool allowed); + + // Clears m_cachedStoragePermissions + void ClearBlockedContentSettings(); + + // Caches the result of AllowStorage. + using StoragePermissionsKey = std::pair<GURL, bool>; + base::flat_map<StoragePermissionsKey, bool> m_cachedStoragePermissions; + + int m_currentRequestId; + base::flat_map<int, blink::WebContentSettingCallbacks> m_permissionRequests; + + DISALLOW_COPY_AND_ASSIGN(ContentSettingsObserverQt); +}; + +} // namespace QtWebEngineCore + +#endif // RENDERER_CONTENT_SETTINGS_OBSERVER_QT_H diff --git a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp index 4350575abd7a2003a29fdb8cd7761b7be54a3c03..b24c05a37408cc14dce4ebddbefce9642aa673f8 100644 --- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp +++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp @@ -52,6 +52,7 @@ private Q_SLOTS: void setAndDeleteCookie(); void batchCookieTasks(); void basicFilter(); + void html5featureFilter(); private: QWebEngineProfile m_profile; @@ -219,5 +220,30 @@ void tst_QWebEngineCookieStore::basicFilter() QCOMPARE(cookieAddedSpy.count(), 2); } +void tst_QWebEngineCookieStore::html5featureFilter() +{ + QWebEnginePage page(&m_profile); + QWebEngineCookieStore *client = m_profile.cookieStore(); + + QAtomicInt accessTested = 0; + client->setCookieFilter([&](const QWebEngineCookieStore::FilterRequest &){ ++accessTested; return false;}); + + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + + page.load(QUrl("qrc:///resources/content.html")); + + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(loadSpy.takeFirst().takeFirst().toBool()); + QCOMPARE(accessTested.loadAcquire(), 0); + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression(".*Uncaught SecurityError.*sessionStorage.*")); + page.runJavaScript("sessionStorage.test = 5;"); + QTRY_COMPARE(accessTested.loadAcquire(), 1); + + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression(".*Uncaught SecurityError.*sessionStorage.*")); + QAtomicInt callbackTriggered = 0; + page.runJavaScript("sessionStorage.test", [&](const QVariant &v) { QVERIFY(!v.isValid()); callbackTriggered = 1; }); + QTRY_VERIFY(callbackTriggered); +} + QTEST_MAIN(tst_QWebEngineCookieStore) #include "tst_qwebenginecookiestore.moc"