Bug 462106 - Clear the data copied to clipboard inside the private browsing mode after leaving it (2nd try); r,sr=roc

This commit is contained in:
Ehsan Akhgari 2009-01-30 11:43:17 +03:30
parent c8ac77af60
commit c10937e604
13 changed files with 373 additions and 1 deletions

View File

@ -164,6 +164,14 @@ nsClipboard::SetData(nsITransferable *aTransferable,
return NS_OK;
}
nsresult rv;
if (!mPrivacyHandler) {
rv = NS_NewClipboardPrivacyHandler(getter_AddRefs(mPrivacyHandler));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mPrivacyHandler->PrepareDataForClipboard(aTransferable);
NS_ENSURE_SUCCESS(rv, rv);
// Clear out the clipboard in order to set the new data
EmptyClipboard(aWhichClipboard);
@ -187,7 +195,6 @@ nsClipboard::SetData(nsITransferable *aTransferable,
gtk_selection_clear_targets(mWidget, selectionAtom);
// Get the types of supported flavors
nsresult rv;
nsCOMPtr<nsISupportsArray> flavors;
rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavors));

View File

@ -40,6 +40,8 @@
#define __nsClipboard_h_
#include "nsIClipboard.h"
#include "nsClipboardPrivacyHandler.h"
#include "nsAutoPtr.h"
#include <gtk/gtk.h>
class nsClipboard : public nsIClipboard
@ -84,6 +86,7 @@ private:
nsCOMPtr<nsIClipboardOwner> mGlobalOwner;
nsCOMPtr<nsITransferable> mSelectionTransferable;
nsCOMPtr<nsITransferable> mGlobalTransferable;
nsRefPtr<nsClipboardPrivacyHandler> mPrivacyHandler;
};

View File

@ -130,6 +130,14 @@ NS_IMETHODIMP nsClipboard::SetData(nsITransferable * aTransferable,
return NS_OK;
}
nsresult rv;
if (!mPrivacyHandler) {
rv = NS_NewClipboardPrivacyHandler(getter_AddRefs(mPrivacyHandler));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mPrivacyHandler.PrepareDataForClipboard(aTransferable);
NS_ENSURE_SUCCESS(rv, rv);
EmptyClipboard(aWhichClipboard);
switch (aWhichClipboard)

View File

@ -46,6 +46,8 @@
#include "nsIClipboard.h"
#include "nsITransferable.h"
#include "nsIClipboardOwner.h"
#include "nsClipboardPrivacyHandler.h"
#include "nsAutoPtr.h"
#include <nsCOMPtr.h>
class nsITransferable;
@ -91,6 +93,7 @@ private:
nsCOMPtr<nsIClipboardOwner> mGlobalOwner;
nsCOMPtr<nsITransferable> mSelectionTransferable;
nsCOMPtr<nsITransferable> mGlobalTransferable;
nsRefPtr<nsClipboardPrivacyHandler> mPrivacyHandler;
// Used for communicating pasted data
// from the asynchronous X routines back to a blocking paste:

View File

@ -308,6 +308,14 @@ nsClipboard::SetData(nsITransferable *aTransferable,
return NS_OK;
}
nsresult rv;
if (!mPrivacyHandler) {
rv = NS_NewClipboardPrivacyHandler(getter_AddRefs(mPrivacyHandler));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mPrivacyHandler.PrepareDataForClipboard(aTransferable);
NS_ENSURE_SUCCESS(rv, rv);
EmptyClipboard(aWhichClipboard);
QClipboard::Mode mode;

View File

@ -41,6 +41,8 @@
#include "nsIClipboard.h"
#include "nsITransferable.h"
#include "nsIClipboardOwner.h"
#include "nsClipboardPrivacyHandler.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include <qclipboard.h>
@ -68,6 +70,7 @@ protected:
nsCOMPtr<nsIClipboardOwner> mGlobalOwner;
nsCOMPtr<nsITransferable> mSelectionTransferable;
nsCOMPtr<nsITransferable> mGlobalTransferable;
nsRefPtr<nsClipboardPrivacyHandler> mPrivacyHandler;
};
#endif // nsClipboard_h__

View File

@ -81,6 +81,7 @@ CPPSRCS = \
nsPrintSession.cpp \
nsWidgetAtoms.cpp \
nsIdleService.cpp \
nsClipboardPrivacyHandler.cpp \
$(NULL)
ifneq (,$(filter beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))

View File

@ -86,6 +86,12 @@ NS_IMETHODIMP nsBaseClipboard::SetData(nsITransferable * aTransferable, nsIClipb
if ( mTransferable ) {
NS_ADDREF(mTransferable);
if (!mPrivacyHandler) {
rv = NS_NewClipboardPrivacyHandler(getter_AddRefs(mPrivacyHandler));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mPrivacyHandler->PrepareDataForClipboard(mTransferable);
NS_ENSURE_SUCCESS(rv, rv);
rv = SetNativeClipboardData(aWhichClipboard);
}

View File

@ -40,6 +40,8 @@
#include "nsIClipboard.h"
#include "nsITransferable.h"
#include "nsClipboardPrivacyHandler.h"
#include "nsAutoPtr.h"
class nsITransferable;
class nsDataObj;
@ -71,6 +73,7 @@ protected:
PRBool mIgnoreEmptyNotification;
nsIClipboardOwner * mClipboardOwner;
nsITransferable * mTransferable;
nsRefPtr<nsClipboardPrivacyHandler> mPrivacyHandler;
};

View File

@ -0,0 +1,149 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Ehsan Akhgari.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsClipboardPrivacyHandler.h"
#include "nsITransferable.h"
#include "nsISupportsPrimitives.h"
#include "nsIObserverService.h"
#include "nsIClipboard.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsLiteralString.h"
#include "nsNetCID.h"
#include "nsXPCOM.h"
#define NS_MOZ_DATA_FROM_PRIVATEBROWSING "application/x-moz-private-browsing"
NS_IMPL_ISUPPORTS2(nsClipboardPrivacyHandler, nsIObserver, nsISupportsWeakReference)
nsresult
nsClipboardPrivacyHandler::Init()
{
nsresult rv;
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = observerService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_TRUE);
return rv;
}
/**
* Prepare the transferable object to be inserted into the clipboard
*
*/
nsresult
nsClipboardPrivacyHandler::PrepareDataForClipboard(nsITransferable * aTransferable)
{
NS_ASSERTION(aTransferable, "clipboard given a null transferable");
nsresult rv = NS_OK;
if (InPrivateBrowsing()) {
nsCOMPtr<nsISupportsPRBool> data = do_CreateInstance(NS_SUPPORTS_PRBOOL_CONTRACTID);
if (data) {
rv = data->SetData(PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
rv = aTransferable->AddDataFlavor(NS_MOZ_DATA_FROM_PRIVATEBROWSING);
NS_ENSURE_SUCCESS(rv, rv);
rv = aTransferable->SetTransferData(NS_MOZ_DATA_FROM_PRIVATEBROWSING, data, sizeof(PRBool));
NS_ENSURE_SUCCESS(rv, rv);
}
}
return rv;
}
NS_IMETHODIMP
nsClipboardPrivacyHandler::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
{
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
nsresult rv;
nsCOMPtr<nsIClipboard> clipboard =
do_GetService("@mozilla.org/widget/clipboard;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
const char * flavors[] = { NS_MOZ_DATA_FROM_PRIVATEBROWSING };
PRBool haveFlavors;
rv = clipboard->HasDataMatchingFlavors(flavors,
NS_ARRAY_LENGTH(flavors),
nsIClipboard::kGlobalClipboard,
&haveFlavors);
if (NS_SUCCEEDED(rv) && haveFlavors) {
// Empty the native clipboard by copying an empty transferable
nsCOMPtr<nsITransferable> nullData =
do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = clipboard->SetData(nullData, nsnull,
nsIClipboard::kGlobalClipboard);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
PRBool
nsClipboardPrivacyHandler::InPrivateBrowsing()
{
PRBool inPrivateBrowsingMode = PR_FALSE;
if (!mPBService)
mPBService = do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
if (mPBService)
mPBService->GetPrivateBrowsingEnabled(&inPrivateBrowsingMode);
return inPrivateBrowsingMode;
}
nsresult
NS_NewClipboardPrivacyHandler(nsClipboardPrivacyHandler ** aHandler)
{
NS_PRECONDITION(aHandler != nsnull, "null ptr");
if (!aHandler)
return NS_ERROR_NULL_POINTER;
*aHandler = new nsClipboardPrivacyHandler();
if (!*aHandler)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aHandler);
nsresult rv = (*aHandler)->Init();
if (NS_FAILED(rv))
NS_RELEASE(*aHandler);
return rv;
}

View File

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Ehsan Akhgari.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsClipboardPrivacyHandler_h__
#define nsClipboardPrivacyHandler_h__
#include "nsIObserver.h"
#include "nsIPrivateBrowsingService.h"
#include "nsWeakReference.h"
#include "nsCOMPtr.h"
class nsITransferable;
// nsClipboardPrivacyHandler makes sure that clipboard data copied during
// the private browsing mode does not leak after exiting this mode.
// In order to ensure this, callers should store an object of this class
// for their lifetime, and call PrepareDataForClipboard in their
// nsIClipboard::SetData implementation before starting to use the
// nsITransferable object in any way.
class nsClipboardPrivacyHandler : public nsIObserver,
public nsSupportsWeakReference
{
public:
// nsISupports
NS_DECL_ISUPPORTS
// nsIObserver
NS_DECL_NSIOBSERVER
nsresult Init();
nsresult PrepareDataForClipboard(nsITransferable * aTransferable);
private:
PRBool InPrivateBrowsing();
nsCOMPtr<nsIPrivateBrowsingService> mPBService;
};
nsresult NS_NewClipboardPrivacyHandler(nsClipboardPrivacyHandler ** aHandler);
#endif // nsClipboardPrivacyHandler_h__

View File

@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_bug343416.xul \
test_bug444800.xul \
test_bug462106.xul \
test_keycodes.xul \
$(NULL)

View File

@ -0,0 +1,99 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=462106
-->
<window title="Mozilla Bug 462106"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="initAndRunTests()">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
<!-- test code goes here -->
<script class="testbody" type="application/javascript">
<![CDATA[
/** Test for Bug 462106 **/
const Cc = Components.classes;
const Ci = Components.interfaces;
function copy(str) {
Cc["@mozilla.org/widget/clipboardhelper;1"].
getService(Ci.nsIClipboardHelper).
copyString(str);
}
function paste() {
let trans = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
trans.addDataFlavor("text/unicode");
let clip = Cc["@mozilla.org/widget/clipboard;1"].
getService(Ci.nsIClipboard);
clip.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
let str = {}, length = {};
try {
trans.getTransferData("text/unicode", str, length);
} catch (e) {
str = null;
}
if (str) {
str = str.value.QueryInterface(Ci.nsISupportsString);
if (str)
str = str.data.substring(0, length.value / 2);
}
return str;
}
function initAndRunTests() {
let pb;
try {
pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
} catch (e) {
return;
}
SimpleTest.waitForExplicitFinish();
let prefBranch = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
const data = "random number: " + Math.random();
copy(data);
is(data, paste(), "Data successfully copied before entering the private browsing mode");
pb.privateBrowsingEnabled = true;
pb.privateBrowsingEnabled = false;
// the data should still be on the clipboard because it was copied before
// entering the private browsing mode
is(data, paste(), "Copied data persisted after leaving the private browsing mode");
const data2 = "another random number: " + Math.random();
pb.privateBrowsingEnabled = true;
copy(data2); // copy the data inside the private browsing mode
setTimeout(function() { // without this, the test fails sporadically
// the data should be on the clipboard inside the private browsing mode
is(data2, paste(), "Data successfully copied inside the private browsing mode");
pb.privateBrowsingEnabled = false;
// the data should no longer be on the clipboard at this stage
isnot(data2, paste(), "Data no longer available after leaving the private browsing mode");
prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
SimpleTest.finish();
}, 0);
}
]]>
</script>
</window>