michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include "nsClipboardPrivacyHandler.h" michael@0: #include "nsITransferable.h" michael@0: #include "nsISupportsPrimitives.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsIClipboard.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsLiteralString.h" michael@0: #include "nsNetCID.h" michael@0: #include "nsXPCOM.h" michael@0: #include "mozilla/Services.h" michael@0: michael@0: #if defined(XP_WIN) michael@0: #include michael@0: #endif michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #define NS_MOZ_DATA_FROM_PRIVATEBROWSING "application/x-moz-private-browsing" michael@0: michael@0: NS_IMPL_ISUPPORTS(nsClipboardPrivacyHandler, nsIObserver, nsISupportsWeakReference) michael@0: michael@0: nsresult michael@0: nsClipboardPrivacyHandler::Init() michael@0: { michael@0: nsCOMPtr observerService = michael@0: mozilla::services::GetObserverService(); michael@0: if (!observerService) michael@0: return NS_ERROR_FAILURE; michael@0: return observerService->AddObserver(this, "last-pb-context-exited", true); michael@0: } michael@0: michael@0: /** michael@0: * Prepare the transferable object to be inserted into the clipboard michael@0: * michael@0: */ michael@0: nsresult michael@0: nsClipboardPrivacyHandler::PrepareDataForClipboard(nsITransferable * aTransferable) michael@0: { michael@0: NS_ASSERTION(aTransferable, "clipboard given a null transferable"); michael@0: michael@0: bool isPrivateData = false; michael@0: aTransferable->GetIsPrivateData(&isPrivateData); michael@0: michael@0: nsresult rv = NS_OK; michael@0: if (isPrivateData) { michael@0: nsCOMPtr data = do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID); michael@0: if (data) { michael@0: rv = data->SetData(true); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // Ignore the error code of AddDataFlavor, since we might have added michael@0: // this flavor before. If this call really fails, so will the next michael@0: // one (SetTransferData). michael@0: aTransferable->AddDataFlavor(NS_MOZ_DATA_FROM_PRIVATEBROWSING); michael@0: michael@0: rv = aTransferable->SetTransferData(NS_MOZ_DATA_FROM_PRIVATEBROWSING, data, sizeof(bool)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsClipboardPrivacyHandler::Observe(nsISupports *aSubject, char const *aTopic, char16_t const *aData) michael@0: { michael@0: nsresult rv; michael@0: nsCOMPtr clipboard = michael@0: do_GetService("@mozilla.org/widget/clipboard;1", &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: const char * flavors[] = { NS_MOZ_DATA_FROM_PRIVATEBROWSING }; michael@0: bool haveFlavors; michael@0: rv = clipboard->HasDataMatchingFlavors(flavors, michael@0: ArrayLength(flavors), michael@0: nsIClipboard::kGlobalClipboard, michael@0: &haveFlavors); michael@0: if (NS_SUCCEEDED(rv) && haveFlavors) { michael@0: #if defined(XP_WIN) michael@0: // Workaround for bug 518412. On Windows 7 x64, there is a bug michael@0: // in handling clipboard data without any formats between michael@0: // 32-bit/64-bit boundaries, which could lead Explorer to crash. michael@0: // We work around the problem by clearing the clipboard using michael@0: // the usual Win32 API. michael@0: NS_ENSURE_TRUE(SUCCEEDED(::OleSetClipboard(nullptr)), NS_ERROR_FAILURE); michael@0: #else michael@0: // Empty the native clipboard by copying an empty transferable michael@0: nsCOMPtr nullData = michael@0: do_CreateInstance("@mozilla.org/widget/transferable;1", &rv); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: nullData->Init(nullptr); michael@0: rv = clipboard->SetData(nullData, nullptr, michael@0: nsIClipboard::kGlobalClipboard); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: #endif michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: NS_NewClipboardPrivacyHandler(nsClipboardPrivacyHandler ** aHandler) michael@0: { michael@0: NS_PRECONDITION(aHandler != nullptr, "null ptr"); michael@0: if (!aHandler) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: *aHandler = new nsClipboardPrivacyHandler(); michael@0: michael@0: NS_ADDREF(*aHandler); michael@0: nsresult rv = (*aHandler)->Init(); michael@0: if (NS_FAILED(rv)) michael@0: NS_RELEASE(*aHandler); michael@0: michael@0: return rv; michael@0: }