forked from mirrors/gecko-dev
		
	Bug 1869868 part 2 - do not consult DLP when copy/pasting items in the same tab r=edgar,dlp-reviewers,credential-management-reviewers,handyman,sgalich
Differential Revision: https://phabricator.services.mozilla.com/D205744
This commit is contained in:
		
							parent
							
								
									8ee343bb45
								
							
						
					
					
						commit
						37d28f9cf5
					
				
					 25 changed files with 205 additions and 70 deletions
				
			
		|  | @ -2175,7 +2175,10 @@ class nsContextMenu { | |||
|     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( | ||||
|       Ci.nsIClipboardHelper | ||||
|     ); | ||||
|     clipboard.copyString(addresses); | ||||
|     clipboard.copyString( | ||||
|       addresses, | ||||
|       this.actor.manager.browsingContext.currentWindowGlobal | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   // Extract phone and put it on clipboard
 | ||||
|  | @ -2195,7 +2198,10 @@ class nsContextMenu { | |||
|     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( | ||||
|       Ci.nsIClipboardHelper | ||||
|     ); | ||||
|     clipboard.copyString(phone); | ||||
|     clipboard.copyString( | ||||
|       phone, | ||||
|       this.actor.manager.browsingContext.currentWindowGlobal | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   copyLink() { | ||||
|  | @ -2204,7 +2210,10 @@ class nsContextMenu { | |||
|     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( | ||||
|       Ci.nsIClipboardHelper | ||||
|     ); | ||||
|     clipboard.copyString(linkURL); | ||||
|     clipboard.copyString( | ||||
|       linkURL, | ||||
|       this.actor.manager.browsingContext.currentWindowGlobal | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -2220,7 +2229,10 @@ class nsContextMenu { | |||
|       let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( | ||||
|         Ci.nsIClipboardHelper | ||||
|       ); | ||||
|       clipboard.copyString(strippedLinkURL); | ||||
|       clipboard.copyString( | ||||
|         strippedLinkURL, | ||||
|         this.actor.manager.browsingContext.currentWindowGlobal | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -2458,7 +2470,10 @@ class nsContextMenu { | |||
|     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( | ||||
|       Ci.nsIClipboardHelper | ||||
|     ); | ||||
|     clipboard.copyString(this.originalMediaURL); | ||||
|     clipboard.copyString( | ||||
|       this.originalMediaURL, | ||||
|       this.actor.manager.browsingContext.currentWindowGlobal | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   getImageText() { | ||||
|  |  | |||
|  | @ -160,7 +160,11 @@ export class AboutLoginsChild extends JSWindowActorChild { | |||
|   } | ||||
| 
 | ||||
|   #aboutLoginsCopyLoginDetail(detail) { | ||||
|     lazy.ClipboardHelper.copyString(detail, lazy.ClipboardHelper.Sensitive); | ||||
|     lazy.ClipboardHelper.copyString( | ||||
|       detail, | ||||
|       this.windowContext, | ||||
|       lazy.ClipboardHelper.Sensitive | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   #aboutLoginsCreateLogin(login) { | ||||
|  |  | |||
|  | @ -553,6 +553,7 @@ export var Policies = { | |||
|         ["IsPerUser", "is_per_user"], | ||||
|         ["ShowBlockedResult", "show_blocked_result"], | ||||
|         ["DefaultAllow", "default_allow"], | ||||
|         ["BypassForSameTabOperations", "bypass_for_same_tab_operations"], | ||||
|       ]; | ||||
|       for (let pref of boolPrefs) { | ||||
|         if (pref[0] in param) { | ||||
|  |  | |||
|  | @ -267,6 +267,9 @@ | |||
|         }, | ||||
|         "DefaultAllow": { | ||||
|           "type": "boolean" | ||||
|         }, | ||||
|         "BypassForSameTabOperations": { | ||||
|           "type": "boolean" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  |  | |||
|  | @ -332,7 +332,8 @@ static nsresult PutToClipboard( | |||
|   rv = CreateTransferable(aEncodedDocumentWithContext, aDocument, transferable); | ||||
|   NS_ENSURE_SUCCESS(rv, rv); | ||||
| 
 | ||||
|   rv = clipboard->SetData(transferable, nullptr, aClipboardID); | ||||
|   rv = clipboard->SetData(transferable, nullptr, aClipboardID, | ||||
|                           aDocument.GetWindowContext()); | ||||
|   NS_ENSURE_SUCCESS(rv, rv); | ||||
| 
 | ||||
|   return rv; | ||||
|  | @ -455,9 +456,9 @@ nsresult nsCopySupport::GetContents(const nsACString& aMimeType, | |||
|   return docEncoder->EncodeToString(outdata); | ||||
| } | ||||
| 
 | ||||
| nsresult nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement, | ||||
|                                   nsILoadContext* aLoadContext, | ||||
|                                   int32_t aCopyFlags) { | ||||
| nsresult nsCopySupport::ImageCopy( | ||||
|     nsIImageLoadingContent* aImageElement, nsILoadContext* aLoadContext, | ||||
|     int32_t aCopyFlags, mozilla::dom::WindowContext* aSettingWindowContext) { | ||||
|   nsresult rv; | ||||
| 
 | ||||
|   nsCOMPtr<nsINode> imageNode = do_QueryInterface(aImageElement, &rv); | ||||
|  | @ -527,11 +528,13 @@ nsresult nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement, | |||
|   // check whether the system supports the selection clipboard or not.
 | ||||
|   if (clipboard->IsClipboardTypeSupported(nsIClipboard::kSelectionClipboard)) { | ||||
|     // put the transferable on the clipboard
 | ||||
|     rv = clipboard->SetData(trans, nullptr, nsIClipboard::kSelectionClipboard); | ||||
|     rv = clipboard->SetData(trans, nullptr, nsIClipboard::kSelectionClipboard, | ||||
|                             aSettingWindowContext); | ||||
|     NS_ENSURE_SUCCESS(rv, rv); | ||||
|   } | ||||
| 
 | ||||
|   return clipboard->SetData(trans, nullptr, nsIClipboard::kGlobalClipboard); | ||||
|   return clipboard->SetData(trans, nullptr, nsIClipboard::kGlobalClipboard, | ||||
|                             aSettingWindowContext); | ||||
| } | ||||
| 
 | ||||
| static nsresult AppendString(nsITransferable* aTransferable, | ||||
|  | @ -928,7 +931,12 @@ bool nsCopySupport::FireClipboardEvent(EventMessage aEventMessage, | |||
|       NS_ENSURE_TRUE(transferable, false); | ||||
| 
 | ||||
|       // put the transferable on the clipboard
 | ||||
|       nsresult rv = clipboard->SetData(transferable, nullptr, aClipboardType); | ||||
|       WindowContext* settingWindowContext = nullptr; | ||||
|       if (aPresShell && aPresShell->GetDocument()) { | ||||
|         settingWindowContext = aPresShell->GetDocument()->GetWindowContext(); | ||||
|       } | ||||
|       nsresult rv = clipboard->SetData(transferable, nullptr, aClipboardType, | ||||
|                                        settingWindowContext); | ||||
|       if (NS_FAILED(rv)) { | ||||
|         return false; | ||||
|       } | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ class PresShell; | |||
| namespace dom { | ||||
| class Document; | ||||
| class Selection; | ||||
| class WindowContext; | ||||
| }  // namespace dom
 | ||||
| }  // namespace mozilla
 | ||||
| 
 | ||||
|  | @ -46,7 +47,8 @@ class nsCopySupport { | |||
|                               mozilla::dom::Document* aDoc, nsAString& outdata); | ||||
| 
 | ||||
|   static nsresult ImageCopy(nsIImageLoadingContent* aImageElement, | ||||
|                             nsILoadContext* aLoadContext, int32_t aCopyFlags); | ||||
|                             nsILoadContext* aLoadContext, int32_t aCopyFlags, | ||||
|                             mozilla::dom::WindowContext* aSettingWindowContext); | ||||
| 
 | ||||
|   // Get the selection as a transferable.
 | ||||
|   // @param aSelection Can be nullptr.
 | ||||
|  |  | |||
|  | @ -731,7 +731,8 @@ already_AddRefed<Promise> Clipboard::Write( | |||
|   RefPtr<ClipboardWriteCallback> callback = | ||||
|       MakeRefPtr<ClipboardWriteCallback>(p, aData[0]); | ||||
|   nsresult rv = clipboard->AsyncSetData(nsIClipboard::kGlobalClipboard, | ||||
|                                         callback, getter_AddRefs(request)); | ||||
|                                         owner->GetWindowContext(), callback, | ||||
|                                         getter_AddRefs(request)); | ||||
|   if (NS_FAILED(rv)) { | ||||
|     p->MaybeReject(rv); | ||||
|     return p.forget(); | ||||
|  |  | |||
|  | @ -3409,7 +3409,8 @@ void ContentParent::OnVarChanged(const GfxVarUpdate& aVar) { | |||
| } | ||||
| 
 | ||||
| mozilla::ipc::IPCResult ContentParent::RecvSetClipboard( | ||||
|     const IPCTransferable& aTransferable, const int32_t& aWhichClipboard) { | ||||
|     const IPCTransferable& aTransferable, const int32_t& aWhichClipboard, | ||||
|     const MaybeDiscarded<WindowContext>& aRequestingWindowContext) { | ||||
|   // aRequestingPrincipal is allowed to be nullptr here.
 | ||||
| 
 | ||||
|   if (!ValidatePrincipal(aTransferable.requestingPrincipal(), | ||||
|  | @ -3434,7 +3435,12 @@ mozilla::ipc::IPCResult ContentParent::RecvSetClipboard( | |||
|       true /* aFilterUnknownFlavors */); | ||||
|   NS_ENSURE_SUCCESS(rv, IPC_OK()); | ||||
| 
 | ||||
|   clipboard->SetData(trans, nullptr, aWhichClipboard); | ||||
|   // OK if this is null
 | ||||
|   RefPtr<WindowGlobalParent> window; | ||||
|   if (!aRequestingWindowContext.IsDiscarded()) { | ||||
|     window = aRequestingWindowContext.get_canonical(); | ||||
|   } | ||||
|   clipboard->SetData(trans, nullptr, aWhichClipboard, window); | ||||
|   return IPC_OK(); | ||||
| } | ||||
| 
 | ||||
|  | @ -3682,10 +3688,15 @@ mozilla::ipc::IPCResult ContentParent::RecvGetClipboardDataSnapshotSync( | |||
| 
 | ||||
| already_AddRefed<PClipboardWriteRequestParent> | ||||
| ContentParent::AllocPClipboardWriteRequestParent( | ||||
|     const int32_t& aClipboardType) { | ||||
|     const int32_t& aClipboardType, | ||||
|     const MaybeDiscarded<WindowContext>& aSettingWindowContext) { | ||||
|   WindowContext* settingWindowContext = nullptr; | ||||
|   if (!aSettingWindowContext.IsDiscarded()) { | ||||
|     settingWindowContext = aSettingWindowContext.get(); | ||||
|   } | ||||
|   RefPtr<ClipboardWriteRequestParent> request = | ||||
|       MakeAndAddRef<ClipboardWriteRequestParent>(this); | ||||
|   request->Init(aClipboardType); | ||||
|   request->Init(aClipboardType, settingWindowContext); | ||||
|   return request.forget(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -949,8 +949,9 @@ class ContentParent final : public PContentParent, | |||
|       PBrowserParent* aBrowser, | ||||
|       const MaybeDiscarded<BrowsingContext>& aContext); | ||||
| 
 | ||||
|   mozilla::ipc::IPCResult RecvSetClipboard(const IPCTransferable& aTransferable, | ||||
|                                            const int32_t& aWhichClipboard); | ||||
|   mozilla::ipc::IPCResult RecvSetClipboard( | ||||
|       const IPCTransferable& aTransferable, const int32_t& aWhichClipboard, | ||||
|       const MaybeDiscarded<WindowContext>& aRequestingWindowContext); | ||||
| 
 | ||||
|   mozilla::ipc::IPCResult RecvGetClipboard( | ||||
|       nsTArray<nsCString>&& aTypes, const int32_t& aWhichClipboard, | ||||
|  | @ -975,7 +976,9 @@ class ContentParent final : public PContentParent, | |||
|       ClipboardReadRequestOrError* aRequestOrError); | ||||
| 
 | ||||
|   already_AddRefed<PClipboardWriteRequestParent> | ||||
|   AllocPClipboardWriteRequestParent(const int32_t& aClipboardType); | ||||
|   AllocPClipboardWriteRequestParent( | ||||
|       const int32_t& aClipboardType, | ||||
|       const MaybeDiscarded<WindowContext>& aSettingWindowContext); | ||||
| 
 | ||||
|   mozilla::ipc::IPCResult RecvGetIconForExtension(const nsACString& aFileExt, | ||||
|                                                   const uint32_t& aIconSize, | ||||
|  |  | |||
|  | @ -1219,7 +1219,7 @@ parent: | |||
| 
 | ||||
|     // Places the items within dataTransfer on the clipboard. | ||||
|     async SetClipboard(IPCTransferable aTransferable, | ||||
|                        int32_t aWhichClipboard); | ||||
|                        int32_t aWhichClipboard, MaybeDiscardedWindowContext aRequestingWindowContext); | ||||
| 
 | ||||
|     // Given a list of supported types, returns the clipboard data for the | ||||
|     // first type that matches. | ||||
|  | @ -1252,8 +1252,12 @@ parent: | |||
|      * and that the data will be sent over another IPC message once it is ready. | ||||
|      * @param  aClipboardType | ||||
|      *         The clipboard type defined in nsIClipboard. | ||||
|      * @param  aSettingWindowContext | ||||
|      *         The window context that is setting the clipboard, if any. This is used | ||||
|      *         to possibly bypass Content Analysis if a set clipboard and get clipboard | ||||
|      *         operation are done on the same page. | ||||
|      */ | ||||
|     async PClipboardWriteRequest(int32_t aClipboardType); | ||||
|     async PClipboardWriteRequest(int32_t aClipboardType, MaybeDiscardedWindowContext aSettingWindowContext); | ||||
| 
 | ||||
|     sync GetIconForExtension(nsCString aFileExt, uint32_t aIconSize) | ||||
|         returns (uint8_t[] bits); | ||||
|  |  | |||
|  | @ -1265,7 +1265,7 @@ nsresult gfxUtils::EncodeSourceSurface(SourceSurface* aSurface, | |||
|     nsCOMPtr<nsIClipboardHelper> clipboard( | ||||
|         do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv)); | ||||
|     if (clipboard) { | ||||
|       clipboard->CopyString(NS_ConvertASCIItoUTF16(dataURI)); | ||||
|       clipboard->CopyString(NS_ConvertASCIItoUTF16(dataURI), nullptr); | ||||
|     } | ||||
|   } | ||||
|   return NS_OK; | ||||
|  |  | |||
|  | @ -2426,7 +2426,7 @@ NS_IMETHODIMP nsDocumentViewer::CopyLinkLocation() { | |||
|   NS_ENSURE_SUCCESS(rv, rv); | ||||
| 
 | ||||
|   // copy the href onto the clipboard
 | ||||
|   return clipboard->CopyString(locationText); | ||||
|   return clipboard->CopyString(locationText, mDocument->GetWindowContext()); | ||||
| } | ||||
| 
 | ||||
| NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags) { | ||||
|  | @ -2436,7 +2436,8 @@ NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags) { | |||
|   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); | ||||
| 
 | ||||
|   nsCOMPtr<nsILoadContext> loadContext(mContainer); | ||||
|   return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags); | ||||
|   return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags, | ||||
|                                   mDocument->GetWindowContext()); | ||||
| } | ||||
| 
 | ||||
| NS_IMETHODIMP nsDocumentViewer::GetCopyable(bool* aCopyable) { | ||||
|  |  | |||
|  | @ -1211,6 +1211,13 @@ | |||
|   value: true | ||||
|   mirror: always | ||||
| 
 | ||||
| # Should Firefox bypass content analysis for pastes and drags whose source | ||||
| # is the same tab? | ||||
| - name: browser.contentanalysis.bypass_for_same_tab_operations | ||||
|   type: bool | ||||
|   value: false | ||||
|   mirror: always | ||||
| 
 | ||||
| # Content blocking for Enhanced Tracking Protection | ||||
| - name: browser.contentblocking.database.enabled | ||||
|   type: bool | ||||
|  |  | |||
|  | @ -816,6 +816,7 @@ NS_IMETHODIMP ContentAnalysisResult::GetShouldAllowContent( | |||
|                         ALLOW_DUE_TO_CONTENT_ANALYSIS_NOT_ACTIVE || | ||||
|           result == NoContentAnalysisResult:: | ||||
|                         ALLOW_DUE_TO_CONTEXT_EXEMPT_FROM_CONTENT_ANALYSIS || | ||||
|           result == NoContentAnalysisResult::ALLOW_DUE_TO_SAME_TAB_SOURCE || | ||||
|           result == NoContentAnalysisResult::ALLOW_DUE_TO_COULD_NOT_GET_DATA; | ||||
|     } | ||||
|   } else { | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ namespace contentanalysis { | |||
| enum class NoContentAnalysisResult : uint8_t { | ||||
|   ALLOW_DUE_TO_CONTENT_ANALYSIS_NOT_ACTIVE, | ||||
|   ALLOW_DUE_TO_CONTEXT_EXEMPT_FROM_CONTENT_ANALYSIS, | ||||
|   ALLOW_DUE_TO_SAME_TAB_SOURCE, | ||||
|   ALLOW_DUE_TO_COULD_NOT_GET_DATA, | ||||
|   DENY_DUE_TO_CANCELED, | ||||
|   DENY_DUE_TO_INVALID_JSON_RESPONSE, | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ const kClientSignaturePref = "client_signature"; | |||
| const kPerUserPref = "is_per_user"; | ||||
| const kShowBlockedPref = "show_blocked_result"; | ||||
| const kDefaultAllowPref = "default_allow"; | ||||
| const kBypassForSameTabOperationsPref = "bypass_for_same_tab_operations"; | ||||
| 
 | ||||
| const ca = Cc["@mozilla.org/contentanalysis;1"].getService( | ||||
|   Ci.nsIContentAnalysis | ||||
|  | @ -88,6 +89,7 @@ add_task(async function test_ca_enterprise_config() { | |||
|         IsPerUser: true, | ||||
|         ShowBlockedResult: false, | ||||
|         DefaultAllow: true, | ||||
|         BypassForSameTabOperations: true, | ||||
|       }, | ||||
|     }, | ||||
|   }); | ||||
|  | @ -139,6 +141,13 @@ add_task(async function test_ca_enterprise_config() { | |||
|     true, | ||||
|     "default allow match" | ||||
|   ); | ||||
|   is( | ||||
|     Services.prefs.getBoolPref( | ||||
|       "browser.contentanalysis." + kBypassForSameTabOperationsPref | ||||
|     ), | ||||
|     true, | ||||
|     "bypass for same tab operations match" | ||||
|   ); | ||||
|   PoliciesPrefTracker.stop(); | ||||
| }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,7 +27,9 @@ ClipboardWriteRequestParent::ClipboardWriteRequestParent( | |||
| 
 | ||||
| ClipboardWriteRequestParent::~ClipboardWriteRequestParent() = default; | ||||
| 
 | ||||
| nsresult ClipboardWriteRequestParent::Init(const int32_t& aClipboardType) { | ||||
| nsresult ClipboardWriteRequestParent::Init( | ||||
|     const int32_t& aClipboardType, | ||||
|     mozilla::dom::WindowContext* aSettingWindowContext) { | ||||
|   nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID)); | ||||
|   if (!clipboard) { | ||||
|     Unused << PClipboardWriteRequestParent::Send__delete__(this, | ||||
|  | @ -35,8 +37,9 @@ nsresult ClipboardWriteRequestParent::Init(const int32_t& aClipboardType) { | |||
|     return NS_ERROR_FAILURE; | ||||
|   } | ||||
| 
 | ||||
|   nsresult rv = clipboard->AsyncSetData(aClipboardType, this, | ||||
|                                         getter_AddRefs(mAsyncSetClipboardData)); | ||||
|   nsresult rv = | ||||
|       clipboard->AsyncSetData(aClipboardType, aSettingWindowContext, this, | ||||
|                               getter_AddRefs(mAsyncSetClipboardData)); | ||||
|   if (NS_FAILED(rv)) { | ||||
|     Unused << PClipboardWriteRequestParent::Send__delete__(this, rv); | ||||
|     return rv; | ||||
|  |  | |||
|  | @ -27,7 +27,8 @@ class ClipboardWriteRequestParent final | |||
| 
 | ||||
|   explicit ClipboardWriteRequestParent(ContentParent* aManager); | ||||
| 
 | ||||
|   nsresult Init(const int32_t& aClipboardType); | ||||
|   nsresult Init(const int32_t& aClipboardType, | ||||
|                 mozilla::dom::WindowContext* aSettingWindowContext); | ||||
| 
 | ||||
|   IPCResult RecvSetData(const IPCTransferable& aTransferable); | ||||
|   IPCResult Recv__delete__(nsresult aReason); | ||||
|  |  | |||
|  | @ -211,9 +211,11 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard::AsyncSetClipboardData, | |||
| 
 | ||||
| nsBaseClipboard::AsyncSetClipboardData::AsyncSetClipboardData( | ||||
|     int32_t aClipboardType, nsBaseClipboard* aClipboard, | ||||
|     mozilla::dom::WindowContext* aSettingWindowContext, | ||||
|     nsIAsyncClipboardRequestCallback* aCallback) | ||||
|     : mClipboardType(aClipboardType), | ||||
|       mClipboard(aClipboard), | ||||
|       mWindowContext(aSettingWindowContext), | ||||
|       mCallback(aCallback) { | ||||
|   MOZ_ASSERT(mClipboard); | ||||
|   MOZ_ASSERT( | ||||
|  | @ -247,7 +249,8 @@ nsBaseClipboard::AsyncSetClipboardData::SetData(nsITransferable* aTransferable, | |||
| 
 | ||||
|   RefPtr<AsyncSetClipboardData> request = | ||||
|       std::move(mClipboard->mPendingWriteRequests[mClipboardType]); | ||||
|   nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType); | ||||
|   nsresult rv = mClipboard->SetData(aTransferable, aOwner, mClipboardType, | ||||
|                                     mWindowContext); | ||||
|   MaybeNotifyCallback(rv); | ||||
| 
 | ||||
|   return rv; | ||||
|  | @ -292,7 +295,8 @@ void nsBaseClipboard::RejectPendingAsyncSetDataRequestIfAny( | |||
| } | ||||
| 
 | ||||
| NS_IMETHODIMP nsBaseClipboard::AsyncSetData( | ||||
|     int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback, | ||||
|     int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext, | ||||
|     nsIAsyncClipboardRequestCallback* aCallback, | ||||
|     nsIAsyncSetClipboardData** _retval) { | ||||
|   MOZ_CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard); | ||||
| 
 | ||||
|  | @ -308,8 +312,8 @@ NS_IMETHODIMP nsBaseClipboard::AsyncSetData( | |||
| 
 | ||||
|   // Create a new AsyncSetClipboardData.
 | ||||
|   RefPtr<AsyncSetClipboardData> request = | ||||
|       mozilla::MakeRefPtr<AsyncSetClipboardData>(aWhichClipboard, this, | ||||
|                                                  aCallback); | ||||
|       mozilla::MakeRefPtr<AsyncSetClipboardData>( | ||||
|           aWhichClipboard, this, aSettingWindowContext, aCallback); | ||||
|   mPendingWriteRequests[aWhichClipboard] = request; | ||||
|   request.forget(_retval); | ||||
|   return NS_OK; | ||||
|  | @ -408,7 +412,7 @@ nsBaseClipboard::CheckClipboardContentAnalysisAsFile( | |||
| 
 | ||||
| void nsBaseClipboard::CheckClipboardContentAnalysis( | ||||
|     mozilla::dom::WindowGlobalParent* aWindow, nsITransferable* aTransferable, | ||||
|     SafeContentAnalysisResultCallback* aResolver) { | ||||
|     int32_t aClipboardType, SafeContentAnalysisResultCallback* aResolver) { | ||||
|   using namespace mozilla::contentanalysis; | ||||
| 
 | ||||
|   // Content analysis is only needed if an outside webpage has access to
 | ||||
|  | @ -441,8 +445,24 @@ void nsBaseClipboard::CheckClipboardContentAnalysis( | |||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   nsCOMPtr<nsIURI> currentURI = aWindow->Canonical()->GetDocumentURI(); | ||||
|   uint64_t innerWindowId = aWindow->InnerWindowId(); | ||||
|   if (mozilla::StaticPrefs:: | ||||
|           browser_contentanalysis_bypass_for_same_tab_operations()) { | ||||
|     const auto* clipboardCache = GetClipboardCacheIfValid(aClipboardType); | ||||
|     if (clipboardCache) { | ||||
|       if (clipboardCache->GetInnerWindowId().isSome() && | ||||
|           *(clipboardCache->GetInnerWindowId()) == innerWindowId) { | ||||
|         // If the same page copied this data to the clipboard (and the above
 | ||||
|         // preference is set) we can skip content analysis and immediately allow
 | ||||
|         // this.
 | ||||
|         aResolver->Callback(ContentAnalysisResult::FromNoResult( | ||||
|             NoContentAnalysisResult::ALLOW_DUE_TO_SAME_TAB_SOURCE)); | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   nsCOMPtr<nsIURI> currentURI = aWindow->Canonical()->GetDocumentURI(); | ||||
|   nsTArray<nsCString> flavors; | ||||
|   rv = aTransferable->FlavorsTransferableCanExport(flavors); | ||||
|   if (NS_WARN_IF(NS_FAILED(rv))) { | ||||
|  | @ -482,7 +502,7 @@ void nsBaseClipboard::CheckClipboardContentAnalysis( | |||
| 
 | ||||
| bool nsBaseClipboard::CheckClipboardContentAnalysisSync( | ||||
|     mozilla::dom::WindowGlobalParent* aWindow, | ||||
|     const nsCOMPtr<nsITransferable>& trans) { | ||||
|     const nsCOMPtr<nsITransferable>& trans, int32_t aClipboardType) { | ||||
|   bool requestDone = false; | ||||
|   RefPtr<nsIContentAnalysisResult> result; | ||||
|   auto callback = mozilla::MakeRefPtr<SafeContentAnalysisResultCallback>( | ||||
|  | @ -490,7 +510,7 @@ bool nsBaseClipboard::CheckClipboardContentAnalysisSync( | |||
|         result = std::move(aResult); | ||||
|         requestDone = true; | ||||
|       }); | ||||
|   CheckClipboardContentAnalysis(aWindow, trans, callback); | ||||
|   CheckClipboardContentAnalysis(aWindow, trans, aClipboardType, callback); | ||||
|   mozilla::SpinEventLoopUntil("CheckClipboardContentAnalysisSync"_ns, | ||||
|                               [&requestDone]() -> bool { return requestDone; }); | ||||
|   return result->GetShouldAllowContent(); | ||||
|  | @ -527,9 +547,9 @@ NS_IMPL_ISUPPORTS(nsBaseClipboard, nsIClipboard) | |||
|  * Sets the transferable object | ||||
|  * | ||||
|  */ | ||||
| NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable, | ||||
|                                        nsIClipboardOwner* aOwner, | ||||
|                                        int32_t aWhichClipboard) { | ||||
| NS_IMETHODIMP nsBaseClipboard::SetData( | ||||
|     nsITransferable* aTransferable, nsIClipboardOwner* aOwner, | ||||
|     int32_t aWhichClipboard, mozilla::dom::WindowContext* aWindowContext) { | ||||
|   NS_ASSERTION(aTransferable, "clipboard given a null transferable"); | ||||
| 
 | ||||
|   MOZ_CLIPBOARD_LOG("%s: clipboard=%d", __FUNCTION__, aWhichClipboard); | ||||
|  | @ -580,7 +600,10 @@ NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable* aTransferable, | |||
|     return result.unwrapErr(); | ||||
|   } | ||||
| 
 | ||||
|   clipboardCache->Update(aTransferable, aOwner, result.unwrap()); | ||||
|   clipboardCache->Update(aTransferable, aOwner, result.unwrap(), | ||||
|                          aWindowContext | ||||
|                              ? mozilla::Some(aWindowContext->InnerWindowId()) | ||||
|                              : mozilla::Nothing()); | ||||
|   return NS_OK; | ||||
| } | ||||
| 
 | ||||
|  | @ -623,7 +646,7 @@ NS_IMETHODIMP nsBaseClipboard::GetData( | |||
|             GetDataFromClipboardCache(aTransferable, aWhichClipboard))) { | ||||
|       // maybe try to fill in more types? Is there a point?
 | ||||
|       if (!CheckClipboardContentAnalysisSync(aWindowContext->Canonical(), | ||||
|                                              aTransferable)) { | ||||
|                                              aTransferable, aWhichClipboard)) { | ||||
|         aTransferable->ClearAllData(); | ||||
|         return NS_ERROR_CONTENT_BLOCKED; | ||||
|       } | ||||
|  | @ -638,7 +661,7 @@ NS_IMETHODIMP nsBaseClipboard::GetData( | |||
|     return rv; | ||||
|   } | ||||
|   if (!CheckClipboardContentAnalysisSync(aWindowContext->Canonical(), | ||||
|                                          aTransferable)) { | ||||
|                                          aTransferable, aWhichClipboard)) { | ||||
|     aTransferable->ClearAllData(); | ||||
|     return NS_ERROR_CONTENT_BLOCKED; | ||||
|   } | ||||
|  | @ -1203,7 +1226,7 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData( | |||
|       mClipboard->CheckClipboardContentAnalysis( | ||||
|           mRequestingWindowContext ? mRequestingWindowContext->Canonical() | ||||
|                                    : nullptr, | ||||
|           aTransferable, contentAnalysisCallback); | ||||
|           aTransferable, mClipboardType, contentAnalysisCallback); | ||||
|       return NS_OK; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1233,7 +1256,7 @@ NS_IMETHODIMP nsBaseClipboard::AsyncGetClipboardData::GetData( | |||
|             self->mRequestingWindowContext | ||||
|                 ? self->mRequestingWindowContext->Canonical() | ||||
|                 : nullptr, | ||||
|             transferable, contentAnalysisCallback); | ||||
|             transferable, self->mClipboardType, contentAnalysisCallback); | ||||
|       }); | ||||
|   return NS_OK; | ||||
| } | ||||
|  |  | |||
|  | @ -44,9 +44,12 @@ class nsBaseClipboard : public nsIClipboard { | |||
|   NS_DECL_ISUPPORTS | ||||
| 
 | ||||
|   // nsIClipboard
 | ||||
|   NS_IMETHOD SetData(nsITransferable* aTransferable, nsIClipboardOwner* aOwner, | ||||
|                      int32_t aWhichClipboard) override final; | ||||
|   NS_IMETHOD SetData( | ||||
|       nsITransferable* aTransferable, nsIClipboardOwner* aOwner, | ||||
|       int32_t aWhichClipboard, | ||||
|       mozilla::dom::WindowContext* aWindowContext) override final; | ||||
|   NS_IMETHOD AsyncSetData(int32_t aWhichClipboard, | ||||
|                           mozilla::dom::WindowContext* aSettingWindowContext, | ||||
|                           nsIAsyncClipboardRequestCallback* aCallback, | ||||
|                           nsIAsyncSetClipboardData** _retval) override final; | ||||
|   NS_IMETHOD GetData( | ||||
|  | @ -108,6 +111,7 @@ class nsBaseClipboard : public nsIClipboard { | |||
|     NS_DECL_NSIASYNCSETCLIPBOARDDATA | ||||
| 
 | ||||
|     AsyncSetClipboardData(int32_t aClipboardType, nsBaseClipboard* aClipboard, | ||||
|                           mozilla::dom::WindowContext* aRequestingWindowContext, | ||||
|                           nsIAsyncClipboardRequestCallback* aCallback); | ||||
| 
 | ||||
|    private: | ||||
|  | @ -125,6 +129,7 @@ class nsBaseClipboard : public nsIClipboard { | |||
|     // NotifyCallback()) once nsBaseClipboard stops tracking us. This is
 | ||||
|     // also used to indicate whether this request is valid.
 | ||||
|     nsBaseClipboard* mClipboard; | ||||
|     RefPtr<mozilla::dom::WindowContext> mWindowContext; | ||||
|     // mCallback will be nullified once the callback is notified to ensure the
 | ||||
|     // callback is only notified once.
 | ||||
|     nsCOMPtr<nsIAsyncClipboardRequestCallback> mCallback; | ||||
|  | @ -174,22 +179,26 @@ class nsBaseClipboard : public nsIClipboard { | |||
|      */ | ||||
|     void Clear(); | ||||
|     void Update(nsITransferable* aTransferable, | ||||
|                 nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber) { | ||||
|                 nsIClipboardOwner* aClipboardOwner, int32_t aSequenceNumber, | ||||
|                 mozilla::Maybe<uint64_t> aInnerWindowId) { | ||||
|       // Clear first to notify the old clipboard owner.
 | ||||
|       Clear(); | ||||
|       mTransferable = aTransferable; | ||||
|       mClipboardOwner = aClipboardOwner; | ||||
|       mSequenceNumber = aSequenceNumber; | ||||
|       mInnerWindowId = aInnerWindowId; | ||||
|     } | ||||
|     nsITransferable* GetTransferable() const { return mTransferable; } | ||||
|     nsIClipboardOwner* GetClipboardOwner() const { return mClipboardOwner; } | ||||
|     int32_t GetSequenceNumber() const { return mSequenceNumber; } | ||||
|     mozilla::Maybe<uint64_t> GetInnerWindowId() const { return mInnerWindowId; } | ||||
|     nsresult GetData(nsITransferable* aTransferable) const; | ||||
| 
 | ||||
|    private: | ||||
|     nsCOMPtr<nsITransferable> mTransferable; | ||||
|     nsCOMPtr<nsIClipboardOwner> mClipboardOwner; | ||||
|     int32_t mSequenceNumber = -1; | ||||
|     mozilla::Maybe<uint64_t> mInnerWindowId; | ||||
|   }; | ||||
| 
 | ||||
|   class SafeContentAnalysisResultCallback final | ||||
|  | @ -245,10 +254,10 @@ class nsBaseClipboard : public nsIClipboard { | |||
|                                      int32_t aClipboardType); | ||||
|   bool CheckClipboardContentAnalysisSync( | ||||
|       mozilla::dom::WindowGlobalParent* aWindow, | ||||
|       const nsCOMPtr<nsITransferable>& trans); | ||||
|       const nsCOMPtr<nsITransferable>& trans, int32_t aClipboardType); | ||||
|   void CheckClipboardContentAnalysis( | ||||
|       mozilla::dom::WindowGlobalParent* aWindow, nsITransferable* aTransferable, | ||||
|       SafeContentAnalysisResultCallback* aResolver); | ||||
|       int32_t aClipboardType, SafeContentAnalysisResultCallback* aResolver); | ||||
|   //  - true means a content analysis request was fired
 | ||||
|   //  - false means there is no text data in the transferable
 | ||||
|   //  - NoContentAnalysisResult means there was an error
 | ||||
|  |  | |||
|  | @ -36,9 +36,10 @@ nsClipboardHelper::~nsClipboardHelper() { | |||
|  *****************************************************************************/ | ||||
| 
 | ||||
| NS_IMETHODIMP | ||||
| nsClipboardHelper::CopyStringToClipboard(const nsAString& aString, | ||||
|                                          int32_t aClipboardID, | ||||
|                                          SensitiveData aSensitive) { | ||||
| nsClipboardHelper::CopyStringToClipboard( | ||||
|     const nsAString& aString, int32_t aClipboardID, | ||||
|     mozilla::dom::WindowContext* aSettingWindowContext, | ||||
|     SensitiveData aSensitive) { | ||||
|   nsresult rv; | ||||
| 
 | ||||
|   // get the clipboard
 | ||||
|  | @ -92,20 +93,22 @@ nsClipboardHelper::CopyStringToClipboard(const nsAString& aString, | |||
|   NS_ENSURE_SUCCESS(rv, rv); | ||||
| 
 | ||||
|   // put the transferable on the clipboard
 | ||||
|   rv = clipboard->SetData(trans, nullptr, aClipboardID); | ||||
|   rv = clipboard->SetData(trans, nullptr, aClipboardID, aSettingWindowContext); | ||||
|   NS_ENSURE_SUCCESS(rv, rv); | ||||
| 
 | ||||
|   return NS_OK; | ||||
| } | ||||
| 
 | ||||
| NS_IMETHODIMP | ||||
| nsClipboardHelper::CopyString(const nsAString& aString, | ||||
|                               SensitiveData aSensitive) { | ||||
| nsClipboardHelper::CopyString( | ||||
|     const nsAString& aString, | ||||
|     mozilla::dom::WindowContext* aSettingWindowContext, | ||||
|     SensitiveData aSensitive) { | ||||
|   nsresult rv; | ||||
| 
 | ||||
|   // copy to the global clipboard. it's bad if this fails in any way.
 | ||||
|   rv = CopyStringToClipboard(aString, nsIClipboard::kGlobalClipboard, | ||||
|                              aSensitive); | ||||
|                              aSettingWindowContext, aSensitive); | ||||
|   NS_ENSURE_SUCCESS(rv, rv); | ||||
| 
 | ||||
|   // unix also needs us to copy to the selection clipboard. this will
 | ||||
|  | @ -117,7 +120,8 @@ nsClipboardHelper::CopyString(const nsAString& aString, | |||
|   // if this fails in any way other than "not being unix", we'll get
 | ||||
|   // the assertion we need in CopyStringToClipboard, and we needn't
 | ||||
|   // assert again here.
 | ||||
|   CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard, aSensitive); | ||||
|   CopyStringToClipboard(aString, nsIClipboard::kSelectionClipboard, | ||||
|                         aSettingWindowContext, aSensitive); | ||||
| 
 | ||||
|   return NS_OK; | ||||
| } | ||||
|  |  | |||
|  | @ -32,7 +32,8 @@ nsClipboardProxy::nsClipboardProxy() : mClipboardCaps(false, false, false) {} | |||
| 
 | ||||
| NS_IMETHODIMP | ||||
| nsClipboardProxy::SetData(nsITransferable* aTransferable, | ||||
|                           nsIClipboardOwner* anOwner, int32_t aWhichClipboard) { | ||||
|                           nsIClipboardOwner* anOwner, int32_t aWhichClipboard, | ||||
|                           mozilla::dom::WindowContext* aWindowContext) { | ||||
| #if defined(ACCESSIBILITY) && defined(XP_WIN) | ||||
|   a11y::Compatibility::SuppressA11yForClipboardCopy(); | ||||
| #endif | ||||
|  | @ -41,17 +42,19 @@ nsClipboardProxy::SetData(nsITransferable* aTransferable, | |||
|   IPCTransferable ipcTransferable; | ||||
|   nsContentUtils::TransferableToIPCTransferable(aTransferable, &ipcTransferable, | ||||
|                                                 false, nullptr); | ||||
|   child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard); | ||||
|   child->SendSetClipboard(std::move(ipcTransferable), aWhichClipboard, | ||||
|                           aWindowContext); | ||||
|   return NS_OK; | ||||
| } | ||||
| 
 | ||||
| NS_IMETHODIMP nsClipboardProxy::AsyncSetData( | ||||
|     int32_t aWhichClipboard, nsIAsyncClipboardRequestCallback* aCallback, | ||||
|     int32_t aWhichClipboard, mozilla::dom::WindowContext* aSettingWindowContext, | ||||
|     nsIAsyncClipboardRequestCallback* aCallback, | ||||
|     nsIAsyncSetClipboardData** _retval) { | ||||
|   RefPtr<ClipboardWriteRequestChild> request = | ||||
|       MakeRefPtr<ClipboardWriteRequestChild>(aCallback); | ||||
|   ContentChild::GetSingleton()->SendPClipboardWriteRequestConstructor( | ||||
|       request, aWhichClipboard); | ||||
|       request, aWhichClipboard, aSettingWindowContext); | ||||
|   request.forget(_retval); | ||||
|   return NS_OK; | ||||
| } | ||||
|  |  | |||
|  | @ -115,20 +115,28 @@ interface nsIClipboard : nsISupports | |||
|     * @param  aTransferable The transferable | ||||
|     * @param  anOwner The owner of the transferable | ||||
|     * @param  aWhichClipboard Specifies the clipboard to which this operation applies. | ||||
|     * @result NS_Ok if no errors | ||||
|     * @param  aSettingWindowContext [optional] | ||||
|     *         The window context that is setting the clipboard, if any. This is used | ||||
|     *         to possibly bypass Content Analysis if a set clipboard and get clipboard | ||||
|     *         operation are done on the same page. | ||||
|     * @result NS_OK if no errors | ||||
|     */ | ||||
| 
 | ||||
|     void setData ( in nsITransferable aTransferable, in nsIClipboardOwner anOwner, | ||||
|                     in long aWhichClipboard ) ; | ||||
|     void setData (in nsITransferable aTransferable, in nsIClipboardOwner anOwner, | ||||
|                   in long aWhichClipboard, [optional] in WindowContext aSettingWindowContext); | ||||
| 
 | ||||
|     /** | ||||
|      * Requests setting data to the native clipboard. The acutal set occur | ||||
|      * Requests setting data to the native clipboard. The actual set occurs | ||||
|      * when the data is provided by calling nsIAsyncSetClipboardData::setData(). | ||||
|      * The result will be notified by nsIClipboardCallback. A new set request | ||||
|      * will cancel any prior pending requests, if any exist. | ||||
|      * | ||||
|      * @param  aWhichClipboard | ||||
|      *         Specifies the clipboard to which this operation applies. | ||||
|      * @param  aSettingWindowContext [optional] | ||||
|      *         The window context that is setting the clipboard, if any. This is used | ||||
|      *         to possibly bypass Content Analysis if a set clipboard and get clipboard | ||||
|      *         operation are done on the same page. | ||||
|      * @param  aCallback [optional] | ||||
|      *         The callback object that will be notified upon completion. | ||||
|      * @return nsIAsyncSetClipboardData | ||||
|  | @ -136,6 +144,7 @@ interface nsIClipboard : nsISupports | |||
|      *         data is provided by calling nsIAsyncSetClipboardData::setData(). | ||||
|      */ | ||||
|     nsIAsyncSetClipboardData asyncSetData(in long aWhichClipboard, | ||||
|                                           [optional] in WindowContext aSettingWindowContext, | ||||
|                                           [optional] in nsIAsyncClipboardRequestCallback aCallback); | ||||
| 
 | ||||
|    /** | ||||
|  |  | |||
|  | @ -29,17 +29,29 @@ interface nsIClipboardHelper : nsISupports | |||
|    * @param aString, the string to copy to the clipboard | ||||
|    * @param aClipboardID, the ID of the clipboard to copy to | ||||
|    *        (eg. kSelectionClipboard -- see nsIClipboard.idl) | ||||
|    * @param aSettingWindowContext | ||||
|    *         The window context that is setting the clipboard, if any. This is used | ||||
|    *         to possibly bypass Content Analysis if a set clipboard and get clipboard | ||||
|    *         operation are done on the same page. | ||||
|    * @param aSensitive, optional flag to indicate that data is sensitive, like a password. | ||||
|    *        That will exclude data from Cloud Clipboard/Clipboard History on Windows. | ||||
|    */ | ||||
|   void copyStringToClipboard(in AString aString, in long aClipboardID, | ||||
|                              [optional] in WindowContext aSettingWindowContext, | ||||
|                              [optional, default(NotSensitive)] in nsIClipboardHelper_SensitiveData aSensitive); | ||||
| 
 | ||||
|   /** | ||||
|    * copy string to (default) clipboard | ||||
|    * | ||||
|    * @param aString, the string to copy to the clipboard | ||||
|    * @param aSettingWindowContext | ||||
|    *         The window context that is setting the clipboard, if any. This is used | ||||
|    *         to possibly bypass Content Analysis if a set clipboard and get clipboard | ||||
|    *         operation are done on the same page. | ||||
|    * @param aSensitive, optional flag to indicate that data is sensitive, like a password. | ||||
|    *        That will exclude data from Cloud Clipboard/Clipboard History on Windows. | ||||
|    */ | ||||
|   void copyString(in AString aString, | ||||
|                   [optional] in WindowContext aSettingWindowContext, | ||||
|                   [optional, default(NotSensitive)] in nsIClipboardHelper_SensitiveData aSensitive); | ||||
| }; | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ clipboardTypes.forEach(function (type) { | |||
|             let priorResult; | ||||
|             let priorRequest; | ||||
|             let priorPromise = new Promise(resolve => { | ||||
|               priorRequest = clipboard.asyncSetData(type, { | ||||
|               priorRequest = clipboard.asyncSetData(type, null, { | ||||
|                 QueryInterface: SpecialPowers.ChromeUtils.generateQI([ | ||||
|                   "nsIAsyncSetClipboardDataCallback", | ||||
|                 ]), | ||||
|  | @ -119,7 +119,7 @@ clipboardTypes.forEach(function (type) { | |||
| 
 | ||||
|       // Create a pending asyncSetData request
 | ||||
|       let result; | ||||
|       let request = clipboard.asyncSetData(type, rv => { | ||||
|       let request = clipboard.asyncSetData(type, null, rv => { | ||||
|         result = rv; | ||||
|       }); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Greg Stoll
						Greg Stoll