Merge m-c to devtools

This commit is contained in:
Dave Camp 2011-05-21 17:43:04 -07:00
commit eb5d5ebaa0
1335 changed files with 23677 additions and 78435 deletions

View File

@ -62,3 +62,4 @@ b70744835d94e54eec97b8fd186c96da5708a506 PRE_MOBILE_MERGE_20110406
a71bd564ebf5bf4f93d13e84114f759c263130b0 MOBILE_MERGE_DONE
a71bd564ebf5bf4f93d13e84114f759c263130b0 MOBILE_MERGE_DONE_20110406
a95d426422816513477e5863add1b00ac7041dcb AURORA_BASE_20110412
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R14

View File

@ -162,7 +162,7 @@ ifdef MOZ_SYMBOLS_EXTRA_BUILDID
EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
endif
export SYMBOL_INDEX_NAME = \
SYMBOL_INDEX_NAME = \
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
buildsymbols:
@ -194,7 +194,7 @@ endif # MOZ_CRASHREPORTER
uploadsymbols:
ifdef MOZ_CRASHREPORTER
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh "$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip"
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) "$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip"
endif
# defined in package-name.mk

View File

@ -341,9 +341,7 @@ void nsAccessibleWrap::SetMaiHyperlink(MaiHyperlink* aMaiHyperlink)
if (!maiHyperlink && !aMaiHyperlink) {
return; // Never set and we're shutting down
}
if (maiHyperlink) {
delete maiHyperlink;
}
delete maiHyperlink;
g_object_set_qdata(G_OBJECT(mAtkObject), quark_mai_hyperlink,
aMaiHyperlink);
}

View File

@ -199,23 +199,32 @@ private:
printf("uri: %s", spec);
#define NS_LOG_ACCDOC_TYPE(aDocument) \
PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \
printf("%s document", (isContent ? "content" : "chrome"));
if (aDocument->IsActive()) { \
PRBool isContent = nsCoreUtils::IsContentDocument(aDocument); \
printf("%s document", (isContent ? "content" : "chrome")); \
} else { \
printf("document type: [failed]"); \
}
#define NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
nsCOMPtr<nsISupports> container = aDocument->GetContainer(); \
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); \
PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; \
docShell->GetBusyFlags(&busyFlags); \
nsCAutoString docShellBusy; \
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \
docShellBusy.AppendLiteral("'none'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) \
docShellBusy.AppendLiteral("'busy'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) \
docShellBusy.AppendLiteral(", 'before page load'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) \
docShellBusy.AppendLiteral(", 'page loading'"); \
nsCOMPtr<nsISupports> container = aDocument->GetContainer(); \
if (container) { \
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container); \
PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; \
docShell->GetBusyFlags(&busyFlags); \
if (busyFlags == nsIDocShell::BUSY_FLAGS_NONE) \
docShellBusy.AppendLiteral("'none'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY) \
docShellBusy.AppendLiteral("'busy'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_BEFORE_PAGE_LOAD) \
docShellBusy.AppendLiteral(", 'before page load'"); \
if (busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING) \
docShellBusy.AppendLiteral(", 'page loading'"); \
} \
else { \
docShellBusy.AppendLiteral("[failed]"); \
} \
printf("docshell busy: %s", docShellBusy.get());
#define NS_LOG_ACCDOC_DOCSTATES(aDocument) \
@ -336,20 +345,22 @@ private:
printf(" "); \
NS_LOG_ACCDOC_ADDRESS(aDocument, aDocAcc) \
printf("\n "); \
NS_LOG_ACCDOC_URI(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
printf("; "); \
NS_LOG_ACCDOC_TYPE(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_DOCSTATES(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \
printf(", "); \
NS_LOG_ACCDOC_DOCPARENT(aDocument) \
printf("\n"); \
if (aDocument) { \
NS_LOG_ACCDOC_URI(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_SHELLSTATE(aDocument) \
printf("; "); \
NS_LOG_ACCDOC_TYPE(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_DOCSTATES(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \
printf("\n "); \
NS_LOG_ACCDOC_DOCLOADGROUP(aDocument) \
printf(", "); \
NS_LOG_ACCDOC_DOCPARENT(aDocument) \
printf("\n"); \
} \
}
#define NS_LOG_ACCDOC_DOCINFO_END \
printf(" }\n");

View File

@ -67,7 +67,7 @@ struct WalkState
nsAccTreeWalker::
nsAccTreeWalker(nsIWeakReference* aShell, nsIContent* aContent,
PRBool aWalkAnonContent, bool aWalkCache) :
mWeakShell(aShell), mState(nsnull), mWalkCache(aWalkCache)
mWeakShell(aShell), mWalkCache(aWalkCache), mState(nsnull)
{
NS_ASSERTION(aContent, "No node for the accessible tree walker!");

View File

@ -160,7 +160,8 @@ nsAccUtils::GetPositionAndSizeForXULSelectControlItem(nsIContent *aContent,
control->GetItemAtIndex(index, getter_AddRefs(currItem));
nsCOMPtr<nsINode> currNode(do_QueryInterface(currItem));
nsAccessible* itemAcc = GetAccService()->GetAccessible(currNode);
nsAccessible* itemAcc = currNode ?
GetAccService()->GetAccessible(currNode) : nsnull;
if (!itemAcc || itemAcc->State() & states::INVISIBLE) {
(*aSetSize)--;
@ -201,7 +202,8 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
container->GetItemAtIndex(index, getter_AddRefs(item));
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
nsAccessible* itemAcc = GetAccService()->GetAccessible(itemNode);
nsAccessible* itemAcc = itemNode ?
GetAccService()->GetAccessible(itemNode) : nsnull;
if (itemAcc) {
PRUint32 itemRole = Role(itemAcc);
@ -221,7 +223,8 @@ nsAccUtils::GetPositionAndSizeForXULContainerItem(nsIContent *aContent,
container->GetItemAtIndex(index, getter_AddRefs(item));
nsCOMPtr<nsINode> itemNode(do_QueryInterface(item));
nsAccessible* itemAcc = GetAccService()->GetAccessible(itemNode);
nsAccessible* itemAcc =
itemNode ? GetAccService()->GetAccessible(itemNode) : nsnull;
if (itemAcc) {
PRUint32 itemRole = Role(itemAcc);

View File

@ -171,7 +171,7 @@ public:
nsINode* node = GetNode();
return node && node->IsElement();
}
PRBool IsDocument() const
bool IsDocumentNode() const
{
return GetNode() && GetNode()->IsNodeOfType(nsINode::eDOCUMENT);
}

View File

@ -68,7 +68,7 @@
#include "nsImageFrame.h"
#include "nsILink.h"
#include "nsIObserverService.h"
#include "nsIPluginInstance.h"
#include "nsNPAPIPluginInstance.h"
#include "nsISupportsUtils.h"
#include "nsObjectFrame.h"
#include "nsOuterDocAccessible.h"
@ -346,8 +346,8 @@ nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame,
#if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
// 2) for plugins
nsCOMPtr<nsIPluginInstance> pluginInstance;
if (NS_SUCCEEDED(aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance))) &&
nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
pluginInstance) {
#ifdef XP_WIN
// Note: pluginPort will be null if windowless.
@ -842,6 +842,8 @@ nsAccessibilityService::GetAccessibleInShell(nsINode* aNode,
nsAccessible*
nsAccessibilityService::GetAccessible(nsINode* aNode)
{
NS_PRECONDITION(aNode, "Getting an accessible for null node! Crash.");
nsDocAccessible* document = GetDocAccessible(aNode->GetOwnerDoc());
return document ? document->GetAccessible(aNode) : nsnull;
}

View File

@ -376,6 +376,9 @@ public:
inline bool IsApplication() const { return mFlags & eApplicationAccessible; }
inline bool IsDoc() const { return mFlags & eDocAccessible; }
nsDocAccessible* AsDoc();
inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
nsHyperTextAccessible* AsHyperText();
@ -529,10 +532,11 @@ protected:
*/
enum AccessibleTypes {
eApplicationAccessible = 1 << 2,
eHyperTextAccessible = 1 << 3,
eHTMLListItemAccessible = 1 << 4,
eRootAccessible = 1 << 5,
eTextLeafAccessible = 1 << 6
eDocAccessible = 1 << 3,
eHyperTextAccessible = 1 << 4,
eHTMLListItemAccessible = 1 << 5,
eRootAccessible = 1 << 6,
eTextLeafAccessible = 1 << 7
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -93,7 +93,7 @@ nsLeafAccessible::CacheChildren()
nsLinkableAccessible::
nsLinkableAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
nsAccessibleWrap(aContent, aShell),
mActionContent(nsnull),
mActionAcc(nsnull),
mIsLink(PR_FALSE),
mIsOnclick(PR_FALSE)
{
@ -107,11 +107,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsAccessibleWrap)
NS_IMETHODIMP
nsLinkableAccessible::TakeFocus()
{
nsAccessible *actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->TakeFocus();
return nsAccessibleWrap::TakeFocus();
return mActionAcc ? mActionAcc->TakeFocus() : nsAccessibleWrap::TakeFocus();
}
PRUint64
@ -120,8 +116,7 @@ nsLinkableAccessible::NativeState()
PRUint64 states = nsAccessibleWrap::NativeState();
if (mIsLink) {
states |= states::LINKED;
nsAccessible* actionAcc = GetActionAccessible();
if (actionAcc->State() & states::TRAVERSED)
if (mActionAcc->State() & states::TRAVERSED)
states |= states::TRAVERSED;
}
@ -137,13 +132,7 @@ nsLinkableAccessible::GetValue(nsAString& aValue)
if (!aValue.IsEmpty())
return NS_OK;
if (mIsLink) {
nsAccessible *actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->GetValue(aValue);
}
return NS_ERROR_NOT_IMPLEMENTED;
return mIsLink ? mActionAcc->GetValue(aValue) : NS_ERROR_NOT_IMPLEMENTED;
}
@ -152,7 +141,7 @@ nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
{
NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = mActionContent ? 1 : 0;
*aNumActions = mActionAcc ? 1 : 0;
return NS_OK;
}
@ -182,11 +171,8 @@ nsLinkableAccessible::DoAction(PRUint8 aIndex)
if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG;
nsAccessible *actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->DoAction(aIndex);
return nsAccessibleWrap::DoAction(aIndex);
return mActionAcc ? mActionAcc->DoAction(aIndex) :
nsAccessibleWrap::DoAction(aIndex);
}
NS_IMETHODIMP
@ -194,11 +180,8 @@ nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
{
aKeyboardShortcut.Truncate();
nsAccessible *actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
return mActionAcc ? mActionAcc->GetKeyboardShortcut(aKeyboardShortcut) :
nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
}
////////////////////////////////////////////////////////////////////////////////
@ -207,7 +190,9 @@ nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
void
nsLinkableAccessible::Shutdown()
{
mActionContent = nsnull;
mIsLink = PR_FALSE;
mIsOnclick = PR_FALSE;
mActionAcc = nsnull;
nsAccessibleWrap::Shutdown();
}
@ -218,14 +203,11 @@ already_AddRefed<nsIURI>
nsLinkableAccessible::GetAnchorURI(PRUint32 aAnchorIndex)
{
if (mIsLink) {
nsAccessible* link = GetActionAccessible();
if (link) {
NS_ASSERTION(link->IsHyperLink(),
"nsIAccessibleHyperLink isn't implemented.");
NS_ASSERTION(mActionAcc->IsHyperLink(),
"nsIAccessibleHyperLink isn't implemented.");
if (link->IsHyperLink())
return link->GetAnchorURI(aAnchorIndex);
}
if (mActionAcc->IsHyperLink())
return mActionAcc->GetAnchorURI(aAnchorIndex);
}
return nsnull;
@ -241,55 +223,36 @@ nsLinkableAccessible::BindToParent(nsAccessible* aParent,
nsAccessibleWrap::BindToParent(aParent, aIndexInParent);
// Cache action content.
mActionContent = nsnull;
mActionAcc = nsnull;
mIsLink = PR_FALSE;
mIsOnclick = PR_FALSE;
nsIContent* walkUpContent = mContent;
PRBool isOnclick = nsCoreUtils::HasClickListener(walkUpContent);
if (isOnclick) {
mActionContent = walkUpContent;
if (nsCoreUtils::HasClickListener(mContent)) {
mActionAcc = this;
mIsOnclick = PR_TRUE;
return;
}
while ((walkUpContent = walkUpContent->GetParent())) {
nsAccessible* walkUpAcc =
GetAccService()->GetAccessibleInWeakShell(walkUpContent, mWeakShell);
// XXX: The logic looks broken since the click listener may be registered
// on non accessible node in parent chain but this node is skipped when tree
// is traversed.
nsAccessible* walkUpAcc = this;
while ((walkUpAcc = walkUpAcc->GetParent()) && !walkUpAcc->IsDoc()) {
if (walkUpAcc && walkUpAcc->Role() == nsIAccessibleRole::ROLE_LINK &&
walkUpAcc->State() & states::LINKED) {
mIsLink = PR_TRUE;
mActionContent = walkUpContent;
mActionAcc = walkUpAcc;
return;
}
isOnclick = nsCoreUtils::HasClickListener(walkUpContent);
if (isOnclick) {
mActionContent = walkUpContent;
if (nsCoreUtils::HasClickListener(walkUpAcc->GetContent())) {
mActionAcc = walkUpAcc;
mIsOnclick = PR_TRUE;
return;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible: protected
nsAccessible *
nsLinkableAccessible::GetActionAccessible() const
{
// Return accessible for the action content if it's different from node of
// this accessible. If the action accessible is not null then it is used to
// redirect methods calls otherwise we use method implementation from the
// base class.
if (!mActionContent || mContent == mActionContent)
return nsnull;
return GetAccService()->GetAccessibleInWeakShell(mActionContent, mWeakShell);
}
////////////////////////////////////////////////////////////////////////////////
// nsEnumRoleAccessible
////////////////////////////////////////////////////////////////////////////////

View File

@ -108,14 +108,10 @@ protected:
// nsAccessible
virtual void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
// nsLinkableAccessible
/**
* Return an accessible for cached action node.
* Parent accessible that provides an action for this linkable accessible.
*/
nsAccessible *GetActionAccessible() const;
nsCOMPtr<nsIContent> mActionContent;
nsAccessible* mActionAcc;
PRPackedBool mIsLink;
PRPackedBool mIsOnclick;
};

View File

@ -493,12 +493,10 @@ nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
nsCAutoString path;
uri->GetPath(path);
nsCAutoString::const_iterator start, end;
path.BeginReading(start);
path.EndReading(end);
NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
return FindInReadable(neterror, start, end);
NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
}
PRBool

View File

@ -109,6 +109,8 @@ nsDocAccessible::
mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE),
mCacheRoot(nsnull), mIsPostCacheProcessing(PR_FALSE)
{
mFlags |= eDocAccessible;
mDependentIDsHash.Init();
// XXX aaronl should we use an algorithm for the initial cache size?
mAccessibleCache.Init(kDefaultCacheSize);
@ -1114,7 +1116,8 @@ nsDocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
// at least until native API comes up with a more meaningful event.
if (aAttribute == nsAccessibilityAtoms::aria_grabbed ||
aAttribute == nsAccessibilityAtoms::aria_dropeffect ||
aAttribute == nsAccessibilityAtoms::aria_hidden) {
aAttribute == nsAccessibilityAtoms::aria_hidden ||
aAttribute == nsAccessibilityAtoms::aria_sort) {
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
aContent);
}

View File

@ -552,4 +552,11 @@ protected:
NS_DEFINE_STATIC_IID_ACCESSOR(nsDocAccessible,
NS_DOCACCESSIBLE_IMPL_CID)
inline nsDocAccessible*
nsAccessible::AsDoc()
{
return mFlags & eDocAccessible ?
static_cast<nsDocAccessible*>(this) : nsnull;
}
#endif

View File

@ -213,8 +213,8 @@ nsOuterDocAccessible::RemoveChild(nsAccessible *aAccessible)
return PR_FALSE;
}
NS_LOG_ACCDOCDESTROY("remove document from outerdoc",
child->GetDocumentNode())
NS_LOG_ACCDOCDESTROY_FOR("remove document from outerdoc",
child->GetDocumentNode(), child)
NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this)
PRBool wasRemoved = nsAccessible::RemoveChild(child);

View File

@ -297,7 +297,7 @@ nsTextEquivUtils::AppendFromValue(nsAccessible *aAccessible,
}
//XXX: is it necessary to care the accessible is not a document?
if (aAccessible->IsDocument())
if (aAccessible->IsDocumentNode())
return NS_ERROR_UNEXPECTED;
nsIContent *content = aAccessible->GetContent();

View File

@ -916,7 +916,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
nsCOMPtr<nsFrameSelection> frameSelection;
nsRefPtr<nsFrameSelection> frameSelection;
rv = privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
NS_ENSURE_SUCCESS(rv, rv);
@ -1014,7 +1014,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
}
if (aType == eGetBefore) {
endOffset = aOffset;
finalEndOffset = aOffset;
}
else {
// Start moving forward from the start so that we don't get
@ -1680,7 +1680,7 @@ PRInt32 nsHyperTextAccessible::GetCaretLineNumber()
getter_AddRefs(domSel));
nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSel));
NS_ENSURE_TRUE(privateSelection, -1);
nsCOMPtr<nsFrameSelection> frameSelection;
nsRefPtr<nsFrameSelection> frameSelection;
privateSelection->GetFrameSelection(getter_AddRefs(frameSelection));
NS_ENSURE_TRUE(frameSelection, -1);

View File

@ -238,7 +238,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute])
return NSAccessibilityRoleDescription([self role], nil);
#endif
if ([attribute isEqualToString:kInstanceDescriptionAttribute])
if ([attribute isEqualToString: (NSString*) kInstanceDescriptionAttribute])
return [self customDescription];
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
return [NSNumber numberWithBool:[self isFocused]];
@ -246,7 +246,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
return [self size];
if ([attribute isEqualToString:NSAccessibilityWindowAttribute])
return [self window];
if ([attribute isEqualToString:kTopLevelUIElementAttribute])
if ([attribute isEqualToString: (NSString*) kTopLevelUIElementAttribute])
return [self window];
if ([attribute isEqualToString:NSAccessibilityTitleAttribute] ||
[attribute isEqualToString:NSAccessibilityTitleUIElementAttribute])
@ -471,7 +471,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(mGeckoAccessible),
"Does not support nsIAccessibleText when it should");
#endif
return AXRoles[mRole];
return (NSString*) AXRoles[mRole];
}
- (NSString*)subrole

View File

@ -43,6 +43,8 @@
#ifndef _nsAccessibleWrap_H_
#define _nsAccessibleWrap_H_
#include <objc/objc.h>
#include "nsAccessible.h"
#include "nsAccUtils.h"
#include "States.h"
@ -54,7 +56,6 @@
#include "nsAutoPtr.h"
struct AccessibleWrapper;
struct objc_class;
class nsAccessibleWrap : public nsAccessible
{
@ -71,7 +72,7 @@ class nsAccessibleWrap : public nsAccessible
// the objective-c |Class| type that this accessible's native object
// should be instantied with. used on runtime to determine the
// right type for this accessible's associated native object.
virtual objc_class* GetNativeType ();
virtual Class GetNativeType ();
virtual void Shutdown ();
virtual void InvalidateChildren();

View File

@ -88,7 +88,7 @@ nsAccessibleWrap::GetNativeInterface (void **aOutInterface)
// overridden in subclasses to create the right kind of object. by default we create a generic
// 'mozAccessible' node.
objc_class*
Class
nsAccessibleWrap::GetNativeType ()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;

View File

@ -54,7 +54,7 @@ public:
nsIWeakReference *aShell);
virtual ~nsRootAccessibleWrap();
objc_class* GetNativeType ();
Class GetNativeType ();
// let's our native accessible get in touch with the
// native cocoa view that is our accessible parent.

View File

@ -59,7 +59,7 @@ nsRootAccessibleWrap::~nsRootAccessibleWrap()
{
}
objc_class*
Class
nsRootAccessibleWrap::GetNativeType ()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;

View File

@ -275,7 +275,7 @@ STDMETHODIMP nsAccessNodeWrap::get_attributes(
__try{
*aNumAttribs = 0;
if (IsDefunct() || IsDocument())
if (IsDefunct() || IsDocumentNode())
return E_FAIL;
PRUint32 numAttribs = mContent->GetAttrCount();
@ -348,7 +348,7 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyle(
__try{
*aNumStyleProperties = 0;
if (IsDefunct() || IsDocument())
if (IsDefunct() || IsDocumentNode())
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
@ -383,7 +383,7 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
/* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues)
{
__try {
if (IsDefunct() || IsDocument())
if (IsDefunct() || IsDocumentNode())
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =

View File

@ -1762,6 +1762,38 @@ nsAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
if (nsAccUtils::MustPrune(this))
return nsnull;
// If lVal negative then it is treated as child ID and we should look for
// accessible through whole accessible subtree including subdocuments.
// Otherwise we treat lVal as index in parent.
if (aVarChild.lVal < 0) {
// Convert child ID to unique ID.
void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
// Document.
if (IsDoc())
return AsDoc()->GetAccessibleByUniqueIDInSubtree(uniqueID);
// ARIA document.
if (ARIARole() == nsIAccessibleRole::ROLE_DOCUMENT) {
nsDocAccessible* document = GetDocAccessible();
nsAccessible* child =
document->GetAccessibleByUniqueIDInSubtree(uniqueID);
// Check whether the accessible for the given ID is a child of ARIA
// document.
nsAccessible* parent = child ? child->GetParent() : nsnull;
while (parent && parent != document) {
if (parent == this)
return child;
parent = parent->GetParent();
}
}
return nsnull;
}
// Gecko child indices are 0-based in contrast to indices used in MSAA.
return GetChildAt(aVarChild.lVal - 1);
}

View File

@ -327,7 +327,7 @@ public: // construction, destruction
/**
* Find an accessible by the given child ID in cached documents.
*/
virtual nsAccessible *GetXPAccessibleFor(const VARIANT& aVarChild);
nsAccessible* GetXPAccessibleFor(const VARIANT& aVarChild);
NS_IMETHOD GetNativeInterface(void **aOutAccessible);

View File

@ -99,22 +99,6 @@ STDMETHODIMP nsDocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
return S_OK;
}
nsAccessible*
nsDocAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
{
// If lVal negative then it is treated as child ID and we should look for
// accessible through whole accessible subtree including subdocuments.
// Otherwise we treat lVal as index in parent.
if (aVarChild.vt == VT_I4 && aVarChild.lVal < 0) {
// Convert child ID to unique ID.
void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
return GetAccessibleByUniqueIDInSubtree(uniqueID);
}
return nsAccessibleWrap::GetXPAccessibleFor(aVarChild);
}
STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
{
__try {

View File

@ -92,9 +92,6 @@ public:
// nsAccessNode
virtual void Shutdown();
// nsAccessibleWrap
virtual nsAccessible *GetXPAccessibleFor(const VARIANT& varChild);
// nsDocAccessible
virtual void* GetNativeWindow() const;

View File

@ -51,8 +51,8 @@ _TEST_FILES =\
focus.html \
scroll.html \
test_aria_alert.html \
test_aria_hidden.html \
test_aria_menu.html \
test_aria_objattr.html \
test_aria_statechange.html \
test_attrs.html \
test_caretmove.html \

View File

@ -192,11 +192,11 @@
/**
* Load wrong URI what results in error page loading.
*/
function loadErrorPageInvoker()
function loadErrorPageInvoker(aURL, aURLDescr)
{
this.invoke = function loadErrorPageInvoker_invoke()
{
gTabBrowser.loadURI("www.wronguri.wronguri");
gTabBrowser.loadURI(aURL);
}
this.eventSeq = [
@ -209,7 +209,7 @@
this.getID = function loadErrorPageInvoker_getID()
{
return "load error page";
return "load error page: '" + aURLDescr + "'";
}
}
@ -230,7 +230,11 @@
gQueue.push(new clickReloadBtnInvoker());
gQueue.push(new loadURIInvoker("about:mozilla"));
gQueue.push(new reloadInvoker());
gQueue.push(new loadErrorPageInvoker());
gQueue.push(new loadErrorPageInvoker("www.wronguri.wronguri",
"Server not found"));
gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
"Untrusted Connection"));
gQueue.onFinish = function() { window.close(); }
gQueue.invoke();
}

View File

@ -1,7 +1,7 @@
<html>
<head>
<title>Accessible ARIA hidden attribute</title>
<title>Accessible ARIA object attribute changes</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
@ -43,14 +43,38 @@
}
}
function updateSort(aID, aSort)
{
this.node = getNode(aID);
this.accessible = getAccessible(this.node);
this.eventSeq = [
new invokerChecker(EVENT_OBJECT_ATTRIBUTE_CHANGED, this.accessible),
];
this.invoke = function updateSort_invoke()
{
this.node.setAttribute("aria-sort", aSort);
}
this.getID = function updateSort_getID()
{
return "aria-sort for " + aID + " " + aSort;
}
}
// Debug stuff.
// gA11yEventDumpID = "eventdump";
// gA11yEventDumpToConsole = true;
function doTests()
{
//gA11yEventDumpID = "eventdump"; // debug stuff
gQueue = new eventQueue();
gQueue.push(new hideNode("hideable", "true"));
gQueue.push(new updateSort("sortable", "ascending"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -67,6 +91,12 @@
Mozilla Bug 581096
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=640707"
title="Add event support for aria-sort">
Mozilla Bug 640707
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -75,5 +105,6 @@
<div id="hideable"><div>Hi</div><div>there</div></div>
<div id="sortable" role="columnheader" aria-sort"none">aria-sort</div>
</body>
</html>

View File

@ -50,8 +50,8 @@ _TEST_FILES = \
test_doc.html \
test_hypertext.html \
test_passwords.html \
$(warning test_singleline.html disabled due to bug 652459) \
$(warning test_whitespaces.html disabled due to bug 652459) \
test_singleline.html \
test_whitespaces.html \
test_words.html \
$(NULL)

View File

@ -216,10 +216,10 @@
// BOUNDARY_WORD_START
testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
@ -231,10 +231,10 @@
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
testTextBeforeOffset(6, BOUNDARY_WORD_START, "hello ", 0, 6,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(7, BOUNDARY_WORD_START, "hello ", 0, 6,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
@ -246,10 +246,10 @@
"editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo);
testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
@ -268,10 +268,10 @@
// BOUNDARY_WORD_END
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
@ -283,10 +283,10 @@
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
testTextBeforeOffset(6, BOUNDARY_WORD_END, "hello ", 0, 6,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
"editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo);
"input", kTodo, kTodo, kOk,
"div", kTodo, kTodo, kOk,
"editable", kTodo, kTodo, kOk,
"textarea", kTodo, kTodo, kOk);
testTextBeforeOffset(7, BOUNDARY_WORD_END, "hello ", 0, 6,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
@ -320,10 +320,10 @@
// BOUNDARY_LINE_START
testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
@ -342,10 +342,10 @@
// BOUNDARY_LINE_END
testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,

View File

@ -196,10 +196,10 @@
// BOUNDARY_WORD_START
testTextBeforeOffset(0, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_START, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
@ -211,10 +211,10 @@
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
testTextBeforeOffset(6, BOUNDARY_WORD_START, "Brave ", 0, 6,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(9, BOUNDARY_WORD_START, "Brave ", 0, 6,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
@ -226,10 +226,10 @@
"editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo);
testTextBeforeOffset(11, BOUNDARY_WORD_START, "Sir ", 6, 11,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(15, BOUNDARY_WORD_START, "Sir ", 6, 11,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
@ -251,10 +251,10 @@
"editable", kTodo, kTodo, kTodo,
"textarea", kTodo, kTodo, kTodo);
testTextBeforeOffset(19, BOUNDARY_WORD_START, "Robin ", 11, 19,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(20, BOUNDARY_WORD_START, "Robin ", 11, 19,
"input", kTodo, kTodo, kTodo,
"div", kTodo, kTodo, kTodo,
@ -268,10 +268,10 @@
// BOUNDARY_WORD_END
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kOk, kOk, kOk);
testTextBeforeOffset(1, BOUNDARY_WORD_END, "", 0, 0,
"input", kTodo, kOk, kTodo,
"div", kTodo, kOk, kTodo,

View File

@ -185,8 +185,7 @@ endif
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool)
OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32 delayimp)
LDFLAGS += -delayload:xul.dll -delayload:xpcom.dll -delayload:plc4.dll -delayload:nspr4.dll -delayload:mozalloc.dll
OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32)
endif
ifeq ($(OS_ARCH),WINNT)

View File

@ -56,7 +56,6 @@
#ifdef XP_WIN
// we want to use the DLL blocklist if possible
#define XRE_WANT_DLL_BLOCKLIST
#define XRE_PRELOAD_XUL
// we want a wmain entry point
#include "nsWindowsWMain.cpp"
#endif

View File

@ -254,18 +254,15 @@ let TestPilotSetup = {
Ci.nsITimer.TYPE_REPEATING_SLACK);
this.getVersion(function() {
// Show first run page (in front window) if newly installed or upgraded.
let currVersion = self._prefs.getValue(VERSION_PREF, "firstrun");
if (currVersion != self.version) {
if(!self._isBetaChannel()) {
// Don't show first run page in ffx4 beta version.
/* Show first run page (in front window) only the first time after install;
* Don't show first run page in Feedback UI version. */
if ((self._prefs.getValue(VERSION_PREF, "") == "") &&
(!self._interfaceBuilder.channelUsesFeedback())) {
self._prefs.setValue(VERSION_PREF, self.version);
let browser = self._getFrontBrowserWindow().getBrowser();
let url = self._prefs.getValue(FIRST_RUN_PREF, "");
let tab = browser.addTab(url);
browser.selectedTab = tab;
}
}
// Install tasks. (This requires knowing the version, so it is

View File

@ -785,6 +785,8 @@ pref("browser.sessionstore.max_resumed_crashes", 1);
// Other tabs won't be restored until they are selected
// N = The number of tabs to restore at the same time
pref("browser.sessionstore.max_concurrent_tabs", 3);
// Whether to automatically restore hidden tabs (i.e., tabs in other tab groups) or not
pref("browser.sessionstore.restore_hidden_tabs", false);
// allow META refresh by default
pref("accessibility.blockautorefresh", false);

View File

@ -359,7 +359,6 @@ appUpdater.prototype =
// notified with the normal app update user interface so this is safe.
gAppUpdater.isChecking = false;
gAppUpdater.selectPanel("noUpdatesFound");
return;
},
/**
@ -613,6 +612,8 @@ var gChannelSelector = {
// Change app update channel.
Services.prefs.setCharPref("app.update.desiredChannel", this.channelValue);
// Stop any downloads in progress
gAppUpdater.aus.pauseDownload();
// App updater will look at app.update.desiredChannel for new channel value
// and will clear it when the update is complete.
gAppUpdater.isChecking = true;

View File

@ -40,10 +40,13 @@ let TabView = {
_deck: null,
_iframe: null,
_window: null,
_firstUseExperienced: false,
_browserKeyHandlerInitialized: false,
_isFrameLoading: false,
_initFrameCallbacks: [],
PREF_BRANCH: "browser.panorama.",
PREF_FIRST_RUN: "browser.panorama.experienced_first_run",
PREF_STARTUP_PAGE: "browser.startup.page",
PREF_RESTORE_ENABLED_ONCE: "browser.panorama.session_restore_enabled_once",
VISIBILITY_IDENTIFIER: "tabview-visibility",
// ----------
@ -57,24 +60,35 @@ let TabView = {
// ----------
get firstUseExperienced() {
return this._firstUseExperienced;
let pref = this.PREF_FIRST_RUN;
if (Services.prefs.prefHasUserValue(pref))
return Services.prefs.getBoolPref(pref);
return false;
},
// ----------
set firstUseExperienced(val) {
if (val != this._firstUseExperienced)
Services.prefs.setBoolPref("browser.panorama.experienced_first_run", val);
Services.prefs.setBoolPref(this.PREF_FIRST_RUN, val);
},
// ----------
get sessionRestoreEnabledOnce() {
let pref = this.PREF_RESTORE_ENABLED_ONCE;
if (Services.prefs.prefHasUserValue(pref))
return Services.prefs.getBoolPref(pref);
return false;
},
// ----------
set sessionRestoreEnabledOnce(val) {
Services.prefs.setBoolPref(this.PREF_RESTORE_ENABLED_ONCE, val);
},
// ----------
init: function TabView_init() {
if (!Services.prefs.prefHasUserValue("browser.panorama.experienced_first_run") ||
!Services.prefs.getBoolPref("browser.panorama.experienced_first_run")) {
Services.prefs.addObserver(
"browser.panorama.experienced_first_run", this, false);
} else {
this._firstUseExperienced = true;
if (this.firstUseExperienced) {
if ((gBrowser.tabs.length - gBrowser.visibleTabs.length) > 0)
this._setBrowserKeyHandlers();
@ -100,26 +114,24 @@ let TabView = {
"TabShow", this._tabShowEventListener, true);
}
}
Services.prefs.addObserver(this.PREF_BRANCH, this, false);
},
// ----------
// Observes topic changes.
observe: function TabView_observe(subject, topic, data) {
if (topic == "nsPref:changed") {
Services.prefs.removeObserver(
"browser.panorama.experienced_first_run", this);
this._firstUseExperienced = true;
if (data == this.PREF_FIRST_RUN && this.firstUseExperienced) {
this._addToolbarButton();
this.enableSessionRestore();
}
},
// ----------
// Uninitializes TabView.
uninit: function TabView_uninit() {
if (!this._firstUseExperienced) {
Services.prefs.removeObserver(
"browser.panorama.experienced_first_run", this);
}
Services.prefs.removeObserver(this.PREF_BRANCH, this);
if (this._tabShowEventListener) {
gBrowser.tabContainer.removeEventListener(
"TabShow", this._tabShowEventListener, true);
@ -366,5 +378,23 @@ let TabView = {
toolbar.currentSet = currentSet;
toolbar.setAttribute("currentset", currentSet);
document.persist(toolbar.id, "currentset");
},
// ----------
// Function: enableSessionRestore
// Enables automatic session restore when the browser is started. Does
// nothing if we already did that once in the past.
enableSessionRestore: function UI_enableSessionRestore() {
if (!this._window || !this.firstUseExperienced)
return;
// do nothing if we already enabled session restore once
if (this.sessionRestoreEnabledOnce)
return;
this.sessionRestoreEnabledOnce = true;
// enable session restore
Services.prefs.setIntPref(this.PREF_STARTUP_PAGE, 3);
}
};

View File

@ -306,22 +306,28 @@ function SetClickAndHoldHandlers() {
aElm.addEventListener("click", clickHandler, true);
}
// Bug 414797: Clone the dropmarker's menu into both the back and
// the forward buttons.
// Bug 414797: Clone unified-back-forward-button's context menu into both the
// back and the forward buttons.
var unifiedButton = document.getElementById("unified-back-forward-button");
if (unifiedButton && !unifiedButton._clickHandlersAttached) {
var popup = document.getElementById("backForwardMenu").cloneNode(true);
unifiedButton._clickHandlersAttached = true;
let popup = document.getElementById("backForwardMenu").cloneNode(true);
popup.removeAttribute("id");
var backButton = document.getElementById("back-button");
// Prevent the context attribute on unified-back-forward-button from being
// inherited.
popup.setAttribute("context", "");
let backButton = document.getElementById("back-button");
backButton.setAttribute("type", "menu");
backButton.appendChild(popup);
_addClickAndHoldListenersOnElement(backButton);
var forwardButton = document.getElementById("forward-button");
let forwardButton = document.getElementById("forward-button");
popup = popup.cloneNode(true);
forwardButton.setAttribute("type", "menu");
forwardButton.appendChild(popup);
_addClickAndHoldListenersOnElement(forwardButton);
unifiedButton._clickHandlersAttached = true;
}
}
@ -4118,7 +4124,7 @@ var XULBrowserWindow = {
startTime: 0,
statusText: "",
isBusy: false,
inContentWhitelist: ["about:addons"],
inContentWhitelist: ["about:addons", "about:permissions"],
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIWebProgressListener) ||

View File

@ -92,9 +92,9 @@ var gSyncSetup = {
init: function () {
let obs = [
["weave:service:changepph:finish", "onResetPassphrase"],
["weave:service:verify-login:start", "onLoginStart"],
["weave:service:verify-login:error", "onLoginEnd"],
["weave:service:verify-login:finish", "onLoginEnd"]];
["weave:service:login:start", "onLoginStart"],
["weave:service:login:error", "onLoginEnd"],
["weave:service:login:finish", "onLoginEnd"]];
// Add the observers now and remove them on unload
let self = this;
@ -216,6 +216,8 @@ var gSyncSetup = {
feedback = server;
break;
case Weave.LOGIN_FAILED_LOGIN_REJECTED:
case Weave.LOGIN_FAILED_NO_USERNAME:
case Weave.LOGIN_FAILED_NO_PASSWORD:
feedback = password;
break;
case Weave.LOGIN_FAILED_INVALID_PASSPHRASE:

View File

@ -194,12 +194,13 @@ let gSyncUtils = {
*/
passphraseSave: function(elid) {
let dialogTitle = this.bundle.GetStringFromName("save.synckey.title");
let defaultSaveName = this.bundle.GetStringFromName("save.default.label");
this._preparePPiframe(elid, function(iframe) {
let filepicker = Cc["@mozilla.org/filepicker;1"]
.createInstance(Ci.nsIFilePicker);
filepicker.init(window, dialogTitle, Ci.nsIFilePicker.modeSave);
filepicker.appendFilters(Ci.nsIFilePicker.filterHTML);
filepicker.defaultString = "Firefox Sync Key.html";
filepicker.defaultString = defaultSaveName;
let rv = filepicker.show();
if (rv == Ci.nsIFilePicker.returnOK
|| rv == Ci.nsIFilePicker.returnReplace) {

View File

@ -1540,8 +1540,10 @@
}
this._removingTabs.push(aTab);
this.tabContainer.updateVisibility();
if (newTab)
this.addTab("about:blank", {skipAnimation: true});
else
this.tabContainer.updateVisibility();
// We're committed to closing the tab now.
// Dispatch a notification.
@ -1597,8 +1599,6 @@
// update the UI early for responsiveness
aTab.collapsed = true;
if (aNewTab)
this.addTab("about:blank", {skipAnimation: true});
this.tabContainer._fillTrailingGap();
this._blurTab(aTab);

View File

@ -2163,7 +2163,16 @@ let GroupItems = {
}
toClose.forEach(function(groupItem) {
groupItem.destroy({immediately: true});
// All remaining children in to-be-closed groups are re-used by
// session restore. Reconnect them so that they're put into their
// right groups.
groupItem.getChildren().forEach(function (tabItem) {
if (tabItem.parent && tabItem.parent.hidden)
iQ(tabItem.container).show();
tabItem._reconnected = false;
tabItem._reconnect();
});
groupItem.close({immediately: true});
});
}

View File

@ -57,7 +57,10 @@ let AllTabs = {
get tabs() {
// Get tabs from each browser window and flatten them into one array
return Array.concat.apply(null, browserWindows.map(function(browserWindow) {
return Array.slice(browserWindow.gBrowser.tabs);
let removingTabs = browserWindow.gBrowser._removingTabs;
return Array.filter(browserWindow.gBrowser.tabs, function (tab) {
return removingTabs.indexOf(tab) == -1;
});
}));
},

View File

@ -552,6 +552,9 @@ let UI = {
TabItems.resumePainting();
}
if (gTabView.firstUseExperienced)
gTabView.enableSessionRestore();
},
// ----------
@ -739,7 +742,7 @@ let UI = {
} else {
// If we're currently in the process of entering private browsing,
// we don't want to go to the Tab View UI.
if (self._privateBrowsing.transitionMode)
if (self._storageBusyCount)
return;
// if not closing the last tab

View File

@ -201,6 +201,7 @@ _BROWSER_FILES = \
browser_scratchpad_ui.js \
browser_scratchpad_bug_646070_chrome_context_pref.js \
browser_overflowScroll.js \
browser_locationBarExternalLoad.js \
browser_pageInfo.js \
browser_page_style_menu.js \
browser_pinnedTabs.js \

View File

@ -96,11 +96,10 @@ function test_disabled_install() {
wait_for_notification_close(function() {
try {
Services.prefs.getBoolPref("xpinstall.disabled");
ok(false, "xpinstall.disabled should not be set");
ok(Services.prefs.getBoolPref("xpinstall.enabled"), "Installation should be enabled");
}
catch (e) {
ok(true, "xpinstall.disabled should not be set");
ok(false, "xpinstall.enabled should be set");
}
gBrowser.removeTab(gBrowser.selectedTab);

View File

@ -0,0 +1,45 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
nextTest();
}
let urls = [
"javascript:'foopy';",
"data:text/html,<script>document.write(document.domain);</script>"
];
function nextTest() {
let url = urls.shift();
if (url)
testURL(url, nextTest);
else
finish();
}
function testURL(newURL, func) {
let tab = gBrowser.selectedTab = gBrowser.addTab();
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
});
addPageShowListener(function () {
let pagePrincipal = gBrowser.contentPrincipal;
gURLBar.value = newURL;
gURLBar.handleCommand();
addPageShowListener(function () {
ok(!gBrowser.contentPrincipal.equals(pagePrincipal), "load of " + newURL + " produced a page with a different principal");
func();
});
});
}
function addPageShowListener(func) {
gBrowser.selectedBrowser.addEventListener("pageshow", function loadListener() {
gBrowser.selectedBrowser.removeEventListener("pageshow", loadListener, false);
func();
});
}

View File

@ -64,6 +64,7 @@ _BROWSER_FILES = \
browser_tabview_bug595518.js \
browser_tabview_bug595521.js \
browser_tabview_bug595560.js \
browser_tabview_bug595601.js \
browser_tabview_bug595804.js \
browser_tabview_bug595930.js \
browser_tabview_bug595943.js \
@ -131,13 +132,16 @@ _BROWSER_FILES = \
browser_tabview_bug640765.js \
browser_tabview_bug641802.js \
browser_tabview_bug642793.js \
browser_tabview_bug643392.js \
browser_tabview_bug644097.js \
browser_tabview_bug645653.js \
browser_tabview_bug648882.js \
browser_tabview_bug649006.js \
browser_tabview_bug649307.js \
browser_tabview_bug650573.js \
browser_tabview_bug651311.js \
browser_tabview_bug654941.js \
browser_tabview_bug656778.js \
browser_tabview_dragdrop.js \
browser_tabview_exit_button.js \
browser_tabview_expander.js \

View File

@ -1,93 +1,121 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
const DUMMY_PAGE_URL = "http://mochi.test:8888/browser/browser/base/content/test/tabview/dummy_page.html";
const DUMMY_PAGE_URL_2 = "http://mochi.test:8888/";
const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
const DUMMY_PAGE_URL = "http://mochi.test:8888/browser/browser/base/content/test/tabview/dummy_page.html";
const DUMMY_PAGE_URL_2 = "http://mochi.test:8888/";
let state = {
windows: [{
tabs: [{
entries: [{ url: DUMMY_PAGE_URL }],
hidden: true,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":21,"top":29,"width":204,"height":153},' +
'"userSize":null,"url":"' + DUMMY_PAGE_URL + '","groupID":1,' +
'"imageData":null,"title":null}'
}
},{
entries: [{ url: DUMMY_PAGE_URL_2 }],
hidden: false,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":315,"top":29,"width":111,"height":84},' +
'"userSize":null,"url":"' + DUMMY_PAGE_URL_2 + '","groupID":2,' +
'"imageData":null,"title":null}'
},
}],
selected:2,
_closedTabs: [],
extData: {
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
"tabview-group":
'{"1":{"bounds":{"left":15,"top":5,"width":280,"height":232},' +
'"userSize":null,"title":"","id":1},' +
'"2":{"bounds":{"left":309,"top":5,"width":267,"height":226},' +
'"userSize":null,"title":"","id":2}}',
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":788,"height":548}}'
}, sizemode:"normal"
}]
};
function test() {
waitForExplicitFinish();
// open a new window and setup the window state.
let newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
newWin.addEventListener("load", function(event) {
this.removeEventListener("load", arguments.callee, false);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
});
let newState = {
windows: [{
tabs: [{
entries: [{ url: DUMMY_PAGE_URL }],
hidden: true,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":21,"top":29,"width":204,"height":153},' +
'"userSize":null,"url":"' + DUMMY_PAGE_URL + '","groupID":1,' +
'"imageData":null,"title":null}'
}
},{
entries: [{ url: DUMMY_PAGE_URL_2 }],
hidden: false,
attributes: {},
extData: {
"tabview-tab":
'{"bounds":{"left":315,"top":29,"width":111,"height":84},' +
'"userSize":null,"url":"' + DUMMY_PAGE_URL_2 + '","groupID":2,' +
'"imageData":null,"title":null}'
},
}],
selected:2,
_closedTabs: [],
extData: {
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
"tabview-group":
'{"1":{"bounds":{"left":15,"top":5,"width":280,"height":232},' +
'"userSize":null,"title":"","id":1},' +
'"2":{"bounds":{"left":309,"top":5,"width":267,"height":226},' +
'"userSize":null,"title":"","id":2}}',
"tabview-ui": '{"pageBounds":{"left":0,"top":0,"width":788,"height":548}}'
}, sizemode:"normal"
}]
};
ss.setWindowState(newWin, JSON.stringify(newState), true);
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", false);
let firstTab = newWin.gBrowser.tabs[0];
let secondTab = newWin.gBrowser.tabs[1];
testTabSwitchAfterRestore(function () {
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", true);
// wait until the first tab is fully loaded
let browser = newWin.gBrowser.getBrowserForTab(firstTab);
let onLoad = function() {
browser.removeEventListener("load", onLoad, true);
testTabSwitchAfterRestore(function () {
waitForFocus(finish);
});
});
}
is(browser.currentURI.spec, DUMMY_PAGE_URL,
"The url of first tab url is dummy_page.html");
function testTabSwitchAfterRestore(callback) {
newWindowWithState(state, function (win) {
registerCleanupFunction(function () win.close());
// check the hidden state of both tabs.
ok(firstTab.hidden, "The first tab is hidden");
ok(!secondTab.hidden, "The second tab is not hidden");
is(secondTab, newWin.gBrowser.selectedTab, "The second tab is selected");
let [firstTab, secondTab] = win.gBrowser.tabs;
is(firstTab.linkedBrowser.currentURI.spec, DUMMY_PAGE_URL,
"The url of first tab url is dummy_page.html");
// when the second tab is hidden, the iframe should be initialized and
// the first tab should be visible.
let onTabHide = function() {
newWin.gBrowser.tabContainer.removeEventListener("TabHide", onTabHide, true);
// check the hidden state of both tabs.
ok(firstTab.hidden, "The first tab is hidden");
ok(!secondTab.hidden, "The second tab is not hidden");
is(secondTab, win.gBrowser.selectedTab, "The second tab is selected");
ok(newWin.TabView.getContentWindow(), "");
// when the second tab is hidden, Panorama should be initialized and
// the first tab should be visible.
let container = win.gBrowser.tabContainer;
container.addEventListener("TabHide", function onTabHide() {
container.removeEventListener("TabHide", onTabHide, false);
ok(!firstTab.hidden, "The first tab is not hidden");
is(firstTab, newWin.gBrowser.selectedTab, "The first tab is selected");
ok(secondTab.hidden, "The second tab is hidden");
ok(win.TabView.getContentWindow(), "Panorama is loaded");
ok(!firstTab.hidden, "The first tab is not hidden");
is(firstTab, win.gBrowser.selectedTab, "The first tab is selected");
ok(secondTab.hidden, "The second tab is hidden");
// clean up and finish
newWin.close();
callback();
}, false);
finish();
};
newWin.gBrowser.tabContainer.addEventListener("TabHide", onTabHide, true);
// switch to another tab
win.switchToTabHavingURI(DUMMY_PAGE_URL);
});
}
// switch to another tab
newWin.switchToTabHavingURI(DUMMY_PAGE_URL);
}
browser.addEventListener("load", onLoad, true);
function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
whenWindowLoaded(win, function () {
ss.setWindowState(win, JSON.stringify(state), true);
});
whenWindowStateReady(win, function () {
afterAllTabsLoaded(function () callback(win), win);
});
}
function whenWindowLoaded(win, callback) {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(callback);
}, false);
}
function whenWindowStateReady(win, callback) {
win.addEventListener("SSWindowStateReady", function onReady() {
win.removeEventListener("SSWindowStateReady", onReady, false);
executeSoon(callback);
}, false);
}

View File

@ -1,134 +1,97 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let newTabOne;
let originalTab;
let win;
let cw;
function test() {
waitForExplicitFinish();
originalTab = gBrowser.visibleTabs[0];
newTabOne = gBrowser.addTab("http://mochi.test:8888/");
let browser = gBrowser.getBrowserForTab(newTabOne);
let onLoad = function() {
browser.removeEventListener("load", onLoad, true);
// show the tab view
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
browser.addEventListener("load", onLoad, true);
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(TabView.isVisible(), "Tab View is visible");
afterAllTabItemsUpdated(function() {
let contentWindow = document.getElementById("tab-view").contentWindow;
testOne(contentWindow);
});
}
function testOne(contentWindow) {
onSearchEnabledAndDisabled(contentWindow, function() {
testTwo(contentWindow);
});
// press cmd/ctrl F
EventUtils.synthesizeKey("f", { accelKey: true });
}
function testTwo(contentWindow) {
onSearchEnabledAndDisabled(contentWindow, function() {
testThree(contentWindow);
});
// press /
EventUtils.synthesizeKey("VK_SLASH", { type: "keydown" }, contentWindow);
}
function testThree(contentWindow) {
let groupItem = createEmptyGroupItem(contentWindow, 200);
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
TabView.toggle();
let onLoad = function (tvwin) {
win = tvwin;
registerCleanupFunction(function () win.close());
win.gBrowser.loadOneTab("http://mochi.test:8888/", {inBackground: true});
};
let onTabViewShown = function() {
window.removeEventListener("tabviewshown", onTabViewShown, false);
is(contentWindow.UI.getActiveTab(), groupItem.getChild(0),
let onShow = function () {
cw = win.TabView.getContentWindow();
ok(win.TabView.isVisible(), "Tab View is visible");
afterAllTabItemsUpdated(testOne, win);
};
newWindowWithTabView(onShow, onLoad);
}
function testOne() {
whenSearchEnabledAndDisabled(testTwo);
// press cmd/ctrl F
EventUtils.synthesizeKey("f", {accelKey: true}, cw);
}
function testTwo() {
whenSearchEnabledAndDisabled(testThree);
// press /
EventUtils.synthesizeKey("VK_SLASH", {}, cw);
}
function testThree() {
let onTabViewShown = function () {
is(cw.UI.getActiveTab(), groupItem.getChild(0),
"The active tab is newly created tab item");
let onSearchEnabled = function() {
contentWindow.removeEventListener(
"tabviewsearchenabled", onSearchEnabled, false);
let onSearchEnabled = function () {
let doc = cw.document;
let searchBox = cw.iQ("#searchbox");
let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0];
ok(hasFocus, "The search box has focus");
let searchBox = contentWindow.iQ("#searchbox");
let tab = win.gBrowser.tabs[1];
searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML);
ok(contentWindow.document.hasFocus() &&
contentWindow.document.activeElement == searchBox[0],
"The search box has focus");
searchBox.val(newTabOne._tabViewTabItem.$tabTitle[0].innerHTML);
cw.performSearch();
contentWindow.performSearch();
let checkSelectedTab = function() {
window.removeEventListener("tabviewhidden", checkSelectedTab, false);
is(newTabOne, gBrowser.selectedTab, "The search result tab is shown");
cleanUpAndFinish(groupItem.getChild(0), contentWindow);
};
window.addEventListener("tabviewhidden", checkSelectedTab, false);
whenTabViewIsHidden(function () {
is(tab, win.gBrowser.selectedTab, "The search result tab is shown");
waitForFocus(finish);
}, win);
// use the tabview menu (the same as pressing cmd/ctrl + e)
document.getElementById("menu_tabview").doCommand();
};
contentWindow.addEventListener("tabviewsearchenabled", onSearchEnabled, false);
EventUtils.synthesizeKey("VK_SLASH", { type: "keydown" }, contentWindow);
win.document.getElementById("menu_tabview").doCommand();
};
whenSearchEnabled(onSearchEnabled);
EventUtils.synthesizeKey("VK_SLASH", {}, cw);
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
window.addEventListener("tabviewshown", onTabViewShown, false);
whenTabViewIsHidden(function () {
showTabView(onTabViewShown, win);
}, win);
// click on the + button
let groupItem = createEmptyGroupItem(cw, 300, 300, 200);
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
ok(newTabButton[0], "New tab button exists");
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
EventUtils.sendMouseEvent({type: "click"}, newTabButton[0], cw);
}
function onSearchEnabledAndDisabled(contentWindow, callback) {
let onSearchEnabled = function() {
contentWindow.removeEventListener(
"tabviewsearchenabled", onSearchEnabled, false);
contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled, false);
contentWindow.hideSearch();
}
let onSearchDisabled = function() {
contentWindow.removeEventListener(
"tabviewsearchdisabled", onSearchDisabled, false);
function whenSearchEnabledAndDisabled(callback) {
whenSearchEnabled(function () {
whenSearchDisabled(callback);
cw.hideSearch();
});
}
function whenSearchEnabled(callback) {
cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
callback();
}
contentWindow.addEventListener("tabviewsearchenabled", onSearchEnabled, false);
}, false);
}
function cleanUpAndFinish(tabItem, contentWindow) {
gBrowser.selectedTab = originalTab;
gBrowser.removeTab(newTabOne);
gBrowser.removeTab(tabItem.tab);
finish();
function whenSearchDisabled(callback) {
cw.addEventListener("tabviewsearchdisabled", function onSearchDisabled() {
cw.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false);
callback();
}, false);
}
function createEmptyGroupItem(contentWindow, padding) {
let pageBounds = contentWindow.Items.getPageBounds();
pageBounds.inset(padding, padding);
let box = new contentWindow.Rect(pageBounds);
box.width = 300;
box.height = 300;
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box });
return emptyGroupItem;
}

View File

@ -0,0 +1,184 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;
let stateBackup = ss.getBrowserState();
let state = {windows:[{tabs:[
// first group
{entries:[{url:"http://example.com#1"}],extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#1\",\"groupID\":2}"}},
{entries:[{url:"http://example.com#2"}],extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#2\",\"groupID\":2}"}},
{entries:[{url:"http://example.com#3"}],extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#3\",\"groupID\":2}"}},
{entries:[{url:"http://example.com#4"}],extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#4\",\"groupID\":2}"}},
// second group
{entries:[{url:"http://example.com#5"}],hidden:true,extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#5\",\"groupID\":1}"}},
{entries:[{url:"http://example.com#6"}],hidden:true,extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#6\",\"groupID\":1}"}},
{entries:[{url:"http://example.com#7"}],hidden:true,extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#7\",\"groupID\":1}"}},
{entries:[{url:"http://example.com#8"}],hidden:true,extData:{"tabview-tab":"{\"bounds\":{\"left\":20,\"top\":20,\"width\":20,\"height\":20},\"url\":\"http://example.com#8\",\"groupID\":1}"}}
],selected:5,extData:{
"tabview-groups":"{\"nextID\":8,\"activeGroupId\":1}","tabview-group":"{\"1\":{\"bounds\":{\"left\":15,\"top\":10,\"width\":415,\"height\":367},\"userSize\":{\"x\":415,\"y\":367},\"title\":\"\",\"id\":1},\"2\":{\"bounds\":{\"left\":286,\"top\":488,\"width\":418,\"height\":313},\"title\":\"\",\"id\":2}}",
"tabview-ui":"{\"pageBounds\":{\"left\":0,\"top\":0,\"width\":940,\"height\":1075}}"
}}]};
function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("browser.sessionstore.restore_hidden_tabs", false);
TabsProgressListener.init();
registerCleanupFunction(function () {
TabsProgressListener.uninit();
Services.prefs.clearUserPref("browser.sessionstore.max_concurrent_tabs");
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
ss.setBrowserState(stateBackup);
});
Services.prefs.setIntPref("browser.sessionstore.max_concurrent_tabs", 3);
TabView._initFrame(function () {
executeSoon(testRestoreWithHiddenTabs);
});
}
function testRestoreWithHiddenTabs() {
let checked = false;
let ssReady = false;
let tabsRestored = false;
let check = function () {
if (checked || !ssReady || !tabsRestored)
return;
checked = true;
is(gBrowser.tabs.length, 8, "there are now eight tabs");
is(gBrowser.visibleTabs.length, 4, "four visible tabs");
let cw = TabView.getContentWindow();
is(cw.GroupItems.groupItems.length, 2, "there are now two groupItems");
testSwitchToInactiveGroup();
}
whenSessionStoreReady(function () {
ssReady = true;
check();
});
TabsProgressListener.setCallback(function (needsRestore, isRestoring) {
if (4 < needsRestore)
return;
TabsProgressListener.unsetCallback();
is(needsRestore, 4, "4/8 tabs restored");
tabsRestored = true;
check();
});
ss.setBrowserState(JSON.stringify(state));
}
function testSwitchToInactiveGroup() {
let firstProgress = true;
TabsProgressListener.setCallback(function (needsRestore, isRestoring) {
if (firstProgress) {
firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently");
} else {
ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
}
if (needsRestore)
return;
TabsProgressListener.unsetCallback();
is(gBrowser.visibleTabs.length, 4, "four visible tabs");
waitForFocus(finish);
});
gBrowser.selectedTab = gBrowser.tabs[4];
}
function whenSessionStoreReady(callback) {
window.addEventListener("SSWindowStateReady", function onReady() {
window.removeEventListener("SSWindowStateReady", onReady, false);
executeSoon(callback);
}, false);
}
function countTabs() {
let needsRestore = 0, isRestoring = 0;
let windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let window = windowsEnum.getNext();
if (window.closed)
continue;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
let browser = window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
}
return [needsRestore, isRestoring];
}
let TabsProgressListener = {
init: function () {
gBrowser.addTabsProgressListener(this);
},
uninit: function () {
this.unsetCallback();
gBrowser.removeTabsProgressListener(this);
},
setCallback: function (callback) {
this.callback = callback;
},
unsetCallback: function () {
delete this.callback;
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
let isNetwork = aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
let isWindow = aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
if (!(this.callback && isNetwork && isWindow))
return;
let self = this;
let finalize = function () {
if (wasRestoring)
delete aBrowser.__wasRestoring;
self.callback.apply(null, countTabs());
};
let isRestoring = aBrowser.__SS_restoreState == TAB_STATE_RESTORING;
let wasRestoring = !aBrowser.__SS_restoreState && aBrowser.__wasRestoring;
let hasStopped = aStateFlags & Ci.nsIWebProgressListener.STATE_STOP;
if (isRestoring && !hasStopped)
aBrowser.__wasRestoring = true;
if (hasStopped && (isRestoring || wasRestoring))
finalize();
}
}

View File

@ -38,6 +38,7 @@ function test() {
if (!callback)
callback = finish;
assertOneSingleGroupItem();
callback();
});
}
@ -111,7 +112,7 @@ function test() {
// some callback waiting to be fired after gBrowser.loadOneTab(). After
// that the browser is in a state where loadURI() will create a new entry
// in the session history (that is vital for back/forward functionality).
afterAllTabsLoaded(function () SimpleTest.executeSoon(continueTest));
afterAllTabsLoaded(function () executeSoon(continueTest));
}
// ----------
@ -190,7 +191,7 @@ function enterAndLeavePrivateBrowsing(callback) {
pb.privateBrowsingEnabled = false;
else {
Services.obs.removeObserver(pbObserver, "private-browsing-transition-complete");
afterAllTabsLoaded(callback);
afterAllTabsLoaded(function () executeSoon(callback));
}
}

View File

@ -62,7 +62,10 @@ function test() {
let testStateAfterEnteringPB = function () {
let prefix = 'enter';
ok(!pb.privateBrowsingEnabled, prefix + ': private browsing is disabled');
registerCleanupFunction(function () pb.privateBrowsingEnabled = false);
registerCleanupFunction(function () {
if (pb.privateBrowsingEnabled)
pb.privateBrowsingEnabled = false
});
togglePrivateBrowsing(function () {
assertTabViewIsHidden(prefix);
@ -110,6 +113,8 @@ function test() {
showTabView(function () {
cw = TabView.getContentWindow();
assertNumberOfGroups('start', 1);
createGroupItem();
afterAllTabsLoaded(function () {

View File

@ -16,10 +16,8 @@ function test() {
showTabView(function() {
registerCleanupFunction(function () {
if (gBrowser.tabs[1])
while (gBrowser.tabs.length > 1)
gBrowser.removeTab(gBrowser.tabs[1]);
if (gBrowser.tabs[2])
gBrowser.removeTab(gBrowser.tabs[2]);
TabView.hide();
});

View File

@ -109,6 +109,6 @@ function restore(groupId) {
}]
};
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
ss.setWindowState(win, JSON.stringify(newState), false);
ss.setWindowState(win, JSON.stringify(newState), true);
}

View File

@ -0,0 +1,56 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let state = {
windows: [{
tabs: [{
entries: [{ url: "about:home" }],
hidden: true,
extData: {"tabview-tab": '{"url":"about:home","groupID":1,"bounds":{"left":20,"top":20,"width":20,"height":20}}'}
},{
entries: [{ url: "about:home" }],
hidden: false,
extData: {"tabview-tab": '{"url":"about:home","groupID":2,"bounds":{"left":20,"top":20,"width":20,"height":20}}'},
}],
selected: 2,
extData: {
"tabview-groups": '{"nextID":3,"activeGroupId":2}',
"tabview-group":
'{"1":{"bounds":{"left":15,"top":5,"width":280,"height":232},"id":1},' +
'"2":{"bounds":{"left":309,"top":5,"width":267,"height":226},"id":2}}'
}
}]
};
function test() {
waitForExplicitFinish();
newWindowWithState(state, function (win) {
registerCleanupFunction(function () win.close());
is(win.gBrowser.tabs.length, 2, "two tabs");
let opts = {animate: true, byMouse: true};
win.gBrowser.removeTab(win.gBrowser.visibleTabs[0], opts);
let checkTabCount = function () {
if (win.gBrowser.tabs.length > 1) {
executeSoon(checkTabCount);
return;
}
is(win.gBrowser.tabs.length, 1, "one tab");
showTabView(function () {
let cw = win.TabView.getContentWindow();
is(cw.TabItems.items.length, 1, "one tabItem");
waitForFocus(finish);
}, win);
};
checkTabCount();
});
}

View File

@ -0,0 +1,100 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
let stateBackup = ss.getBrowserState();
function test() {
waitForExplicitFinish();
registerCleanupFunction(function () {
ss.setBrowserState(stateBackup);
});
TabView._initFrame(function() {
executeSoon(testRestoreNormal);
});
}
function testRestoreNormal() {
testRestore("normal", function () {
waitForBrowserState(JSON.parse(stateBackup), testRestorePinned);
});
}
function testRestorePinned() {
gBrowser.loadOneTab("about:blank", {inBackground: true});
gBrowser.pinTab(gBrowser.tabs[0]);
testRestore("pinned", function () {
waitForBrowserState(JSON.parse(stateBackup), testRestoreHidden);
});
}
function testRestoreHidden() {
let groupItem = createGroupItemWithBlankTabs(window, 20, 20, 20, 1);
let tabItem = groupItem.getChild(0);
hideGroupItem(groupItem, function () {
testRestore("hidden", function () {
isnot(tabItem.container.style.display, "none", "tabItem is visible");
waitForFocus(finish);
});
});
}
function testRestore(prefix, callback) {
waitForBrowserState(createBrowserState(), function () {
is(gBrowser.tabs.length, 2, prefix + ": two tabs restored");
let cw = TabView.getContentWindow();
is(cw.GroupItems.groupItems.length, 2, prefix + ": we have two groupItems");
let [groupItem1, groupItem2] = cw.GroupItems.groupItems;
is(groupItem1.id, "1st-group-id", prefix + ": groupItem1's ID is valid");
is(groupItem1.getChildren().length, 1, prefix + ": groupItem1 has one child");
is(groupItem2.id, "2nd-group-id", prefix + ": groupItem2's ID is valid");
is(groupItem2.getChildren().length, 1, prefix + ": groupItem2 has one child");
callback();
});
}
function waitForBrowserState(state, callback) {
window.addEventListener("SSWindowStateReady", function onReady() {
window.removeEventListener("SSWindowStateReady", onReady, false);
executeSoon(callback);
}, false);
ss.setBrowserState(JSON.stringify(state));
}
function createBrowserState() {
let bounds = {left: 20, top: 20, width: 20, height: 20};
let tabViewGroups = {nextID: 99, activeGroupId: 1};
let tabViewGroup = {
"1st-group-id": {bounds: bounds, title: "new group 1", id: "1st-group-id"},
"2nd-group-id": {bounds: bounds, title: "new group 2", id: "2nd-group-id"}
};
let tab1Data = {bounds: bounds, url: "about:robots", groupID: "2nd-group-id"};
let tab1 = {
entries: [{url: "about:robots"}],
extData: {"tabview-tab": JSON.stringify(tab1Data)}
};
let tab2Data = {bounds: bounds, url: "about:mozilla", groupID: "1st-group-id"};
let tab2 = {
entries: [{url: "about:mozilla"}],
extData: {"tabview-tab": JSON.stringify(tab2Data)}
};
return {windows: [{
tabs: [tab1, tab2],
selected: 1,
extData: {"tabview-groups": JSON.stringify(tabViewGroups),
"tabview-group": JSON.stringify(tabViewGroup)}
}]};
}

View File

@ -0,0 +1,141 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
registerCleanupFunction(function () {
Services.prefs.clearUserPref(TabView.PREF_FIRST_RUN);
Services.prefs.clearUserPref(TabView.PREF_STARTUP_PAGE);
Services.prefs.clearUserPref(TabView.PREF_RESTORE_ENABLED_ONCE);
});
let assertBoolPref = function (pref, value) {
is(Services.prefs.getBoolPref(pref), value, pref + " is " + value);
};
let assertIntPref = function (pref, value) {
is(Services.prefs.getIntPref(pref), value, pref + " is " + value);
};
let setPreferences = function (startupPage, firstRun, enabledOnce) {
Services.prefs.setIntPref(TabView.PREF_STARTUP_PAGE, startupPage);
Services.prefs.setBoolPref(TabView.PREF_FIRST_RUN, firstRun);
Services.prefs.setBoolPref(TabView.PREF_RESTORE_ENABLED_ONCE, enabledOnce);
};
let assertPreferences = function (startupPage, firstRun, enabledOnce) {
assertIntPref(TabView.PREF_STARTUP_PAGE, startupPage);
assertBoolPref(TabView.PREF_FIRST_RUN, firstRun);
assertBoolPref(TabView.PREF_RESTORE_ENABLED_ONCE, enabledOnce);
};
let next = function () {
if (tests.length == 0) {
waitForFocus(finish);
return;
}
let test = tests.shift();
info("running " + test.name + "...");
test();
};
// State:
// Panorama was already used before (firstUseExperienced = true) but session
// restore is deactivated. We did not automatically enable SR, yet.
//
// Expected result:
// When entering Panorma session restore will be enabled and a notification
// banner is shown.
let test1 = function test1() {
setPreferences(1, true, false);
newWindowWithTabView(function (win) {
assertPreferences(3, true, true);
win.close();
next();
});
};
// State:
// Panorama has not been used before (firstUseExperienced = false) and session
// restore is deactivated. We did not automatically enable SR, yet. That state
// is equal to starting the browser the first time.
//
// Expected result:
// When entering Panorma nothing happens. When we detect that Panorama is
// really used (firstUseExperienced = true) we notify that session restore
// is now enabled.
let test2 = function test2() {
setPreferences(1, false, false);
newWindowWithTabView(function (win) {
assertPreferences(1, false, false);
win.TabView.firstUseExperienced = true;
assertPreferences(3, true, true);
win.close();
next();
});
};
// State:
// Panorama was already used before (firstUseExperienced = true) and session
// restore is activated. We did not automatically enable SR, yet.
//
// Expected result:
// When entering Panorama nothing happens because session store is already
// enabled so there's no reason to notify.
let test3 = function test3() {
setPreferences(3, true, false);
newWindowWithTabView(function (win) {
assertPreferences(3, true, true);
win.close();
next();
});
};
// State:
// Panorama was already used before (firstUseExperienced = true) and session
// restore has been automatically activated.
//
// Expected result:
// When entering Panorama nothing happens.
let test4 = function test4() {
setPreferences(3, true, true);
newWindowWithTabView(function (win) {
assertPreferences(3, true, true);
win.close();
next();
});
};
// State:
// Panorama was already used before (firstUseExperienced = true) and session
// restore has been automatically activated. Session store was afterwards
// disabled by the user so we won't touch that again.
//
// Expected result:
// When entering Panorama nothing happens and we didn't enable session restore.
let test5 = function test5() {
setPreferences(1, true, true);
newWindowWithTabView(function (win) {
assertPreferences(1, true, true);
win.close();
next();
});
};
let tests = [test1, test2, test3, test4, test5];
next();
}

View File

@ -93,9 +93,13 @@ function newWindowWithTabView(shownCallback, loadCallback, width, height) {
// ----------
function afterAllTabsLoaded(callback, win) {
const TAB_STATE_NEEDS_RESTORE = 1;
win = win || window;
let stillToLoad = 0;
let restoreHiddenTabs = Services.prefs.getBoolPref(
"browser.sessionstore.restore_hidden_tabs");
function onLoad() {
this.removeEventListener("load", onLoad, true);
@ -105,8 +109,14 @@ function afterAllTabsLoaded(callback, win) {
}
for (let a = 0; a < win.gBrowser.tabs.length; a++) {
let browser = win.gBrowser.tabs[a].linkedBrowser;
if (browser.contentDocument.readyState != "complete" ||
let tab = win.gBrowser.tabs[a];
let browser = tab.linkedBrowser;
let isRestorable = !(tab.hidden && !restoreHiddenTabs &&
browser.__SS_restoreState &&
browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE);
if (isRestorable && browser.contentDocument.readyState != "complete" ||
browser.webProgress.isLoadingDocument) {
stillToLoad++;
browser.addEventListener("load", onLoad, true);
@ -114,7 +124,7 @@ function afterAllTabsLoaded(callback, win) {
}
if (!stillToLoad)
callback();
executeSoon(callback);
}
// ----------
@ -261,3 +271,33 @@ function unhideGroupItem(groupItem, callback) {
});
groupItem._unhide();
}
// ----------
function whenWindowLoaded(win, callback) {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(callback);
}, false);
}
// ----------
function whenWindowStateReady(win, callback) {
win.addEventListener("SSWindowStateReady", function onReady() {
win.removeEventListener("SSWindowStateReady", onReady, false);
executeSoon(callback);
}, false);
}
// ----------
function newWindowWithState(state, callback) {
let opts = "chrome,all,dialog=no,height=800,width=800";
let win = window.openDialog(getBrowserURL(), "_blank", opts);
whenWindowLoaded(win, function () {
ss.setWindowState(win, JSON.stringify(state), true);
});
whenWindowStateReady(win, function () {
afterAllTabsLoaded(function () callback(win), win);
});
}

View File

@ -316,9 +316,13 @@
allowThirdPartyFixup: true});
aTriggeringEvent.preventDefault();
aTriggeringEvent.stopPropagation();
} else {
// Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
// inheriting the currently loaded document's principal.
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
gBrowser.loadURIWithFlags(url, flags, null, null, postData);
}
else
loadURI(url, null, postData, true /* allow third party fixup */);
gBrowser.selectedBrowser.focus();
]]></body>

View File

@ -103,6 +103,8 @@ static RedirEntry kRedirMap[] = {
{ "home", "chrome://browser/content/aboutHome.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT },
{ "permissions", "chrome://browser/content/preferences/aboutPermissions.xul",
nsIAboutModule::ALLOW_SCRIPT },
};
static const int kRedirTotal = NS_ARRAY_LENGTH(kRedirMap);

View File

@ -46,33 +46,14 @@
#ifdef XP_MACOSX
#define NS_SAFARIPROFILEMIGRATOR_CID \
{ 0x29e3b139, 0xad19, 0x44f3, { 0xb2, 0xc2, 0xe9, 0xf1, 0x3b, 0xa2, 0xbb, 0xc6 } }
#define NS_MACIEPROFILEMIGRATOR_CID \
{ 0xf1a4e549, 0x5c4b, 0x41ff, { 0xb5, 0xe3, 0xeb, 0x87, 0xae, 0x31, 0x41, 0x9b } }
#define NS_OMNIWEBPROFILEMIGRATOR_CID \
{ 0xb80ae6d8, 0x766c, 0x43da, { 0x9c, 0x7a, 0xd, 0x82, 0x44, 0x52, 0x61, 0x6a } }
#define NS_CAMINOPROFILEMIGRATOR_CID \
{ 0x01d88ea9, 0x0feb, 0x495e, { 0x8c, 0x9b, 0x41, 0x65, 0x99, 0x55, 0x52, 0x65 } }
#define NS_ICABPROFILEMIGRATOR_CID \
{ 0xf394a036, 0xc5e1, 0x46d8, { 0x99, 0x39, 0x6b, 0x35, 0xe1, 0x13, 0x0a, 0x27 } }
#endif
#define NS_OPERAPROFILEMIGRATOR_CID \
{ 0xf34ff792, 0x722e, 0x4490, { 0xb1, 0x95, 0x47, 0xd2, 0x42, 0xed, 0xca, 0x1c } }
#define NS_DOGBERTPROFILEMIGRATOR_CID \
{ 0x24f92fae, 0xf793, 0x473b, { 0x80, 0x61, 0x71, 0x34, 0x8, 0xbd, 0x11, 0xd5 } }
#define NS_SEAMONKEYPROFILEMIGRATOR_CID \
{ 0x9a28ffa7, 0xe6ef, 0x4b52, { 0xa1, 0x27, 0x6a, 0xd9, 0x51, 0xde, 0x8e, 0x9b } }
#define NS_PHOENIXPROFILEMIGRATOR_CID \
{ 0x78481e4a, 0x50e4, 0x4489, { 0xb6, 0x8a, 0xef, 0x82, 0x67, 0xe, 0xd6, 0x3f } }
#define NS_SHELLSERVICE_CID \
{ 0x63c7b9f4, 0xcc8, 0x43f8, { 0xb6, 0x66, 0xa, 0x66, 0x16, 0x55, 0xcb, 0x73 } }

View File

@ -50,20 +50,14 @@
#endif
#include "nsProfileMigrator.h"
#include "nsDogbertProfileMigrator.h"
#if !defined(XP_OS2)
#include "nsOperaProfileMigrator.h"
#endif
#include "nsPhoenixProfileMigrator.h"
#include "nsSeamonkeyProfileMigrator.h"
#if defined(XP_WIN) && !defined(__MINGW32__)
#include "nsIEProfileMigrator.h"
#elif defined(XP_MACOSX)
#include "nsSafariProfileMigrator.h"
#include "nsOmniWebProfileMigrator.h"
#include "nsMacIEProfileMigrator.h"
#include "nsCaminoProfileMigrator.h"
#include "nsICabProfileMigrator.h"
#endif
#include "rdf.h"
@ -87,21 +81,15 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDogbertProfileMigrator)
#if !defined(XP_OS2)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsOperaProfileMigrator)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPhoenixProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSeamonkeyProfileMigrator)
#if defined(XP_WIN) && !defined(__MINGW32__)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator)
#elif defined(XP_MACOSX)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafariProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsOmniWebProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacIEProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCaminoProfileMigrator)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsICabProfileMigrator)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
@ -122,16 +110,10 @@ NS_DEFINE_NAMED_CID(NS_WINIEPROFILEMIGRATOR_CID);
#elif defined(XP_MACOSX)
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_MACIEPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_OMNIWEBPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_CAMINOPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_ICABPROFILEMIGRATOR_CID);
#endif
#if !defined(XP_OS2)
NS_DEFINE_NAMED_CID(NS_OPERAPROFILEMIGRATOR_CID);
#endif
NS_DEFINE_NAMED_CID(NS_DOGBERTPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_PHOENIXPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_SEAMONKEYPROFILEMIGRATOR_CID);
NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID);
@ -150,16 +132,10 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
#elif defined(XP_MACOSX)
{ &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
{ &kNS_SAFARIPROFILEMIGRATOR_CID, false, NULL, nsSafariProfileMigratorConstructor },
{ &kNS_MACIEPROFILEMIGRATOR_CID, false, NULL, nsMacIEProfileMigratorConstructor },
{ &kNS_OMNIWEBPROFILEMIGRATOR_CID, false, NULL, nsOmniWebProfileMigratorConstructor },
{ &kNS_CAMINOPROFILEMIGRATOR_CID, false, NULL, nsCaminoProfileMigratorConstructor },
{ &kNS_ICABPROFILEMIGRATOR_CID, false, NULL, nsICabProfileMigratorConstructor },
#endif
#if !defined(XP_OS2)
{ &kNS_OPERAPROFILEMIGRATOR_CID, false, NULL, nsOperaProfileMigratorConstructor },
#endif
{ &kNS_DOGBERTPROFILEMIGRATOR_CID, false, NULL, nsDogbertProfileMigratorConstructor },
{ &kNS_PHOENIXPROFILEMIGRATOR_CID, false, NULL, nsPhoenixProfileMigratorConstructor },
{ &kNS_SEAMONKEYPROFILEMIGRATOR_CID, false, NULL, nsSeamonkeyProfileMigratorConstructor },
{ &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor },
{ NULL }
@ -186,22 +162,17 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#endif
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_PROFILEMIGRATOR_CONTRACTID, &kNS_FIREFOX_PROFILEMIGRATOR_CID },
#if defined(XP_WIN) && !defined(__MINGW32__)
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "ie", &kNS_WINIEPROFILEMIGRATOR_CID },
#elif defined(XP_MACOSX)
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "safari", &kNS_SAFARIPROFILEMIGRATOR_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "macie", &kNS_MACIEPROFILEMIGRATOR_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "omniweb", &kNS_OMNIWEBPROFILEMIGRATOR_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "camino", &kNS_CAMINOPROFILEMIGRATOR_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "icab", &kNS_ICABPROFILEMIGRATOR_CID },
#endif
#if !defined(XP_OS2)
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "opera", &kNS_OPERAPROFILEMIGRATOR_CID },
#endif
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "dogbert", &kNS_DOGBERTPROFILEMIGRATOR_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "phoenix", &kNS_PHOENIXPROFILEMIGRATOR_CID },
{ NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey", &kNS_SEAMONKEYPROFILEMIGRATOR_CID },
{ NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID },
{ NULL }

View File

@ -0,0 +1,6 @@
[DEFAULT]
head = head_dirprovider.js
tail =
[test_bookmark_pref.js]
[test_keys.js]

View File

@ -0,0 +1,5 @@
[DEFAULT]
head = head_feeds.js
tail =
[test_355473.js]

View File

@ -128,8 +128,7 @@ var MigrationWizard = {
return;
}
if (migrator.sourceExists &&
!(suffix == "phoenix" && !this._autoMigrate)) {
if (migrator.sourceExists) {
// Save this as the first selectable item, if we don't already have
// one, or if it is the migrator that was passed to us.
if (!selectedMigrator || this._source == suffix)
@ -333,15 +332,11 @@ var MigrationWizard = {
var source = null;
switch (this._source) {
case "ie":
case "macie":
source = "sourceNameIE";
break;
case "opera":
source = "sourceNameOpera";
break;
case "dogbert":
source = "sourceNameDogbert";
break;
case "safari":
source = "sourceNameSafari";
break;

View File

@ -68,43 +68,21 @@
<!-- If you are adding a migrator, please add the appropriate
hooks to GetDefaultBrowserMigratorKey in
browser/components/migration/src/nsProfileMigrator.cpp -->
<radio id="phoenix" label="&importFromPhoenix.label;" accesskey="&importFromPhoenix.accesskey;"/>
#ifdef XP_UNIX
#ifdef XP_MACOSX
<radio id="safari" label="&importFromSafari.label;" accesskey="&importFromSafari.accesskey;"/>
<radio id="macie" label="&importFromIE.label;" accesskey="&importFromIE.accesskey;"/>
<!-- XXXben - uncomment these as we write migrators for them
<radio id="camino" label="&importFromCamino.label;" accesskey="&importFromCamino.accesskey;"/>
<radio id="omniweb" label="&importFromOmniWeb.label;" accesskey="&importFromOmniWeb.accesskey;"/>
<radio id="icab" label="&importFromICab.label;" accesskey="&importFromICab.accesskey;"/>
-->
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
<radio id="dogbert" label="&importFromNetscape4.label;" accesskey="&importFromNetscape4.accesskey;"/>
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
#else
#elifdef XP_UNIX
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
<radio id="dogbert" label="&importFromNetscape4.label;" accesskey="&importFromNetscape4.accesskey;"/>
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
<!-- XXXben - uncomment these as we write migrators for them
<radio id="konqueror" label="&importFromKonqueror.label;" accesskey="&importFromKonqueror.accesskey;"/>
<radio id="epiphany" label="&importFromEpiphany.label;" accesskey="&importFromEpiphany.accesskey;"/>
<radio id="galeon" label="&importFromGaleon.label;" accesskey="&importFromGaleon.accesskey;"/>
-->
#endif
#endif
#ifdef XP_WIN
#elifdef XP_WIN
#ifndef NO_IE_MIGRATOR
<radio id="ie" label="&importFromIE.label;" accesskey="&importFromIE.accesskey;"/>
#endif
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
<radio id="dogbert" label="&importFromNetscape4.label;" accesskey="&importFromNetscape4.accesskey;"/>
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
#endif
#ifndef XP_UNIX
#ifndef XP_WIN
#else
<radio id="seamonkey" label="&importFromSeamonkey.label;" accesskey="&importFromSeamonkey.accesskey;"/>
<radio id="dogbert" label="&importFromNetscape4.label;" accesskey="&importFromNetscape4.accesskey;"/>
#endif
#endif
<radio id="fromfile" label="&importFromHTMLFile.label;" accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
<radio id="nothing" label="&importFromNothing.label;" accesskey="&importFromNothing.accesskey;" hidden="true"/>

View File

@ -54,8 +54,6 @@ CPPSRCS = nsProfileMigrator.cpp \
nsBrowserProfileMigratorUtils.cpp \
nsNetscapeProfileMigratorBase.cpp \
nsSeamonkeyProfileMigrator.cpp \
nsPhoenixProfileMigrator.cpp \
nsDogbertProfileMigrator.cpp \
$(NULL)
ifneq ($(OS_ARCH),OS2)
@ -69,10 +67,6 @@ endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += nsSafariProfileMigrator.cpp \
nsMacIEProfileMigrator.cpp \
nsOmniWebProfileMigrator.cpp \
nsCaminoProfileMigrator.cpp \
nsICabProfileMigrator.cpp \
$(NULL)
endif

View File

@ -1,115 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* 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 "nsBrowserProfileMigratorUtils.h"
#include "nsCaminoProfileMigrator.h"
#include "nsIObserverService.h"
#include "nsIProfileMigrator.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
///////////////////////////////////////////////////////////////////////////////
// nsCaminoProfileMigrator
NS_IMPL_ISUPPORTS1(nsCaminoProfileMigrator, nsIBrowserProfileMigrator)
nsCaminoProfileMigrator::nsCaminoProfileMigrator()
{
mObserverService = do_GetService("@mozilla.org/observer-service;1");
}
nsCaminoProfileMigrator::~nsCaminoProfileMigrator()
{
}
///////////////////////////////////////////////////////////////////////////////
// nsIBrowserProfileMigrator
NS_IMETHODIMP
nsCaminoProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
{
nsresult rv = NS_OK;
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
return rv;
}
NS_IMETHODIMP
nsCaminoProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
PRBool aReplace,
PRUint16* aResult)
{
*aResult = 0; // XXXben implement me
return NS_OK;
}
NS_IMETHODIMP
nsCaminoProfileMigrator::GetSourceExists(PRBool* aResult)
{
*aResult = PR_FALSE; // XXXben implement me
return NS_OK;
}
NS_IMETHODIMP
nsCaminoProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
{
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsCaminoProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
*aResult = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsCaminoProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
{
aResult.Truncate();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsCaminoProfileMigrator

View File

@ -1,672 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* 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 "nsAppDirectoryServiceDefs.h"
#include "nsBrowserProfileMigratorUtils.h"
#include "nsDogbertProfileMigrator.h"
#include "nsICookieManager2.h"
#include "nsIFile.h"
#include "nsIInputStream.h"
#include "nsILineInputStream.h"
#include "nsIObserverService.h"
#include "nsIOutputStream.h"
#include "nsIPrefBranch.h"
#include "nsIPrefLocalizedString.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "prprf.h"
#include "prenv.h"
#include "NSReg.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include <stdlib.h>
#include <limits.h>
#ifndef MAXPATHLEN
#ifdef PATH_MAX
#define MAXPATHLEN PATH_MAX
#elif defined(_MAX_PATH)
#define MAXPATHLEN _MAX_PATH
#elif defined(CCHMAXPATH)
#define MAXPATHLEN CCHMAXPATH
#else
#define MAXPATHLEN 1024
#endif
#endif
#define PREF_FILE_HEADER_STRING "# Mozilla User Preferences "
#if defined(XP_MACOSX)
#define OLDREG_NAME "Netscape Registry"
#define OLDREG_DIR NS_MAC_PREFS_DIR
#define PREF_FILE_NAME_IN_4x NS_LITERAL_STRING("Netscape Preferences")
#define COOKIES_FILE_NAME_IN_4x NS_LITERAL_STRING("MagicCookie")
#define BOOKMARKS_FILE_NAME_IN_4x NS_LITERAL_STRING("Bookmarks.html")
#define SECURITY_PATH "Security"
#define PSM_CERT7_DB NS_LITERAL_STRING("Certificates7")
#define PSM_KEY3_DB NS_LITERAL_STRING("Key Database3")
#define PSM_SECMODULE_DB NS_LITERAL_STRING("Security Modules")
#elif defined(XP_WIN) || defined(XP_OS2)
#define OLDREG_NAME "nsreg.dat"
#ifdef XP_WIN
#define OLDREG_DIR NS_WIN_WINDOWS_DIR
#else
#define OLDREG_DIR NS_OS2_DIR
#endif
#define PREF_FILE_NAME_IN_4x NS_LITERAL_STRING("prefs.js")
#define COOKIES_FILE_NAME_IN_4x NS_LITERAL_STRING("cookies.txt")
#define BOOKMARKS_FILE_NAME_IN_4x NS_LITERAL_STRING("bookmark.htm")
#define PSM_CERT7_DB NS_LITERAL_STRING("cert7.db")
#define PSM_KEY3_DB NS_LITERAL_STRING("key3.db")
#define PSM_SECMODULE_DB NS_LITERAL_STRING("secmod.db")
#elif defined(XP_UNIX)
#define PREF_FILE_NAME_IN_4x NS_LITERAL_STRING("preferences.js")
#define COOKIES_FILE_NAME_IN_4x NS_LITERAL_STRING("cookies")
#define BOOKMARKS_FILE_NAME_IN_4x NS_LITERAL_STRING("bookmarks.html")
#define PSM_CERT7_DB NS_LITERAL_STRING("cert7.db")
#define PSM_KEY3_DB NS_LITERAL_STRING("key3.db")
#define PSM_SECMODULE_DB NS_LITERAL_STRING("secmodule.db")
#define HOME_ENVIRONMENT_VARIABLE "HOME"
#define PROFILE_HOME_ENVIRONMENT_VARIABLE "PROFILE_HOME"
#define DEFAULT_UNIX_PROFILE_NAME "default"
#else
#error No netscape4.x profile-migrator on this platform.
#endif /* XP_UNIX */
#define COOKIES_FILE_NAME_IN_5x NS_LITERAL_STRING("cookies.txt")
#define BOOKMARKS_FILE_NAME_IN_5x NS_LITERAL_STRING("bookmarks.html")
#define PREF_FILE_NAME_IN_5x NS_LITERAL_STRING("prefs.js")
///////////////////////////////////////////////////////////////////////////////
// nsDogbertProfileMigrator
NS_IMPL_ISUPPORTS1(nsDogbertProfileMigrator, nsIBrowserProfileMigrator)
nsDogbertProfileMigrator::nsDogbertProfileMigrator()
{
mObserverService = do_GetService("@mozilla.org/observer-service;1");
}
nsDogbertProfileMigrator::~nsDogbertProfileMigrator()
{
}
///////////////////////////////////////////////////////////////////////////////
// nsIBrowserProfileMigrator
NS_IMETHODIMP
nsDogbertProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup,
const PRUnichar* aProfile)
{
nsresult rv = NS_OK;
PRBool aReplace = aStartup ? PR_TRUE : PR_FALSE;
if (!mTargetProfile) {
GetProfilePath(aStartup, mTargetProfile);
if (!mTargetProfile) return NS_ERROR_FAILURE;
}
if (!mSourceProfile) {
GetSourceProfile(aProfile);
if (!mSourceProfile)
return NS_ERROR_FAILURE;
}
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
COPY_DATA(CopyPreferences, aReplace, nsIBrowserProfileMigrator::SETTINGS);
COPY_DATA(CopyCookies, aReplace, nsIBrowserProfileMigrator::COOKIES);
COPY_DATA(CopyBookmarks, aReplace, nsIBrowserProfileMigrator::BOOKMARKS);
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
return rv;
}
// on win/mac/os2, NS4x uses a registry to determine profile locations
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2)
void
nsDogbertProfileMigrator::GetSourceProfile(const PRUnichar* aProfile)
{
nsresult rv;
nsCOMPtr<nsIFile> regFile;
rv = NS_GetSpecialDirectory(OLDREG_DIR, getter_AddRefs(regFile));
if (NS_FAILED(rv)) return;
regFile->AppendNative(NS_LITERAL_CSTRING(OLDREG_NAME));
nsCAutoString path;
rv = regFile->GetNativePath(path);
if (NS_FAILED(rv)) return;
if (NR_StartupRegistry())
return;
HREG reg = nsnull;
RKEY profile = nsnull;
if (NR_RegOpen(path.get(), &reg))
goto cleanup;
{
// on macos, registry entries are UTF8 encoded
NS_ConvertUTF16toUTF8 profileName(aProfile);
if (NR_RegGetKey(reg, ROOTKEY_USERS, profileName.get(), &profile))
goto cleanup;
}
char profilePath[MAXPATHLEN];
if (NR_RegGetEntryString(reg, profile, "ProfileLocation", profilePath, MAXPATHLEN))
goto cleanup;
mSourceProfile = do_CreateInstance("@mozilla.org/file/local;1");
if (!mSourceProfile) goto cleanup;
{
// the string is UTF8 encoded, which forces us to do some strange string-do
rv = mSourceProfile->InitWithPath(NS_ConvertUTF8toUTF16(profilePath));
}
if (NS_FAILED(rv))
mSourceProfile = nsnull;
cleanup:
if (reg)
NR_RegClose(reg);
NR_ShutdownRegistry();
}
#else
#endif
NS_IMETHODIMP
nsDogbertProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
PRBool aReplace,
PRUint16* aResult)
{
*aResult = 0;
if (!mSourceProfile) {
GetSourceProfile(aProfile);
if (!mSourceProfile)
return NS_ERROR_FILE_NOT_FOUND;
}
MigrationData data[] = { { ToNewUnicode(PREF_FILE_NAME_IN_4x),
nsIBrowserProfileMigrator::SETTINGS,
PR_TRUE },
{ ToNewUnicode(COOKIES_FILE_NAME_IN_4x),
nsIBrowserProfileMigrator::COOKIES,
PR_FALSE },
{ ToNewUnicode(BOOKMARKS_FILE_NAME_IN_4x),
nsIBrowserProfileMigrator::BOOKMARKS,
PR_FALSE } };
// Frees file name strings allocated above.
GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData),
aReplace, mSourceProfile, aResult);
return NS_OK;
}
NS_IMETHODIMP
nsDogbertProfileMigrator::GetSourceExists(PRBool* aResult)
{
nsCOMPtr<nsISupportsArray> profiles;
GetSourceProfiles(getter_AddRefs(profiles));
if (profiles) {
PRUint32 count;
profiles->Count(&count);
*aResult = count > 0;
}
else
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsDogbertProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
{
nsCOMPtr<nsISupportsArray> profiles;
GetSourceProfiles(getter_AddRefs(profiles));
if (profiles) {
PRUint32 count;
profiles->Count(&count);
*aResult = count > 1;
}
else
*aResult = PR_FALSE;
return NS_OK;
}
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_MACOSX)
NS_IMETHODIMP
nsDogbertProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
if (!mProfiles) {
nsresult rv;
mProfiles = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> regFile;
rv = NS_GetSpecialDirectory(OLDREG_DIR, getter_AddRefs(regFile));
NS_ENSURE_SUCCESS(rv, rv);
regFile->AppendNative(NS_LITERAL_CSTRING(OLDREG_NAME));
nsCAutoString path;
rv = regFile->GetNativePath(path);
NS_ENSURE_SUCCESS(rv, rv);
if (NR_StartupRegistry())
return NS_ERROR_FAILURE;
HREG reg = nsnull;
REGENUM enumstate = 0;
if (NR_RegOpen(path.get(), &reg)) {
NR_ShutdownRegistry();
return NS_ERROR_FAILURE;
}
char profileName[MAXREGNAMELEN];
while (!NR_RegEnumSubkeys(reg, ROOTKEY_USERS, &enumstate,
profileName, MAXREGNAMELEN, REGENUM_CHILDREN)) {
nsCOMPtr<nsISupportsString> nameString
(do_CreateInstance("@mozilla.org/supports-string;1"));
if (nameString) {
nameString->SetData(NS_ConvertUTF8toUTF16(profileName));
mProfiles->AppendElement(nameString);
}
}
}
NS_IF_ADDREF(*aResult = mProfiles);
return NS_OK;
}
#else // XP_UNIX
NS_IMETHODIMP
nsDogbertProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
nsresult rv;
const char* profileDir = PR_GetEnv(PROFILE_HOME_ENVIRONMENT_VARIABLE);
if (!profileDir) {
profileDir = PR_GetEnv(HOME_ENVIRONMENT_VARIABLE);
}
if (!profileDir) return NS_ERROR_FAILURE;
nsCAutoString profilePath(profileDir);
profilePath += "/.netscape";
nsCOMPtr<nsILocalFile> profileFile;
rv = NS_NewNativeLocalFile(profilePath, PR_TRUE, getter_AddRefs(profileFile));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> prefFile;
rv = profileFile->Clone(getter_AddRefs(prefFile));
NS_ENSURE_SUCCESS(rv, rv);
prefFile->AppendNative(NS_LITERAL_CSTRING("preferences.js"));
PRBool exists;
rv = prefFile->Exists(&exists);
if (NS_FAILED(rv) || !exists) {
return NS_ERROR_FAILURE;
}
mSourceProfile = profileFile;
mProfiles = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsString> nameString
(do_CreateInstance("@mozilla.org/supports-string;1"));
if (!nameString) return NS_ERROR_FAILURE;
nameString->SetData(NS_LITERAL_STRING("Netscape 4.x"));
mProfiles->AppendElement(nameString);
NS_ADDREF(*aResult = mProfiles);
return NS_OK;
}
void
nsDogbertProfileMigrator::GetSourceProfile(const PRUnichar* aProfile)
{
// if GetSourceProfiles didn't do its magic, we're screwed
}
#endif // GetSourceProfiles
NS_IMETHODIMP
nsDogbertProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
{
aResult.Truncate();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsDogbertProfileMigrator
#define F(a) nsDogbertProfileMigrator::a
static
nsDogbertProfileMigrator::PrefTransform gTransforms[] = {
// Simple Copy Prefs
{ "browser.anchor_color", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "browser.visited_color", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "browser.startup.homepage", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.cookie.cookieBehavior", 0, F(GetInt), F(SetInt), PR_FALSE, { -1 } },
{ "network.cookie.warnAboutCookies",0, F(GetBool), F(SetBool), PR_FALSE, { -1 } },
{ "javascript.enabled", 0, F(GetBool), F(SetBool), PR_FALSE, { -1 } },
{ "network.proxy.type", 0, F(GetInt), F(SetInt), PR_FALSE, { -1 } },
{ "network.proxy.no_proxies_on", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.proxy.autoconfig_url", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.proxy.ftp", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.proxy.ftp_port", 0, F(GetInt), F(SetInt), PR_FALSE, { -1 } },
{ "network.proxy.http", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.proxy.http_port", 0, F(GetInt), F(SetInt), PR_FALSE, { -1 } },
{ "network.proxy.ssl", 0, F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.proxy.ssl_port", 0, F(GetInt), F(SetInt), PR_FALSE, { -1 } },
// Prefs with Different Names
{ "network.hosts.socks_server", "network.proxy.socks", F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "network.hosts.socks_serverport", "network.proxy.socks_port", F(GetInt), F(SetInt), PR_FALSE, { -1 } },
{ "browser.background_color", "browser.display.background_color", F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "browser.foreground_color", "browser.display.foreground_color", F(GetString), F(SetString), PR_FALSE, { -1 } },
{ "browser.wfe.use_windows_colors", "browser.display.use_system_colors", F(GetBool), F(SetBool), PR_FALSE, { -1 } },
{ "browser.use_document_colors", "browser.display.use_document_colors",F(GetBool), F(SetBool), PR_FALSE, { -1 } },
{ "browser.use_document.fonts", "browser.display.use_document_fonts", F(GetInt), F(SetInt), PR_FALSE, { -1 } },
{ "browser.startup.page", "browser.startup.homepage", F(GetHomepage), F(SetWStringFromASCII), PR_FALSE, { -1 } },
{ "general.always_load_images", "permissions.default.image", F(GetImagePref),F(SetInt), PR_FALSE, { -1 } },
};
nsresult
nsDogbertProfileMigrator::TransformPreferences(const nsAString& aSourcePrefFileName,
const nsAString& aTargetPrefFileName)
{
PrefTransform* transform;
PrefTransform* end = gTransforms + sizeof(gTransforms)/sizeof(PrefTransform);
// Load the source pref file
nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
psvc->ResetPrefs();
nsCOMPtr<nsIFile> sourcePrefsFile;
mSourceProfile->Clone(getter_AddRefs(sourcePrefsFile));
sourcePrefsFile->Append(aSourcePrefFileName);
psvc->ReadUserPrefs(sourcePrefsFile);
nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
for (transform = gTransforms; transform < end; ++transform)
transform->prefGetterFunc(transform, branch);
// Now that we have all the pref data in memory, load the target pref file,
// and write it back out
psvc->ResetPrefs();
for (transform = gTransforms; transform < end; ++transform)
transform->prefSetterFunc(transform, branch);
nsCOMPtr<nsIFile> targetPrefsFile;
mTargetProfile->Clone(getter_AddRefs(targetPrefsFile));
targetPrefsFile->Append(aTargetPrefFileName);
psvc->SavePrefFile(targetPrefsFile);
return NS_OK;
}
nsresult
nsDogbertProfileMigrator::CopyPreferences(PRBool aReplace)
{
nsresult rv = NS_OK;
if (!aReplace)
return rv;
// 1) Copy Preferences
TransformPreferences(PREF_FILE_NAME_IN_4x, PREF_FILE_NAME_IN_5x);
// 2) Copy Certficates
rv |= CopyFile(PSM_CERT7_DB, PSM_CERT7_DB);
rv |= CopyFile(PSM_KEY3_DB, PSM_KEY3_DB);
rv |= CopyFile(PSM_SECMODULE_DB, PSM_SECMODULE_DB);
return rv;
}
nsresult
nsDogbertProfileMigrator::GetHomepage(void* aTransform, nsIPrefBranch* aBranch)
{
PrefTransform* xform = (PrefTransform*)aTransform;
PRInt32 val;
nsresult rv = aBranch->GetIntPref(xform->sourcePrefName, &val);
if (NS_SUCCEEDED(rv) && val == 0) {
xform->stringValue = ToNewCString(NS_LITERAL_CSTRING("about:blank"));
if (!xform->stringValue)
rv = NS_ERROR_OUT_OF_MEMORY;
xform->prefHasValue = PR_TRUE;
}
return rv;
}
nsresult
nsDogbertProfileMigrator::GetImagePref(void* aTransform, nsIPrefBranch* aBranch)
{
PrefTransform* xform = (PrefTransform*)aTransform;
PRBool loadImages;
nsresult rv = aBranch->GetBoolPref(xform->sourcePrefName, &loadImages);
if (NS_SUCCEEDED(rv)) {
xform->intValue = loadImages ? 1 : 2;
xform->prefHasValue = PR_TRUE;
}
return rv;
}
nsresult
nsDogbertProfileMigrator::CopyCookies(PRBool aReplace)
{
nsresult rv;
if (aReplace) {
#ifdef NEED_TO_FIX_4X_COOKIES
rv = CopyFile(COOKIES_FILE_NAME_IN_4x, COOKIES_FILE_NAME_IN_5x);
if (NS_FAILED(rv)) return rv;
rv = FixDogbertCookies();
#else
rv = CopyFile(COOKIES_FILE_NAME_IN_4x, COOKIES_FILE_NAME_IN_5x);
#endif
}
else {
nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID));
if (!cookieManager)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIFile> dogbertCookiesFile;
mSourceProfile->Clone(getter_AddRefs(dogbertCookiesFile));
dogbertCookiesFile->Append(COOKIES_FILE_NAME_IN_4x);
rv = ImportNetscapeCookies(dogbertCookiesFile);
}
return rv;
}
#if NEED_TO_FIX_4X_COOKIES
nsresult
nsDogbertProfileMigrator::FixDogbertCookies()
{
nsCOMPtr<nsIFile> dogbertCookiesFile;
mSourceProfile->Clone(getter_AddRefs(dogbertCookiesFile));
dogbertCookiesFile->Append(COOKIES_FILE_NAME_IN_4x);
nsCOMPtr<nsIInputStream> fileInputStream;
NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), dogbertCookiesFile);
if (!fileInputStream) return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIFile> firebirdCookiesFile;
mTargetProfile->Clone(getter_AddRefs(firebirdCookiesFile));
firebirdCookiesFile->Append(COOKIES_FILE_NAME_IN_5x);
nsCOMPtr<nsIOutputStream> fileOutputStream;
NS_NewLocalFileOutputStream(getter_AddRefs(fileOutputStream), firebirdCookiesFile);
if (!fileOutputStream) return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsILineInputStream> lineInputStream(do_QueryInterface(fileInputStream));
nsCAutoString buffer, outBuffer;
PRBool moreData = PR_FALSE;
PRUint32 written = 0;
do {
nsresult rv = lineInputStream->ReadLine(buffer, &moreData);
if (NS_FAILED(rv)) return rv;
if (!moreData)
break;
// skip line if it is a comment or null line
if (buffer.IsEmpty() || buffer.CharAt(0) == '#' ||
buffer.CharAt(0) == '\r' || buffer.CharAt(0) == '\n') {
fileOutputStream->Write(buffer.get(), buffer.Length(), &written);
continue;
}
// locate expire field, skip line if it does not contain all its fields
int hostIndex, isDomainIndex, pathIndex, xxxIndex, expiresIndex, nameIndex, cookieIndex;
hostIndex = 0;
if ((isDomainIndex = buffer.FindChar('\t', hostIndex)+1) == 0 ||
(pathIndex = buffer.FindChar('\t', isDomainIndex)+1) == 0 ||
(xxxIndex = buffer.FindChar('\t', pathIndex)+1) == 0 ||
(expiresIndex = buffer.FindChar('\t', xxxIndex)+1) == 0 ||
(nameIndex = buffer.FindChar('\t', expiresIndex)+1) == 0 ||
(cookieIndex = buffer.FindChar('\t', nameIndex)+1) == 0 )
continue;
// separate the expires field from the rest of the cookie line
const nsDependentCSubstring prefix =
Substring(buffer, hostIndex, expiresIndex-hostIndex-1);
const nsDependentCSubstring expiresString =
Substring(buffer, expiresIndex, nameIndex-expiresIndex-1);
const nsDependentCSubstring suffix =
Substring(buffer, nameIndex, buffer.Length()-nameIndex);
// correct the expires field
char* expiresCString = ToNewCString(expiresString);
unsigned long expires = strtoul(expiresCString, nsnull, 10);
NS_Free(expiresCString);
// if the cookie is supposed to expire at the end of the session
// expires == 0. don't adjust those cookies.
if (expires)
expires -= SECONDS_BETWEEN_1900_AND_1970;
char dateString[36];
PR_snprintf(dateString, sizeof(dateString), "%lu", expires);
// generate the output buffer and write it to file
outBuffer = prefix;
outBuffer.Append('\t');
outBuffer.Append(dateString);
outBuffer.Append('\t');
outBuffer.Append(suffix);
fileOutputStream->Write(outBuffer.get(), outBuffer.Length(), &written);
}
while (1);
return NS_OK;
}
#endif // NEED_TO_FIX_4X_COOKIES
nsresult
nsDogbertProfileMigrator::CopyBookmarks(PRBool aReplace)
{
// If we're blowing away existing content, just copy the file, don't do fancy importing.
if (aReplace) {
nsresult rv = InitializeBookmarks(mTargetProfile);
NS_ENSURE_SUCCESS(rv, rv);
return MigrateDogbertBookmarks();
}
return ImportNetscapeBookmarks(BOOKMARKS_FILE_NAME_IN_4x,
NS_LITERAL_STRING("sourceNameDogbert").get());
}
nsresult
nsDogbertProfileMigrator::MigrateDogbertBookmarks()
{
nsresult rv;
// Find out what the personal toolbar folder was called, this is stored in a pref
// in 4.x
nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
psvc->ResetPrefs();
nsCOMPtr<nsIFile> dogbertPrefsFile;
mSourceProfile->Clone(getter_AddRefs(dogbertPrefsFile));
dogbertPrefsFile->Append(PREF_FILE_NAME_IN_4x);
psvc->ReadUserPrefs(dogbertPrefsFile);
nsCString toolbarName;
nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
rv = branch->GetCharPref("custtoolbar.personal_toolbar_folder", getter_Copies(toolbarName));
// If the pref wasn't set in the user's 4.x preferences, there's no way we can "Fix" the
// file when importing it to set the personal toolbar folder correctly, so don't bother
// with the more involved file correction procedure and just copy the file over.
if (NS_FAILED(rv))
return CopyFile(BOOKMARKS_FILE_NAME_IN_4x, BOOKMARKS_FILE_NAME_IN_5x);
// Now read the 4.x bookmarks file, correcting the Personal Toolbar Folder line
// and writing to the new location.
nsCOMPtr<nsIFile> sourceBookmarksFile;
mSourceProfile->Clone(getter_AddRefs(sourceBookmarksFile));
sourceBookmarksFile->Append(BOOKMARKS_FILE_NAME_IN_4x);
nsCOMPtr<nsIFile> targetBookmarksFile;
mTargetProfile->Clone(getter_AddRefs(targetBookmarksFile));
targetBookmarksFile->Append(BOOKMARKS_FILE_NAME_IN_5x);
return AnnotatePersonalToolbarFolder(sourceBookmarksFile,
targetBookmarksFile, toolbarName.get());
}

View File

@ -1,89 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* 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 dogbertprofilemigrator___h___
#define dogbertprofilemigrator___h___
#include "nsIBrowserProfileMigrator.h"
#include "nsILocalFile.h"
#include "nsIObserverService.h"
#include "nsISupportsArray.h"
#include "nsNetscapeProfileMigratorBase.h"
#include "nsStringAPI.h"
#ifdef XP_MACOSX
#define NEED_TO_FIX_4X_COOKIES 1
#define SECONDS_BETWEEN_1900_AND_1970 2208988800UL
#endif /* XP_MACOSX */
class nsIFile;
class nsDogbertProfileMigrator : public nsNetscapeProfileMigratorBase,
public nsIBrowserProfileMigrator
{
public:
NS_DECL_NSIBROWSERPROFILEMIGRATOR
NS_DECL_ISUPPORTS
nsDogbertProfileMigrator();
virtual ~nsDogbertProfileMigrator();
public:
static nsresult GetHomepage(void* aTransform, nsIPrefBranch* aBranch);
static nsresult GetImagePref(void* aTransform, nsIPrefBranch* aBranch);
protected:
nsresult CopyPreferences(PRBool aReplace);
nsresult TransformPreferences(const nsAString& aSourcePrefFileName,
const nsAString& aTargetPrefFileName);
nsresult CopyCookies(PRBool aReplace);
#ifdef NEED_TO_FIX_4X_COOKIES
nsresult FixDogbertCookies();
#endif
nsresult CopyBookmarks(PRBool aReplace);
nsresult MigrateDogbertBookmarks();
void GetSourceProfile(const PRUnichar* aProfile);
private:
nsCOMPtr<nsISupportsArray> mProfiles;
nsCOMPtr<nsIObserverService> mObserverService;
};
#endif

View File

@ -1,116 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* 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 "nsBrowserProfileMigratorUtils.h"
#include "nsICabProfileMigrator.h"
#include "nsIObserverService.h"
#include "nsIProfileMigrator.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
///////////////////////////////////////////////////////////////////////////////
// nsICabProfileMigrator
NS_IMPL_ISUPPORTS1(nsICabProfileMigrator, nsIBrowserProfileMigrator)
nsICabProfileMigrator::nsICabProfileMigrator()
{
mObserverService = do_GetService("@mozilla.org/observer-service;1");
}
nsICabProfileMigrator::~nsICabProfileMigrator()
{
}
///////////////////////////////////////////////////////////////////////////////
// nsIBrowserProfileMigrator
NS_IMETHODIMP
nsICabProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
{
nsresult rv = NS_OK;
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
return rv;
}
NS_IMETHODIMP
nsICabProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
PRBool aReplace,
PRUint16* aResult)
{
*aResult = 0; // XXXben implement me
return NS_OK;
}
NS_IMETHODIMP
nsICabProfileMigrator::GetSourceExists(PRBool* aResult)
{
*aResult = PR_FALSE; // XXXben implement me
return NS_OK;
}
NS_IMETHODIMP
nsICabProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
{
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsICabProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
*aResult = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsICabProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
{
aResult.Truncate();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsICabProfileMigrator

View File

@ -1,259 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* 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 "nsDirectoryServiceDefs.h"
#include "nsBrowserProfileMigratorUtils.h"
#include "nsMacIEProfileMigrator.h"
#include "nsILocalFile.h"
#include "nsIObserverService.h"
#include "nsIProfileMigrator.h"
#include "nsIServiceManager.h"
#include "nsIStringBundle.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
#include "nsIProperties.h"
#include <Carbon/Carbon.h>
#define MACIE_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("Favorites.html")
#define MACIE_PREFERENCES_FOLDER_NAME NS_LITERAL_STRING("Explorer")
#define MACIE_DEFAULT_HOMEPAGE_PREF "\p4D534945¥WWWHomePage"
#define TEMP_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("bookmarks_tmp.html")
#define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
///////////////////////////////////////////////////////////////////////////////
// nsMacIEProfileMigrator
NS_IMPL_ISUPPORTS1(nsMacIEProfileMigrator, nsIBrowserProfileMigrator)
nsMacIEProfileMigrator::nsMacIEProfileMigrator()
{
mObserverService = do_GetService("@mozilla.org/observer-service;1");
}
nsMacIEProfileMigrator::~nsMacIEProfileMigrator()
{
}
///////////////////////////////////////////////////////////////////////////////
// nsIBrowserProfileMigrator
NS_IMETHODIMP
nsMacIEProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
{
nsresult rv = NS_OK;
PRBool replace = aStartup ? PR_TRUE : PR_FALSE;
if (!mTargetProfile) {
GetProfilePath(aStartup, mTargetProfile);
if (!mTargetProfile) return NS_ERROR_FAILURE;
}
if (!mSourceProfile) {
nsCOMPtr<nsIProperties> fileLocator =
do_GetService("@mozilla.org/file/directory_service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR,
NS_GET_IID(nsILocalFile),
getter_AddRefs(mSourceProfile));
mSourceProfile->Append(MACIE_PREFERENCES_FOLDER_NAME);
}
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
COPY_DATA(CopyBookmarks, replace, nsIBrowserProfileMigrator::BOOKMARKS);
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
return rv;
}
NS_IMETHODIMP
nsMacIEProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
PRBool aReplace,
PRUint16* aResult)
{
*aResult = 0;
if (!mSourceProfile) {
nsresult rv;
nsCOMPtr<nsIProperties> fileLocator =
do_GetService("@mozilla.org/file/directory_service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
fileLocator->Get(NS_OSX_USER_PREFERENCES_DIR,
NS_GET_IID(nsILocalFile),
getter_AddRefs(mSourceProfile));
mSourceProfile->Append(MACIE_PREFERENCES_FOLDER_NAME);
}
MigrationData data[] = { { ToNewUnicode(MACIE_BOOKMARKS_FILE_NAME),
nsIBrowserProfileMigrator::BOOKMARKS,
PR_FALSE } };
// Frees file name strings allocated above.
GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData),
aReplace, mSourceProfile, aResult);
return NS_OK;
}
NS_IMETHODIMP
nsMacIEProfileMigrator::GetSourceExists(PRBool* aResult)
{
// Since the IE bookmarks file can sometimes be created by programs
// other than Internet Explorer, thus misleading, we must first
// check whether IE is even installed on this Mac. We accomplish this by
// checking one of IEs stored preferences in the apple.internetconfig file.
PRBool prefExists = PR_FALSE;
OSErr err;
ICInstance icInstance;
err = ::ICStart(&icInstance, 'FRFX');
if (err == noErr) {
ICAttr attrs;
Str255 IEhomePageValue;
long size = kICFileSpecHeaderSize;
err = ::ICGetPref(icInstance, MACIE_DEFAULT_HOMEPAGE_PREF, &attrs,
IEhomePageValue, &size);
if (err == noErr)
prefExists = PR_TRUE;
::ICStop(icInstance);
}
if (!prefExists) {
*aResult = PR_FALSE;
return NS_OK;
}
PRUint16 data;
GetMigrateData(nsnull, PR_FALSE, &data);
*aResult = data != 0;
return NS_OK;
}
NS_IMETHODIMP
nsMacIEProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
{
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsMacIEProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
*aResult = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsMacIEProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
{
aResult.Truncate();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsMacIEProfileMigrator
nsresult
nsMacIEProfileMigrator::CopyBookmarks(PRBool aReplace)
{
nsresult rv;
nsCOMPtr<nsIFile> sourceFile;
mSourceProfile->Clone(getter_AddRefs(sourceFile));
sourceFile->Append(MACIE_BOOKMARKS_FILE_NAME);
PRBool exists = PR_FALSE;
sourceFile->Exists(&exists);
if (!exists)
return NS_OK;
// it's an import
if (!aReplace)
return ImportBookmarksHTML(sourceFile,
PR_FALSE,
PR_FALSE,
NS_LITERAL_STRING("sourceNameIE").get());
// Initialize the default bookmarks
rv = InitializeBookmarks(mTargetProfile);
NS_ENSURE_SUCCESS(rv, rv);
// If we're blowing away existing content, annotate the Personal Toolbar and
// then import the file.
nsCOMPtr<nsIFile> tempFile;
mTargetProfile->Clone(getter_AddRefs(tempFile));
tempFile->Append(TEMP_BOOKMARKS_FILE_NAME);
// Look for the localized name of the IE Favorites Bar
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStringBundle> bundle;
rv = bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle));
NS_ENSURE_SUCCESS(rv, rv);
nsString toolbarFolderNameMacIE;
rv = bundle->GetStringFromName(NS_LITERAL_STRING("toolbarFolderNameMacIE").get(),
getter_Copies(toolbarFolderNameMacIE));
NS_ENSURE_SUCCESS(rv, rv);
// Now read the 4.x bookmarks file, correcting the Personal Toolbar Folder
// line and writing to the temporary file.
rv = AnnotatePersonalToolbarFolder(sourceFile,
tempFile,
NS_ConvertUTF16toUTF8(toolbarFolderNameMacIE).get());
NS_ENSURE_SUCCESS(rv, rv);
// import the temp file
rv = ImportBookmarksHTML(tempFile,
PR_TRUE,
PR_FALSE,
EmptyString().get());
NS_ENSURE_SUCCESS(rv, rv);
// remove the temp file
return tempFile->Remove(PR_FALSE);
}

View File

@ -1,116 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* 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 "nsBrowserProfileMigratorUtils.h"
#include "nsOmniWebProfileMigrator.h"
#include "nsIObserverService.h"
#include "nsIProfileMigrator.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
///////////////////////////////////////////////////////////////////////////////
// nsOmniWebProfileMigrator
NS_IMPL_ISUPPORTS1(nsOmniWebProfileMigrator, nsIBrowserProfileMigrator)
nsOmniWebProfileMigrator::nsOmniWebProfileMigrator()
{
mObserverService = do_GetService("@mozilla.org/observer-service;1");
}
nsOmniWebProfileMigrator::~nsOmniWebProfileMigrator()
{
}
///////////////////////////////////////////////////////////////////////////////
// nsIBrowserProfileMigrator
NS_IMETHODIMP
nsOmniWebProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
{
nsresult rv = NS_OK;
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
return rv;
}
NS_IMETHODIMP
nsOmniWebProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
PRBool aReplace,
PRUint16* aResult)
{
*aResult = 0; // XXXben implement me
return NS_OK;
}
NS_IMETHODIMP
nsOmniWebProfileMigrator::GetSourceExists(PRBool* aResult)
{
*aResult = PR_FALSE; // XXXben implement me
return NS_OK;
}
NS_IMETHODIMP
nsOmniWebProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
{
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsOmniWebProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
*aResult = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsOmniWebProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
{
aResult.Truncate();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsOmniWebProfileMigrator

View File

@ -46,6 +46,7 @@
#include "nsStringAPI.h"
#include "nsTArray.h"
#include "nsINavHistoryService.h"
#include "nsIStringBundle.h"
class nsICookieManager2;
class nsILineInputStream;

View File

@ -1,438 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* 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 "nsBrowserProfileMigratorUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIObserverService.h"
#include "nsIPrefService.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsISupportsPrimitives.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsPhoenixProfileMigrator.h"
///////////////////////////////////////////////////////////////////////////////
// nsPhoenixProfileMigrator
#define FILE_NAME_BOOKMARKS NS_LITERAL_STRING("bookmarks.html")
#define FILE_NAME_COOKIES NS_LITERAL_STRING("cookies.txt")
#define FILE_NAME_SITEPERM_OLD NS_LITERAL_STRING("cookperm.txt")
#define FILE_NAME_SITEPERM_NEW NS_LITERAL_STRING("hostperm.1")
#define FILE_NAME_CERT8DB NS_LITERAL_STRING("cert8.db")
#define FILE_NAME_KEY3DB NS_LITERAL_STRING("key3.db")
#define FILE_NAME_SECMODDB NS_LITERAL_STRING("secmod.db")
#define FILE_NAME_HISTORY NS_LITERAL_STRING("history.dat")
#define FILE_NAME_FORMHISTORY NS_LITERAL_STRING("formhistory.dat")
#define FILE_NAME_LOCALSTORE NS_LITERAL_STRING("localstore.rdf")
#define FILE_NAME_MIMETYPES NS_LITERAL_STRING("mimeTypes.rdf")
#define FILE_NAME_DOWNLOADS NS_LITERAL_STRING("downloads.rdf")
#define FILE_NAME_PREFS NS_LITERAL_STRING("prefs.js")
#define FILE_NAME_USER_PREFS NS_LITERAL_STRING("user.js")
#define FILE_NAME_USERCHROME NS_LITERAL_STRING("userChrome.css")
#define FILE_NAME_USERCONTENT NS_LITERAL_STRING("userContent.css")
#define DIR_NAME_CHROME NS_LITERAL_STRING("chrome")
NS_IMPL_ISUPPORTS1(nsPhoenixProfileMigrator, nsIBrowserProfileMigrator)
nsPhoenixProfileMigrator::nsPhoenixProfileMigrator()
{
mObserverService = do_GetService("@mozilla.org/observer-service;1");
}
nsPhoenixProfileMigrator::~nsPhoenixProfileMigrator()
{
}
///////////////////////////////////////////////////////////////////////////////
// nsIBrowserProfileMigrator
NS_IMETHODIMP
nsPhoenixProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
{
nsresult rv = NS_OK;
// At this time the only reason for this migrator is to get data across from the
// Phoenix profile directory on initial run, so we don't need to support after-the-fact
// importing.
NS_ASSERTION(aStartup, "Can't migrate from Phoenix/Firebird/Firefox profiles once Firefox is running!");
if (!aStartup)
return NS_ERROR_FAILURE;
if (!mTargetProfile) {
GetProfilePath(aStartup, mTargetProfile);
if (!mTargetProfile) return NS_ERROR_FAILURE;
}
if (!mSourceProfile)
GetSourceProfile(aProfile);
NOTIFY_OBSERVERS(MIGRATION_STARTED, nsnull);
COPY_DATA(CopyPreferences, PR_TRUE, nsIBrowserProfileMigrator::SETTINGS);
COPY_DATA(CopyCookies, PR_TRUE, nsIBrowserProfileMigrator::COOKIES);
COPY_DATA(CopyHistory, PR_TRUE, nsIBrowserProfileMigrator::HISTORY);
COPY_DATA(CopyPasswords, PR_TRUE, nsIBrowserProfileMigrator::PASSWORDS);
COPY_DATA(CopyOtherData, PR_TRUE, nsIBrowserProfileMigrator::OTHERDATA);
COPY_DATA(CopyBookmarks, PR_TRUE, nsIBrowserProfileMigrator::BOOKMARKS);
if (aItems & nsIBrowserProfileMigrator::SETTINGS ||
aItems & nsIBrowserProfileMigrator::COOKIES ||
aItems & nsIBrowserProfileMigrator::PASSWORDS ||
!aItems) {
// Permissions (Images, Cookies, Popups)
rv |= CopyFile(FILE_NAME_SITEPERM_NEW, FILE_NAME_SITEPERM_NEW);
rv |= CopyFile(FILE_NAME_SITEPERM_OLD, FILE_NAME_SITEPERM_OLD);
}
NOTIFY_OBSERVERS(MIGRATION_ENDED, nsnull);
return rv;
}
NS_IMETHODIMP
nsPhoenixProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
PRBool aReplace,
PRUint16* aResult)
{
*aResult = 0;
if (!mSourceProfile) {
GetSourceProfile(aProfile);
if (!mSourceProfile)
return NS_ERROR_FILE_NOT_FOUND;
}
MigrationData data[] = { { ToNewUnicode(FILE_NAME_PREFS),
nsIBrowserProfileMigrator::SETTINGS,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_USER_PREFS),
nsIBrowserProfileMigrator::SETTINGS,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_COOKIES),
nsIBrowserProfileMigrator::COOKIES,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_HISTORY),
nsIBrowserProfileMigrator::HISTORY,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_BOOKMARKS),
nsIBrowserProfileMigrator::BOOKMARKS,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_DOWNLOADS),
nsIBrowserProfileMigrator::OTHERDATA,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_MIMETYPES),
nsIBrowserProfileMigrator::OTHERDATA,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_USERCHROME),
nsIBrowserProfileMigrator::OTHERDATA,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_USERCONTENT),
nsIBrowserProfileMigrator::OTHERDATA,
PR_TRUE },
{ ToNewUnicode(FILE_NAME_FORMHISTORY),
nsIBrowserProfileMigrator::OTHERDATA,
PR_TRUE } };
// Frees file name strings allocated above.
GetMigrateDataFromArray(data, sizeof(data)/sizeof(MigrationData),
aReplace, mSourceProfile, aResult);
// Now locate passwords
nsCString signonsFileName;
GetSignonFileName(aReplace, getter_Copies(signonsFileName));
if (!signonsFileName.IsEmpty()) {
NS_ConvertASCIItoUTF16 fileName(signonsFileName);
nsCOMPtr<nsIFile> sourcePasswordsFile;
mSourceProfile->Clone(getter_AddRefs(sourcePasswordsFile));
sourcePasswordsFile->Append(fileName);
PRBool exists;
sourcePasswordsFile->Exists(&exists);
if (exists)
*aResult |= nsIBrowserProfileMigrator::PASSWORDS;
}
return NS_OK;
}
NS_IMETHODIMP
nsPhoenixProfileMigrator::GetSourceExists(PRBool* aResult)
{
nsCOMPtr<nsISupportsArray> profiles;
GetSourceProfiles(getter_AddRefs(profiles));
if (profiles) {
PRUint32 count;
profiles->Count(&count);
*aResult = count > 0;
}
else
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsPhoenixProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
{
nsCOMPtr<nsISupportsArray> profiles;
GetSourceProfiles(getter_AddRefs(profiles));
if (profiles) {
PRUint32 count;
profiles->Count(&count);
*aResult = count > 1;
}
else
*aResult = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsPhoenixProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
{
if (!mProfileNames && !mProfileLocations) {
mProfileNames = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
mProfileLocations = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
NS_ENSURE_TRUE(mProfileNames && mProfileLocations, NS_ERROR_UNEXPECTED);
// Fills mProfileNames and mProfileLocations
FillProfileDataFromPhoenixRegistry();
}
NS_IF_ADDREF(*aResult = mProfileNames);
return NS_OK;
}
NS_IMETHODIMP
nsPhoenixProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
{
aResult.Truncate();
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////
// nsPhoenixProfileMigrator
nsresult
nsPhoenixProfileMigrator::GetSourceProfile(const PRUnichar* aProfile)
{
PRUint32 count;
mProfileNames->Count(&count);
for (PRUint32 i = 0; i < count; ++i) {
nsCOMPtr<nsISupportsString> str;
mProfileNames->QueryElementAt(i, NS_GET_IID(nsISupportsString),
getter_AddRefs(str));
nsString profileName;
str->GetData(profileName);
if (profileName.Equals(aProfile)) {
mProfileLocations->QueryElementAt(i, NS_GET_IID(nsILocalFile),
getter_AddRefs(mSourceProfile));
break;
}
}
return NS_OK;
}
nsresult
nsPhoenixProfileMigrator::FillProfileDataFromPhoenixRegistry()
{
// Find the Phoenix Registry
nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
nsCOMPtr<nsILocalFile> phoenixRegistry;
#ifdef XP_WIN
fileLocator->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(phoenixRegistry));
phoenixRegistry->Append(NS_LITERAL_STRING("Phoenix"));
phoenixRegistry->Append(NS_LITERAL_STRING("registry.dat"));
#elif defined(XP_MACOSX)
fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(phoenixRegistry));
phoenixRegistry->Append(NS_LITERAL_STRING("Phoenix"));
phoenixRegistry->Append(NS_LITERAL_STRING("Application Registry"));
#elif defined(XP_UNIX)
fileLocator->Get(NS_UNIX_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(phoenixRegistry));
phoenixRegistry->Append(NS_LITERAL_STRING(".phoenix"));
phoenixRegistry->Append(NS_LITERAL_STRING("appreg"));
#elif defined(XP_OS2)
fileLocator->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(phoenixRegistry));
phoenixRegistry->Append(NS_LITERAL_STRING("Phoenix"));
phoenixRegistry->Append(NS_LITERAL_STRING("registry.dat"));
#endif
return GetProfileDataFromRegistry(phoenixRegistry, mProfileNames, mProfileLocations);
}
nsresult
nsPhoenixProfileMigrator::CopyPreferences(PRBool aReplace)
{
nsresult rv = NS_OK;
if (!aReplace)
return rv;
// Prefs files
rv |= CopyFile(FILE_NAME_PREFS, FILE_NAME_PREFS);
rv |= CopyFile(FILE_NAME_USER_PREFS, FILE_NAME_USER_PREFS);
// Security Stuff
rv |= CopyFile(FILE_NAME_CERT8DB, FILE_NAME_CERT8DB);
rv |= CopyFile(FILE_NAME_KEY3DB, FILE_NAME_KEY3DB);
rv |= CopyFile(FILE_NAME_SECMODDB, FILE_NAME_SECMODDB);
// User MIME Type overrides
rv |= CopyFile(FILE_NAME_MIMETYPES, FILE_NAME_MIMETYPES);
rv |= CopyUserStyleSheets();
return rv;
}
nsresult
nsPhoenixProfileMigrator::CopyUserStyleSheets()
{
nsresult rv = NS_OK;
nsCOMPtr<nsIFile> sourceUserContent;
mSourceProfile->Clone(getter_AddRefs(sourceUserContent));
sourceUserContent->Append(DIR_NAME_CHROME);
sourceUserContent->Append(FILE_NAME_USERCONTENT);
PRBool exists = PR_FALSE;
sourceUserContent->Exists(&exists);
if (exists) {
nsCOMPtr<nsIFile> targetUserContent;
mTargetProfile->Clone(getter_AddRefs(targetUserContent));
targetUserContent->Append(DIR_NAME_CHROME);
nsCOMPtr<nsIFile> targetChromeDir;
targetUserContent->Clone(getter_AddRefs(targetChromeDir));
targetUserContent->Append(FILE_NAME_USERCONTENT);
targetUserContent->Exists(&exists);
if (exists)
targetUserContent->Remove(PR_FALSE);
rv |= sourceUserContent->CopyTo(targetChromeDir, FILE_NAME_USERCONTENT);
}
nsCOMPtr<nsIFile> sourceUserChrome;
mSourceProfile->Clone(getter_AddRefs(sourceUserChrome));
sourceUserChrome->Append(DIR_NAME_CHROME);
sourceUserChrome->Append(FILE_NAME_USERCHROME);
sourceUserChrome->Exists(&exists);
if (exists) {
nsCOMPtr<nsIFile> targetUserChrome;
mTargetProfile->Clone(getter_AddRefs(targetUserChrome));
targetUserChrome->Append(DIR_NAME_CHROME);
nsCOMPtr<nsIFile> targetChromeDir;
targetUserChrome->Clone(getter_AddRefs(targetChromeDir));
targetUserChrome->Append(FILE_NAME_USERCHROME);
targetUserChrome->Exists(&exists);
if (exists)
targetUserChrome->Remove(PR_FALSE);
rv |= sourceUserChrome->CopyTo(targetChromeDir, FILE_NAME_USERCHROME);
}
return rv;
}
nsresult
nsPhoenixProfileMigrator::CopyCookies(PRBool aReplace)
{
return aReplace ? CopyFile(FILE_NAME_COOKIES, FILE_NAME_COOKIES) : NS_OK;
}
nsresult
nsPhoenixProfileMigrator::CopyHistory(PRBool aReplace)
{
return aReplace ? CopyFile(FILE_NAME_HISTORY, FILE_NAME_HISTORY) : NS_OK;
}
nsresult
nsPhoenixProfileMigrator::CopyPasswords(PRBool aReplace)
{
nsresult rv;
nsCString signonsFileName;
if (!aReplace)
return NS_OK;
// Find out what the signons file was called, this is stored in a pref
// in Seamonkey.
nsCOMPtr<nsIPrefService> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
psvc->ResetPrefs();
nsCOMPtr<nsIFile> seamonkeyPrefsFile;
mSourceProfile->Clone(getter_AddRefs(seamonkeyPrefsFile));
seamonkeyPrefsFile->Append(FILE_NAME_PREFS);
psvc->ReadUserPrefs(seamonkeyPrefsFile);
nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(psvc));
rv = branch->GetCharPref("signon.SignonFileName", getter_Copies(signonsFileName));
if (signonsFileName.IsEmpty())
return NS_ERROR_FILE_NOT_FOUND;
NS_ConvertASCIItoUTF16 fileName(signonsFileName);
return aReplace ? CopyFile(fileName, fileName) : NS_OK;
}
nsresult
nsPhoenixProfileMigrator::CopyBookmarks(PRBool aReplace)
{
// This overwrites the defaults. This might be ok in this instance.
return aReplace ? CopyFile(FILE_NAME_BOOKMARKS, FILE_NAME_BOOKMARKS) : NS_OK;
}
nsresult
nsPhoenixProfileMigrator::CopyOtherData(PRBool aReplace)
{
if (!aReplace)
return NS_OK;
nsresult rv = NS_OK;
rv |= CopyFile(FILE_NAME_DOWNLOADS, FILE_NAME_DOWNLOADS);
rv |= CopyFile(FILE_NAME_LOCALSTORE, FILE_NAME_LOCALSTORE);
rv |= CopyFile(FILE_NAME_FORMHISTORY, FILE_NAME_FORMHISTORY);
return rv;
}

View File

@ -1,87 +0,0 @@
/* -*- 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 The Browser Profile Migrator.
*
* The Initial Developer of the Original Code is Ben Goodger.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@bengoodger.com>
*
* 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 phoenixprofilemigrator___h___
#define phoenixprofilemigrator___h___
#include "nsIBrowserProfileMigrator.h"
#include "nsILocalFile.h"
#include "nsIObserverService.h"
#include "nsISupportsArray.h"
#include "nsNetscapeProfileMigratorBase.h"
#include "nsStringAPI.h"
class nsIFile;
class nsIPrefBranch;
class nsIPrefService;
class nsPhoenixProfileMigrator : public nsNetscapeProfileMigratorBase,
public nsIBrowserProfileMigrator
{
public:
NS_DECL_NSIBROWSERPROFILEMIGRATOR
NS_DECL_ISUPPORTS
nsPhoenixProfileMigrator();
virtual ~nsPhoenixProfileMigrator();
public:
static nsresult SetImage(void* aTransform, nsIPrefBranch* aBranch);
static nsresult SetCookie(void* aTransform, nsIPrefBranch* aBranch);
static nsresult SetDownloadManager(void* aTransform, nsIPrefBranch* aBranch);
protected:
nsresult FillProfileDataFromPhoenixRegistry();
nsresult GetSourceProfile(const PRUnichar* aProfile);
nsresult CopyPreferences(PRBool aReplace);
nsresult CopyUserStyleSheets();
nsresult CopyCookies(PRBool aReplace);
nsresult CopyHistory(PRBool aReplace);
nsresult CopyPasswords(PRBool aReplace);
nsresult CopyBookmarks(PRBool aReplace);
nsresult CopyOtherData(PRBool aReplace);
private:
nsCOMPtr<nsISupportsArray> mProfileNames;
nsCOMPtr<nsISupportsArray> mProfileLocations;
nsCOMPtr<nsIObserverService> mObserverService;
};
#endif

View File

@ -160,13 +160,9 @@ NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
#ifdef XP_WIN
#define INTERNAL_NAME_FIREBIRD "firebird"
#define INTERNAL_NAME_FIREFOX "firefox"
#define INTERNAL_NAME_PHOENIX "phoenix"
#define INTERNAL_NAME_IEXPLORE "iexplore"
#define INTERNAL_NAME_MOZILLA_SUITE "apprunner"
#define INTERNAL_NAME_SEAMONKEY "seamonkey"
#define INTERNAL_NAME_DOGBERT "netscape"
#define INTERNAL_NAME_OPERA "opera"
#endif
@ -252,22 +248,11 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
aKey = "seamonkey";
return NS_OK;
}
if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_DOGBERT)) {
aKey = "dogbert";
return NS_OK;
}
if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
aKey = "opera";
return NS_OK;
}
// Migrate data from any existing Application Data\Phoenix\* installations.
if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_FIREBIRD) ||
internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_FIREFOX) ||
internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_PHOENIX)) {
aKey = "phoenix";
return NS_OK;
}
#else
PRBool exists = PR_FALSE;
#define CHECK_MIGRATOR(browser) do {\
@ -281,9 +266,7 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
#if defined(XP_MACOSX)
CHECK_MIGRATOR("safari");
CHECK_MIGRATOR("macie");
#endif
CHECK_MIGRATOR("phoenix");
CHECK_MIGRATOR("seamonkey");
CHECK_MIGRATOR("opera");

View File

@ -60,7 +60,7 @@ protected:
nsCOMPtr<nsIBrowserProfileMigrator>& bpm);
/**
* Import profiles from ~/.firefox/ or ~/.phoenix/
* Import profiles from ~/.firefox/
* @return PR_TRUE if any profiles imported.
*/
PRBool ImportRegistryProfiles(const nsACString& aAppName);

View File

@ -1269,29 +1269,5 @@ nsSafariProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
return NS_OK;
}
#ifdef __LP64__
return NS_ERROR_FAILURE;
#else
// Couldn't find the home page in com.apple.safai, time to check
// com.apple.internetconfig for this key!
ICInstance internetConfig;
OSStatus error = ::ICStart(&internetConfig, 'FRFX');
if (error != noErr)
return NS_ERROR_FAILURE;
ICAttr dummy;
Str255 homePagePValue;
long prefSize = sizeof(homePagePValue);
error = ::ICGetPref(internetConfig, kICWWWHomePage, &dummy,
homePagePValue, &prefSize);
if (error != noErr)
return NS_ERROR_FAILURE;
char homePageValue[256] = "";
CopyPascalStringToC((ConstStr255Param)homePagePValue, homePageValue);
aResult.Assign(homePageValue);
::ICStop(internetConfig);
return NS_OK;
#endif
}

View File

@ -749,7 +749,8 @@ PlacesViewBase.prototype = {
aPopup._endOptOpenAllInTabs = document.createElement("menuitem");
aPopup._endOptOpenAllInTabs.className = "openintabs-menuitem";
aPopup._endOptOpenAllInTabs.setAttribute("oncommand",
"PlacesUIUtils.openContainerNodeInTabs(this.parentNode._placesNode, event);");
"PlacesUIUtils.openContainerNodeInTabs(this.parentNode._placesNode, event, " +
"PlacesUIUtils.getViewForNode(this));");
aPopup._endOptOpenAllInTabs.setAttribute("onclick",
"checkForMiddleClick(this, event); event.stopPropagation();");
aPopup._endOptOpenAllInTabs.setAttribute("label",

View File

@ -187,12 +187,12 @@
<toolbox id="placesToolbox">
<toolbar class="chromeclass-toolbar" id="placesToolbar" align="center">
<toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
<toolbarbutton id="back-button"
command="OrganizerCommand:Back"
tooltiptext="&backButton.tooltip;"
disabled="true"/>
<toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
<toolbarbutton id="forward-button"
command="OrganizerCommand:Forward"
tooltiptext="&forwardButton.tooltip;"
disabled="true"/>

View File

@ -774,8 +774,9 @@ var PlacesUIUtils = {
// Prefer the caller window if it's a browser window, otherwise use
// the top browser window.
var browserWindow =
aWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser" ?
var browserWindow = null;
browserWindow =
aWindow && aWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser" ?
aWindow : this._getTopBrowserWin();
// whereToOpenLink doesn't return "window" when there's no browser window
@ -783,8 +784,16 @@ var PlacesUIUtils = {
var where = browserWindow ?
browserWindow.whereToOpenLink(aEvent, false, true) : "window";
if (where == "window") {
aWindow.openDialog(aWindow.getBrowserURL(), "_blank",
"chrome,all,dialog=no", urls.join("|"));
// There is no browser window open, thus open a new one.
var uriList = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
uriList.data = urls.join("|");
var args = Cc["@mozilla.org/supports-array;1"].
createInstance(Ci.nsISupportsArray);
args.AppendElement(uriList);
browserWindow = Services.ww.openWindow(aWindow,
"chrome://browser/content/browser.xul",
null, "chrome,dialog=no,all", args);
return;
}

View File

@ -247,10 +247,9 @@ var bookmarksObserver = {
var index = null;
[node, index] = getNodeForTreeItem(aItemId, gLibrary.PlacesOrganizer._places);
// Left pane should not be updated for normal bookmarks or separators.
var type = PlacesUtils.bookmarks.getItemType(aItemId);
switch (type) {
switch (aItemType) {
case PlacesUtils.bookmarks.TYPE_BOOKMARK:
var uriString = PlacesUtils.bookmarks.getBookmarkURI(aItemId).spec;
var uriString = aURI.spec;
var isQuery = uriString.substr(0, 6) == "place:";
if (isQuery) {
isnot(node, null, "Found new Places node in left pane");
@ -276,13 +275,12 @@ var bookmarksObserver = {
onItemMoved: function(aItemId,
aOldFolderId, aOldIndex,
aNewFolderId, aNewIndex) {
aNewFolderId, aNewIndex, aItemType) {
var node = null;
var index = null;
[node, index] = getNodeForTreeItem(aItemId, gLibrary.PlacesOrganizer._places);
// Left pane should not be updated for normal bookmarks or separators.
var type = PlacesUtils.bookmarks.getItemType(aItemId);
switch (type) {
switch (aItemType) {
case PlacesUtils.bookmarks.TYPE_BOOKMARK:
var uriString = PlacesUtils.bookmarks.getBookmarkURI(aItemId).spec;
var isQuery = uriString.substr(0, 6) == "place:";

View File

@ -319,11 +319,13 @@ var bookmarksObserver = {
onItemVisited: function() {},
onItemChanged: function PSB_onItemChanged(aItemId, aProperty,
aIsAnnotationProperty, aNewValue) {
aIsAnnotationProperty, aNewValue,
aLastModified, aItemType,
aParentId) {
if (aProperty !== "title")
return;
var views = getViewsForFolder(PlacesUtils.bookmarks.getFolderIdForItem(aItemId));
var views = getViewsForFolder(aParentId);
ok(views.length > 0, "Found affected views (" + views.length + "): " + views);
// Check that item has been moved in the correct position.

View File

@ -0,0 +1,23 @@
[DEFAULT]
head = head_bookmarks.js
tail =
[test_384370.js]
[test_398914.js]
[test_421483.js]
[test_457441-import-export-corrupt-bookmarks-html.js]
[test_bookmarksRestoreNotification.js]
[test_bookmarks_html.js]
[test_browserGlue_corrupt.js]
[test_browserGlue_corrupt_nobackup.js]
[test_browserGlue_corrupt_nobackup_default.js]
[test_browserGlue_distribution.js]
[test_browserGlue_migrate.js]
[test_browserGlue_prefs.js]
[test_browserGlue_restore.js]
[test_browserGlue_shutdown.js]
[test_browserGlue_smartBookmarks.js]
[test_clearHistory_shutdown.js]
[test_leftpane_corruption_handling.js]
[test_placesTxn.js]
[test_txnGUIDs.js]

View File

@ -0,0 +1,3 @@
.site {
-moz-binding: url("chrome://browser/content/preferences/aboutPermissions.xml#site");
}

View File

@ -0,0 +1,810 @@
/* ***** 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 about:permissions code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Margaret Leibovic <margaret.leibovic@gmail.com>
*
* 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 ***** */
let Ci = Components.interfaces;
let Cc = Components.classes;
let Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/PluralForm.jsm");
Cu.import("resource://gre/modules/DownloadUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
let gFaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
getService(Ci.nsIFaviconService);
let gPlacesDatabase = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsPIPlacesDatabase).
DBConnection.
clone(true);
let gSitesStmt = gPlacesDatabase.createAsyncStatement(
"SELECT get_unreversed_host(rev_host) AS host " +
"FROM moz_places " +
"WHERE rev_host > '.' " +
"AND visit_count > 0 " +
"GROUP BY rev_host " +
"ORDER BY MAX(frecency) DESC " +
"LIMIT :limit");
let gVisitStmt = gPlacesDatabase.createAsyncStatement(
"SELECT SUM(visit_count) AS count " +
"FROM moz_places " +
"WHERE rev_host = :rev_host");
/**
* Permission types that should be tested with testExactPermission, as opposed
* to testPermission. This is based on what consumers use to test these permissions.
*/
let TEST_EXACT_PERM_TYPES = ["geo"];
/**
* Site object represents a single site, uniquely identified by a host.
*/
function Site(host) {
this.host = host;
this.listitem = null;
this.httpURI = NetUtil.newURI("http://" + this.host);
this.httpsURI = NetUtil.newURI("https://" + this.host);
this._favicon = "";
}
Site.prototype = {
/**
* Gets the favicon to use for the site. This will return the default favicon
* if there is no favicon stored for the site.
*
* @return A favicon image URL.
*/
get favicon() {
if (!this._favicon) {
// TODO: Bug 657961: Make this async when bug 655270 is fixed.
try {
// First try to see if a favicon is stored for the http URI.
this._favicon = gFaviconService.getFaviconForPage(this.httpURI).spec;
} catch (e) {
// getFaviconImageForPage returns the default favicon if no stored favicon is found.
this._favicon = gFaviconService.getFaviconImageForPage(this.httpsURI).spec;
}
}
return this._favicon;
},
/**
* Gets the number of history visits for the site.
*
* @param aCallback
* A function that takes the visit count (a number) as a parameter.
*/
getVisitCount: function Site_getVisitCount(aCallback) {
let rev_host = this.host.split("").reverse().join("") + ".";
gVisitStmt.params.rev_host = rev_host;
gVisitStmt.executeAsync({
handleResult: function(aResults) {
let row = aResults.getNextRow();
let count = row.getResultByName("count") || 0;
try {
aCallback(count);
} catch (e) {
Cu.reportError("AboutPermissions: " + e);
}
},
handleError: function(aError) {
Cu.reportError("AboutPermissions: " + aError);
},
handleCompletion: function(aReason) {
}
});
},
/**
* Gets the permission value stored for a specified permission type.
*
* @param aType
* The permission type string stored in permission manager.
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
* @param aResultObj
* An object that stores the permission value set for aType.
*
* @return A boolean indicating whether or not a permission is set.
*/
getPermission: function Site_getPermission(aType, aResultObj) {
let permissionValue;
if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) {
permissionValue = Services.perms.testPermission(this.httpURI, aType);
} else {
permissionValue = Services.perms.testExactPermission(this.httpURI, aType);
}
aResultObj.value = permissionValue;
return permissionValue != Ci.nsIPermissionManager.UNKNOWN_ACTION;
},
/**
* Sets a permission for the site given a permission type and value.
*
* @param aType
* The permission type string stored in permission manager.
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
* @param aPerm
* The permission value to set for the permission type. This should
* be one of the constants defined in nsIPermissionManager.
*/
setPermission: function Site_setPermission(aType, aPerm) {
// Using httpURI is kind of bogus, but the permission manager stores the
// permission for the host, so the right thing happens in the end.
Services.perms.add(this.httpURI, aType, aPerm);
},
/**
* Clears a user-set permission value for the site given a permission type.
*
* @param aType
* The permission type string stored in permission manager.
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
*/
clearPermission: function Site_clearPermission(aType) {
Services.perms.remove(this.host, aType);
},
/**
* Gets cookies stored for the site. This does not return cookies stored
* for the base domain, only the exact hostname stored for the site.
*
* @return An array of the cookies set for the site.
*/
get cookies() {
let cookies = [];
let enumerator = Services.cookies.getCookiesFromHost(this.host);
while (enumerator.hasMoreElements()) {
let cookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
// getCookiesFromHost returns cookies for base domain, but we only want
// the cookies for the exact domain.
if (cookie.rawHost == this.host) {
cookies.push(cookie);
}
}
return cookies;
},
/**
* Removes a set of specific cookies from the browser.
*/
clearCookies: function Site_clearCookies() {
this.cookies.forEach(function(aCookie) {
Services.cookies.remove(aCookie.host, aCookie.name, aCookie.path, false);
});
},
/**
* Gets logins stored for the site.
*
* @return An array of the logins stored for the site.
*/
get logins() {
// There could be more logins for different schemes/ports, but this covers
// the vast majority of cases.
let httpLogins = Services.logins.findLogins({}, this.httpURI.prePath, "", null);
let httpsLogins = Services.logins.findLogins({}, this.httpsURI.prePath, "", null);
return httpLogins.concat(httpsLogins);
},
get loginSavingEnabled() {
// Only say that login saving is blocked if it is blocked for both http and https.
return Services.logins.getLoginSavingEnabled(this.httpURI.prePath) &&
Services.logins.getLoginSavingEnabled(this.httpsURI.prePath);
},
set loginSavingEnabled(isEnabled) {
Services.logins.setLoginSavingEnabled(this.httpURI.prePath, isEnabled);
Services.logins.setLoginSavingEnabled(this.httpsURI.prePath, isEnabled);
},
/**
* Removes all data from the browser corresponding to the site.
*/
forgetSite: function Site_forgetSite() {
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
pb.removeDataFromDomain(this.host);
}
}
/**
* PermissionDefaults object keeps track of default permissions for sites based
* on global preferences.
*
* Inspired by pageinfo/permissions.js
*/
let PermissionDefaults = {
UNKNOWN: Ci.nsIPermissionManager.UNKNOWN_ACTION, // 0
ALLOW: Ci.nsIPermissionManager.ALLOW_ACTION, // 1
DENY: Ci.nsIPermissionManager.DENY_ACTION, // 2
SESSION: Ci.nsICookiePermission.ACCESS_SESSION, // 8
get password() {
if (Services.prefs.getBoolPref("signon.rememberSignons")) {
return this.ALLOW;
}
return this.DENY;
},
set password(aValue) {
let value = (aValue == this.ALLOW);
Services.prefs.setBoolPref("signon.rememberSignons", value);
},
// For use with network.cookie.* prefs.
COOKIE_ACCEPT: 0,
COOKIE_DENY: 2,
COOKIE_NORMAL: 0,
COOKIE_SESSION: 2,
get cookie() {
if (Services.prefs.getIntPref("network.cookie.cookieBehavior") == this.COOKIE_DENY) {
return this.DENY;
}
if (Services.prefs.getIntPref("network.cookie.lifetimePolicy") == this.COOKIE_DENY) {
return this.SESSION;
}
return this.ALLOW;
},
set cookie(aValue) {
let value = (aValue == this.DENY) ? this.COOKIE_DENY : this.COOKIE_ACCEPT;
Services.prefs.setIntPref("network.cookie.cookieBehavior", value);
let lifetimeValue = aValue == this.SESSION ? this.COOKIE_SESSION :
this.COOKIE_NORMAL;
Services.prefs.setIntPref("network.cookie.lifetimePolicy", lifetimeValue);
},
get geo() {
if (!Services.prefs.getBoolPref("geo.enabled")) {
return this.DENY;
}
// We always ask for permission to share location with a specific site, so
// there is no global ALLOW.
return this.UNKNOWN;
},
set geo(aValue) {
let value = (aValue == this.ALLOW);
Services.prefs.setBoolPref("geo.enabled", value);
},
get indexedDB() {
if (!Services.prefs.getBoolPref("dom.indexedDB.enabled")) {
return this.DENY;
}
// We always ask for permission to enable indexedDB storage for a specific
// site, so there is no global ALLOW.
return this.UNKNOWN;
},
set indexedDB(aValue) {
let value = (aValue == this.ALLOW);
Services.prefs.setBoolPref("dom.indexedDB.enabled", value);
},
get popup() {
if (Services.prefs.getBoolPref("dom.disable_open_during_load")) {
return this.DENY;
}
return this.ALLOW;
},
set popup(aValue) {
let value = (aValue == this.DENY);
Services.prefs.setBoolPref("dom.disable_open_during_load", value);
}
}
/**
* AboutPermissions manages the about:permissions page.
*/
let AboutPermissions = {
/**
* Number of sites to return from the places database.
*/
PLACES_SITES_LIMIT: 50,
/**
* Stores a mapping of host strings to Site objects.
*/
_sites: {},
sitesList: null,
_selectedSite: null,
/**
* This reflects the permissions that we expose in the UI. These correspond
* to permission type strings in the permission manager, PermissionDefaults,
* and element ids in aboutPermissions.xul.
*
* Potential future additions: "sts/use", "sts/subd"
*/
_supportedPermissions: ["password", "cookie", "geo", "indexedDB", "popup"],
/**
* Permissions that don't have a global "Allow" option.
*/
_noGlobalAllow: ["geo", "indexedDB"],
_stringBundle: Services.strings.
createBundle("chrome://browser/locale/preferences/aboutPermissions.properties"),
/**
* Called on page load.
*/
init: function() {
this.sitesList = document.getElementById("sites-list");
this.getSitesFromPlaces();
this.enumerateServices();
// Attach observers in case data changes while the page is open.
Services.prefs.addObserver("signon.rememberSignons", this, false);
Services.prefs.addObserver("network.cookie.", this, false);
Services.prefs.addObserver("geo.enabled", this, false);
Services.prefs.addObserver("dom.indexedDB.enabled", this, false);
Services.prefs.addObserver("dom.disable_open_during_load", this, false);
Services.obs.addObserver(this, "perm-changed", false);
Services.obs.addObserver(this, "passwordmgr-storage-changed", false);
Services.obs.addObserver(this, "cookie-changed", false);
Services.obs.addObserver(this, "browser:purge-domain-data", false);
this._observersInitialized = true;
},
/**
* Called on page unload.
*/
cleanUp: function() {
if (this._observersInitialized) {
Services.prefs.removeObserver("signon.rememberSignons", this, false);
Services.prefs.removeObserver("network.cookie.", this, false);
Services.prefs.removeObserver("geo.enabled", this, false);
Services.prefs.removeObserver("dom.indexedDB.enabled", this, false);
Services.prefs.removeObserver("dom.disable_open_during_load", this, false);
Services.obs.removeObserver(this, "perm-changed", false);
Services.obs.removeObserver(this, "passwordmgr-storage-changed", false);
Services.obs.removeObserver(this, "cookie-changed", false);
Services.obs.removeObserver(this, "browser:purge-domain-data", false);
}
gSitesStmt.finalize();
gVisitStmt.finalize();
},
observe: function (aSubject, aTopic, aData) {
switch(aTopic) {
case "perm-changed":
// Permissions changes only affect individual sites.
if (!this._selectedSite) {
break;
}
// aSubject is null when nsIPermisionManager::removeAll() is called.
if (!aSubject) {
this._supportedPermissions.forEach(function(aType){
this.updatePermission(aType);
}, this);
break;
}
let permission = aSubject.QueryInterface(Ci.nsIPermission);
// We can't compare selectedSite.host and permission.host here because
// we need to handle the case where a parent domain was changed in a
// way that affects the subdomain.
if (this._supportedPermissions.indexOf(permission.type) != -1) {
this.updatePermission(permission.type);
}
break;
case "nsPref:changed":
this._supportedPermissions.forEach(function(aType){
this.updatePermission(aType);
}, this);
break;
case "passwordmgr-storage-changed":
this.updatePermission("password");
if (this._selectedSite) {
this.updatePasswordsCount();
}
break;
case "cookie-changed":
if (this._selectedSite) {
this.updateCookiesCount();
}
break;
case "browser:purge-domain-data":
this.deleteFromSitesList(aData);
break;
}
},
/**
* Creates Site objects for the top-frecency sites in the places database and stores
* them in _sites. The number of sites created is controlled by PLACES_SITES_LIMIT.
*/
getSitesFromPlaces: function() {
gSitesStmt.params.limit = this.PLACES_SITES_LIMIT;
gSitesStmt.executeAsync({
handleResult: function(aResults) {
let row;
while (row = aResults.getNextRow()) {
let host = row.getResultByName("host");
AboutPermissions.addHost(host);
}
},
handleError: function(aError) {
Cu.reportError("AboutPermissions: " + aError);
},
handleCompletion: function(aReason) {
// Notify oberservers for testing purposes.
Services.obs.notifyObservers(null, "browser-permissions-initialized", null);
}
});
},
/**
* Finds sites that have non-default permissions and creates Site objects for
* them if they are not already stored in _sites.
*/
enumerateServices: function() {
let logins = Services.logins.getAllLogins();
logins.forEach(function(aLogin) {
try {
// aLogin.hostname is a string in origin URL format (e.g. "http://foo.com")
let uri = NetUtil.newURI(aLogin.hostname);
this.addHost(uri.host);
} catch (e) {
// newURI will throw for add-ons logins stored in chrome:// URIs
}
}, this);
let disabledHosts = Services.logins.getAllDisabledHosts();
disabledHosts.forEach(function(aHostname) {
try {
// aHostname is a string in origin URL format (e.g. "http://foo.com")
let uri = NetUtil.newURI(aHostname);
this.addHost(uri.host);
} catch (e) {
// newURI will throw for add-ons logins stored in chrome:// URIs
}
}, this);
let (enumerator = Services.perms.enumerator) {
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
// Only include sites with exceptions set for supported permission types.
if (this._supportedPermissions.indexOf(permission.type) != -1) {
this.addHost(permission.host);
}
}
}
},
/**
* Creates a new Site and adds it to _sites if it's not already there.
*
* @param aHost
* A host string.
*/
addHost: function(aHost) {
if (aHost in this._sites) {
return;
}
let site = new Site(aHost);
this._sites[aHost] = site;
this.addToSitesList(site);
},
/**
* Populates sites-list richlistbox with data from Site object.
*
* @param aSite
* A Site object.
*/
addToSitesList: function(aSite) {
let item = document.createElement("richlistitem");
item.setAttribute("class", "site");
item.setAttribute("value", aSite.host);
item.setAttribute("favicon", aSite.favicon);
aSite.listitem = item;
this.sitesList.appendChild(item);
},
/**
* Hides sites in richlistbox based on search text in sites-filter textbox.
*/
filterSitesList: function() {
let siteItems = this.sitesList.children;
let filterValue = document.getElementById("sites-filter").value.toLowerCase();
if (filterValue == "") {
for (let i = 0; i < siteItems.length; i++) {
siteItems[i].collapsed = false;
}
return;
}
for (let i = 0; i < siteItems.length; i++) {
let siteValue = siteItems[i].value.toLowerCase();
siteItems[i].collapsed = siteValue.indexOf(filterValue) == -1;
}
},
/**
* Removes all evidence of the selected site. The "forget this site" observer
* will call deleteFromSitesList to update the UI.
*/
forgetSite: function() {
this._selectedSite.forgetSite();
},
/**
* Deletes sites for a host and all of its sub-domains. Removes these sites
* from _sites and removes their corresponding elements from the DOM.
*
* @param aHost
* The host string corresponding to the site to delete.
*/
deleteFromSitesList: function(aHost) {
for each (let site in this._sites) {
if (site.host.hasRootDomain(aHost)) {
if (site == this._selectedSite) {
// Replace site-specific interface with "All Sites" interface.
this.sitesList.selectedItem = document.getElementById("all-sites-item");
}
this.sitesList.removeChild(site.listitem);
delete this._sites[site.host];
}
}
},
/**
* Shows interface for managing site-specific permissions.
*/
onSitesListSelect: function(event) {
if (event.target.selectedItem.id == "all-sites-item") {
// Clear the header label value from the previously selected site.
document.getElementById("site-label").value = "";
this.manageDefaultPermissions();
return;
}
let host = event.target.value;
let site = this._selectedSite = this._sites[host];
document.getElementById("site-label").value = host;
document.getElementById("header-deck").selectedPanel =
document.getElementById("site-header");
this.updateVisitCount();
this.updatePermissionsBox();
},
/**
* Shows interface for managing default permissions. This corresponds to
* the "All Sites" list item.
*/
manageDefaultPermissions: function() {
this._selectedSite = null;
document.getElementById("header-deck").selectedPanel =
document.getElementById("defaults-header");
this.updatePermissionsBox();
},
/**
* Updates permissions interface based on selected site.
*/
updatePermissionsBox: function() {
this._supportedPermissions.forEach(function(aType){
this.updatePermission(aType);
}, this);
this.updatePasswordsCount();
this.updateCookiesCount();
},
/**
* Sets menulist for a given permission to the correct state, based on the
* stored permission.
*
* @param aType
* The permission type string stored in permission manager.
* e.g. "cookie", "geo", "indexedDB", "popup", "image"
*/
updatePermission: function(aType) {
let allowItem = document.getElementById(aType + "-" + PermissionDefaults.ALLOW);
if (!this._selectedSite &&
this._noGlobalAllow.indexOf(aType) != -1) {
allowItem.hidden = true;
return;
}
allowItem.hidden = false;
let permissionMenulist = document.getElementById(aType + "-menulist");
let permissionValue;
if (!this._selectedSite) {
// If there is no selected site, we are updating the default permissions interface.
permissionValue = PermissionDefaults[aType];
} else if (aType == "password") {
// Services.logins.getLoginSavingEnabled already looks at the default
// permission, so we don't need to.
permissionValue = this._selectedSite.loginSavingEnabled ?
PermissionDefaults.ALLOW : PermissionDefaults.DENY;
} else {
let result = {};
permissionValue = this._selectedSite.getPermission(aType, result) ?
result.value : PermissionDefaults[aType];
}
permissionMenulist.selectedItem = document.getElementById(aType + "-" + permissionValue);
},
onPermissionCommand: function(event) {
let permissionType = event.currentTarget.getAttribute("type");
let permissionValue = event.target.value;
if (!this._selectedSite) {
// If there is no selected site, we are setting the default permission.
PermissionDefaults[permissionType] = permissionValue;
} else if (permissionType == "password") {
let isEnabled = permissionValue == PermissionDefaults.ALLOW;
this._selectedSite.loginSavingEnabled = isEnabled;
} else {
this._selectedSite.setPermission(permissionType, permissionValue);
}
},
updateVisitCount: function() {
this._selectedSite.getVisitCount(function(aCount) {
let visitForm = AboutPermissions._stringBundle.GetStringFromName("visitCount");
let visitLabel = PluralForm.get(aCount, visitForm)
.replace("#1", aCount);
document.getElementById("site-visit-count").value = visitLabel;
});
},
updatePasswordsCount: function() {
if (!this._selectedSite) {
document.getElementById("passwords-count").hidden = true;
document.getElementById("passwords-manage-all-button").hidden = false;
return;
}
let passwordsCount = this._selectedSite.logins.length;
let passwordsForm = this._stringBundle.GetStringFromName("passwordsCount");
let passwordsLabel = PluralForm.get(passwordsCount, passwordsForm)
.replace("#1", passwordsCount);
document.getElementById("passwords-label").value = passwordsLabel;
document.getElementById("passwords-manage-button").disabled = (passwordsCount < 1);
document.getElementById("passwords-manage-all-button").hidden = true;
document.getElementById("passwords-count").hidden = false;
},
/**
* Opens password manager dialog.
*/
managePasswords: function() {
let selectedHost = "";
if (this._selectedSite) {
selectedHost = this._selectedSite.host;
}
let win = Services.wm.getMostRecentWindow("Toolkit:PasswordManager");
if (win) {
win.setFilter(selectedHost);
win.focus();
} else {
window.openDialog("chrome://passwordmgr/content/passwordManager.xul",
"Toolkit:PasswordManager", "", {filterString : selectedHost});
}
},
updateCookiesCount: function() {
if (!this._selectedSite) {
document.getElementById("cookies-count").hidden = true;
document.getElementById("cookies-clear-all-button").hidden = false;
document.getElementById("cookies-manage-all-button").hidden = false;
return;
}
let cookiesCount = this._selectedSite.cookies.length;
let cookiesForm = this._stringBundle.GetStringFromName("cookiesCount");
let cookiesLabel = PluralForm.get(cookiesCount, cookiesForm)
.replace("#1", cookiesCount);
document.getElementById("cookies-label").value = cookiesLabel;
document.getElementById("cookies-clear-button").disabled = (cookiesCount < 1);
document.getElementById("cookies-manage-button").disabled = (cookiesCount < 1);
document.getElementById("cookies-clear-all-button").hidden = true;
document.getElementById("cookies-manage-all-button").hidden = true;
document.getElementById("cookies-count").hidden = false;
},
/**
* Clears cookies for the selected site.
*/
clearCookies: function() {
if (!this._selectedSite) {
return;
}
let site = this._selectedSite;
site.clearCookies(site.cookies);
this.updateCookiesCount();
},
/**
* Opens cookie manager dialog.
*/
manageCookies: function() {
let selectedHost = "";
if (this._selectedSite) {
selectedHost = this._selectedSite.host;
}
let win = Services.wm.getMostRecentWindow("Browser:Cookies");
if (win) {
win.gCookiesWindow.setFilter(selectedHost);
win.focus();
} else {
window.openDialog("chrome://browser/content/preferences/cookies.xul",
"Browser:Cookies", "", {filterString : selectedHost});
}
}
}
// See nsPrivateBrowsingService.js
String.prototype.hasRootDomain = function hasRootDomain(aDomain) {
let index = this.indexOf(aDomain);
if (index == -1)
return false;
if (this == aDomain)
return true;
let prevChar = this[index - 1];
return (index == (this.length - aDomain.length)) &&
(prevChar == "." || prevChar == "/");
}

View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<!-- ***** 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 about:permssions code.
-
- The Initial Developer of the Original Code is
- the Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2011
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Margaret Leibovic <margaret.leibovic@gmail.com>
-
- 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 LGPL or the GPL. 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 ***** -->
<!DOCTYPE bindings>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="site" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<content>
<xul:hbox class="site-container" align="center">
<xul:image xbl:inherits="src=favicon" class="site-favicon"/>
<xul:label xbl:inherits="value,selected" class="site-domain" crop="end"/>
</xul:hbox>
</content>
</binding>
</bindings>

View File

@ -0,0 +1,228 @@
<?xml version="1.0"?>
<!-- ***** 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 about:permssions code.
-
- The Initial Developer of the Original Code is
- the Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2011
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Margaret Leibovic <margaret.leibovic@gmail.com>
-
- 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 LGPL or the GPL. 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 ***** -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/preferences/aboutPermissions.css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/aboutPermissions.css"?>
<!DOCTYPE page [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
%brandDTD;
<!ENTITY % aboutPermissionsDTD SYSTEM "chrome://browser/locale/preferences/aboutPermissions.dtd" >
%aboutPermissionsDTD;
]>
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
id="permissions-page" title="&permissionsManager.title;"
onload="AboutPermissions.init();"
onunload="AboutPermissions.cleanUp();"
role="application">
<script type="application/javascript"
src="chrome://browser/content/preferences/aboutPermissions.js"/>
<hbox flex="1" id="permissions-content">
<vbox id="sites-box">
<textbox id="sites-filter"
emptytext="&sites.search;"
oncommand="AboutPermissions.filterSitesList();"
type="search"/>
<richlistbox id="sites-list"
flex="1"
class="list"
onselect="AboutPermissions.onSitesListSelect(event);">
<richlistitem id="all-sites-item"
class="site"
value="&sites.allSites;"/>
</richlistbox>
</vbox>
<vbox id="permissions-box" flex="1">
<deck id="header-deck">
<hbox id="site-header" class="pref-item" align="center">
<description id="site-description">
&header.site.start;<label id="site-label"/>&header.site.end;
</description>
<label id="site-visit-count"/>
<spacer flex="1"/>
<button id="forget-site-button"
label="&permissions.forgetSite;"
oncommand="AboutPermissions.forgetSite();"/>
</hbox>
<hbox id="defaults-header" class="pref-item" align="center">
<description id="defaults-description">
&header.defaults;
</description>
</hbox>
</deck>
<!-- Passwords -->
<hbox id="password-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="password"/>
<vbox>
<label class="pref-title" value="&password.label;"/>
<hbox align="center">
<menulist id="password-menulist"
class="pref-menulist"
type="password"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="password-1" value="1" label="&permission.allow;"/>
<menuitem id="password-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
<button id="passwords-manage-all-button"
label="&password.manage;"
oncommand="AboutPermissions.managePasswords();"/>
</hbox>
<hbox id="passwords-count" align="center">
<label id="passwords-label"/>
<button id="passwords-manage-button"
label="&password.manage;"
oncommand="AboutPermissions.managePasswords();"/>
</hbox>
</vbox>
</hbox>
<!-- Geolocation -->
<hbox id="geo-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="geo"/>
<vbox>
<label class="pref-title" value="&geo.label;"/>
<hbox>
<menulist id="geo-menulist"
class="pref-menulist"
type="geo"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="geo-0" value="0" label="&permission.alwaysAsk;"/>
<menuitem id="geo-1" value="1" label="&permission.allow;"/>
<menuitem id="geo-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
</hbox>
</vbox>
</hbox>
<!-- Cookies -->
<hbox id="cookie-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="cookie"/>
<vbox>
<label class="pref-title" value="&cookie.label;"/>
<hbox algin="center">
<menulist id="cookie-menulist"
class="pref-menulist"
type="cookie"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="cookie-1" value="1" label="&permission.allow;"/>
<menuitem id="cookie-8" value="8" label="&permission.allowForSession;"/>
<menuitem id="cookie-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
<button id="cookies-clear-all-button"
label="&cookie.clearAll;"
oncommand="Services.cookies.removeAll();"/>
<button id="cookies-manage-all-button"
label="&cookie.manage;"
oncommand="AboutPermissions.manageCookies();"/>
</hbox>
<hbox id="cookies-count" align="center">
<label id="cookies-label"/>
<button id="cookies-clear-button"
label="&cookie.clear;"
oncommand="AboutPermissions.clearCookies();"/>
<button id="cookies-manage-button"
label="&cookie.manage;"
oncommand="AboutPermissions.manageCookies();"/>
</hbox>
</vbox>
</hbox>
<!-- Pop-up Blocking -->
<hbox id="popup-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="popup"/>
<vbox>
<label class="pref-title" value="&popup.label;"/>
<hbox>
<menulist id="popup-menulist"
class="pref-menulist"
type="popup"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="popup-1" value="1" label="&permission.allow;"/>
<menuitem id="popup-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
</hbox>
</vbox>
</hbox>
<!-- IndexedDB Storage -->
<hbox id="indexedDB-pref-item"
class="pref-item" align="top">
<image class="pref-icon" type="indexedDB"/>
<vbox>
<label class="pref-title" value="&indexedDB.label;"/>
<hbox>
<menulist id="indexedDB-menulist"
class="pref-menulist"
type="indexedDB"
oncommand="AboutPermissions.onPermissionCommand(event);">
<menupopup>
<menuitem id="indexedDB-0" value="0" label="&permission.alwaysAsk;"/>
<menuitem id="indexedDB-1" value="1" label="&permission.allow;"/>
<menuitem id="indexedDB-2" value="2" label="&permission.block;"/>
</menupopup>
</menulist>
</hbox>
</vbox>
</hbox>
</vbox>
</hbox>
</page>

View File

@ -1,4 +1,8 @@
browser.jar:
* content/browser/preferences/aboutPermissions.xul
* content/browser/preferences/aboutPermissions.js
* content/browser/preferences/aboutPermissions.css
* content/browser/preferences/aboutPermissions.xml
* content/browser/preferences/advanced.xul
* content/browser/preferences/advanced.js
* content/browser/preferences/advanced-scripts.xul

View File

@ -55,6 +55,7 @@ _BROWSER_FILES = \
browser_privacypane_6.js \
browser_privacypane_7.js \
browser_privacypane_8.js \
browser_permissions.js \
$(NULL)
libs:: $(_BROWSER_FILES)

View File

@ -1,5 +1,6 @@
function test() {
waitForExplicitFinish();
resetPreferences();
function observer(win, topic, data) {
if (topic != "main-pane-loaded")
@ -57,11 +58,13 @@ function runTest(win) {
is(menu.selectedItem, option, "The correct value should be restored");
// cleanup
[pbAutoStartPref, startupPref].forEach(function (pref) {
if (pref.hasUserValue)
pref.reset();
});
resetPreferences();
win.close();
finish();
}
function resetPreferences() {
Services.prefs.clearUserPref("browser.startup.page");
Services.prefs.clearUserPref("browser.privatebrowsing.autostart");
}

View File

@ -0,0 +1,304 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
const ABOUT_PERMISSIONS_SPEC = "about:permissions";
const TEST_URI_1 = NetUtil.newURI("http://mozilla.com/");
const TEST_URI_2 = NetUtil.newURI("http://mozilla.org/");
// values from DefaultPermissions object
const PERM_UNKNOWN = 0;
const PERM_ALLOW = 1;
const PERM_DENY = 2;
const PERM_SESION = 8;
// used to set permissions on test sites
const TEST_PERMS = {
"password": PERM_ALLOW,
"cookie": PERM_ALLOW,
"geo": PERM_UNKNOWN,
"indexedDB": PERM_UNKNOWN,
"popup": PERM_DENY
};
// number of managed permissions in the interface
const TEST_PERMS_COUNT = 5;
function test() {
waitForExplicitFinish();
registerCleanupFunction(cleanUp);
// add test history visit
PlacesUtils.history.addVisit(TEST_URI_1, Date.now() * 1000, null,
Ci.nsINavHistoryService.TRANSITION_LINK, false, 0);
// set permissions ourselves to avoid problems with different defaults
// from test harness configuration
for (let type in TEST_PERMS) {
if (type == "password") {
Services.logins.setLoginSavingEnabled(TEST_URI_2.prePath, true);
} else {
// set permissions on a site without history visits to test enumerateServices
Services.perms.add(TEST_URI_2, type, TEST_PERMS[type]);
}
}
function observer() {
Services.obs.removeObserver(observer, "browser-permissions-initialized", false);
runNextTest();
}
Services.obs.addObserver(observer, "browser-permissions-initialized", false);
// open about:permissions
gBrowser.selectedTab = gBrowser.addTab("about:permissions");
}
function cleanUp() {
for (let type in TEST_PERMS) {
if (type != "password") {
Services.perms.remove(TEST_URI_1.host, type);
Services.perms.remove(TEST_URI_2.host, type);
}
}
gBrowser.removeTab(gBrowser.selectedTab);
}
function runNextTest() {
if (gTestIndex == tests.length) {
waitForClearHistory(finish);
return;
}
let nextTest = tests[gTestIndex++];
info("[" + nextTest.name + "] running test");
nextTest();
}
var gSitesList;
var gHeaderDeck;
var gSiteLabel;
var gTestIndex = 0;
var tests = [
function test_page_load() {
is(gBrowser.currentURI.spec, ABOUT_PERMISSIONS_SPEC, "about:permissions loaded");
gSitesList = gBrowser.contentDocument.getElementById("sites-list");
ok(gSitesList, "got sites list");
gHeaderDeck = gBrowser.contentDocument.getElementById("header-deck");
ok(gHeaderDeck, "got header deck");
gSiteLabel = gBrowser.contentDocument.getElementById("site-label");
ok(gSiteLabel, "got site label");
runNextTest();
},
function test_sites_list() {
is(gSitesList.firstChild.id, "all-sites-item",
"all sites is the first item in the sites list");
ok(getSiteItem(TEST_URI_1.host), "site item from places db exists");
ok(getSiteItem(TEST_URI_2.host), "site item from enumerating services exists");
runNextTest();
},
function test_filter_sites_list() {
// set filter to test host
let sitesFilter = gBrowser.contentDocument.getElementById("sites-filter");
sitesFilter.value = TEST_URI_1.host;
sitesFilter.doCommand();
// make sure correct sites are collapsed/showing
let testSite1 = getSiteItem(TEST_URI_1.host);
ok(!testSite1.collapsed, "test site 1 is not collapsed");
let testSite2 = getSiteItem(TEST_URI_2.host);
ok(testSite2.collapsed, "test site 2 is collapsed");
// clear filter
sitesFilter.value = "";
sitesFilter.doCommand();
runNextTest();
},
function test_all_sites() {
// "All Sites" item should be selected when the page is first loaded
is(gSitesList.selectedItem, gBrowser.contentDocument.getElementById("all-sites-item"),
"all sites item is selected");
let defaultsHeader = gBrowser.contentDocument.getElementById("defaults-header");
is(defaultsHeader, gHeaderDeck.selectedPanel,
"correct header shown for all sites");
ok(gBrowser.contentDocument.getElementById("passwords-count").hidden,
"passwords count is hidden");
ok(gBrowser.contentDocument.getElementById("cookies-count").hidden,
"cookies count is hidden");
runNextTest();
},
function test_all_sites_permission() {
// there should be no user-set pref for cookie behavior
is(Services.prefs.getIntPref("network.cookie.cookieBehavior"), PERM_UNKNOWN,
"network.cookie.cookieBehavior is expected default");
// the default behavior is to allow cookies
let cookieMenulist = getPermissionMenulist("cookie");
is(cookieMenulist.value, PERM_ALLOW,
"menulist correctly shows that cookies are allowed");
// set the pref to block cookies
Services.prefs.setIntPref("network.cookie.cookieBehavior", PERM_DENY);
// check to make sure this change is reflected in the UI
is(cookieMenulist.value, PERM_DENY, "menulist correctly shows that cookies are blocked");
// clear the pref
Services.prefs.clearUserPref("network.cookie.cookieBehavior");
runNextTest();
},
function test_manage_all_passwords() {
// make sure "Manage All Passwords..." button opens the correct dialog
addWindowListener("chrome://passwordmgr/content/passwordManager.xul", runNextTest);
gBrowser.contentDocument.getElementById("passwords-manage-all-button").doCommand();
},
function test_manage_all_cookies() {
// make sure "Manage All Cookies..." button opens the correct dialog
addWindowListener("chrome://browser/content/preferences/cookies.xul", runNextTest);
gBrowser.contentDocument.getElementById("cookies-manage-all-button").doCommand();
},
function test_select_site() {
// select the site that has the permissions we set at the beginning of the test
let testSiteItem = getSiteItem(TEST_URI_2.host);
gSitesList.selectedItem = testSiteItem;
let siteHeader = gBrowser.contentDocument.getElementById("site-header");
is(siteHeader, gHeaderDeck.selectedPanel,
"correct header shown for a specific site");
is(gSiteLabel.value, TEST_URI_2.host, "header updated for selected site");
ok(!gBrowser.contentDocument.getElementById("passwords-count").hidden,
"passwords count is not hidden");
ok(!gBrowser.contentDocument.getElementById("cookies-count").hidden,
"cookies count is not hidden");
runNextTest();
},
function test_permissions() {
let menulists = gBrowser.contentDocument.getElementsByClassName("pref-menulist");
is(menulists.length, TEST_PERMS_COUNT, "got expected number of managed permissions");
for (let i = 0; i < menulists.length; i++) {
let permissionMenulist = menulists.item(i);
let permissionType = permissionMenulist.getAttribute("type");
// permissions should reflect what we set at the beginning of the test
is(permissionMenulist.value, TEST_PERMS[permissionType],
"got expected value for " + permissionType + " permission");
}
runNextTest();
},
function test_permission_change() {
let geoMenulist = getPermissionMenulist("geo");
is(geoMenulist.value, PERM_UNKNOWN, "menulist correctly shows that geolocation permission is unspecified");
// change a permission programatically
Services.perms.add(TEST_URI_2, "geo", PERM_DENY);
// check to make sure this change is reflected in the UI
is(geoMenulist.value, PERM_DENY, "menulist shows that geolocation is blocked");
// change a permisssion in the UI
let geoAllowItem = gBrowser.contentDocument.getElementById("geo-" + PERM_ALLOW);
geoMenulist.selectedItem = geoAllowItem;
geoMenulist.doCommand();
// check to make sure this change is reflected in the permission manager
is(Services.perms.testPermission(TEST_URI_2, "geo"), PERM_ALLOW,
"permission manager shows that geolocation is allowed");
runNextTest();
},
function test_forget_site() {
// click "Forget About This Site" button
gBrowser.contentDocument.getElementById("forget-site-button").doCommand();
is(gSiteLabel.value, "", "site label cleared");
let allSitesItem = gBrowser.contentDocument.getElementById("all-sites-item");
is(gSitesList.selectedItem, allSitesItem,
"all sites item selected after forgetting selected site");
// check to make sure site is gone from sites list
let testSiteItem = getSiteItem(TEST_URI_2.host);
ok(!testSiteItem, "site removed from sites list");
// check to make sure we forgot all permissions corresponding to site
for (let type in TEST_PERMS) {
if (type == "password") {
ok(Services.logins.getLoginSavingEnabled(TEST_URI_2.prePath),
"password saving should be enabled by default");
} else {
is(Services.perms.testPermission(TEST_URI_2, type), PERM_UNKNOWN,
type + " permission should not be set for test site 2");
}
}
runNextTest();
}
];
function getPermissionMenulist(aType) {
return gBrowser.contentDocument.getElementById(aType + "-menulist");
}
function getSiteItem(aHost) {
return gBrowser.contentDocument.
querySelector(".site[value='" + aHost + "']");
}
function addWindowListener(aURL, aCallback) {
Services.wm.addListener({
onOpenWindow: function(aXULWindow) {
info("window opened, waiting for focus");
Services.wm.removeListener(this);
var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal);
waitForFocus(function() {
is(domwindow.document.location.href, aURL, "should have seen the right window open");
domwindow.close();
aCallback();
}, domwindow);
},
onCloseWindow: function(aXULWindow) { },
onWindowTitleChange: function(aXULWindow, aNewTitle) { }
});
}
// copied from toolkit/components/places/tests/head_common.js
function waitForClearHistory(aCallback) {
let observer = {
observe: function(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
aCallback();
}
};
Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
PlacesUtils.bhistory.removeAllPages();
}

View File

@ -0,0 +1,23 @@
[DEFAULT]
head = head_privatebrowsing.js
tail = tail_privatebrowsing.js
[test_0-privatebrowsing.js]
[test_0-privatebrowsingwrapper.js]
[test_aboutprivatebrowsing.js]
[test_geoClearCookie.js]
[test_httpauth.js]
[test_openLocationLastURL.js]
[test_placesTitleNoUpdate.js]
[test_privatebrowsing_autostart.js]
[test_privatebrowsing_commandline.js]
[test_privatebrowsing_exit.js]
[test_privatebrowsingwrapper_autostart.js]
[test_privatebrowsingwrapper_commandline.js]
[test_privatebrowsingwrapper_exit.js]
[test_privatebrowsingwrapper_placesTitleNoUpdate.js]
[test_privatebrowsingwrapper_removeDataFromDomain.js]
[test_privatebrowsingwrapper_removeDataFromDomain_activeDownloads.js]
[test_removeDataFromDomain.js]
[test_removeDataFromDomain_activeDownloads.js]
[test_transition_nooffline.js]

View File

@ -225,6 +225,9 @@ SessionStoreService.prototype = {
// number of tabs to restore concurrently, pref controlled.
_maxConcurrentTabRestores: null,
// whether to restore hidden tabs or not, pref controlled.
_restoreHiddenTabs: null,
// The state from the previous session (after restoring pinned tabs)
_lastSessionState: null,
@ -281,6 +284,10 @@ SessionStoreService.prototype = {
this._prefBranch.getIntPref("sessionstore.max_concurrent_tabs");
this._prefBranch.addObserver("sessionstore.max_concurrent_tabs", this, true);
this._restoreHiddenTabs =
this._prefBranch.getBoolPref("sessionstore.restore_hidden_tabs");
this._prefBranch.addObserver("sessionstore.restore_hidden_tabs", this, true);
// Make sure gRestoreTabsProgressListener has a reference to sessionstore
// so that it can make calls back in
gRestoreTabsProgressListener.ss = this;
@ -598,6 +605,10 @@ SessionStoreService.prototype = {
this._maxConcurrentTabRestores =
this._prefBranch.getIntPref("sessionstore.max_concurrent_tabs");
break;
case "sessionstore.restore_hidden_tabs":
this._restoreHiddenTabs =
this._prefBranch.getBoolPref("sessionstore.restore_hidden_tabs");
break;
}
break;
case "timer-callback": // timer call back for delayed saving
@ -1078,6 +1089,10 @@ SessionStoreService.prototype = {
this._tabsToRestore.hidden.splice(this._tabsToRestore.hidden.indexOf(aTab));
// Just put it at the end of the list of visible tabs;
this._tabsToRestore.visible.push(aTab);
// let's kick off tab restoration again to ensure this tab gets restored
// with "restore_hidden_tabs" == false (now that it has become visible)
this.restoreNextTab();
}
// Default delay of 2 seconds gives enough time to catch multiple TabShow
@ -1329,8 +1344,6 @@ SessionStoreService.prototype = {
if (aWindow.__SSi && this._windows[aWindow.__SSi].extData &&
this._windows[aWindow.__SSi].extData[aKey])
delete this._windows[aWindow.__SSi].extData[aKey];
else
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
},
getTabValue: function sss_getTabValue(aTab, aKey) {
@ -1377,8 +1390,6 @@ SessionStoreService.prototype = {
if (deleteFrom && deleteFrom[aKey])
delete deleteFrom[aKey];
else
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
},
persistTabAttribute: function sss_persistTabAttribute(aName) {
@ -2944,7 +2955,7 @@ SessionStoreService.prototype = {
if (this._tabsToRestore.visible.length) {
nextTabArray = this._tabsToRestore.visible;
}
else if (this._tabsToRestore.hidden.length) {
else if (this._restoreHiddenTabs && this._tabsToRestore.hidden.length) {
nextTabArray = this._tabsToRestore.hidden;
}
@ -3974,7 +3985,8 @@ SessionStoreService.prototype = {
this._removeTabsProgressListener(window);
if (previousState == TAB_STATE_RESTORING) {
this._tabsRestoringCount--;
if (this._tabsRestoringCount)
this._tabsRestoringCount--;
}
else if (previousState == TAB_STATE_NEEDS_RESTORE) {
// Make sure the session history listener is removed. This is normally

View File

@ -127,6 +127,7 @@ _BROWSER_TEST_FILES = \
browser_589246.js \
browser_590268.js \
browser_590563.js \
browser_595601-restore_hidden.js \
browser_597315.js \
browser_597315_index.html \
browser_597315_a.html \
@ -145,6 +146,7 @@ _BROWSER_TEST_FILES = \
browser_625257.js \
browser_628270.js \
browser_635418.js \
browser_636279.js \
$(NULL)
ifneq ($(OS_ARCH),Darwin)

View File

@ -72,14 +72,6 @@ function test() {
"Invalid index for undoCloseTab throws");
ok(test(function() ss.getWindowValue({}, "")),
"Invalid window for getWindowValue throws");
ok(test(function() ss.getWindowValue({}, "")),
"Invalid window for getWindowValue throws");
ok(test(function() ss.getWindowValue({}, "", "")),
ok(test(function() ss.setWindowValue({}, "", "")),
"Invalid window for setWindowValue throws");
ok(test(function() ss.deleteWindowValue({}, "")),
"Invalid window for deleteWindowValue throws");
ok(test(function() ss.deleteWindowValue(window, Date.now().toString())),
"Nonexistent value for deleteWindowValue throws");
ok(test(function() ss.deleteTabValue(gBrowser.selectedTab, Date.now().toString())),
"Nonexistent value for deleteTabValue throws");
}

Some files were not shown because too many files have changed in this diff Show More