WebKit Bugzilla
Attachment 361305 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
bug-194271-20190206105317.patch (text/plain), 48.12 KB, created by
Wenson Hsieh
on 2019-02-06 10:53:17 PST
(
hide
)
Description:
Part 1
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2019-02-06 10:53:17 PST
Size:
48.12 KB
patch
obsolete
>Subversion Revision: 240926 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index ad89714ce17a3527e1228d0ac5779ad5d80cd1bd..58435f05f470f10c6f675f8a67566fae08465680 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,66 @@ >+2019-02-05 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 the content off of the system pasteboard (even on >+ user interaction, since unintended user interaction isn't altogether rare). >+ >+ In order to make it possible for web pages to programmatically paste without opening the door to privacy and >+ security concerns, 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 (thereby causing 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. >+ >+ * dom/Document.cpp: >+ (WebCore::Document::hasGrantedProgrammaticClipboardAccess const): >+ (WebCore::Document::hasDeniedProgrammaticClipboardAccess const): >+ (WebCore::Document::didRequestProgrammaticClipboardAccess): >+ >+ Add helpers on Document to update and query programmatic clipboard access state. The programmatic clipboard >+ access states are "Pending" (i.e. pending a response from the user), "Granted" (the user has granted clipboard >+ access to the page), or "denied" (the user has prevented the page from reading the contents of the clipboard). >+ >+ (WebCore::Document::programmaticClipboardAccessTimerFired): >+ (WebCore::Document::suspendScheduledTasks): >+ >+ When programmatic clipboard access is granted to a Document, make the decision sticky until the end of the >+ runloop by resetting the access state to "Pending" on a zero-delay timer. >+ >+ * dom/Document.h: >+ * editing/EditorCommand.cpp: >+ (WebCore::executePaste): >+ (WebCore::executePasteAndMatchStyle): >+ (WebCore::executePasteAsPlainText): >+ (WebCore::executePasteAsQuotation): >+ >+ When executing a paste command where the source is DOM bindings, try to request programmatic clipboard access as >+ needed before proceeding with the paste. >+ >+ (WebCore::supportedPaste): >+ * loader/EmptyClients.cpp: >+ * page/EditorClient.h: >+ * page/Frame.cpp: >+ (WebCore::Frame::requestProgrammaticClipboardAccess): >+ >+ Add a helper method that requests access to the clipboard when pasting. >+ >+ * page/Frame.h: >+ * page/RuntimeEnabledFeatures.h: >+ (WebCore::RuntimeEnabledFeatures::programmaticClipboardAccessRequestEnabled const): >+ (WebCore::RuntimeEnabledFeatures::setProgrammaticClipboardAccessRequestEnabled): >+ >+ Introduce a new runtime-enabled feature, used to gate requests for programmatic clipboard access. >+ > 2019-02-04 Wenson Hsieh <wenson_hsieh@apple.com> > > [iOS] Unable to make a selection in jsfiddle.net using arrow keys when requesting desktop site >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 9f125cc22a6d892366ad6880335ebfbc70e66e6d..697a2a7f0aa5efb4adde221de857bfc1fd384378 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,116 @@ >+2019-02-06 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 programmatic clipboard 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::requestProgrammaticClipboardAccess): >+ * UIProcess/API/gtk/PageClientImpl.h: >+ * UIProcess/API/wpe/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::requestProgrammaticClipboardAccess): >+ * UIProcess/API/wpe/PageClientImpl.h: >+ * UIProcess/PageClient.h: >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::requestProgrammaticClipboardAccess): >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/WebPageProxy.messages.in: >+ * UIProcess/ios/PageClientImplIOS.h: >+ * UIProcess/ios/PageClientImplIOS.mm: >+ (WebKit::PageClientImpl::requestProgrammaticClipboardAccess): >+ >+ Plumb programmatic clipboard access requests from the web process (WebEditorClient) to the view (WKContentView). >+ As per usual, this involves WebEditorClient, WebPage, WebPageProxy, PageClient and finally WKContentView. >+ >+ * UIProcess/ios/WKContentViewInteraction.h: >+ * UIProcess/ios/WKContentViewInteraction.mm: >+ (-[WKContentView cleanupInteraction]): >+ (-[WKContentView resignFirstResponderForWebView]): >+ (-[WKContentView _webTouchEventsRecognized:]): >+ >+ Bail from any pending clipboard access handler the moment we start handling touches on the web view. >+ >+ (-[WKContentView textInteractionGesture:shouldBeginAtPoint:]): >+ (-[WKContentView canPerformAction:withSender:]): >+ >+ If we're handling a programmatic 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 programmatic paste request, immediately >+ cancel the programmatic paste. >+ >+ (-[WKContentView pasteForWebView:]): >+ >+ Adjust -pasteForWebView: on WKContentView to first check whether there's an outstanding programmatic paste >+ completion handler to invoke, instead of telling the page to execute a paste command. >+ >+ (-[WKContentView _invokeProgrammaticPasteCompletionHandlerWithResult:]): >+ >+ Add a helper to take and invoke the current programmatic 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 programmatic paste in `-_willPerformAction:sender:` prior to handling the other action. >+ >+ (-[WKContentView handleKeyWebEvent:withCompletionHandler:]): >+ >+ Dismiss programmatic 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 _requestProgrammaticClipboardAccessWithElementRect:completionHandler:]): >+ (-[WKContentView _resetShowingTextStyle:]): Deleted. >+ >+ Rename this to `-_didHideMenu:`. >+ >+ * UIProcess/mac/PageClientImplMac.h: >+ * UIProcess/win/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::requestProgrammaticClipboardAccess): >+ * UIProcess/win/PageClientImpl.h: >+ * WebProcess/WebCoreSupport/WebEditorClient.cpp: >+ (WebKit::WebEditorClient::requestProgrammaticClipboardAccess): >+ * WebProcess/WebCoreSupport/WebEditorClient.h: >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::requestProgrammaticClipboardAccess): >+ >+ Add more plumbing and method stubs. >+ >+ (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-04 Michael Catanzaro <mcatanzaro@igalia.com> > > Unreviewed, avoid -Wswitch warnings introduced in r240880 >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index 33d630cece425aa3d8e3d8110d2a8f444c91b86d..d9eff3d718f2646651aab1ebad936a7b7780266d 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,15 @@ >+2019-02-05 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-03 Simon Fraser <simon.fraser@apple.com> > > Make setNeedsLayout on the root more explicitly about triggering its side-effects >diff --git a/Source/WebKitLegacy/win/ChangeLog b/Source/WebKitLegacy/win/ChangeLog >index ab77a87ccc1c490b92640979310815480a1557ac..3c8b1155201a69ba8eced212b10f0b827def7f4d 100644 >--- a/Source/WebKitLegacy/win/ChangeLog >+++ b/Source/WebKitLegacy/win/ChangeLog >@@ -1,3 +1,13 @@ >+2019-02-05 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-03 Ryosuke Niwa <rniwa@webkit.org> > > Validate navigation policy decisions to avoid crashes in continueLoadAfterNavigationPolicy >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 50bccefcde471977ce9bf431e310104a809b9e2a..b116f20eca377a38f1048ccda269f5b648762e16 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -64,6 +64,7 @@ > #include "DocumentType.h" > #include "Editing.h" > #include "Editor.h" >+#include "EditorClient.h" > #include "ElementIterator.h" > #include "EventHandler.h" > #include "ExtensionStyleSheets.h" >@@ -534,6 +535,7 @@ Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsig > , m_isNonRenderedPlaceholder(constructionFlags & NonRenderedPlaceholder) > , m_orientationNotifier(currentOrientation(frame)) > , m_identifier(DocumentIdentifier::generate()) >+ , m_programmaticClipboardAccessResetTimer(*this, &Document::programmaticClipboardAccessTimerFired) > , m_undoManager(UndoManager::create(*this)) > { > auto addResult = allDocumentsMap().add(m_identifier, this); >@@ -5492,6 +5494,29 @@ static Editor::Command command(Document* document, const String& commandName, bo > userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM); > } > >+bool Document::hasGrantedProgrammaticClipboardAccess() const >+{ >+ return m_programmaticClipboardAccess == ProgrammaticClipboardAccess::Granted; >+} >+ >+bool Document::hasDeniedProgrammaticClipboardAccess() const >+{ >+ return m_programmaticClipboardAccess == ProgrammaticClipboardAccess::Denied; >+} >+ >+void Document::didRequestProgrammaticClipboardAccess(bool granted) >+{ >+ m_programmaticClipboardAccess = granted ? ProgrammaticClipboardAccess::Granted : ProgrammaticClipboardAccess::Denied; >+ >+ if (!m_programmaticClipboardAccessResetTimer.isActive()) >+ m_programmaticClipboardAccessResetTimer.startOneShot(0_s); >+} >+ >+void Document::programmaticClipboardAccessTimerFired() >+{ >+ m_programmaticClipboardAccess = ProgrammaticClipboardAccess::Pending; >+} >+ > bool Document::execCommand(const String& commandName, bool userInterface, const String& value) > { > EventQueueScope eventQueueScope; >@@ -6247,6 +6272,9 @@ void Document::suspendScheduledTasks(ReasonForSuspension reason) > m_applyPendingXSLTransformsTimer.stop(); > #endif > >+ m_programmaticClipboardAccessResetTimer.stop(); >+ m_programmaticClipboardAccess = ProgrammaticClipboardAccess::Pending; >+ > // Deferring loading and suspending parser is necessary when we need to prevent re-entrant JavaScript execution > // (e.g. while displaying an alert). > // It is not currently possible to suspend parser unless loading is deferred, because new data arriving from network >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 8e2878f4d15ab8515067a3aa5da3f25731102d03..9afd229bf6f182b8eecf6977115c78fb433fe9e9 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -1550,6 +1550,10 @@ public: > void setAlwaysAllowLocalWebarchive() { m_alwaysAllowLocalWebarchive = true; } > bool alwaysAllowLocalWebarchive() const { return m_alwaysAllowLocalWebarchive; } > >+ bool hasGrantedProgrammaticClipboardAccess() const; >+ bool hasDeniedProgrammaticClipboardAccess() const; >+ void didRequestProgrammaticClipboardAccess(bool granted); >+ > protected: > enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 }; > Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0); >@@ -1684,6 +1688,8 @@ private: > > bool isBodyPotentiallyScrollable(HTMLBodyElement&); > >+ void programmaticClipboardAccessTimerFired(); >+ > const Ref<Settings> m_settings; > > UniqueRef<Quirks> m_quirks; >@@ -2109,6 +2115,10 @@ private: > > bool m_alwaysAllowLocalWebarchive { false }; > >+ enum class ProgrammaticClipboardAccess : uint8_t { Pending, Denied, Granted }; >+ ProgrammaticClipboardAccess m_programmaticClipboardAccess { ProgrammaticClipboardAccess::Pending }; >+ Timer m_programmaticClipboardAccessResetTimer; >+ > Ref<UndoManager> m_undoManager; > }; > >diff --git a/Source/WebCore/editing/EditorCommand.cpp b/Source/WebCore/editing/EditorCommand.cpp >index 0b3bbb9be69569eb82cf054dc24c715e7e4ad438..c53139706f797ddd3bb608f48634b2638f05931a 100644 >--- a/Source/WebCore/editing/EditorCommand.cpp >+++ b/Source/WebCore/editing/EditorCommand.cpp >@@ -53,6 +53,7 @@ > #include "Pasteboard.h" > #include "RenderBox.h" > #include "ReplaceSelectionCommand.h" >+#include "RuntimeEnabledFeatures.h" > #include "Scrollbar.h" > #include "Settings.h" > #include "StyleProperties.h" >@@ -908,8 +909,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.requestProgrammaticClipboardAccess()) >+ return false; >+ >+ frame.editor().paste(); > return true; > } > >@@ -934,8 +940,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.requestProgrammaticClipboardAccess()) >+ return false; >+ >+ frame.editor().pasteAsPlainText(); > return true; > } > >@@ -944,8 +955,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.requestProgrammaticClipboardAccess()) >+ return false; >+ >+ frame.editor().pasteAsPlainText(); > return true; > } > >@@ -954,8 +970,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.requestProgrammaticClipboardAccess()) >+ return false; >+ >+ frame.editor().pasteAsQuotation(); > return true; > } > >@@ -1220,7 +1241,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()) || RuntimeEnabledFeatures::sharedFeatures().programmaticClipboardAccessRequestEnabled(); > > 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 b58322168ff5aa4db2c8b3d4cff89e53be29c96a..e7b84a27536c272e84dd90966a8015d8780d59e7 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 requestProgrammaticClipboardAccess() 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..ee519df4b9fcc7ab0785cffefb9f94af56cba48a 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 requestProgrammaticClipboardAccess() = 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..1f766e2bff7011070c5bafa4ff1ad60e3d8d0a9b 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,32 @@ bool Frame::selectionChangeCallbacksDisabled() const > } > #endif // PLATFORM(IOS_FAMILY) > >+bool Frame::requestProgrammaticClipboardAccess() >+{ >+ if (m_settings->javaScriptCanAccessClipboard() && m_settings->DOMPasteAllowed()) >+ return true; >+ >+ if (!RuntimeEnabledFeatures::sharedFeatures().programmaticClipboardAccessRequestEnabled() || !UserGestureIndicator::processingUserGesture()) >+ return false; >+ >+ if (!m_doc) >+ return false; >+ >+ if (m_doc->hasGrantedProgrammaticClipboardAccess()) >+ return true; >+ >+ if (m_doc->hasDeniedProgrammaticClipboardAccess()) >+ return false; >+ >+ auto* client = m_editor->client(); >+ if (!client) >+ return false; >+ >+ bool granted = client->requestProgrammaticClipboardAccess(); >+ m_doc->didRequestProgrammaticClipboardAccess(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..fc6c036a6290d46c79c5b8f4fd64b05f735d14f1 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 requestProgrammaticClipboardAccess(); >+ > // ======== 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/RuntimeEnabledFeatures.h b/Source/WebCore/page/RuntimeEnabledFeatures.h >index 0f7e7a500450a6506df3e28d3ca934fc0cc0763a..d8cac9ae5d84e616f6ec43b041593f70ec1459ef 100644 >--- a/Source/WebCore/page/RuntimeEnabledFeatures.h >+++ b/Source/WebCore/page/RuntimeEnabledFeatures.h >@@ -344,6 +344,9 @@ public: > bool adClickAttributionEnabled() const { return m_adClickAttributionEnabled; } > void setAdClickAttributionEnabled(bool isEnabled) { m_adClickAttributionEnabled = isEnabled; } > >+ bool programmaticClipboardAccessRequestEnabled() const { return m_programmaticClipboardAccessRequestEnabled; } >+ void setProgrammaticClipboardAccessRequestEnabled(bool enabled) { m_programmaticClipboardAccessRequestEnabled = enabled; } >+ > WEBCORE_EXPORT static RuntimeEnabledFeatures& sharedFeatures(); > > private: >@@ -521,6 +524,8 @@ private: > > bool m_adClickAttributionEnabled { false }; > >+ bool m_programmaticClipboardAccessRequestEnabled { false }; >+ > friend class WTF::NeverDestroyed<RuntimeEnabledFeatures>; > }; > >diff --git a/Source/WebKit/Shared/WebPreferences.yaml b/Source/WebKit/Shared/WebPreferences.yaml >index cce4ace8356325e7a0a00e523f9e4c992f9152ff..f9500bc1a359cd255a59c4fed74d985f385a7536 100644 >--- a/Source/WebKit/Shared/WebPreferences.yaml >+++ b/Source/WebKit/Shared/WebPreferences.yaml >@@ -1534,6 +1534,14 @@ AdClickAttributionEnabled: > webcoreBinding: RuntimeEnabledFeatures > category: internal > >+ProgrammaticClipboardAccessRequestEnabled: >+ type: bool >+ defaultValue: DEFAULT_PROGRAMMATIC_CLIPBOARD_ACCESS_REQUEST_ENABLED >+ humanReadableName: "Programmatic clipboard access" >+ humanReadableDescription: "Enable programmatic clipboard access" >+ webcoreBinding: RuntimeEnabledFeatures >+ category: internal >+ > # Deprecated > > ICECandidateFilteringEnabled: >diff --git a/Source/WebKit/Shared/WebPreferencesDefaultValues.h b/Source/WebKit/Shared/WebPreferencesDefaultValues.h >index 0a52167c20fa5ae0404734784a49ec91c9106ff7..79502be8d5fea0b20a74643bc244daecebf3ac6a 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_PROGRAMMATIC_CLIPBOARD_ACCESS_REQUEST_ENABLED true >+#else >+#define DEFAULT_PROGRAMMATIC_CLIPBOARD_ACCESS_REQUEST_ENABLED false >+#endif >diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp >index 317859d75335e7ddca0307204dcce5e4de1e012e..8308dd5d41829c56ad3990b18eace6791a07fcdd 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::requestProgrammaticClipboardAccess(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..e78475af10aa855bb744f621a9161a08e3dbbc5c 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 requestProgrammaticClipboardAccess(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..45f194bdca4c88acaba34b0cb4dd5c21fad21347 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::requestProgrammaticClipboardAccess(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..b2cccc58f291bfaf675b96bef9d7cd0f66b0875d 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 requestProgrammaticClipboardAccess(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..c96640769a4c90a0eb87e78592e946a8285885cc 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 requestProgrammaticClipboardAccess(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 6a15c801beafdc6ad2d8d5fc42cd707c31d2fbf1..3cfcd0f0cde9f7fe738ccd8cd73af94aef1dcb6a 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -5438,6 +5438,11 @@ void WebPageProxy::setNeedsPlainTextQuirk(bool needsPlainTextQuirk) > m_needsPlainTextQuirk = needsPlainTextQuirk; > } > >+void WebPageProxy::requestProgrammaticClipboardAccess(const WebCore::IntRect& elementRect, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ m_pageClient->requestProgrammaticClipboardAccess(elementRect, WTFMove(completionHandler)); >+} >+ > // BackForwardList > > void WebPageProxy::backForwardAddItem(BackForwardListItemState&& itemState) >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index a7f9c5d18cc3f56974b36c261b85f3668ed77248..5d105d53354f1972610e0ee6e02bfeb6c5eed59f 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -1650,6 +1650,8 @@ private: > void setNeedsHiddenContentEditableQuirk(bool); > void setNeedsPlainTextQuirk(bool); > >+ void requestProgrammaticClipboardAccess(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..baa5a79a2dea17d3d771c2a765b930af40cc226c 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) >+ RequestProgrammaticClipboardAccess(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..2b6c4fd2dd9d6a0ac487ed73dd5464ec7ff1e301 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 requestProgrammaticClipboardAccess(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..5c8d42ba96c69dd9d305e923657238e08e902b37 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::requestProgrammaticClipboardAccess(const WebCore::IntRect& elementRect, CompletionHandler<void(bool)>&& completionHandler) >+{ >+ [m_contentView _requestProgrammaticClipboardAccessWithElementRect: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 fad0bcbae2833bfe1fd7fc9551f46c857dbdea01..4d8e0a847d06b4b394cf5f22698630e7fa58705d 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> >@@ -317,6 +318,7 @@ struct WKAutoCorrectionData { > BOOL _focusRequiresStrongPasswordAssistance; > > BOOL _hasSetUpInteractions; >+ CompletionHandler<void(bool)> _programmaticPasteCompletionHandler; > > #if ENABLE(DATA_INTERACTION) > WebKit::DragDropInteractionState _dragDropInteractionState; >@@ -438,6 +440,8 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW) > - (void)_accessibilityClearSelection; > - (WKFormInputSession *)_formInputSession; > >+- (void)_requestProgrammaticClipboardAccessWithElementRect:(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 2122840b323f43ee08c884407b6eed629d5e4811..fdcc3ea255122c738cb43a6de062a85a05222bd3 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >@@ -742,7 +742,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; >@@ -888,6 +888,7 @@ - (void)cleanupInteraction > #if ENABLE(POINTER_EVENTS) > [self _resetPanningPreventionFlags]; > #endif >+ [self _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; > } > > - (void)_removeDefaultGestureRecognizers >@@ -1140,8 +1141,10 @@ - (BOOL)resignFirstResponderForWebView > > bool superDidResign = [super resignFirstResponder]; > >- if (superDidResign) >+ if (superDidResign) { > _page->activityStateDidChange(WebCore::ActivityState::IsFocused); >+ [self _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; >+ } > > return superDidResign; > } >@@ -1170,8 +1173,10 @@ - (void)_webTouchEventsRecognized:(UIWebTouchEventsGestureRecognizer *)gestureRe > const _UIWebTouchEvent* lastTouchEvent = gestureRecognizer.lastTouchEvent; > > _lastInteractionLocation = lastTouchEvent->locationInDocumentCoordinates; >- if (lastTouchEvent->type == UIWebTouchEventTouchBegin) >+ if (lastTouchEvent->type == UIWebTouchEventTouchBegin) { >+ [self _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; > _layerTreeTransactionIdAtLastTouchStart = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).lastCommittedLayerTreeTransactionID(); >+ } > > #if ENABLE(TOUCH_EVENTS) > WebKit::NativeWebTouchEvent nativeWebTouchEvent(lastTouchEvent); >@@ -1988,6 +1993,9 @@ - (BOOL)textInteractionGesture:(UIWKGestureType)gesture shouldBeginAtPoint:(CGPo > if (!_webView.configuration._textInteractionGesturesEnabled) > return NO; > >+ if (_programmaticPasteCompletionHandler) >+ return NO; >+ > if (_suppressSelectionAssistantReasons) > return NO; > >@@ -2413,7 +2421,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) >@@ -2658,6 +2669,9 @@ - (void)tintColorDidChange > > - (BOOL)canPerformAction:(SEL)action withSender:(id)sender > { >+ if (_programmaticPasteCompletionHandler && action == @selector(paste:)) >+ return YES; >+ > return [_webView canPerformAction:action withSender:sender]; > } > >@@ -2809,10 +2823,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 _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; > } > > - (void)_keyboardDidRequestDismissal:(NSNotification *)notification >@@ -2834,6 +2849,9 @@ - (void)cutForWebView:(id)sender > > - (void)pasteForWebView:(id)sender > { >+ if (sender == UIMenuController.sharedMenuController && [self _invokeProgrammaticPasteCompletionHandlerWithResult:YES]) >+ return; >+ > _page->executeEditCommand("paste"_s); > } > >@@ -2963,6 +2981,28 @@ - (void)_accessibilityClearSelection > _page->storeSelectionForAccessibility(false); > } > >+- (BOOL)_invokeProgrammaticPasteCompletionHandlerWithResult:(BOOL)allowPaste >+{ >+ if (auto pasteHandler = WTFMove(_programmaticPasteCompletionHandler)) { >+ [self hideGlobalMenuController]; >+ pasteHandler(allowPaste); >+ return YES; >+ } >+ return NO; >+} >+ >+- (void)_willPerformAction:(SEL)action sender:(id)sender >+{ >+ if (action != @selector(paste:)) >+ [self _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; >+} >+ >+- (void)_didPerformAction:(SEL)action sender:(id)sender >+{ >+ if (action == @selector(paste:)) >+ [self _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; >+} >+ > // UIWKInteractionViewProtocol > > static inline WebKit::GestureType toGestureType(UIWKGestureType gestureType) >@@ -4126,6 +4166,8 @@ - (void)handleKeyWebEvent:(::WebEvent *)theEvent > > - (void)handleKeyWebEvent:(::WebEvent *)theEvent withCompletionHandler:(void (^)(::WebEvent *theEvent, BOOL wasHandled))completionHandler > { >+ [self _invokeProgrammaticPasteCompletionHandlerWithResult:NO]; >+ > _keyWebEventHandler = makeBlockPtr(completionHandler); > _page->handleKeyboardEvent(WebKit::NativeWebKeyboardEvent(theEvent)); > } >@@ -4821,6 +4863,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)_requestProgrammaticClipboardAccessWithElementRect:(const WebCore::IntRect&)elementRect completionHandler:(CompletionHandler<void(bool)>&&)completionHandler >+{ >+ if (auto existingCompletionHandler = std::exchange(_programmaticPasteCompletionHandler, 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..46f6a35b8c3ea8a29c570b4628b559df4f72f603 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 requestProgrammaticClipboardAccess(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..4f273cb7a5cf13aa4e10a9210871372b4f8117fb 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::requestProgrammaticClipboardAccess(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..c2fade701c24ae62bb75516f201396b71a8c9202 100644 >--- a/Source/WebKit/UIProcess/win/PageClientImpl.h >+++ b/Source/WebKit/UIProcess/win/PageClientImpl.h >@@ -142,6 +142,8 @@ private: > > void didFinishProcessingAllPendingMouseEvents() final { } > >+ void requestProgrammaticClipboardAccess(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..258f3b76f578468a292124148b5f58429806a70a 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::requestProgrammaticClipboardAccess() >+{ >+ return m_page->requestProgrammaticClipboardAccess(); >+} >+ > #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..cd846faedc851bff60ea30e4e9c5103d4867ee9f 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 requestProgrammaticClipboardAccess() 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 512128abae0e3c97cf17dbfbbc519b8c42be92e3..6f4d1d77164ff494f20ad34556d826c0c5035da8 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -6423,6 +6423,15 @@ void WebPage::didCompleteShareSheet(bool wasGranted, ShareSheetCallbackID callba > callback(wasGranted); > } > >+bool WebPage::requestProgrammaticClipboardAccess() >+{ >+ bool granted = false; >+ if (!sendSyncWithDelayedReply(Messages::WebPageProxy::RequestProgrammaticClipboardAccess(rectForElementAtInteractionLocation()), Messages::WebPageProxy::RequestProgrammaticClipboardAccess::Reply(granted))) >+ return false; >+ >+ return granted; >+} >+ > void WebPage::simulateDeviceOrientationChange(double alpha, double beta, double gamma) > { > #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) >@@ -6496,7 +6505,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 c711456905f650d73aa3ef51771945d6f2de0b70..af36f227bbe4649e480c037c3627cb035b7aca49 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.h >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h >@@ -657,7 +657,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); >@@ -1144,6 +1143,9 @@ public: > return sendSync(WTFMove(message), WTFMove(reply), m_pageID, Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend); > } > >+ bool requestProgrammaticClipboardAccess(); >+ 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..6415c86e4a21baccc13ab947f543d819dcabfc14 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 requestProgrammaticClipboardAccess() 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..ab7994b19bb1351d00c849deb8094f4866363256 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 requestProgrammaticClipboardAccess() 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