WebKit Bugzilla
Attachment 361398 Details for
Bug 194271
: Allow pages to trigger programmatic paste from script on iOS
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Part 1 (v2)
bug-194271-20190207084001.patch (text/plain), 49.30 KB, created by
Wenson Hsieh
on 2019-02-07 08:40:01 PST
(
hide
)
Description:
Part 1 (v2)
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2019-02-07 08:40:01 PST
Size:
49.30 KB
patch
obsolete
>Subversion Revision: 241111 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index f496024ce162c248c55b417751be1bea9b264c5e..84c15cb57acd0733161dd9265d0ddcb8f376b9f6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,59 @@ >+2019-02-07 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Allow pages to trigger programmatic paste from script on iOS >+ https://bugs.webkit.org/show_bug.cgi?id=194271 >+ <rdar://problem/47808810> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add support for allowing script to trigger programmatic paste commands. Currently on macOS and iOS, the ability >+ to trigger programmatic paste (i.e. `document.execCommand('Paste');`) is disabled by default, such that >+ execCommand is simply a no-op that returns false. This policy is a privacy measure (common among other major >+ browsers) that prevents untrusted web content from sniffing content from the system pasteboard (even on user >+ interaction, since unintended user interaction occasionally happens as well!). >+ >+ In order to make it possible for web pages to programmatically paste without opening the door to privacy and >+ security issues, we make paste commands triggered from bindings present platform UI on iOS, in the form of a >+ callout bar with the single option to paste. This UI is dismissed upon any user interaction; furthermore, any >+ user interaction short of explicitly triggering the "Paste" action subsequently prevents the page from executing >+ the paste (and causes execCommand to return false). However, if the paste action is chosen by the user, we >+ instead follow through with the programmatic paste command. >+ >+ New tests to come in a followup patch. >+ >+ * WebCore.xcodeproj/project.pbxproj: >+ * dom/DOMPasteAccessPolicy.h: Added. >+ * dom/UserGestureIndicator.h: >+ (WebCore::UserGestureToken::domPasteAccessPolicy const): >+ (WebCore::UserGestureToken::didRequestDOMPasteAccess): >+ >+ Add helpers on UserGestureToken to update and query the current DOM paste access policy. The access policies are >+ "Pending" (i.e. pending a response from the user), "Granted" (the user has granted DOM paste access to the >+ page), or "Denied" (the user has prevented the page from reading the contents of the clipboard). When DOM paste >+ access is granted or rejected, make this decision sticky until the end of the current user gesture. >+ >+ * editing/EditorCommand.cpp: >+ (WebCore::executePaste): >+ (WebCore::executePasteAndMatchStyle): >+ (WebCore::executePasteAsPlainText): >+ (WebCore::executePasteAsQuotation): >+ >+ When executing a paste command where the source is DOM bindings, request DOM paste if needed before proceeding >+ with the paste. >+ >+ (WebCore::supportedPaste): >+ * loader/EmptyClients.cpp: >+ * page/EditorClient.h: >+ * page/Frame.cpp: >+ (WebCore::Frame::requestDOMPasteAccess): >+ >+ Add a helper method that requests access to the clipboard on behalf of script when pasting. >+ >+ * page/Frame.h: >+ * page/Settings.yaml: >+ >+ Introduce a new WebCore setting, used to gate DOM paste access requests. >+ > 2019-02-06 Keith Rollin <krollin@apple.com> > > Update .xcfilelist files >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 68247487d4360995925e7948224879923ff7c3c9..fb6982f7f5c85d902518e09362d3b4934764a5d5 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,123 @@ >+2019-02-07 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Allow pages to trigger programmatic paste from script on iOS >+ https://bugs.webkit.org/show_bug.cgi?id=194271 >+ <rdar://problem/47808810> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Shared/WebPreferences.yaml: >+ * Shared/WebPreferencesDefaultValues.h: >+ >+ Add an internal setting to enable or disable DOM paste access requests. This is on by default in iOS only >+ (excluding watchOS and Apple TV), and is additionally disabled on macOS. >+ >+ * UIProcess/API/gtk/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::requestDOMPasteAccess): >+ * UIProcess/API/gtk/PageClientImpl.h: >+ * UIProcess/API/wpe/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::requestDOMPasteAccess): >+ >+ Plumb DOM paste access requests from the web process (WebEditorClient) to the view (WKContentView). As per the >+ usual, this involves WebEditorClient, WebPage, WebPageProxy, PageClient and finally WKContentView. >+ >+ * UIProcess/API/wpe/PageClientImpl.h: >+ * UIProcess/PageClient.h: >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::requestDOMPasteAccess): >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/WebPageProxy.messages.in: >+ * UIProcess/ios/PageClientImplIOS.h: >+ * UIProcess/ios/PageClientImplIOS.mm: >+ (WebKit::PageClientImpl::requestDOMPasteAccess): >+ * UIProcess/ios/WKContentViewInteraction.h: >+ * UIProcess/ios/WKContentViewInteraction.mm: >+ (-[WKContentView setupInteraction]): >+ (-[WKContentView cleanupInteraction]): >+ (-[WKContentView resignFirstResponderForWebView]): >+ (-[WKContentView _webTouchEventsRecognized:]): >+ >+ Bail from any pending DOM paste access handler the moment we start handling touches on the web view, or if the >+ web view resigns first responder, or if the web process crashes. >+ >+ (-[WKContentView textInteractionGesture:shouldBeginAtPoint:]): >+ >+ Reject text selection gestures while waiting for DOM paste access. >+ >+ (-[WKContentView canPerformAction:withSender:]): >+ (-[WKContentView canPerformActionForWebView:withSender:]): >+ >+ If we're handling a DOM paste, always return YES to allow the callout bar to show the "Paste" option. >+ >+ (-[WKContentView _didHideMenu:]): >+ >+ If the menu is programmatically hidden by the app while handling a DOM paste request, immediately reject the DOM >+ paste request. >+ >+ (-[WKContentView pasteForWebView:]): >+ >+ Adjust -pasteForWebView: on WKContentView to first check whether there's an outstanding DOM paste completion >+ handler to invoke, instead of telling the page to execute a paste command. >+ >+ (-[WKContentView _handleDOMPasteRequestWithResult:]): >+ >+ Add a helper to take and invoke the current DOM paste completion handler (if it exists) with the given result, >+ and then dismiss the shared callout bar. Returns whether or not the paste completion handler exists. Invoked >+ from various sources of user interaction or significant state changes (e.g. following a web process crash in >+ -cleanupInteraction). >+ >+ (-[WKContentView _willPerformAction:sender:]): >+ (-[WKContentView _didPerformAction:sender:]): >+ >+ Add hooks to detect when WKContentView is executing an editing action. This is to ensure that the page doesn't >+ get stuck in a bad state in the case where WKWebView has been subclassed, overrides `-paste:`, and does not >+ invoke the superclass method (which calls back into `-[WKContentView pasteForWebView:]`). There are a few >+ possibilities here: >+ 1. WKWebView's `-paste:` action is not overridden. In this case, we will call back into `-pasteForWebView:`, >+ which will notice that we have a pending paste completion handler and invoke it. >+ 2. WKWebView's `-paste:` action is overridden and does not call back into the content view. In this case, we >+ will invoke the paste completion handler in `-_didPerformAction:sender:`. >+ 3. WKWebView's `-canPerformAction:withSender:` is overridden to include additional actions. In this case, we may >+ get a call to invoke a different action selector while waiting for a potential paste action. If this happens, >+ prevent the DOM paste in `-_willPerformAction:sender:` prior to handling the other action. >+ >+ (-[WKContentView handleKeyWebEvent:withCompletionHandler:]): >+ >+ Dismiss DOM paste UI upon handling any key event. >+ >+ (-[WKContentView showGlobalMenuControllerInRect:]): >+ (-[WKContentView hideGlobalMenuController]): >+ >+ Helper methods to present and dismiss the global UIMenuController, that accounts for available platform APIs for >+ presenting or dismissing the menu controller on iOS. >+ >+ (-[WKContentView _requestDOMPasteAccessWithElementRect:completionHandler:]): >+ (-[WKContentView _resetShowingTextStyle:]): Deleted. >+ >+ Rename this to `-_didHideMenu:`. >+ >+ * UIProcess/mac/PageClientImplMac.h: >+ * UIProcess/win/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::requestDOMPasteAccess): >+ * UIProcess/win/PageClientImpl.h: >+ * WebProcess/WebCoreSupport/WebEditorClient.cpp: >+ (WebKit::WebEditorClient::requestDOMPasteAccess): >+ * WebProcess/WebCoreSupport/WebEditorClient.h: >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::requestDOMPasteAccess): >+ >+ Add more plumbing and method stubs. >+ >+ (WebKit::WebPage::updateCurrentModifierState): >+ (WebKit::WebPage::rectForElementAtInteractionLocation const): >+ * WebProcess/WebPage/WebPage.h: >+ * WebProcess/WebPage/ios/WebPageIOS.mm: >+ (WebKit::WebPage::rectForElementAtInteractionLocation const): >+ (WebKit::WebPage::rectForElementAtInteractionLocation): Deleted. >+ >+ Mark this method as const, add a platform-agnostic stub, and adopt it for the purposes of determining where to >+ position the callout bar when pasting. >+ > 2019-02-06 Daniel Bates <dabates@apple.com> > > Move toNSEventModifierFlags() and toNSButtonNumber() to WebEventFactory.mm >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index 9a36586501c2dd39f6780b66302a81163da64397..3ed443fc1b7012717a9df8a12ee9f0204eec9b91 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,15 @@ >+2019-02-07 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Allow pages to trigger programmatic paste from script on iOS >+ https://bugs.webkit.org/show_bug.cgi?id=194271 >+ <rdar://problem/47808810> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ See WebCore and WebKit ChangeLogs for more details. >+ >+ * WebCoreSupport/WebEditorClient.h: >+ > 2019-02-06 Andy Estes <aestes@apple.com> > > [Payment Request] It should be possible to require a phonetic name for shipping contacts >diff --git a/Source/WebKitLegacy/win/ChangeLog b/Source/WebKitLegacy/win/ChangeLog >index e90cf1ac20f5f5080875b617bc64b8d4bda63d01..c01306e6f844425e93383322f91220b7b71ba3f8 100644 >--- a/Source/WebKitLegacy/win/ChangeLog >+++ b/Source/WebKitLegacy/win/ChangeLog >@@ -1,3 +1,13 @@ >+2019-02-07 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Allow pages to trigger programmatic paste from script on iOS >+ https://bugs.webkit.org/show_bug.cgi?id=194271 >+ <rdar://problem/47808810> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebCoreSupport/WebEditorClient.h: >+ > 2019-02-06 Daniel Bates <dabates@apple.com> > > Standardize on ControlKey instead of CtrlKey >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index aa3b41d8da8f40dfe3ed3fea640853ffede5c367..6151eb31241546faa92ad97c41b8fe58acb9abfd 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -4950,6 +4950,7 @@ > F48D2A7E2157182600C6752B /* FontAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2A712156DC0A00C6752B /* FontAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; }; > F48D2AA52159740D00C6752B /* ColorCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2AA32159740D00C6752B /* ColorCocoa.h */; }; > F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F49786871FF45FA500E060AB /* PasteboardItemInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ F4B422C4220C0568009E1E7D /* DOMPasteAccessPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B422C2220C0000009E1E7D /* DOMPasteAccessPolicy.h */; settings = {ATTRIBUTES = (Private, ); }; }; > F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; }; > F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; }; > F4D43D662188038B00ECECAC /* SerializedAttachmentData.h in Headers */ = {isa = PBXBuildFile; fileRef = F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -15180,6 +15181,7 @@ > F48D2AA42159740D00C6752B /* ColorCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ColorCocoa.mm; sourceTree = "<group>"; }; > F49786871FF45FA500E060AB /* PasteboardItemInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardItemInfo.h; sourceTree = "<group>"; }; > F49E98E421DEE6C1009AE55E /* EditAction.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = EditAction.cpp; sourceTree = "<group>"; }; >+ F4B422C2220C0000009E1E7D /* DOMPasteAccessPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DOMPasteAccessPolicy.h; sourceTree = "<group>"; }; > F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SerializedAttachmentData.h; sourceTree = "<group>"; }; > F4D9817D2195FBF6008230FC /* ChangeListTypeCommand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChangeListTypeCommand.h; sourceTree = "<group>"; }; > F4D9817E2195FBF6008230FC /* ChangeListTypeCommand.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ChangeListTypeCommand.cpp; sourceTree = "<group>"; }; >@@ -27505,6 +27507,7 @@ > A8185F3609765765005826D9 /* DOMImplementation.cpp */, > A8185F3309765765005826D9 /* DOMImplementation.h */, > 93EEC1E909C2877700C515D1 /* DOMImplementation.idl */, >+ F4B422C2220C0000009E1E7D /* DOMPasteAccessPolicy.h */, > 0F4966991DB408C100A274BB /* DOMPoint.h */, > 0F49669A1DB408C100A274BB /* DOMPoint.idl */, > 0F4966A21DB4091000A274BB /* DOMPointInit.h */, >@@ -29079,6 +29082,7 @@ > A9C6E4E40D745E05006442E9 /* DOMMimeType.h in Headers */, > A9C6E4E80D745E18006442E9 /* DOMMimeTypeArray.h in Headers */, > 1ACE53E80A8D18E70022947D /* DOMParser.h in Headers */, >+ F4B422C4220C0568009E1E7D /* DOMPasteAccessPolicy.h in Headers */, > 7A54881714E432A1006AE05A /* DOMPatchSupport.h in Headers */, > A9C6E4EC0D745E2B006442E9 /* DOMPlugin.h in Headers */, > A9C6E4F00D745E38006442E9 /* DOMPluginArray.h in Headers */, >diff --git a/Source/WebCore/dom/DOMPasteAccessPolicy.h b/Source/WebCore/dom/DOMPasteAccessPolicy.h >new file mode 100644 >index 0000000000000000000000000000000000000000..7e95a1e8b66d48da689106fb2808e6830194c827 >--- /dev/null >+++ b/Source/WebCore/dom/DOMPasteAccessPolicy.h >@@ -0,0 +1,36 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+namespace WebCore { >+ >+enum class DOMPasteAccessPolicy : uint8_t { >+ Pending, >+ Denied, >+ Granted >+}; >+ >+} >diff --git a/Source/WebCore/dom/UserGestureIndicator.h b/Source/WebCore/dom/UserGestureIndicator.h >index 5a1cb9ea8a293a9f26710c869318258e04d7ee03..81692f749c2784602f2f05a10c22d7fb6b2cb4dc 100644 >--- a/Source/WebCore/dom/UserGestureIndicator.h >+++ b/Source/WebCore/dom/UserGestureIndicator.h >@@ -25,6 +25,7 @@ > > #pragma once > >+#include "DOMPasteAccessPolicy.h" > #include <wtf/Function.h> > #include <wtf/Noncopyable.h> > #include <wtf/Optional.h> >@@ -63,6 +64,9 @@ public: > m_destructionObservers.append(WTFMove(observer)); > } > >+ DOMPasteAccessPolicy domPasteAccessPolicy() const { return m_domPasteAccessPolicy; } >+ void didRequestDOMPasteAccess(bool granted) { m_domPasteAccessPolicy = granted ? DOMPasteAccessPolicy::Granted : DOMPasteAccessPolicy::Denied; } >+ > private: > UserGestureToken(ProcessingUserGestureState state, UserGestureType gestureType) > : m_state(state) >@@ -73,6 +77,7 @@ private: > ProcessingUserGestureState m_state = NotProcessingUserGesture; > Vector<WTF::Function<void (UserGestureToken&)>> m_destructionObservers; > UserGestureType m_gestureType; >+ DOMPasteAccessPolicy m_domPasteAccessPolicy { DOMPasteAccessPolicy::Pending }; > }; > > class UserGestureIndicator { >diff --git a/Source/WebCore/editing/EditorCommand.cpp b/Source/WebCore/editing/EditorCommand.cpp >index 0b3bbb9be69569eb82cf054dc24c715e7e4ad438..9494709dc6f159c08172b6bfcb22873165d46525 100644 >--- a/Source/WebCore/editing/EditorCommand.cpp >+++ b/Source/WebCore/editing/EditorCommand.cpp >@@ -908,8 +908,13 @@ static bool executePaste(Frame& frame, Event*, EditorCommandSource source, const > if (source == CommandFromMenuOrKeyBinding) { > UserTypingGestureIndicator typingGestureIndicator(frame); > frame.editor().paste(); >- } else >- frame.editor().paste(); >+ return true; >+ } >+ >+ if (!frame.requestDOMPasteAccess()) >+ return false; >+ >+ frame.editor().paste(); > return true; > } > >@@ -934,8 +939,13 @@ static bool executePasteAndMatchStyle(Frame& frame, Event*, EditorCommandSource > if (source == CommandFromMenuOrKeyBinding) { > UserTypingGestureIndicator typingGestureIndicator(frame); > frame.editor().pasteAsPlainText(); >- } else >- frame.editor().pasteAsPlainText(); >+ return true; >+ } >+ >+ if (!frame.requestDOMPasteAccess()) >+ return false; >+ >+ frame.editor().pasteAsPlainText(); > return true; > } > >@@ -944,8 +954,13 @@ static bool executePasteAsPlainText(Frame& frame, Event*, EditorCommandSource so > if (source == CommandFromMenuOrKeyBinding) { > UserTypingGestureIndicator typingGestureIndicator(frame); > frame.editor().pasteAsPlainText(); >- } else >- frame.editor().pasteAsPlainText(); >+ return true; >+ } >+ >+ if (!frame.requestDOMPasteAccess()) >+ return false; >+ >+ frame.editor().pasteAsPlainText(); > return true; > } > >@@ -954,8 +969,13 @@ static bool executePasteAsQuotation(Frame& frame, Event*, EditorCommandSource so > if (source == CommandFromMenuOrKeyBinding) { > UserTypingGestureIndicator typingGestureIndicator(frame); > frame.editor().pasteAsQuotation(); >- } else >- frame.editor().pasteAsQuotation(); >+ return true; >+ } >+ >+ if (!frame.requestDOMPasteAccess()) >+ return false; >+ >+ frame.editor().pasteAsQuotation(); > return true; > } > >@@ -1220,7 +1240,8 @@ static bool supportedPaste(Frame* frame) > if (!frame) > return false; > >- bool defaultValue = frame->settings().javaScriptCanAccessClipboard() && frame->settings().DOMPasteAllowed(); >+ auto& settings = frame->settings(); >+ bool defaultValue = (settings.javaScriptCanAccessClipboard() && settings.DOMPasteAllowed()) || settings.domPasteAccessRequestsEnabled(); > > EditorClient* client = frame->editor().client(); > return client ? client->canPaste(frame, defaultValue) : defaultValue; >diff --git a/Source/WebCore/loader/EmptyClients.cpp b/Source/WebCore/loader/EmptyClients.cpp >index fb02baf6755590846fc0279a333aca3c1fd07093..6c2dbdf67211a0b8b15283bf0b74cb863b0a6d2c 100644 >--- a/Source/WebCore/loader/EmptyClients.cpp >+++ b/Source/WebCore/loader/EmptyClients.cpp >@@ -190,6 +190,8 @@ private: > void registerRedoStep(UndoStep&) final; > void clearUndoRedoOperations() final { } > >+ bool requestDOMPasteAccess() final { return false; } >+ > bool canCopyCut(Frame*, bool defaultValue) const final { return defaultValue; } > bool canPaste(Frame*, bool defaultValue) const final { return defaultValue; } > bool canUndo() const final { return false; } >diff --git a/Source/WebCore/page/EditorClient.h b/Source/WebCore/page/EditorClient.h >index 37bf1823a98c2d9e52f3d02cbf5bcffaee358c44..6e0d0bee67a4d4590423b17e92e201847ab84a5c 100644 >--- a/Source/WebCore/page/EditorClient.h >+++ b/Source/WebCore/page/EditorClient.h >@@ -98,6 +98,8 @@ public: > virtual void requestCandidatesForSelection(const VisibleSelection&) { } > virtual void handleAcceptedCandidateWithSoftSpaces(TextCheckingResult) { } > >+ virtual bool requestDOMPasteAccess() = 0; >+ > // Notify an input method that a composition was voluntarily discarded by WebCore, so that it could clean up too. > // This function is not called when a composition is closed per a request from an input method. > virtual void discardedComposition(Frame*) = 0; >diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp >index a4f83b27f0b6ecaf653321d6a554457ece669daa..0167d6e4d9766ed23058b998663315c07756c318 100644 >--- a/Source/WebCore/page/Frame.cpp >+++ b/Source/WebCore/page/Frame.cpp >@@ -95,6 +95,7 @@ > #include "TextResourceDecoder.h" > #include "UserContentController.h" > #include "UserContentURLPattern.h" >+#include "UserGestureIndicator.h" > #include "UserScript.h" > #include "UserTypingGestureIndicator.h" > #include "VisibleUnits.h" >@@ -658,6 +659,35 @@ bool Frame::selectionChangeCallbacksDisabled() const > } > #endif // PLATFORM(IOS_FAMILY) > >+bool Frame::requestDOMPasteAccess() >+{ >+ if (m_settings->javaScriptCanAccessClipboard() && m_settings->DOMPasteAllowed()) >+ return true; >+ >+ if (!m_settings->domPasteAccessRequestsEnabled() || !UserGestureIndicator::processingUserGesture()) >+ return false; >+ >+ if (!m_doc) >+ return false; >+ >+ auto gestureToken = UserGestureIndicator::currentUserGesture(); >+ switch (gestureToken->domPasteAccessPolicy()) { >+ case DOMPasteAccessPolicy::Granted: >+ return true; >+ case DOMPasteAccessPolicy::Denied: >+ return false; >+ case DOMPasteAccessPolicy::Pending: { >+ auto* client = m_editor->client(); >+ if (!client) >+ return false; >+ >+ bool granted = client->requestDOMPasteAccess(); >+ gestureToken->didRequestDOMPasteAccess(granted); >+ return granted; >+ } >+ } >+} >+ > void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize) > { > if (!view()) >diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h >index 8ad13d6e1ccc27a638157d811ab1cf48ce2e2069..74f6f4f03638c6b2a4736119153e5f34dbfa46a0 100644 >--- a/Source/WebCore/page/Frame.h >+++ b/Source/WebCore/page/Frame.h >@@ -175,6 +175,8 @@ public: > bool hasHadUserInteraction() const { return m_hasHadUserInteraction; } > void setHasHadUserInteraction() { m_hasHadUserInteraction = true; } > >+ bool requestDOMPasteAccess(); >+ > // ======== All public functions below this point are candidates to move out of Frame into another class. ======== > > WEBCORE_EXPORT void injectUserScripts(UserScriptInjectionTime); >diff --git a/Source/WebCore/page/Settings.yaml b/Source/WebCore/page/Settings.yaml >index 976c84c4a0f1873754de891c4f678a14e9192a00..54585beb664dd11980692e95195a0c203fc2f173 100644 >--- a/Source/WebCore/page/Settings.yaml >+++ b/Source/WebCore/page/Settings.yaml >@@ -344,6 +344,9 @@ mediaEnabled: > DOMPasteAllowed: > initial: false > >+domPasteAccessRequestsEnabled: >+ initial: false >+ > # When enabled, window.blur() does not change focus, and > # window.focus() only changes focus when invoked from the context that > # created the window. >diff --git a/Source/WebKit/Shared/WebPreferences.yaml b/Source/WebKit/Shared/WebPreferences.yaml >index cce4ace8356325e7a0a00e523f9e4c992f9152ff..405b7a18b138c4bb5bc97aeea5e1c7790730d60b 100644 >--- a/Source/WebKit/Shared/WebPreferences.yaml >+++ b/Source/WebKit/Shared/WebPreferences.yaml >@@ -1534,6 +1534,13 @@ AdClickAttributionEnabled: > webcoreBinding: RuntimeEnabledFeatures > category: internal > >+DOMPasteAccessRequestsEnabled: >+ type: bool >+ defaultValue: DEFAULT_DOM_PASTE_ACCESS_REQUESTS_ENABLED >+ humanReadableName: "DOM Paste Access Requests" >+ humanReadableDescription: "Enable DOM Paste Access Requests" >+ category: internal >+ > # Deprecated > > ICECandidateFilteringEnabled: >diff --git a/Source/WebKit/Shared/WebPreferencesDefaultValues.h b/Source/WebKit/Shared/WebPreferencesDefaultValues.h >index 0a52167c20fa5ae0404734784a49ec91c9106ff7..6e82173b0cb2cbe91531041dec2708c50dfbfe83 100644 >--- a/Source/WebKit/Shared/WebPreferencesDefaultValues.h >+++ b/Source/WebKit/Shared/WebPreferencesDefaultValues.h >@@ -242,3 +242,9 @@ bool defaultCustomPasteboardDataEnabled(); > #define DEFAULT_INPUT_TYPE_COLOR_ENABLED true > #define DEFAULT_DATALIST_ELEMENT_ENABLED true > #endif >+ >+#if PLATFORM(IOS) >+#define DEFAULT_DOM_PASTE_ACCESS_REQUESTS_ENABLED true >+#else >+#define DEFAULT_DOM_PASTE_ACCESS_REQUESTS_ENABLED false >+#endif >diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >index 317859d75335e7ddca0307204dcce5e4de1e012e..15e379370ed0b1712074ca24574bb916e9f85a6a 100644 >--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >@@ -473,4 +473,9 @@ bool PageClientImpl::decidePolicyForInstallMissingMediaPluginsPermissionRequest( > } > #endif > >+void PageClientImpl::requestDOMPasteAccess(const IntRect&, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ completionHandler(false); >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h >index 6dea8f39fd8151d464ce64a15e530ce96f9c4de3..4ee042c76b9d5ff6c8599ab267fecaa9011d85c0 100644 >--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h >+++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h >@@ -145,6 +145,8 @@ private: > > void didFinishProcessingAllPendingMouseEvents() final { } > >+ void requestDOMPasteAccess(const WebCore::IntRect&, CompletionHandler<void(bool)>&&) final; >+ > #if ENABLE(VIDEO) && USE(GSTREAMER) > bool decidePolicyForInstallMissingMediaPluginsPermissionRequest(InstallMissingMediaPluginsPermissionRequest&) override; > #endif >diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp >index 22336150feabf8c40638ffa905cc4217b84014fd..ad159d765e7e3d71b532584b96edc1450c5a8326 100644 >--- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp >+++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp >@@ -384,4 +384,9 @@ void PageClientImpl::beganExitFullScreen(const WebCore::IntRect& /* initialFrame > > #endif // ENABLE(FULLSCREEN_API) > >+void PageClientImpl::requestDOMPasteAccess(const WebCore::IntRect&, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ completionHandler(false); >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h >index b699f29f9b2870a6be0b3ffb44a7896e23f85c46..304ccd78feb45a51952245af1c502a029f4f45b6 100644 >--- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h >+++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h >@@ -143,6 +143,8 @@ private: > > void didFinishProcessingAllPendingMouseEvents() final { } > >+ void requestDOMPasteAccess(const WebCore::IntRect&, CompletionHandler<void(bool)>&&) final; >+ > WebCore::UserInterfaceLayoutDirection userInterfaceLayoutDirection() override; > > WKWPE::View& m_view; >diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h >index 38c6552bb1e8a95d02a1822387a0228300f0eb80..3bdd1fff89fdc8e27b32c3c3a8baf6809b494599 100644 >--- a/Source/WebKit/UIProcess/PageClient.h >+++ b/Source/WebKit/UIProcess/PageClient.h >@@ -465,6 +465,8 @@ public: > virtual void didChangeDragCaretRect(const WebCore::IntRect& previousCaretRect, const WebCore::IntRect& caretRect) = 0; > #endif > >+ virtual void requestDOMPasteAccess(const WebCore::IntRect& elementRect, CompletionHandler<void(bool)>&&) = 0; >+ > #if ENABLE(ATTACHMENT_ELEMENT) > virtual void didInsertAttachment(API::Attachment&, const String& source) { } > virtual void didRemoveAttachment(API::Attachment&) { } >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 7ab56f111e61149a6f1429f54a0d3b2aba748b37..bd72d7ec2254d2735e09cc1fc29a10afb1f46962 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -5436,6 +5436,11 @@ void WebPageProxy::setNeedsPlainTextQuirk(bool needsPlainTextQuirk) > m_needsPlainTextQuirk = needsPlainTextQuirk; > } > >+void WebPageProxy::requestDOMPasteAccess(const WebCore::IntRect& elementRect, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ m_pageClient->requestDOMPasteAccess(elementRect, WTFMove(completionHandler)); >+} >+ > // BackForwardList > > void WebPageProxy::backForwardAddItem(BackForwardListItemState&& itemState) >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index 7be91943890b75d0e28ca3701f5b467ec08747a2..c76266e87aa0f0eb54e0a006ae27eb66330e61d9 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -1652,6 +1652,8 @@ private: > void setNeedsHiddenContentEditableQuirk(bool); > void setNeedsPlainTextQuirk(bool); > >+ void requestDOMPasteAccess(const WebCore::IntRect&, CompletionHandler<void(bool)>&&); >+ > // Back/Forward list management > void backForwardAddItem(BackForwardListItemState&&); > void backForwardGoToItem(const WebCore::BackForwardItemIdentifier&, SandboxExtension::Handle&); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in >index 7875eab4311314a4d87a92207d512e53de28ec71..7d07ca89070e16905aeff0d684cd8054329595cc 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in >@@ -254,6 +254,7 @@ messages -> WebPageProxy { > SetHasHadSelectionChangesFromUserInteraction(bool hasHadUserSelectionChanges) > SetNeedsHiddenContentEditableQuirk(bool needsHiddenContentEditableQuirk) > SetNeedsPlainTextQuirk(bool needsPlainTextQuirk) >+ RequestDOMPasteAccess(WebCore::IntRect elementRect) -> (bool granted) Delayed > > # Find messages > DidCountStringMatches(String string, uint32_t matchCount) >diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.h b/Source/WebKit/UIProcess/ios/PageClientImplIOS.h >index a3c6d3af89d506677958704dd901667db41e96e1..d0d03847d0e2e3b57c75338267aaa204a02a3366 100644 >--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.h >+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.h >@@ -224,6 +224,8 @@ private: > void requestPasswordForQuickLookDocument(const String& fileName, WTF::Function<void(const String&)>&&) override; > #endif > >+ void requestDOMPasteAccess(const WebCore::IntRect& elementRect, CompletionHandler<void(bool)>&&) final; >+ > #if ENABLE(DATA_INTERACTION) > void didPerformDragOperation(bool handled) override; > void didHandleDragStartRequest(bool started) override; >diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >index 1509cc27429943acbdc35a68f255f9eebbad6272..5e0a6907b80336778858fb050ec010a0fc98b25c 100644 >--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >@@ -837,6 +837,11 @@ void PageClientImpl::requestPasswordForQuickLookDocument(const String& fileName, > } > #endif > >+void PageClientImpl::requestDOMPasteAccess(const WebCore::IntRect& elementRect, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ [m_contentView _requestDOMPasteAccessWithElementRect:elementRect completionHandler:WTFMove(completionHandler)]; >+} >+ > #if HAVE(PENCILKIT) > RetainPtr<WKDrawingView> PageClientImpl::createDrawingView(WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID) > { >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >index 38be0d0e2acfc46a2f969ceddbf021b016ed9a6c..503248cbcb352961239f450582e73b6c49e82249 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >@@ -49,6 +49,7 @@ > #import <WebCore/Color.h> > #import <WebCore/FloatQuad.h> > #import <wtf/BlockPtr.h> >+#import <wtf/CompletionHandler.h> > #import <wtf/Forward.h> > #import <wtf/OptionSet.h> > #import <wtf/Vector.h> >@@ -315,6 +316,7 @@ struct WKAutoCorrectionData { > BOOL _focusRequiresStrongPasswordAssistance; > > BOOL _hasSetUpInteractions; >+ CompletionHandler<void(bool)> _domPasteRequestHandler; > > #if ENABLE(DATA_INTERACTION) > WebKit::DragDropInteractionState _dragDropInteractionState; >@@ -436,6 +438,8 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW) > - (void)_accessibilityClearSelection; > - (WKFormInputSession *)_formInputSession; > >+- (void)_requestDOMPasteAccessWithElementRect:(const WebCore::IntRect&)elementRect completionHandler:(CompletionHandler<void(bool)>&&)completionHandler; >+ > @property (nonatomic, readonly) WebKit::InteractionInformationAtPosition currentPositionInformation; > - (void)doAfterPositionInformationUpdate:(void (^)(WebKit::InteractionInformationAtPosition))action forRequest:(WebKit::InteractionInformationRequest)request; > - (BOOL)ensurePositionInformationIsUpToDate:(WebKit::InteractionInformationRequest)request; >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >index de7c5ca0820146735eaa3a5f022f10959cf804c8..1878389f3a27b09613b2cb11854eebab7ba52529 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >@@ -739,7 +739,7 @@ - (void)setupInteraction > #endif > > NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; >- [center addObserver:self selector:@selector(_resetShowingTextStyle:) name:UIMenuControllerDidHideMenuNotification object:nil]; >+ [center addObserver:self selector:@selector(_didHideMenu:) name:UIMenuControllerDidHideMenuNotification object:nil]; > [center addObserver:self selector:@selector(_keyboardDidRequestDismissal:) name:UIKeyboardPrivateDidRequestDismissalNotification object:nil]; > > _showingTextStyleOptions = NO; >@@ -885,6 +885,7 @@ - (void)cleanupInteraction > #if ENABLE(POINTER_EVENTS) > [self _resetPanningPreventionFlags]; > #endif >+ [self _handleDOMPasteRequestWithResult:NO]; > } > > - (void)_removeDefaultGestureRecognizers >@@ -1137,8 +1138,10 @@ - (BOOL)resignFirstResponderForWebView > > bool superDidResign = [super resignFirstResponder]; > >- if (superDidResign) >+ if (superDidResign) { >+ [self _handleDOMPasteRequestWithResult:NO]; > _page->activityStateDidChange(WebCore::ActivityState::IsFocused); >+ } > > return superDidResign; > } >@@ -1167,8 +1170,10 @@ - (void)_webTouchEventsRecognized:(UIWebTouchEventsGestureRecognizer *)gestureRe > const _UIWebTouchEvent* lastTouchEvent = gestureRecognizer.lastTouchEvent; > > _lastInteractionLocation = lastTouchEvent->locationInDocumentCoordinates; >- if (lastTouchEvent->type == UIWebTouchEventTouchBegin) >+ if (lastTouchEvent->type == UIWebTouchEventTouchBegin) { >+ [self _handleDOMPasteRequestWithResult:NO]; > _layerTreeTransactionIdAtLastTouchStart = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).lastCommittedLayerTreeTransactionID(); >+ } > > #if ENABLE(TOUCH_EVENTS) > WebKit::NativeWebTouchEvent nativeWebTouchEvent(lastTouchEvent); >@@ -1966,6 +1971,9 @@ - (BOOL)textInteractionGesture:(UIWKGestureType)gesture shouldBeginAtPoint:(CGPo > if (!_webView.configuration._textInteractionGesturesEnabled) > return NO; > >+ if (_domPasteRequestHandler) >+ return NO; >+ > if (_suppressSelectionAssistantReasons) > return NO; > >@@ -2391,7 +2399,10 @@ - (NSArray *)supportedPasteboardTypesForCurrentSelection > #define FORWARD_ACTION_TO_WKWEBVIEW(_action) \ > - (void)_action:(id)sender \ > { \ >+ SEL action = @selector(_action:);\ >+ [self _willPerformAction:action sender:sender];\ > [_webView _action:sender]; \ >+ [self _didPerformAction:action sender:sender];\ > } > > FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKWEBVIEW) >@@ -2636,11 +2647,17 @@ - (void)tintColorDidChange > > - (BOOL)canPerformAction:(SEL)action withSender:(id)sender > { >+ if (_domPasteRequestHandler) >+ return action == @selector(paste:); >+ > return [_webView canPerformAction:action withSender:sender]; > } > > - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender > { >+ if (_domPasteRequestHandler) >+ return action == @selector(paste:); >+ > if (action == @selector(_nextAccessoryTab:)) > return hasFocusedElement(_focusedElementInformation) && _focusedElementInformation.hasNextNode; > if (action == @selector(_previousAccessoryTab:)) >@@ -2787,10 +2804,11 @@ - (id)targetForActionForWebView:(SEL)action withSender:(id)sender > return [super targetForAction:action withSender:sender]; > } > >-- (void)_resetShowingTextStyle:(NSNotification *)notification >+- (void)_didHideMenu:(NSNotification *)notification > { > _showingTextStyleOptions = NO; > [_textSelectionAssistant hideTextStyleOptions]; >+ [self _handleDOMPasteRequestWithResult:NO]; > } > > - (void)_keyboardDidRequestDismissal:(NSNotification *)notification >@@ -2812,6 +2830,9 @@ - (void)cutForWebView:(id)sender > > - (void)pasteForWebView:(id)sender > { >+ if (sender == UIMenuController.sharedMenuController && [self _handleDOMPasteRequestWithResult:YES]) >+ return; >+ > _page->executeEditCommand("paste"_s); > } > >@@ -2941,6 +2962,28 @@ - (void)_accessibilityClearSelection > _page->storeSelectionForAccessibility(false); > } > >+- (BOOL)_handleDOMPasteRequestWithResult:(BOOL)allowPaste >+{ >+ if (auto pasteHandler = WTFMove(_domPasteRequestHandler)) { >+ [self hideGlobalMenuController]; >+ pasteHandler(allowPaste); >+ return YES; >+ } >+ return NO; >+} >+ >+- (void)_willPerformAction:(SEL)action sender:(id)sender >+{ >+ if (action != @selector(paste:)) >+ [self _handleDOMPasteRequestWithResult:NO]; >+} >+ >+- (void)_didPerformAction:(SEL)action sender:(id)sender >+{ >+ if (action == @selector(paste:)) >+ [self _handleDOMPasteRequestWithResult:NO]; >+} >+ > // UIWKInteractionViewProtocol > > static inline WebKit::GestureType toGestureType(UIWKGestureType gestureType) >@@ -4096,6 +4139,8 @@ - (void)handleKeyWebEvent:(::WebEvent *)theEvent > > - (void)handleKeyWebEvent:(::WebEvent *)theEvent withCompletionHandler:(void (^)(::WebEvent *theEvent, BOOL wasHandled))completionHandler > { >+ [self _handleDOMPasteRequestWithResult:NO]; >+ > _keyWebEventHandler = makeBlockPtr(completionHandler); > _page->handleKeyboardEvent(WebKit::NativeWebKeyboardEvent(theEvent)); > } >@@ -4785,6 +4830,47 @@ - (void)_didUpdateInputMode:(WebCore::InputMode)mode > #endif > } > >+- (void)showGlobalMenuControllerInRect:(CGRect)rect >+{ >+ UIMenuController *controller = UIMenuController.sharedMenuController; >+#if HAVE(MENU_CONTROLLER_SHOW_HIDE_API) >+ [controller showMenuFromView:self rect:rect]; >+#else >+ [controller setTargetRect:rect inView:self]; >+ [controller setMenuVisible:YES animated:YES]; >+#endif >+} >+ >+- (void)hideGlobalMenuController >+{ >+ UIMenuController *controller = UIMenuController.sharedMenuController; >+#if HAVE(MENU_CONTROLLER_SHOW_HIDE_API) >+ [controller hideMenuFromView:self]; >+#else >+ [controller setMenuVisible:NO animated:YES]; >+#endif >+} >+ >+- (void)_requestDOMPasteAccessWithElementRect:(const WebCore::IntRect&)elementRect completionHandler:(CompletionHandler<void(bool)>&&)completionHandler >+{ >+ if (auto existingCompletionHandler = std::exchange(_domPasteRequestHandler, WTFMove(completionHandler))) { >+ ASSERT_NOT_REACHED(); >+ existingCompletionHandler(false); >+ } >+ >+ WebCore::IntRect menuControllerRect = elementRect; >+ >+ const CGFloat maximumElementWidth = 300; >+ const CGFloat maximumElementHeight = 120; >+ if (elementRect.isEmpty() || elementRect.width() > maximumElementWidth || elementRect.height() > maximumElementHeight) { >+ const CGFloat interactionLocationMargin = 10; >+ menuControllerRect = { WebCore::IntPoint(_lastInteractionLocation), { } }; >+ menuControllerRect.inflate(interactionLocationMargin); >+ } >+ >+ [self showGlobalMenuControllerInRect:menuControllerRect]; >+} >+ > - (void)_didReceiveEditorStateUpdateAfterFocus > { > [self _updateInitialWritingDirectionIfNecessary]; >diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h >index 4707a0202e42a828d5a50ed58be4e30f3a88a0b9..d242c05c1d26c4380a27d044d54dc6cbf4eb22cb 100644 >--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h >+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h >@@ -30,6 +30,7 @@ > #include "CorrectionPanel.h" > #include "PageClientImplCocoa.h" > #include "WebFullScreenManagerProxy.h" >+#include <wtf/CompletionHandler.h> > #include <wtf/RetainPtr.h> > > @class WKEditorUndoTarget; >@@ -215,6 +216,8 @@ private: > void willRecordNavigationSnapshot(WebBackForwardListItem&) override; > void didRemoveNavigationGestureSnapshot() override; > >+ void requestDOMPasteAccess(const WebCore::IntRect&, CompletionHandler<void(bool)>&& completion) final { completion(false); } >+ > NSView *activeView() const; > NSWindow *activeWindow() const; > >diff --git a/Source/WebKit/UIProcess/win/PageClientImpl.cpp b/Source/WebKit/UIProcess/win/PageClientImpl.cpp >index 170c2d7763962af02f32b4f8b5ed029b679f6ff1..912b4a99c724d62d3a547ba5b4367b1bb31abcb8 100644 >--- a/Source/WebKit/UIProcess/win/PageClientImpl.cpp >+++ b/Source/WebKit/UIProcess/win/PageClientImpl.cpp >@@ -357,4 +357,9 @@ HWND PageClientImpl::viewWidget() > return m_view.window(); > } > >+void PageClientImpl::requestDOMPasteAccess(const IntRect&, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ completionHandler(false); >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/win/PageClientImpl.h b/Source/WebKit/UIProcess/win/PageClientImpl.h >index 66572bb14058aacff5fac3fdd75106c8b075ef5a..e8426c963ecb6117c40d2a2482a3aefe2c08ff03 100644 >--- a/Source/WebKit/UIProcess/win/PageClientImpl.h >+++ b/Source/WebKit/UIProcess/win/PageClientImpl.h >@@ -142,6 +142,8 @@ private: > > void didFinishProcessingAllPendingMouseEvents() final { } > >+ void requestDOMPasteAccess(const WebCore::IntRect&, CompletionHandler<void(bool)>&&) final; >+ > // Members of PageClientImpl class > DefaultUndoController m_undoController; > >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >index 8f2181bebf181c3dcd787fb4b9fbd620c9d00d7f..96a4dd18f214b594328c5078d7e22555ed7e7f3e 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >@@ -359,6 +359,11 @@ void WebEditorClient::redo() > m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(UndoOrRedo::Redo), Messages::WebPageProxy::ExecuteUndoRedo::Reply()); > } > >+bool WebEditorClient::requestDOMPasteAccess() >+{ >+ return m_page->requestDOMPasteAccess(); >+} >+ > #if PLATFORM(WIN) > void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event) > { >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >index 4720b71175412a59a229bc47106dab2da3c8756e..7be8ddfca3f6d0ca897b7e685ce1993fb80023d8 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >@@ -89,6 +89,8 @@ private: > void registerRedoStep(WebCore::UndoStep&) final; > void clearUndoRedoOperations() final; > >+ bool requestDOMPasteAccess() final; >+ > bool canCopyCut(WebCore::Frame*, bool defaultValue) const final; > bool canPaste(WebCore::Frame*, bool defaultValue) const final; > bool canUndo() const final; >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index de34617e40fc26758000fc4ec9b590d2c9acf449..96cd4422c39080aedf2158a0dc986f7e0829bc24 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -6425,6 +6425,15 @@ void WebPage::didCompleteShareSheet(bool wasGranted, ShareSheetCallbackID callba > callback(wasGranted); > } > >+bool WebPage::requestDOMPasteAccess() >+{ >+ bool granted = false; >+ if (!sendSyncWithDelayedReply(Messages::WebPageProxy::RequestDOMPasteAccess(rectForElementAtInteractionLocation()), Messages::WebPageProxy::RequestDOMPasteAccess::Reply(granted))) >+ return false; >+ >+ return granted; >+} >+ > void WebPage::simulateDeviceOrientationChange(double alpha, double beta, double gamma) > { > #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) >@@ -6498,7 +6507,16 @@ void WebPage::didFinishLoadingApplicationManifest(uint64_t coreCallbackID, const > void WebPage::updateCurrentModifierState(OptionSet<PlatformEvent::Modifier> modifiers) > { > PlatformKeyboardEvent::setCurrentModifierState(modifiers); >-} >+} >+ >+#if !PLATFORM(IOS_FAMILY) >+ >+WebCore::IntRect WebPage::rectForElementAtInteractionLocation() const >+{ >+ return { }; >+} >+ >+#endif // !PLATFORM(IOS_FAMILY) > > } // namespace WebKit > >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h >index a1a0294aa5a6d5af92380413dddc4e33a2ff3ff8..db8f68d0f44efe81d6b28d5e6e00976d7bf584e0 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.h >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h >@@ -658,7 +658,6 @@ public: > void setFocusedElementValue(const String&); > void setFocusedElementValueAsNumber(double); > void setFocusedElementSelectedIndex(uint32_t index, bool allowMultipleSelection); >- WebCore::IntRect rectForElementAtInteractionLocation(); > void updateSelectionAppearance(); > void getSelectionContext(CallbackID); > void handleTwoFingerTapAtPoint(const WebCore::IntPoint&, uint64_t requestID); >@@ -1145,6 +1144,9 @@ public: > return sendSync(WTFMove(message), WTFMove(reply), m_pageID, Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend); > } > >+ bool requestDOMPasteAccess(); >+ WebCore::IntRect rectForElementAtInteractionLocation() const; >+ > private: > WebPage(uint64_t pageID, WebPageCreationParameters&&); > >diff --git a/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm b/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm >index 5d1b1dd90697cf80c4819a2a3e6964041b8eb825..aeca58cd2417834e889ff82892db77368f7d64ca 100644 >--- a/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm >+++ b/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm >@@ -517,7 +517,7 @@ void WebPage::advanceToNextMisspelling(bool) > notImplemented(); > } > >-IntRect WebPage::rectForElementAtInteractionLocation() >+IntRect WebPage::rectForElementAtInteractionLocation() const > { > HitTestResult result = m_page->mainFrame().eventHandler().hitTestResultAtPoint(m_lastInteractionLocation, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent); > Node* hitNode = result.innerNode(); >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h b/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h >index f0f968b7e2b66c891dc14b6c1faaf0b8bbe1d19e..55f40e0b53b1266b68fce4e3898e883cce9a72a7 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h >@@ -81,6 +81,7 @@ private: > String replacementURLForResource(Ref<WebCore::SharedBuffer>&& resourceData, const String& mimeType) final; > > void setInsertionPasteboard(const String&) final; >+ bool requestDOMPasteAccess() final { return false; } > > #if USE(APPKIT) > void uppercaseWord() final; >diff --git a/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h b/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h >index 7a6edde8193613859a31d2f0d2ebb35f822c5d2b..cc5e4d645be56704a092d11fc006c32313995adb 100644 >--- a/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h >+++ b/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h >@@ -115,6 +115,8 @@ private: > void requestCheckingOfString(WebCore::TextCheckingRequest&, const WebCore::VisibleSelection&) final { } > bool performTwoStepDrop(WebCore::DocumentFragment&, WebCore::Range&, bool) final { return false; } > >+ bool requestDOMPasteAccess() final { return false; } >+ > WebCore::TextCheckerClient* textChecker() final { return this; } > > WebView* m_webView;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 194271
:
361202
|
361212
|
361252
|
361305
|
361306
|
361316
|
361350
|
361351
|
361397
|
361398
|
361537
|
361547
|
361582
|
361702
|
361837
|
361847