mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Merge m-c to s-c.
This commit is contained in:
commit
8f2b88b111
@ -150,13 +150,6 @@ SYMBOL_INDEX_NAME = \
|
||||
|
||||
buildsymbols:
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
ifdef USE_ELF_HACK
|
||||
ifeq (mobile,$(MOZ_BUILD_APP))
|
||||
$(MAKE) -C mobile/xul/installer elfhack
|
||||
else
|
||||
$(MAKE) -C $(MOZ_BUILD_APP)/installer elfhack
|
||||
endif
|
||||
endif
|
||||
echo building symbol store
|
||||
$(RM) -r $(DIST)/crashreporter-symbols
|
||||
$(RM) "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
|
||||
|
@ -62,8 +62,8 @@ interface nsIAccessibleProvider : nsISupports
|
||||
const long XULTab = 0x00001017;
|
||||
/** Used for XUL tabs element, a container for tab elements */
|
||||
const long XULTabs = 0x00001018;
|
||||
/** Used for XUL deck frame */
|
||||
const long XULDeck = 0x00001019;
|
||||
/** Used for XUL tabpanels element */
|
||||
const long XULTabpanels = 0x00001019;
|
||||
|
||||
const long XULText = 0x0000101A;
|
||||
const long XULTextBox = 0x0000101B;
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@ -117,10 +118,12 @@ AccReorderEvent::IsShowHideEventTarget(const Accessible* aTarget) const
|
||||
{
|
||||
uint32_t count = mDependentEvents.Length();
|
||||
for (uint32_t index = count - 1; index < count; index--) {
|
||||
if (mDependentEvents[index]->mAccessible == aTarget &&
|
||||
mDependentEvents[index]->mEventType == nsIAccessibleEvent::EVENT_SHOW ||
|
||||
mDependentEvents[index]->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
return mDependentEvents[index]->mEventType;
|
||||
if (mDependentEvents[index]->mAccessible == aTarget) {
|
||||
uint32_t eventType = mDependentEvents[index]->mEventType;
|
||||
if (eventType == nsIAccessibleEvent::EVENT_SHOW ||
|
||||
eventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
return mDependentEvents[index]->mEventType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ enum AccType {
|
||||
eMenuPopupType,
|
||||
eProgressType,
|
||||
eRootType,
|
||||
eXULDeckType,
|
||||
eXULTabpanelsType,
|
||||
eXULTreeType,
|
||||
|
||||
eLastAccType = eXULTreeType
|
||||
|
@ -49,7 +49,7 @@ DocManager::GetDocAccessible(nsIDocument* aDocument)
|
||||
// Ensure CacheChildren is called before we query cache.
|
||||
ApplicationAcc()->EnsureChildren();
|
||||
|
||||
DocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
|
||||
DocAccessible* docAcc = GetExistingDocAccessible(aDocument);
|
||||
if (docAcc)
|
||||
return docAcc;
|
||||
|
||||
@ -181,7 +181,7 @@ DocManager::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
logging::DocLoad("start document loading", aWebProgress, aRequest, aStateFlags);
|
||||
#endif
|
||||
|
||||
DocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
|
||||
DocAccessible* docAcc = GetExistingDocAccessible(document);
|
||||
if (!docAcc)
|
||||
return NS_OK;
|
||||
|
||||
@ -280,7 +280,7 @@ DocManager::HandleEvent(nsIDOMEvent* aEvent)
|
||||
// We're allowed to not remove listeners when accessible document is
|
||||
// shutdown since we don't keep strong reference on chrome event target and
|
||||
// listeners are removed automatically when chrome event target goes away.
|
||||
DocAccessible* docAccessible = mDocAccessibleCache.GetWeak(document);
|
||||
DocAccessible* docAccessible = GetExistingDocAccessible(document);
|
||||
if (docAccessible)
|
||||
docAccessible->Shutdown();
|
||||
|
||||
@ -312,7 +312,7 @@ DocManager::HandleDOMDocumentLoad(nsIDocument* aDocument,
|
||||
{
|
||||
// Document accessible can be created before we were notified the DOM document
|
||||
// was loaded completely. However if it's not created yet then create it.
|
||||
DocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
|
||||
DocAccessible* docAcc = GetExistingDocAccessible(aDocument);
|
||||
if (!docAcc) {
|
||||
docAcc = CreateDocOrRootAccessible(aDocument);
|
||||
if (!docAcc)
|
||||
@ -358,7 +358,7 @@ DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
||||
|
||||
// Ignore documents without presshell and not having root frame.
|
||||
nsIPresShell* presShell = aDocument->GetShell();
|
||||
if (!presShell || !presShell->GetRootFrame() || presShell->IsDestroying())
|
||||
if (!presShell || presShell->IsDestroying())
|
||||
return nullptr;
|
||||
|
||||
bool isRootDoc = nsCoreUtils::IsRootDocument(aDocument);
|
||||
|
@ -59,14 +59,6 @@ public:
|
||||
*/
|
||||
Accessible* FindAccessibleInCache(nsINode* aNode) const;
|
||||
|
||||
/**
|
||||
* Return document accessible from the cache. Convenient method for testing.
|
||||
*/
|
||||
inline DocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const
|
||||
{
|
||||
return mDocAccessibleCache.GetWeak(aDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by document accessible when it gets shutdown.
|
||||
*/
|
||||
@ -154,6 +146,18 @@ private:
|
||||
DocAccessibleHashtable mDocAccessibleCache;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the existing document accessible for the document if any.
|
||||
* Note this returns the doc accessible for the primary pres shell if there is
|
||||
* more than one.
|
||||
*/
|
||||
inline DocAccessible*
|
||||
GetExistingDocAccessible(const nsIDocument* aDocument)
|
||||
{
|
||||
nsIPresShell* ps = aDocument->GetShell();
|
||||
return ps ? ps->GetDocAccessible() : nullptr;
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -400,8 +400,7 @@ logging::DocLoad(const char* aMsg, nsIWebProgress* aWebProgress,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> documentNode(do_QueryInterface(DOMDocument));
|
||||
DocAccessible* document =
|
||||
GetAccService()->GetDocAccessibleFromCache(documentNode);
|
||||
DocAccessible* document = GetExistingDocAccessible(documentNode);
|
||||
|
||||
LogDocInfo(documentNode, document);
|
||||
|
||||
@ -425,8 +424,7 @@ logging::DocLoad(const char* aMsg, nsIDocument* aDocumentNode)
|
||||
{
|
||||
MsgBegin(sDocLoadTitle, aMsg);
|
||||
|
||||
DocAccessible* document =
|
||||
GetAccService()->GetDocAccessibleFromCache(aDocumentNode);
|
||||
DocAccessible* document = GetExistingDocAccessible(aDocumentNode);
|
||||
LogDocInfo(aDocumentNode, document);
|
||||
|
||||
MsgEnd();
|
||||
@ -486,7 +484,7 @@ logging::DocCreate(const char* aMsg, nsIDocument* aDocumentNode,
|
||||
DocAccessible* aDocument)
|
||||
{
|
||||
DocAccessible* document = aDocument ?
|
||||
aDocument : GetAccService()->GetDocAccessibleFromCache(aDocumentNode);
|
||||
aDocument : GetExistingDocAccessible(aDocumentNode);
|
||||
|
||||
MsgBegin(sDocCreateTitle, aMsg);
|
||||
LogDocInfo(aDocumentNode, document);
|
||||
@ -498,7 +496,7 @@ logging::DocDestroy(const char* aMsg, nsIDocument* aDocumentNode,
|
||||
DocAccessible* aDocument)
|
||||
{
|
||||
DocAccessible* document = aDocument ?
|
||||
aDocument : GetAccService()->GetDocAccessibleFromCache(aDocumentNode);
|
||||
aDocument : GetExistingDocAccessible(aDocumentNode);
|
||||
|
||||
MsgBegin(sDocDestroyTitle, aMsg);
|
||||
LogDocInfo(aDocumentNode, document);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "FocusManager.h"
|
||||
#include "Role.h"
|
||||
@ -213,6 +213,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
"Pending content insertions while initial accessible tree isn't created!");
|
||||
}
|
||||
|
||||
// Initialize scroll support if needed.
|
||||
if (!(mDocument->mDocFlags & DocAccessible::eScrollInitialized))
|
||||
mDocument->AddScrollListener();
|
||||
|
||||
// Process content inserted notifications to update the tree. Process other
|
||||
// notifications like DOM events and then flush event queue. If any new
|
||||
// notifications are queued during this processing then they will be processed
|
||||
@ -637,7 +641,6 @@ NotificationController::CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
|
||||
void
|
||||
NotificationController::CreateTextChangeEventFor(AccMutationEvent* aEvent)
|
||||
{
|
||||
DocAccessible* document = aEvent->GetDocAccessible();
|
||||
Accessible* container = aEvent->mAccessible->Parent();
|
||||
if (!container)
|
||||
return;
|
||||
|
@ -249,7 +249,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
eSelect,
|
||||
eListControl | eSelect,
|
||||
kNoReqStates,
|
||||
eARIAMultiSelectable,
|
||||
eARIAReadonly
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "XULAlertAccessible.h"
|
||||
@ -185,6 +186,7 @@ Accessible*
|
||||
nsAccessibilityService::GetRootDocumentAccessible(nsIPresShell* aPresShell,
|
||||
bool aCanCreate)
|
||||
{
|
||||
nsIPresShell* ps = aPresShell;
|
||||
nsIDocument* documentNode = aPresShell->GetDocument();
|
||||
if (documentNode) {
|
||||
nsCOMPtr<nsISupports> container = documentNode->GetContainer();
|
||||
@ -196,11 +198,10 @@ nsAccessibilityService::GetRootDocumentAccessible(nsIPresShell* aPresShell,
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(rootTreeItem));
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
documentNode = presShell->GetDocument();
|
||||
ps = presShell;
|
||||
}
|
||||
|
||||
return aCanCreate ?
|
||||
GetDocAccessible(documentNode) : GetDocAccessibleFromCache(documentNode);
|
||||
return aCanCreate ? GetDocAccessible(ps) : ps->GetDocAccessible();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@ -254,6 +255,47 @@ nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::DeckPanelSwitched(nsIPresShell* aPresShell,
|
||||
nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame,
|
||||
nsIFrame* aCurrentBoxFrame)
|
||||
{
|
||||
// Ignore tabpanels elements (a deck having an accessible) since their
|
||||
// children are accessible not depending on selected tab.
|
||||
DocAccessible* document = GetDocAccessible(aPresShell);
|
||||
if (!document || document->HasAccessible(aDeckNode))
|
||||
return;
|
||||
|
||||
if (aPrevBoxFrame) {
|
||||
nsIContent* panelNode = aPrevBoxFrame->GetContent();
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eTree)) {
|
||||
logging::MsgBegin("TREE", "deck panel unselected");
|
||||
logging::Node("container", panelNode);
|
||||
logging::Node("content", aDeckNode);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
document->ContentRemoved(aDeckNode, panelNode);
|
||||
}
|
||||
|
||||
if (aCurrentBoxFrame) {
|
||||
nsIContent* panelNode = aCurrentBoxFrame->GetContent();
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eTree)) {
|
||||
logging::MsgBegin("TREE", "deck panel selected");
|
||||
logging::Node("container", panelNode);
|
||||
logging::Node("content", aDeckNode);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
document->ContentInserted(aDeckNode, panelNode, panelNode->GetNextSibling());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
@ -364,15 +406,12 @@ nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
|
||||
void
|
||||
nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
|
||||
{
|
||||
nsIDocument* DOMDoc = aPresShell->GetDocument();
|
||||
if (DOMDoc) {
|
||||
DocAccessible* document = GetDocAccessibleFromCache(DOMDoc);
|
||||
if (document) {
|
||||
RootAccessible* rootDocument = document->RootAccessible();
|
||||
NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
|
||||
if (rootDocument)
|
||||
rootDocument->DocumentActivated(document);
|
||||
}
|
||||
DocAccessible* document = aPresShell->GetDocAccessible();
|
||||
if (document) {
|
||||
RootAccessible* rootDocument = document->RootAccessible();
|
||||
NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
|
||||
if (rootDocument)
|
||||
rootDocument->DocumentActivated(document);
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,7 +647,7 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
|
||||
if (!accessible) {
|
||||
nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
|
||||
if (document)
|
||||
accessible = GetDocAccessibleFromCache(document);
|
||||
accessible = GetExistingDocAccessible(document);
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aAccessible = accessible);
|
||||
@ -804,7 +843,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
newAcc = new ARIAGridCellAccessibleWrap(content, document);
|
||||
}
|
||||
|
||||
} else if ((roleMapEntry->accTypes & eTable) &&
|
||||
} else if ((roleMapEntry->IsOfType(eTable)) &&
|
||||
frame->AccessibleType() != eHTMLTableType) {
|
||||
newAcc = new ARIAGridAccessibleWrap(content, document);
|
||||
}
|
||||
@ -824,7 +863,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
if (!roleMapEntry && newAcc) {
|
||||
if (frame->AccessibleType() == eHTMLTableRowType) {
|
||||
nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
|
||||
if (contextRoleMap && !(contextRoleMap->accTypes & eTable))
|
||||
if (contextRoleMap && !(contextRoleMap->IsOfType(eTable)))
|
||||
roleMapEntry = &nsARIAMap::gEmptyRoleMap;
|
||||
|
||||
} else if (frame->AccessibleType() == eHTMLTableCellType &&
|
||||
@ -836,35 +875,50 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
content->Tag() == nsGkAtoms::dd ||
|
||||
frame->AccessibleType() == eHTMLLiType) {
|
||||
nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
|
||||
if (contextRoleMap && !(contextRoleMap->accTypes & eList))
|
||||
if (contextRoleMap && !(contextRoleMap->IsOfType(eList)))
|
||||
roleMapEntry = &nsARIAMap::gEmptyRoleMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!newAcc) {
|
||||
// Accessible XBL types and deck stuff are used in XUL only currently.
|
||||
if (!newAcc && content->IsXUL()) {
|
||||
// No accessible for not selected deck panel and its children.
|
||||
if (!aContext->IsXULTabpanels()) {
|
||||
nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
|
||||
if (deckFrame && deckFrame->GetSelectedBox() != frame) {
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Elements may implement nsIAccessibleProvider via XBL. This allows them to
|
||||
// say what kind of accessible to create.
|
||||
newAcc = CreateAccessibleByType(content, document);
|
||||
|
||||
// Any XUL box can be used as tabpanel, make sure we create a proper
|
||||
// accessible for it.
|
||||
if (!newAcc && aContext->IsXULTabpanels() &&
|
||||
content->GetParent() == aContext->GetContent()) {
|
||||
nsIAtom* frameType = frame->GetType();
|
||||
if (frameType == nsGkAtoms::boxFrame ||
|
||||
frameType == nsGkAtoms::scrollFrame) {
|
||||
newAcc = new XULTabpanelAccessible(content, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!newAcc) {
|
||||
// xul:deck does not have XBL and nsIFrame::CreateAccessible() is only called
|
||||
// on HTML elements
|
||||
nsIAtom* tag = content->Tag();
|
||||
if ((tag == nsGkAtoms::deck) || (tag == nsGkAtoms::tabpanels)) {
|
||||
newAcc = new XULDeckAccessible(content, document);
|
||||
} else if (content->IsSVG(nsGkAtoms::svg)) {
|
||||
if (content->IsSVG(nsGkAtoms::svg)) {
|
||||
newAcc = new EnumRoleAccessible(content, document, roles::DIAGRAM);
|
||||
} else if (content->IsMathML(nsGkAtoms::math)) {
|
||||
newAcc = new EnumRoleAccessible(content, document, roles::EQUATION);
|
||||
}
|
||||
}
|
||||
|
||||
if (!newAcc)
|
||||
newAcc = CreateAccessibleForDeckChild(frame, content, document);
|
||||
|
||||
// If no accessible, see if we need to create a generic accessible because
|
||||
// of some property that makes this object interesting
|
||||
// We don't do this for <body>, <html>, <window>, <dialog> etc. which
|
||||
@ -1011,8 +1065,8 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
|
||||
accessible = new XULComboboxAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULDeck:
|
||||
accessible = new XULDeckAccessible(aContent, aDoc);
|
||||
case nsIAccessibleProvider::XULTabpanels:
|
||||
accessible = new XULTabpanelsAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULDropmarker:
|
||||
@ -1406,6 +1460,9 @@ nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
|
||||
case eTextLeafType:
|
||||
newAcc = new TextLeafAccessibleWrap(aContent, document);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return newAcc.forget();
|
||||
@ -1480,37 +1537,6 @@ NS_GetAccessibilityService(nsIAccessibilityService** aResult)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessibilityService private (DON'T put methods here)
|
||||
|
||||
already_AddRefed<Accessible>
|
||||
nsAccessibilityService::CreateAccessibleForDeckChild(nsIFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
DocAccessible* aDoc)
|
||||
{
|
||||
if (aFrame->GetType() == nsGkAtoms::boxFrame ||
|
||||
aFrame->GetType() == nsGkAtoms::scrollFrame) {
|
||||
|
||||
nsIFrame* parentFrame = aFrame->GetParent();
|
||||
if (parentFrame && parentFrame->GetType() == nsGkAtoms::deckFrame) {
|
||||
// If deck frame is for xul:tabpanels element then the given node has
|
||||
// tabpanel accessible.
|
||||
nsIContent* parentContent = parentFrame->GetContent();
|
||||
#ifdef MOZ_XUL
|
||||
if (parentContent->NodeInfo()->Equals(nsGkAtoms::tabpanels,
|
||||
kNameSpaceID_XUL)) {
|
||||
Accessible* accessible = new XULTabpanelAccessible(aContent, aDoc);
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
#endif
|
||||
Accessible* accessible = new EnumRoleAccessible(aContent, aDoc,
|
||||
roles::PROPERTYPAGE);
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
already_AddRefed<Accessible>
|
||||
nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
|
||||
|
@ -64,6 +64,13 @@ public:
|
||||
virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible);
|
||||
virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible);
|
||||
|
||||
/**
|
||||
* Notification used to update the accessible tree when deck panel is
|
||||
* switched.
|
||||
*/
|
||||
void DeckPanelSwitched(nsIPresShell* aPresShell, nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame, nsIFrame* aCurrentBoxFrame);
|
||||
|
||||
/**
|
||||
* Notification used to update the accessible tree when new content is
|
||||
* inserted.
|
||||
@ -173,13 +180,6 @@ private:
|
||||
CreateAccessibleByFrameType(nsIFrame* aFrame, nsIContent* aContent,
|
||||
Accessible* aContext);
|
||||
|
||||
/**
|
||||
* Create accessible if parent is a deck frame.
|
||||
*/
|
||||
already_AddRefed<Accessible>
|
||||
CreateAccessibleForDeckChild(nsIFrame* aFrame, nsIContent* aContent,
|
||||
DocAccessible* aDoc);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
/**
|
||||
* Create accessible for XUL tree element.
|
||||
|
@ -264,6 +264,16 @@ Accessible::Name(nsString& aName)
|
||||
aName.CompressWhitespace();
|
||||
return eNameFromTooltip;
|
||||
}
|
||||
} else if (mContent->IsSVG()) {
|
||||
// If user agents need to choose among multiple ‘desc’ or ‘title’ elements
|
||||
// for processing, the user agent shall choose the first one.
|
||||
for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
|
||||
childElm = childElm->GetNextSibling()) {
|
||||
if (childElm->IsSVG(nsGkAtoms::title)) {
|
||||
nsTextEquivUtils::AppendTextEquivFromContent(this, childElm, &aName);
|
||||
return eNameFromTooltip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nameFlag != eNoNameOnPurpose)
|
||||
@ -307,25 +317,40 @@ Accessible::Description(nsString& aDescription)
|
||||
// Try XUL <description control="[id]">description text</description>
|
||||
XULDescriptionIterator iter(Document(), mContent);
|
||||
Accessible* descr = nullptr;
|
||||
while ((descr = iter.Next()))
|
||||
while ((descr = iter.Next())) {
|
||||
nsTextEquivUtils::AppendTextEquivFromContent(this, descr->GetContent(),
|
||||
&aDescription);
|
||||
}
|
||||
}
|
||||
|
||||
if (aDescription.IsEmpty()) {
|
||||
nsIAtom *descAtom = isXUL ? nsGkAtoms::tooltiptext :
|
||||
nsGkAtoms::title;
|
||||
if (mContent->GetAttr(kNameSpaceID_None, descAtom, aDescription)) {
|
||||
nsAutoString name;
|
||||
Name(name);
|
||||
if (name.IsEmpty() || aDescription == name)
|
||||
// Don't use tooltip for a description if this object
|
||||
// has no name or the tooltip is the same as the name
|
||||
aDescription.Truncate();
|
||||
if (aDescription.IsEmpty()) {
|
||||
// Keep the Name() method logic.
|
||||
if (mContent->IsHTML()) {
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aDescription);
|
||||
} else if (mContent->IsXUL()) {
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aDescription);
|
||||
} else if (mContent->IsSVG()) {
|
||||
for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
|
||||
childElm = childElm->GetNextSibling()) {
|
||||
if (childElm->IsSVG(nsGkAtoms::title)) {
|
||||
nsTextEquivUtils::AppendTextEquivFromContent(this, childElm,
|
||||
&aDescription);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!aDescription.IsEmpty()) {
|
||||
nsAutoString name;
|
||||
ENameValueFlag nameFlag = Name(name);
|
||||
|
||||
// Don't use tooltip for a description if it was used for a name.
|
||||
if (nameFlag == eNameFromTooltip)
|
||||
aDescription.Truncate();
|
||||
}
|
||||
}
|
||||
aDescription.CompressWhitespace();
|
||||
}
|
||||
aDescription.CompressWhitespace();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -612,6 +637,7 @@ Accessible::VisibilityState()
|
||||
deckFrame->GetContent()->Tag() == nsGkAtoms::tabpanels)
|
||||
return states::OFFSCREEN;
|
||||
|
||||
NS_NOTREACHED("Children of not selected deck panel are not accessible.");
|
||||
return states::INVISIBLE;
|
||||
}
|
||||
|
||||
@ -1589,17 +1615,44 @@ Accessible::GetValue(nsAString& aValue)
|
||||
void
|
||||
Accessible::Value(nsString& aValue)
|
||||
{
|
||||
if (mRoleMapEntry) {
|
||||
if (mRoleMapEntry->valueRule == eNoValue)
|
||||
return;
|
||||
if (!mRoleMapEntry)
|
||||
return;
|
||||
|
||||
// aria-valuenow is a number, and aria-valuetext is the optional text equivalent
|
||||
// For the string value, we will try the optional text equivalent first
|
||||
if (mRoleMapEntry->valueRule != eNoValue) {
|
||||
// aria-valuenow is a number, and aria-valuetext is the optional text
|
||||
// equivalent. For the string value, we will try the optional text
|
||||
// equivalent first.
|
||||
if (!mContent->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_valuetext, aValue)) {
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow,
|
||||
aValue);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Value of combobox is a text of current or selected item.
|
||||
if (mRoleMapEntry->Is(nsGkAtoms::combobox)) {
|
||||
Accessible* option = CurrentItem();
|
||||
if (!option) {
|
||||
Accessible* listbox = nullptr;
|
||||
IDRefsIterator iter(mDoc, mContent, nsGkAtoms::aria_owns);
|
||||
while ((listbox = iter.Next()) && !listbox->IsListControl());
|
||||
|
||||
if (!listbox) {
|
||||
uint32_t childCount = ChildCount();
|
||||
for (uint32_t idx = 0; idx < childCount; idx++) {
|
||||
Accessible* child = mChildren.ElementAt(idx);
|
||||
if (child->IsListControl())
|
||||
listbox = child;
|
||||
}
|
||||
}
|
||||
|
||||
if (listbox)
|
||||
option = listbox->GetSelectedItem(0);
|
||||
}
|
||||
|
||||
if (option)
|
||||
nsTextEquivUtils::GetNameFromSubtree(option, aValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2466,6 +2519,18 @@ Accessible::NativeName(nsString& aName)
|
||||
if (mContent->IsXUL())
|
||||
return GetXULName(aName);
|
||||
|
||||
if (mContent->IsSVG()) {
|
||||
// If user agents need to choose among multiple ‘desc’ or ‘title’ elements
|
||||
// for processing, the user agent shall choose the first one.
|
||||
for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
|
||||
childElm = childElm->GetNextSibling()) {
|
||||
if (childElm->IsSVG(nsGkAtoms::desc)) {
|
||||
nsTextEquivUtils::AppendTextEquivFromContent(this, childElm, &aName);
|
||||
return eNameOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ public:
|
||||
bool IsTextLeaf() const { return mType == eTextLeafType; }
|
||||
TextLeafAccessible* AsTextLeaf();
|
||||
|
||||
bool IsXULDeck() const { return mType == eXULDeckType; }
|
||||
bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
|
||||
|
||||
bool IsXULTree() const { return mType == eXULTreeType; }
|
||||
XULTreeAccessible* AsXULTree();
|
||||
|
@ -65,6 +65,33 @@ DocAccessible::UpdateText(nsIContent* aTextNode)
|
||||
mNotificationController->ScheduleTextUpdate(aTextNode);
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::AddScrollListener()
|
||||
{
|
||||
// Delay scroll initializing until the document has a root frame.
|
||||
if (!mPresShell->GetRootFrame())
|
||||
return;
|
||||
|
||||
mDocFlags |= eScrollInitialized;
|
||||
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollable();
|
||||
if (sf) {
|
||||
sf->AddScrollPositionListener(this);
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eDocCreate))
|
||||
logging::Text("add scroll listener");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::RemoveScrollListener()
|
||||
{
|
||||
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollable();
|
||||
if (sf)
|
||||
sf->RemoveScrollPositionListener(this);
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::NotifyOfLoad(uint32_t aLoadEventType)
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ DocAccessible::
|
||||
nsIPresShell* aPresShell) :
|
||||
HyperTextAccessibleWrap(aRootContent, this),
|
||||
mDocumentNode(aDocument), mScrollPositionChangedTicks(0),
|
||||
mLoadState(eTreeConstructionPending), mLoadEventType(0),
|
||||
mLoadState(eTreeConstructionPending), mDocFlags(0), mLoadEventType(0),
|
||||
mVirtualCursor(nullptr),
|
||||
mPresShell(aPresShell)
|
||||
{
|
||||
@ -93,18 +93,6 @@ DocAccessible::
|
||||
// If this is a XUL Document, it should not implement nsHyperText
|
||||
if (mDocumentNode && mDocumentNode->IsXUL())
|
||||
mGenericTypes &= ~eHyperText;
|
||||
|
||||
// For GTK+ native window, we do nothing here.
|
||||
if (!mDocumentNode)
|
||||
return;
|
||||
|
||||
// DocManager creates document accessible when scrollable frame is
|
||||
// available already, it should be safe time to add scroll listener.
|
||||
AddScrollListener();
|
||||
|
||||
// We provide a virtual cursor if this is a root doc or if it's a tab doc.
|
||||
mIsCursorable = (!(mDocumentNode->GetParentDocument()) ||
|
||||
nsCoreUtils::IsTabDocument(mDocumentNode));
|
||||
}
|
||||
|
||||
DocAccessible::~DocAccessible()
|
||||
@ -145,7 +133,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DocAccessible)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAccessiblePivotObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleCursorable,
|
||||
mIsCursorable)
|
||||
(mDocFlags & eCursorable))
|
||||
foundInterface = 0;
|
||||
|
||||
nsresult status;
|
||||
@ -502,7 +490,8 @@ DocAccessible::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_TRUE(mIsCursorable, NS_ERROR_NOT_IMPLEMENTED);
|
||||
if (!(mDocFlags & eCursorable))
|
||||
return NS_OK;
|
||||
|
||||
if (!mVirtualCursor) {
|
||||
mVirtualCursor = new nsAccessiblePivot(this);
|
||||
@ -603,8 +592,6 @@ DocAccessible::Shutdown()
|
||||
logging::DocDestroy("document shutdown", mDocumentNode, this);
|
||||
#endif
|
||||
|
||||
mPresShell->SetDocAccessible(nullptr);
|
||||
|
||||
if (mNotificationController) {
|
||||
mNotificationController->Shutdown();
|
||||
mNotificationController = nullptr;
|
||||
@ -640,6 +627,7 @@ DocAccessible::Shutdown()
|
||||
mVirtualCursor = nullptr;
|
||||
}
|
||||
|
||||
mPresShell->SetDocAccessible(nullptr);
|
||||
mPresShell = nullptr; // Avoid reentrancy
|
||||
|
||||
mDependentIDsHash.Clear();
|
||||
@ -798,36 +786,6 @@ DocAccessible::ScrollTimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
}
|
||||
}
|
||||
|
||||
// DocAccessible protected member
|
||||
void
|
||||
DocAccessible::AddScrollListener()
|
||||
{
|
||||
if (!mPresShell)
|
||||
return;
|
||||
|
||||
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollableExternal();
|
||||
if (sf) {
|
||||
sf->AddScrollPositionListener(this);
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eDocCreate))
|
||||
logging::Text("add scroll listener");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// DocAccessible protected member
|
||||
void
|
||||
DocAccessible::RemoveScrollListener()
|
||||
{
|
||||
if (!mPresShell)
|
||||
return;
|
||||
|
||||
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollableExternal();
|
||||
if (sf) {
|
||||
sf->RemoveScrollPositionListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIScrollPositionListener
|
||||
|
||||
@ -1511,14 +1469,23 @@ DocAccessible::NotifyOfLoading(bool aIsReloading)
|
||||
void
|
||||
DocAccessible::DoInitialUpdate()
|
||||
{
|
||||
if (nsCoreUtils::IsTabDocument(mDocumentNode))
|
||||
mDocFlags |= eTabDocument;
|
||||
|
||||
// We provide a virtual cursor if this is a root doc or if it's a tab doc.
|
||||
if (!mDocumentNode->GetParentDocument() || (mDocFlags & eTabDocument))
|
||||
mDocFlags |= eCursorable;
|
||||
|
||||
mLoadState |= eTreeConstructed;
|
||||
|
||||
// The content element may be changed before the initial update and then we
|
||||
// miss the notification (since content tree change notifications are ignored
|
||||
// prior to initial update). Make sure the content element is valid.
|
||||
nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocumentNode);
|
||||
if (mContent != contentElm)
|
||||
if (mContent != contentElm) {
|
||||
mContent = contentElm;
|
||||
SetRoleMapEntry(aria::GetRoleMap(mContent));
|
||||
}
|
||||
|
||||
// Build initial tree.
|
||||
CacheChildrenInSubtree(this);
|
||||
@ -1739,8 +1706,10 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
||||
if (aContainer == this) {
|
||||
// If new root content has been inserted then update it.
|
||||
nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocumentNode);
|
||||
if (rootContent != mContent)
|
||||
if (rootContent != mContent) {
|
||||
mContent = rootContent;
|
||||
SetRoleMapEntry(aria::GetRoleMap(mContent));
|
||||
}
|
||||
|
||||
// Continue to update the tree even if we don't have root content.
|
||||
// For example, elements may be inserted under the document element while
|
||||
|
@ -333,8 +333,11 @@ protected:
|
||||
*/
|
||||
void ProcessLoad();
|
||||
|
||||
void AddScrollListener();
|
||||
void RemoveScrollListener();
|
||||
/**
|
||||
* Add/remove scroll listeners, @see nsIScrollPositionListener interface.
|
||||
*/
|
||||
void AddScrollListener();
|
||||
void RemoveScrollListener();
|
||||
|
||||
/**
|
||||
* Append the given document accessible to this document's child document
|
||||
@ -482,6 +485,20 @@ protected:
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* State and property flags, kept by mDocFlags.
|
||||
*/
|
||||
enum {
|
||||
// Whether scroll listeners were added.
|
||||
eScrollInitialized = 1 << 0,
|
||||
|
||||
// Whether we support nsIAccessibleCursorable.
|
||||
eCursorable = 1 << 1,
|
||||
|
||||
// Whether the document is a tab document.
|
||||
eTabDocument = 1 << 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache of accessibles within this document accessible.
|
||||
*/
|
||||
@ -496,7 +513,12 @@ protected:
|
||||
/**
|
||||
* Bit mask of document load states (@see LoadState).
|
||||
*/
|
||||
uint32_t mLoadState;
|
||||
uint32_t mLoadState : 3;
|
||||
|
||||
/**
|
||||
* Bit mask of other states and props.
|
||||
*/
|
||||
uint32_t mDocFlags : 28;
|
||||
|
||||
/**
|
||||
* Type of document load event fired after the document is loaded completely.
|
||||
@ -516,11 +538,6 @@ protected:
|
||||
|
||||
nsTArray<nsRefPtr<DocAccessible> > mChildDocuments;
|
||||
|
||||
/**
|
||||
* Whether we support nsIAccessibleCursorable, used when querying the interface.
|
||||
*/
|
||||
bool mIsCursorable;
|
||||
|
||||
/**
|
||||
* The virtual cursor of the document when it supports nsIAccessibleCursorable.
|
||||
*/
|
||||
|
@ -358,7 +358,7 @@ HTMLTextFieldAccessible::Value(nsString& aValue)
|
||||
textArea->GetValue(aValue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
nsHTMLInputElement* input = nsHTMLInputElement::FromContent(mContent);
|
||||
if (input)
|
||||
input->GetValue(aValue);
|
||||
|
@ -502,7 +502,8 @@ HTMLTableAccessible::SelectedCellCount()
|
||||
int32_t startRow = -1, startCol = -1;
|
||||
cellFrame->GetRowIndex(startRow);
|
||||
cellFrame->GetColIndex(startCol);
|
||||
if (startRow == rowIdx && startCol == colIdx)
|
||||
if (startRow >= 0 && (uint32_t)startRow == rowIdx &&
|
||||
startCol >= 0 && (uint32_t)startCol == colIdx)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@ -551,7 +552,8 @@ HTMLTableAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
|
||||
int32_t startCol = -1, startRow = -1;
|
||||
cellFrame->GetRowIndex(startRow);
|
||||
cellFrame->GetColIndex(startCol);
|
||||
if (startRow != rowIdx || startCol != colIdx)
|
||||
if ((startRow >= 0 && (uint32_t)startRow != rowIdx) ||
|
||||
(startCol >= 0 && (uint32_t)startCol != colIdx))
|
||||
continue;
|
||||
|
||||
Accessible* cell = mDoc->GetAccessible(cellFrame->GetContent());
|
||||
@ -577,7 +579,8 @@ HTMLTableAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
|
||||
int32_t startRow = -1, startCol = -1;
|
||||
cellFrame->GetColIndex(startCol);
|
||||
cellFrame->GetRowIndex(startRow);
|
||||
if (startRow == rowIdx && startCol == colIdx)
|
||||
if (startRow >= 0 && (uint32_t)startRow == rowIdx &&
|
||||
startCol >= 0 && (uint32_t)startCol == colIdx)
|
||||
aCells->AppendElement(CellIndexAt(rowIdx, colIdx));
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ this.EventManager = {
|
||||
if (txtIface.characterCount)
|
||||
throw x;
|
||||
}
|
||||
this.present(Presentation, textChanged(
|
||||
this.present(Presentation.textChanged(
|
||||
isInserted, event.start, event.length,
|
||||
text, event.modifiedText));
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ AccessibleWrap::GetNativeType ()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (IsXULDeck())
|
||||
if (IsXULTabpanels())
|
||||
return [mozPaneAccessible class];
|
||||
|
||||
|
||||
roles::Role role = Role();
|
||||
switch (role) {
|
||||
case roles::PUSHBUTTON:
|
||||
|
@ -223,7 +223,7 @@ DocAccessibleWrap::Shutdown()
|
||||
// Do window emulation specific shutdown if emulation was started.
|
||||
if (nsWinUtils::IsWindowEmulationStarted()) {
|
||||
// Destroy window created for root document.
|
||||
if (nsCoreUtils::IsTabDocument(mDocumentNode)) {
|
||||
if (mDocFlags & eTabDocument) {
|
||||
sHWNDCache.Remove(mHWND);
|
||||
::DestroyWindow(static_cast<HWND>(mHWND));
|
||||
}
|
||||
@ -253,7 +253,7 @@ DocAccessibleWrap::DoInitialUpdate()
|
||||
|
||||
if (nsWinUtils::IsWindowEmulationStarted()) {
|
||||
// Create window for tab document.
|
||||
if (nsCoreUtils::IsTabDocument(mDocumentNode)) {
|
||||
if (mDocFlags & eTabDocument) {
|
||||
mozilla::dom::TabChild* tabChild =
|
||||
mozilla::dom::GetTabChildFrom(mDocumentNode->GetShell());
|
||||
|
||||
|
@ -18,9 +18,7 @@ namespace a11y {
|
||||
inline DocAccessible*
|
||||
sdnAccessible::GetDocument() const
|
||||
{
|
||||
DocManager* docMgr = GetAccService();
|
||||
return docMgr ?
|
||||
docMgr->GetDocAccessibleFromCache(mNode->OwnerDoc()) : nullptr;
|
||||
return GetExistingDocAccessible(mNode->OwnerDoc());
|
||||
}
|
||||
|
||||
inline Accessible*
|
||||
|
@ -163,11 +163,11 @@ XULTabsAccessible::NativeName(nsString& aName)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULDeckAccessible
|
||||
// XULTabpanelsAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
role
|
||||
XULDeckAccessible::NativeRole()
|
||||
XULTabpanelsAccessible::NativeRole()
|
||||
{
|
||||
return roles::PANE;
|
||||
}
|
||||
|
@ -62,12 +62,12 @@ protected:
|
||||
/**
|
||||
* A container of tab panels, xul:tabpanels element.
|
||||
*/
|
||||
class XULDeckAccessible : public AccessibleWrap
|
||||
class XULTabpanelsAccessible : public AccessibleWrap
|
||||
{
|
||||
public:
|
||||
XULDeckAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
XULTabpanelsAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
AccessibleWrap(aContent, aDoc)
|
||||
{ mType = eXULDeckType; }
|
||||
{ mType = eXULTabpanelsType; }
|
||||
|
||||
// Accessible
|
||||
virtual a11y::role NativeRole();
|
||||
|
@ -17,3 +17,16 @@ function testName(aAccOrElmOrID, aName, aMsg)
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accessible description for the given accessible.
|
||||
*/
|
||||
function testDescr(aAccOrElmOrID, aDescr)
|
||||
{
|
||||
var acc = getAccessible(aAccOrElmOrID);
|
||||
if (!acc)
|
||||
return;
|
||||
|
||||
is(acc.description, aDescr,
|
||||
"Wrong description for " + prettyName(aAccOrElmOrID));
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ MOCHITEST_A11Y_FILES =\
|
||||
test_link.html \
|
||||
test_list.html \
|
||||
test_markup.html \
|
||||
test_svg.html \
|
||||
test_browserui.xul \
|
||||
test_tree.xul \
|
||||
markuprules.xml \
|
||||
|
56
accessible/tests/mochitest/name/test_svg.html
Normal file
56
accessible/tests/mochitest/name/test_svg.html
Normal file
@ -0,0 +1,56 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Accessible name and description for SVG elements</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../name.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function doTest()
|
||||
{
|
||||
testName("svg1", "A name");
|
||||
testDescr("svg1", "A description");
|
||||
testName("svg2", "A tooltip");
|
||||
testDescr("svg2", "");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=459357"
|
||||
title="Support accessible name computation for SVG">
|
||||
Mozilla Bug 459357
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg1">
|
||||
<title>A description</title>
|
||||
<desc>A name</desc>
|
||||
</svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2">
|
||||
<title>A tooltip</title>
|
||||
</svg>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -32,7 +32,6 @@
|
||||
"test1: frameDocCheckbox");
|
||||
testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
|
||||
"test1: frameDocTextbox");
|
||||
|
||||
frameDoc.designMode = "on";
|
||||
testStates(frameDoc, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
|
||||
"test2: frameDoc");
|
||||
|
@ -20,7 +20,6 @@
|
||||
<![CDATA[
|
||||
function doTest()
|
||||
{
|
||||
testStates("deck_pane1", STATE_INVISIBLE, 0, STATE_OFFSCREEN);
|
||||
testStates("deck_pane2", 0, 0, STATE_INVISIBLE | STATE_OFFSCREEN);
|
||||
testStates("tabs_pane1", 0, 0, STATE_INVISIBLE | STATE_OFFSCREEN);
|
||||
testStates("tabs_pane2", STATE_OFFSCREEN, 0, STATE_INVISIBLE);
|
||||
|
@ -8,18 +8,10 @@
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="name.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function testDescr(aAccOrElmOrID, aDescr)
|
||||
{
|
||||
var acc = getAccessible(aAccOrElmOrID);
|
||||
if (!acc)
|
||||
return;
|
||||
|
||||
is(acc.description, aDescr,
|
||||
"Wrong description for " + prettyName(aAccOrElmOrID));
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// Description from aria-describedby attribute
|
||||
|
@ -17,6 +17,7 @@ MOCHITEST_A11Y_FILES =\
|
||||
test_colorpicker.xul \
|
||||
test_cssoverflow.html \
|
||||
test_contextmenu.xul \
|
||||
test_deck.xul \
|
||||
test_doc.html \
|
||||
test_gencontent.html \
|
||||
test_hidden.html \
|
||||
|
109
accessible/tests/mochitest/treeupdate/test_deck.xul
Normal file
109
accessible/tests/mochitest/treeupdate/test_deck.xul
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Tree update on XUL deck panel switching">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js" />
|
||||
<script type="application/javascript"
|
||||
src="../role.js" />
|
||||
<script type="application/javascript"
|
||||
src="../states.js" />
|
||||
<script type="application/javascript"
|
||||
src="../events.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function switchDeckPanel(aContainerID, aDeckID)
|
||||
{
|
||||
this.panelIndex = 0;
|
||||
|
||||
this.container = getAccessible(aContainerID);
|
||||
this.deckNode = getNode(aDeckID);
|
||||
this.prevPanel = getAccessible(this.deckNode.selectedPanel);
|
||||
this.panelNode = this.deckNode.childNodes[this.panelIndex];
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.prevPanel),
|
||||
new invokerChecker(EVENT_SHOW, this.panelNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function switchDeckPanel_invoke()
|
||||
{
|
||||
var tree =
|
||||
{ GROUPING: [ // role="group"
|
||||
{ GROUPING: [ // groupbox, a selected panel #2
|
||||
{ PUSHBUTTON: [ ] } // button
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, tree);
|
||||
|
||||
this.deckNode.selectedIndex = this.panelIndex;
|
||||
}
|
||||
|
||||
this.finalCheck = function switchDeckPanel_finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ GROUPING: [ // role="group"
|
||||
{ LABEL: [ // description, a selected panel #1
|
||||
{ TEXT_LEAF: [] } // text leaf, a description value
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, tree);
|
||||
}
|
||||
|
||||
this.getID = function switchDeckPanel_getID()
|
||||
{
|
||||
return "switch deck panel";
|
||||
}
|
||||
}
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new switchDeckPanel("container", "deck"));
|
||||
gQueue.invoke(); // will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=814836"
|
||||
title=" xul:deck element messes up screen reader">
|
||||
Mozilla Bug 814836
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1" id="container" role="group">
|
||||
|
||||
<deck id="deck" selectedIndex="1">
|
||||
<description>This is the first page</description>
|
||||
<groupbox>
|
||||
<button label="This is the second page"/>
|
||||
</groupbox>
|
||||
</deck>
|
||||
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
||||
|
@ -32,7 +32,7 @@
|
||||
return getDocNode(aID).body.firstChild;
|
||||
}
|
||||
|
||||
function rootContentReplaced(aID, aTextName)
|
||||
function rootContentReplaced(aID, aTextName, aRootContentRole)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
|
||||
@ -42,7 +42,7 @@
|
||||
this.finalCheck = function rootContentReplaced_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DOCUMENT,
|
||||
role: aRootContentRole || ROLE_DOCUMENT,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
@ -142,14 +142,14 @@
|
||||
docNode.replaceChild(newHTMLNode, docNode.documentElement);
|
||||
}
|
||||
|
||||
this.getID = function replaceIFrameBody_getID()
|
||||
this.getID = function replaceIFrameHTMLElm_getID()
|
||||
{
|
||||
return "replace HTML element";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace HTML body.
|
||||
* Replace HTML body on new body having ARIA role.
|
||||
*/
|
||||
function replaceIFrameBody(aID)
|
||||
{
|
||||
@ -164,26 +164,36 @@
|
||||
docNode.documentElement.replaceChild(newBodyNode, docNode.body);
|
||||
}
|
||||
|
||||
this.finalCheck = function replaceIFrameBody_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DOCUMENT,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
name: "New Hello"
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(getDocNode(aID), tree);
|
||||
}
|
||||
|
||||
this.getID = function replaceIFrameBody_getID()
|
||||
{
|
||||
return "replace body";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace HTML body on new body having ARIA role.
|
||||
*/
|
||||
function replaceIFrameBodyOnARIARoleBody(aID)
|
||||
{
|
||||
this.__proto__ = new rootContentReplaced(aID, "New Hello",
|
||||
ROLE_PUSHBUTTON);
|
||||
|
||||
this.invoke = function replaceIFrameBodyOnARIARoleBody_invoke()
|
||||
{
|
||||
var docNode = getDocNode(aID);
|
||||
var newBodyNode = docNode.createElement("body");
|
||||
var newTextNode = docNode.createTextNode("New Hello");
|
||||
newBodyNode.appendChild(newTextNode);
|
||||
newBodyNode.setAttribute("role", "button");
|
||||
docNode.documentElement.replaceChild(newBodyNode, docNode.body);
|
||||
}
|
||||
|
||||
this.getID = function replaceIFrameBodyOnARIARoleBody_getID()
|
||||
{
|
||||
return "replace body on body having ARIA role";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open/close document pair.
|
||||
*/
|
||||
@ -401,6 +411,7 @@
|
||||
gQueue.push(new insertElmUnderDocElmWhileBodyMissed("iframe"));
|
||||
gQueue.push(new insertBodyToIFrameDoc("iframe"));
|
||||
gQueue.push(new changeSrc("iframe"));
|
||||
gQueue.push(new replaceIFrameBodyOnARIARoleBody("iframe"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
@ -420,6 +431,9 @@
|
||||
<a target="_blank"
|
||||
title="Reorder event for document must be fired after document initial tree creation"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=669263">Mozilla Bug 669263</a>
|
||||
<a target="_blank"
|
||||
title="Changing the HTML body doesn't pick up ARIA role"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=818407">Mozilla Bug 818407</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
@ -50,6 +50,21 @@
|
||||
testValue("aria_main_link", href);
|
||||
testValue("aria_navigation_link", href);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ARIA comboboxes
|
||||
|
||||
// aria-activedescendant defines a current item the value is computed from
|
||||
testValue("aria_combobox1", kDiscBulletText + "Zoom");
|
||||
|
||||
// aria-selected defines a selected item the value is computed from,
|
||||
// list control is pointed by aria-owns relation.
|
||||
testValue("aria_combobox2", kDiscBulletText + "Zoom");
|
||||
|
||||
// aria-selected defines a selected item the value is computed from,
|
||||
// list control is a child of combobox.
|
||||
testValue("aria_combobox3", kDiscBulletText + "2");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HTML controls
|
||||
testValue("combobox1", "item1");
|
||||
testValue("combobox2", "item2");
|
||||
@ -69,7 +84,12 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=494807"
|
||||
title="Do not expose a11y info specific to hyperlinks when role is overridden using ARIA">
|
||||
Mozilla Bug 494807
|
||||
</a><br />
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=819273"
|
||||
title=" ARIA combobox should have accessible value">
|
||||
Mozilla Bug 819273
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
@ -88,6 +108,32 @@
|
||||
<!-- strange edge case: please don't do this in the wild -->
|
||||
<a id="aria_link_link" role="link" href="foo">link</a>
|
||||
|
||||
<div id="aria_combobox1" role="combobox"
|
||||
aria-owns="aria_combobox1_owned_listbox"
|
||||
aria-activedescendant="aria_combobox1_selected_option">
|
||||
</div>
|
||||
<ul role="listbox" id="aria_combobox1_owned_listbox">
|
||||
<li role="option">Zebra</li>
|
||||
<li role="option" id="aria_combobox1_selected_option">Zoom</li>
|
||||
</ul>
|
||||
|
||||
<div id="aria_combobox2" role="combobox"
|
||||
aria-owns="aria_combobox2_owned_listbox">
|
||||
</div>
|
||||
<ul role="listbox" id="aria_combobox2_owned_listbox">
|
||||
<li role="option">Zebra</li>
|
||||
<li role="option" aria-selected="true">Zoom</li>
|
||||
</ul>
|
||||
|
||||
<div id="aria_combobox3" role="combobox">
|
||||
<div role="textbox"></div>
|
||||
<ul role="listbox">
|
||||
<li role="option">1</li>
|
||||
<li role="option" aria-selected="true">2</li>
|
||||
<li role="option">3</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<select id="combobox1">
|
||||
<option id="cb1_item1">item1</option>
|
||||
<option id="cb1_item2">item2</option>
|
||||
|
@ -363,9 +363,8 @@ AnimationThread(void *)
|
||||
ANativeWindow const * const window = gNativeWindow.get();
|
||||
window->query(window, NATIVE_WINDOW_FORMAT, &format);
|
||||
|
||||
EGLConfig config = NULL;
|
||||
CreateConfig(&config, display, format);
|
||||
if (!config) {
|
||||
EGLConfig config;
|
||||
if (!CreateConfig(&config, display, format)) {
|
||||
LOGW("Could not find config for pixel format");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
|
||||
// If an urlclassifier table has not been updated in this number of seconds,
|
||||
// a gethash request will be forced to check that the result is still in
|
||||
// the database.
|
||||
pref("urlclassifier.confirm-age", 2700);
|
||||
pref("urlclassifier.max-complete-age", 2700);
|
||||
|
||||
// URL for checking the reason for a malware warning.
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
@ -356,13 +356,6 @@ pref("content.ime.strict_policy", true);
|
||||
// $ adb shell start
|
||||
pref("browser.dom.window.dump.enabled", false);
|
||||
|
||||
|
||||
|
||||
// Temporarily relax file:// origin checks so that we can use <img>s
|
||||
// from other dirs as webgl textures and more. Remove me when we have
|
||||
// installable apps or wifi support.
|
||||
pref("security.fileuri.strict_origin_policy", false);
|
||||
|
||||
// Default Content Security Policy to apply to privileged and certified apps
|
||||
pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'");
|
||||
pref("security.apps.certified.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self'");
|
||||
@ -461,9 +454,6 @@ pref("shutdown.watchdog.timeoutSecs", 5);
|
||||
pref("b2g.update.apply-prompt-timeout", 60000); // milliseconds
|
||||
// Amount of time to wait after the user is idle before prompting to apply an update
|
||||
pref("b2g.update.apply-idle-timeout", 600000); // milliseconds
|
||||
// Amount of time the updater waits for the process to exit cleanly before
|
||||
// forcefully exiting the process
|
||||
pref("b2g.update.self-destruct-timeout", 5000); // milliseconds
|
||||
|
||||
pref("app.update.enabled", true);
|
||||
pref("app.update.auto", false);
|
||||
@ -601,6 +591,13 @@ pref("browser.prompt.allowNative", false);
|
||||
// a restart is required to enable a new value.
|
||||
pref("network.activity.blipIntervalMilliseconds", 250);
|
||||
|
||||
// By default we want the NetworkManager service to manage Gecko's offline
|
||||
// status for us according to the state of Wifi/cellular data connections.
|
||||
// In some environments, such as the emulator or hardware with other network
|
||||
// connectivity, this is not desireable, however, in which case this pref
|
||||
// can be flipped to false.
|
||||
pref("network.gonk.manage-offline-status", true);
|
||||
|
||||
pref("jsloader.reuseGlobal", true);
|
||||
|
||||
// Enable font inflation for browser tab content.
|
||||
|
@ -282,14 +282,12 @@ function getJSON(element) {
|
||||
|
||||
// Until the input type=date/datetime/time have been implemented
|
||||
// let's return their real type even if the platform returns 'text'
|
||||
// Related to Bug 769352 - Implement <input type=date>
|
||||
// Related to Bug 777279 - Implement <input type=time>
|
||||
let attributeType = element.getAttribute("type") || "";
|
||||
|
||||
if (attributeType) {
|
||||
var typeLowerCase = attributeType.toLowerCase();
|
||||
switch (typeLowerCase) {
|
||||
case "date":
|
||||
case "time":
|
||||
case "datetime":
|
||||
case "datetime-local":
|
||||
|
@ -98,6 +98,7 @@ function doInternalWatch() {
|
||||
function doInternalRequest() {
|
||||
log("doInternalRequest:", options && isLoaded);
|
||||
if (options && isLoaded) {
|
||||
var stringifiedOptions = JSON.stringify(options);
|
||||
content.wrappedJSObject.BrowserID.internal.get(
|
||||
options.origin,
|
||||
function(assertion, internalParams) {
|
||||
@ -110,7 +111,7 @@ function doInternalRequest() {
|
||||
}
|
||||
closeIdentityDialog();
|
||||
},
|
||||
options);
|
||||
stringifiedOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ var shell = {
|
||||
} catch(e) { }
|
||||
|
||||
// Bail if there isn't a valid crashID.
|
||||
if (!crashID) {
|
||||
if (!crashID && !this.CrashSubmit.pendingIDs().length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -125,10 +125,20 @@ var shell = {
|
||||
});
|
||||
},
|
||||
|
||||
// this function submit the pending crashes.
|
||||
// make sure you are online.
|
||||
submitQueuedCrashes: function shell_submitQueuedCrashes() {
|
||||
// submit the pending queue.
|
||||
let pending = shell.CrashSubmit.pendingIDs();
|
||||
for (let crashid of pending) {
|
||||
shell.CrashSubmit.submit(crashid);
|
||||
}
|
||||
},
|
||||
|
||||
// This function submits a crash when we're online.
|
||||
submitCrash: function shell_submitCrash(aCrashID) {
|
||||
if (this.onlineForCrashReport()) {
|
||||
this.CrashSubmit.submit(aCrashID);
|
||||
this.submitQueuedCrashes();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -136,13 +146,7 @@ var shell = {
|
||||
let network = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED
|
||||
&& network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
shell.CrashSubmit.submit(aCrashID);
|
||||
|
||||
// submit the pending queue.
|
||||
let pending = shell.CrashSubmit.pendingIDs();
|
||||
for (let crashid of pending) {
|
||||
shell.CrashSubmit.submit(crashid);
|
||||
}
|
||||
shell.submitQueuedCrashes();
|
||||
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
}
|
||||
@ -684,7 +688,7 @@ var AlertsHelper = {
|
||||
let message = messages[i];
|
||||
if (message === "notification") {
|
||||
return helper.fullLaunchPath();
|
||||
} else if ("notification" in message) {
|
||||
} else if (typeof message == "object" && "notification" in message) {
|
||||
return helper.resolveFromOrigin(message["notification"]);
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,9 @@ let log =
|
||||
function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
|
||||
function log_noop(msg) { };
|
||||
|
||||
const APPLY_PROMPT_TIMEOUT =
|
||||
Services.prefs.getIntPref("b2g.update.apply-prompt-timeout");
|
||||
const APPLY_IDLE_TIMEOUT =
|
||||
Services.prefs.getIntPref("b2g.update.apply-idle-timeout");
|
||||
const SELF_DESTRUCT_TIMEOUT =
|
||||
Services.prefs.getIntPref("b2g.update.self-destruct-timeout");
|
||||
const PREF_APPLY_PROMPT_TIMEOUT = "b2g.update.apply-prompt-timeout";
|
||||
const PREF_APPLY_IDLE_TIMEOUT = "b2g.update.apply-idle-timeout";
|
||||
|
||||
const APPLY_IDLE_TIMEOUT_SECONDS = APPLY_IDLE_TIMEOUT / 1000;
|
||||
const NETWORK_ERROR_OFFLINE = 111;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "aus",
|
||||
@ -108,6 +103,14 @@ UpdatePrompt.prototype = {
|
||||
_waitingForIdle: false,
|
||||
_updateCheckListner: null,
|
||||
|
||||
get applyPromptTimeout() {
|
||||
return Services.prefs.getIntPref(PREF_APPLY_PROMPT_TIMEOUT);
|
||||
},
|
||||
|
||||
get applyIdleTimeout() {
|
||||
return Services.prefs.getIntPref(PREF_APPLY_IDLE_TIMEOUT);
|
||||
},
|
||||
|
||||
// nsIUpdatePrompt
|
||||
|
||||
// FIXME/bug 737601: we should have users opt-in to downloading
|
||||
@ -130,14 +133,15 @@ UpdatePrompt.prototype = {
|
||||
// update quietly without user intervention.
|
||||
this.sendUpdateEvent("update-downloaded", aUpdate);
|
||||
|
||||
if (Services.idle.idleTime >= APPLY_IDLE_TIMEOUT) {
|
||||
if (Services.idle.idleTime >= this.applyIdleTimeout) {
|
||||
this.showApplyPrompt(aUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
let applyIdleTimeoutSeconds = this.applyIdleTimeout / 1000;
|
||||
// We haven't been idle long enough, so register an observer
|
||||
log("Update is ready to apply, registering idle timeout of " +
|
||||
APPLY_IDLE_TIMEOUT_SECONDS + " seconds before prompting.");
|
||||
applyIdleTimeoutSeconds + " seconds before prompting.");
|
||||
|
||||
this._update = aUpdate;
|
||||
this.waitForIdle();
|
||||
@ -165,7 +169,7 @@ UpdatePrompt.prototype = {
|
||||
}
|
||||
|
||||
this._waitingForIdle = true;
|
||||
Services.idle.addIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
|
||||
Services.idle.addIdleObserver(this, this.applyIdleTimeout / 1000);
|
||||
Services.obs.addObserver(this, "quit-application", false);
|
||||
},
|
||||
|
||||
@ -185,18 +189,18 @@ UpdatePrompt.prototype = {
|
||||
|
||||
// Schedule a fallback timeout in case the UI is unable to respond or show
|
||||
// a prompt for some reason.
|
||||
this._applyPromptTimer = this.createTimer(APPLY_PROMPT_TIMEOUT);
|
||||
this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
|
||||
},
|
||||
|
||||
_copyProperties: ["appVersion", "buildID", "detailsURL", "displayVersion",
|
||||
"errorCode", "isOSUpdate", "platformVersion",
|
||||
"previousAppVersion", "state", "statusText"],
|
||||
|
||||
sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
|
||||
let detail = {
|
||||
displayVersion: aUpdate.displayVersion,
|
||||
detailsURL: aUpdate.detailsURL,
|
||||
statusText: aUpdate.statusText,
|
||||
state: aUpdate.state,
|
||||
errorCode: aUpdate.errorCode,
|
||||
isOSUpdate: aUpdate.isOSUpdate
|
||||
};
|
||||
let detail = {};
|
||||
for each (let property in this._copyProperties) {
|
||||
detail[property] = aUpdate[property];
|
||||
}
|
||||
|
||||
let patch = aUpdate.selectedPatch;
|
||||
if (!patch && aUpdate.patchCount > 0) {
|
||||
@ -429,7 +433,7 @@ UpdatePrompt.prototype = {
|
||||
this.showApplyPrompt(this._update);
|
||||
// Fall through
|
||||
case "quit-application":
|
||||
Services.idle.removeIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
|
||||
Services.idle.removeIdleObserver(this, this.applyIdleTimeout / 1000);
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
break;
|
||||
case "update-check-start":
|
||||
|
@ -16,17 +16,6 @@ XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
|
||||
.getService(Ci.nsIMessageSender);
|
||||
});
|
||||
|
||||
// Splits parameters in a query string.
|
||||
function extractParameters(aQuery) {
|
||||
let params = aQuery.split("&");
|
||||
let res = {};
|
||||
params.forEach(function(aParam) {
|
||||
let obj = aParam.split("=");
|
||||
res[obj[0]] = decodeURIComponent(obj[1]);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
function YoutubeProtocolHandler() {
|
||||
}
|
||||
|
||||
@ -61,24 +50,95 @@ YoutubeProtocolHandler.prototype = {
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", infoURI, true);
|
||||
xhr.addEventListener("load", function() {
|
||||
// Youtube sends the response as a double wrapped url answer:
|
||||
// we first extract the url_encoded_fmt_stream_map parameter,
|
||||
// and from each comma-separated entry in this value, we extract
|
||||
// other parameters (url and type).
|
||||
let key = "url_encoded_fmt_stream_map=";
|
||||
let pos = xhr.responseText.indexOf(key);
|
||||
if (pos == -1) {
|
||||
return;
|
||||
try {
|
||||
let info = parseYoutubeVideoInfo(xhr.responseText);
|
||||
cpmm.sendAsyncMessage("content-handler", info);
|
||||
}
|
||||
let streams = decodeURIComponent(xhr.responseText
|
||||
.substring(pos + key.length)).split(",");
|
||||
let uri;
|
||||
let mimeType;
|
||||
catch(e) {
|
||||
// If parseYoutubeVideoInfo() can't find a video URL, it
|
||||
// throws an Error. We report the error message here and do
|
||||
// nothing. This shouldn't happen often. But if it does, the user
|
||||
// will find that clicking on a video doesn't do anything.
|
||||
log(e.message);
|
||||
}
|
||||
});
|
||||
xhr.send(null);
|
||||
|
||||
// itag is an undocumented value which maps to resolution and mimetype
|
||||
// see https://en.wikipedia.org/wiki/YouTube#Quality_and_codecs
|
||||
// Ordered from least to most preferred
|
||||
let recognizedItags = [
|
||||
function log(msg) {
|
||||
msg = "YoutubeProtocolHandler.js: " + (msg.join ? msg.join(" ") : msg);
|
||||
Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService)
|
||||
.logStringMessage(msg);
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the response from a youtube get_video_info query.
|
||||
//
|
||||
// If youtube's response is a failure, this function returns an object
|
||||
// with status, errorcode, type and reason properties. Otherwise, it returns
|
||||
// an object with status, url, and type properties, and optional
|
||||
// title, poster, and duration properties.
|
||||
//
|
||||
function parseYoutubeVideoInfo(response) {
|
||||
// Splits parameters in a query string.
|
||||
function extractParameters(q) {
|
||||
let params = q.split("&");
|
||||
let result = {};
|
||||
for(let i = 0, n = params.length; i < n; i++) {
|
||||
let param = params[i];
|
||||
let pos = param.indexOf('=');
|
||||
if (pos === -1)
|
||||
continue;
|
||||
let name = param.substring(0, pos);
|
||||
let value = param.substring(pos+1);
|
||||
result[name] = decodeURIComponent(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let params = extractParameters(response);
|
||||
|
||||
// If the request failed, return an object with an error code
|
||||
// and an error message
|
||||
if (params.status === 'fail') {
|
||||
//
|
||||
// Hopefully this error message will be properly localized.
|
||||
// Do we need to add any parameters to the XMLHttpRequest to
|
||||
// specify the language we want?
|
||||
//
|
||||
// Note that we include fake type and url properties in the returned
|
||||
// object. This is because we still need to trigger the video app's
|
||||
// view activity handler to display the error message from youtube,
|
||||
// and those parameters are required.
|
||||
//
|
||||
return {
|
||||
status: params.status,
|
||||
errorcode: params.errorcode,
|
||||
reason: (params.reason || '').replace(/\+/g, ' '),
|
||||
type: 'video/3gpp',
|
||||
url: 'https://m.youtube.com'
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, the query was successful
|
||||
let result = {
|
||||
status: params.status,
|
||||
};
|
||||
|
||||
// Now parse the available streams
|
||||
let streamsText = params.url_encoded_fmt_stream_map;
|
||||
if (!streamsText)
|
||||
throw Error("No url_encoded_fmt_stream_map parameter");
|
||||
let streams = streamsText.split(',');
|
||||
for(let i = 0, n = streams.length; i < n; i++) {
|
||||
streams[i] = extractParameters(streams[i]);
|
||||
}
|
||||
|
||||
// This is the list of youtube video formats, ordered from worst
|
||||
// (but playable) to best. These numbers are values used as the
|
||||
// itag parameter of each stream description. See
|
||||
// https://en.wikipedia.org/wiki/YouTube#Quality_and_codecs
|
||||
let formats = [
|
||||
"17", // 144p 3GP
|
||||
"36", // 240p 3GP
|
||||
"43", // 360p WebM
|
||||
@ -87,39 +147,39 @@ YoutubeProtocolHandler.prototype = {
|
||||
#endif
|
||||
];
|
||||
|
||||
let bestItag = -1;
|
||||
|
||||
let extras = { }
|
||||
|
||||
streams.forEach(function(aStream) {
|
||||
let params = extractParameters(aStream);
|
||||
let url = params["url"];
|
||||
let type = params["type"] ? params["type"].split(";")[0] : null;
|
||||
let itag = params["itag"];
|
||||
|
||||
let index;
|
||||
if (url && type && ((index = recognizedItags.indexOf(itag)) != -1) &&
|
||||
index > bestItag) {
|
||||
uri = url + '&signature=' + (params["sig"] ? params['sig'] : '');
|
||||
mimeType = type;
|
||||
bestItag = index;
|
||||
}
|
||||
for (let param in params) {
|
||||
if (["thumbnail_url", "length_seconds", "title"].indexOf(param) != -1) {
|
||||
extras[param] = decodeURIComponent(params[param]);
|
||||
}
|
||||
}
|
||||
// Sort the array of stream descriptions in order of format
|
||||
// preference, so that the first item is the most preferred one
|
||||
streams.sort(function(a, b) {
|
||||
let x = a.itag ? formats.indexOf(a.itag) : -1;
|
||||
let y = b.itag ? formats.indexOf(b.itag) : -1;
|
||||
return y - x;
|
||||
});
|
||||
|
||||
if (uri && mimeType) {
|
||||
cpmm.sendAsyncMessage("content-handler", {
|
||||
url: uri,
|
||||
type: mimeType,
|
||||
extras: extras
|
||||
});
|
||||
let bestStream = streams[0];
|
||||
|
||||
// If the best stream is a format we don't support just return
|
||||
if (formats.indexOf(bestStream.itag) === -1)
|
||||
throw Error("No supported video formats");
|
||||
|
||||
result.url = bestStream.url + '&signature=' + (bestStream.sig || '');
|
||||
result.type = bestStream.type;
|
||||
// Strip codec information off of the mime type
|
||||
if (result.type && result.type.indexOf(';') !== -1) {
|
||||
result.type = result.type.split(';',1)[0];
|
||||
}
|
||||
});
|
||||
xhr.send(null);
|
||||
|
||||
if (params.title) {
|
||||
result.title = params.title.replace(/\+/g, ' ');
|
||||
}
|
||||
if (params.length_seconds) {
|
||||
result.duration = params.length_seconds;
|
||||
}
|
||||
if (params.thumbnail_url) {
|
||||
result.poster = params.thumbnail_url;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
throw Components.results.NS_ERROR_ILLEGAL_VALUE;
|
||||
},
|
||||
|
@ -206,7 +206,7 @@ function test_options_pass_through() {
|
||||
let randomMixedParams = {
|
||||
loggedInUser: "juanita@mozilla.com",
|
||||
forceAuthentication: true,
|
||||
issuer: "https://foo.com",
|
||||
forceIssuer: "foo.com",
|
||||
someThing: {
|
||||
name: "Pertelote",
|
||||
legs: 4,
|
||||
|
@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r170377"
|
||||
"clang_version": "r170890"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
@ -9,8 +9,8 @@
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56131193,
|
||||
"digest": "a1e705d3a72e0e95eeb15722f538a3908277f9f756909ce5e67f0a09b8531c1ba7fcc4816e20795af2e98839e0308b1bc6df95308cda310ae06abf21d429624f",
|
||||
"size": 56126352,
|
||||
"digest": "e156e2a39abd5bf272ee30748a6825f22ddd27565b097c66662a2a6f2e9892bc5b4bf30a3552dffbe867dbfc39e7ee086e0b2cd7935f6ea216c0cf936178a88f",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
@ -158,6 +158,7 @@
|
||||
@BINPATH@/components/dom_activities.xpt
|
||||
@BINPATH@/components/dom_apps.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
@BINPATH@/components/dom_system.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_wifi.xpt
|
||||
|
@ -244,7 +244,6 @@ pref("browser.chrome.site_icons", true);
|
||||
pref("browser.chrome.favicons", true);
|
||||
// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting
|
||||
pref("browser.warnOnQuit", true);
|
||||
pref("browser.warnOnRestart", false);
|
||||
// browser.showQuitWarning specifically controls the quit warning dialog. We
|
||||
// might still show the window closing dialog with showQuitWarning == false.
|
||||
pref("browser.showQuitWarning", false);
|
||||
@ -741,7 +740,7 @@ pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
|
||||
// If an urlclassifier table has not been updated in this number of seconds,
|
||||
// a gethash request will be forced to check that the result is still in
|
||||
// the database.
|
||||
pref("urlclassifier.confirm-age", 2700);
|
||||
pref("urlclassifier.max-complete-age", 2700);
|
||||
#endif
|
||||
|
||||
pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/geolocation/");
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
var FullScreen = {
|
||||
_XULNS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
get _fullScrToggler() {
|
||||
delete this._fullScrToggler;
|
||||
return this._fullScrToggler = document.getElementById("fullscr-toggler");
|
||||
},
|
||||
toggle: function (event) {
|
||||
var enterFS = window.fullScreen;
|
||||
|
||||
@ -46,15 +50,8 @@ var FullScreen = {
|
||||
// events than raw listening of mouse coords. We don't add the toolbar in DOM full-screen
|
||||
// mode, only browser full-screen mode.
|
||||
if (!document.mozFullScreen) {
|
||||
let fullScrToggler = document.getElementById("fullscr-toggler");
|
||||
if (!fullScrToggler) {
|
||||
fullScrToggler = document.createElement("hbox");
|
||||
fullScrToggler.id = "fullscr-toggler";
|
||||
fullScrToggler.collapsed = true;
|
||||
gNavToolbox.parentNode.insertBefore(fullScrToggler, gNavToolbox.nextSibling);
|
||||
}
|
||||
fullScrToggler.addEventListener("mouseover", this._expandCallback, false);
|
||||
fullScrToggler.addEventListener("dragenter", this._expandCallback, false);
|
||||
this._fullScrToggler.addEventListener("mouseover", this._expandCallback, false);
|
||||
this._fullScrToggler.addEventListener("dragenter", this._expandCallback, false);
|
||||
}
|
||||
if (gPrefService.getBoolPref("browser.fullscreen.autohide"))
|
||||
gBrowser.mPanelContainer.addEventListener("mousemove",
|
||||
@ -152,13 +149,10 @@ var FullScreen = {
|
||||
this._cancelAnimation();
|
||||
this.mouseoverToggle(false);
|
||||
|
||||
// If there's a full-screen toggler, remove its listeners, so that mouseover
|
||||
// Remove listeners on the full-screen toggler, so that mouseover
|
||||
// the top of the screen will not cause the toolbar to re-appear.
|
||||
let fullScrToggler = document.getElementById("fullscr-toggler");
|
||||
if (fullScrToggler) {
|
||||
fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
|
||||
fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
|
||||
}
|
||||
this._fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
|
||||
this._fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
|
||||
},
|
||||
|
||||
cleanup: function () {
|
||||
@ -170,11 +164,8 @@ var FullScreen = {
|
||||
document.removeEventListener("popuphidden", this._setPopupOpen, false);
|
||||
gPrefService.removeObserver("browser.fullscreen", this);
|
||||
|
||||
let fullScrToggler = document.getElementById("fullscr-toggler");
|
||||
if (fullScrToggler) {
|
||||
fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
|
||||
fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
|
||||
}
|
||||
this._fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
|
||||
this._fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
|
||||
this.cancelWarning();
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
|
||||
@ -506,10 +497,7 @@ var FullScreen = {
|
||||
gNavToolbox.style.marginTop =
|
||||
aShow ? "" : -gNavToolbox.getBoundingClientRect().height + "px";
|
||||
|
||||
let toggler = document.getElementById("fullscr-toggler");
|
||||
if (toggler) {
|
||||
toggler.collapsed = aShow;
|
||||
}
|
||||
this._fullScrToggler.collapsed = aShow;
|
||||
this._isChromeCollapsed = !aShow;
|
||||
if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2)
|
||||
this._shouldAnimate = true;
|
||||
|
@ -269,7 +269,11 @@ var PlacesCommandHook = {
|
||||
var description;
|
||||
var charset;
|
||||
try {
|
||||
title = webNav.document.title || url.spec;
|
||||
let isErrorPage = /^about:(neterror|certerror|blocked)/
|
||||
.test(webNav.document.documentURI);
|
||||
title = isErrorPage ? PlacesUtils.history.getPageTitle(url)
|
||||
: webNav.document.title;
|
||||
title = title || url.spec;
|
||||
description = PlacesUIUtils.getDescriptionFromDocument(webNav.document);
|
||||
charset = webNav.document.characterSet;
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ var ctrlTab = {
|
||||
if (tabs.length > 2) {
|
||||
this.open();
|
||||
} else if (tabs.length == 2) {
|
||||
let index = gBrowser.selectedTab == tabs[0] ? 1 : 0;
|
||||
let index = tabs[0].selected ? 1 : 0;
|
||||
gBrowser.selectedTab = tabs[index];
|
||||
}
|
||||
}
|
||||
@ -488,7 +488,7 @@ var ctrlTab = {
|
||||
this.advanceFocus(false);
|
||||
|
||||
// If the current tab is removed, another tab can steal our focus.
|
||||
if (aTab == gBrowser.selectedTab && this.panel.state == "open") {
|
||||
if (aTab.selected && this.panel.state == "open") {
|
||||
setTimeout(function (selected) {
|
||||
selected.focus();
|
||||
}, 0, this.selected);
|
||||
|
52
browser/base/content/browser-webrtcUI.js
Normal file
52
browser/base/content/browser-webrtcUI.js
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
let WebrtcIndicator = {
|
||||
init: function () {
|
||||
let temp = {};
|
||||
Cu.import("resource:///modules/webrtcUI.jsm", temp);
|
||||
this.UIModule = temp.webrtcUI;
|
||||
|
||||
this.updateButton();
|
||||
},
|
||||
|
||||
get button() {
|
||||
delete this.button;
|
||||
return this.button = document.getElementById("webrtc-status-button");
|
||||
},
|
||||
|
||||
updateButton: function () {
|
||||
this.button.hidden = !this.UIModule.showGlobalIndicator;
|
||||
},
|
||||
|
||||
fillPopup: function (aPopup) {
|
||||
this._menuitemData = new WeakMap;
|
||||
for (let streamData of this.UIModule.activeStreams) {
|
||||
let menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("label", streamData.uri);
|
||||
menuitem.setAttribute("tooltiptext", streamData.uri);
|
||||
|
||||
this._menuitemData.set(menuitem, streamData);
|
||||
|
||||
aPopup.appendChild(menuitem);
|
||||
}
|
||||
},
|
||||
|
||||
clearPopup: function (aPopup) {
|
||||
while (aPopup.lastChild)
|
||||
aPopup.removeChild(aPopup.lastChild);
|
||||
},
|
||||
|
||||
menuCommand: function (aMenuitem) {
|
||||
let streamData = this._menuitemData.get(aMenuitem);
|
||||
if (!streamData)
|
||||
return;
|
||||
|
||||
let tab = streamData.tab;
|
||||
let browserWindow = tab.ownerDocument.defaultView;
|
||||
browserWindow.gBrowser.selectedTab = tab;
|
||||
browserWindow.focus();
|
||||
}
|
||||
}
|
@ -476,10 +476,6 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
#geolocation-notification {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#geolocation-notification");
|
||||
}
|
||||
|
||||
#addon-progress-notification {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
|
||||
}
|
||||
|
@ -155,6 +155,7 @@ let gInitialPages = [
|
||||
#include browser-tabPreviews.js
|
||||
#include browser-tabview.js
|
||||
#include browser-thumbnails.js
|
||||
#include browser-webrtcUI.js
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
#include browser-syncui.js
|
||||
@ -1254,6 +1255,7 @@ var gBrowserInit = {
|
||||
gFormSubmitObserver.init();
|
||||
SocialUI.init();
|
||||
AddonManager.addAddonListener(AddonsMgrListener);
|
||||
WebrtcIndicator.init();
|
||||
|
||||
gBrowser.addEventListener("pageshow", function(event) {
|
||||
// Filter out events that are not about the document load we are interested in
|
||||
@ -1262,7 +1264,7 @@ var gBrowserInit = {
|
||||
}, true);
|
||||
|
||||
// Ensure login manager is up and running.
|
||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
Services.logins;
|
||||
|
||||
if (mustLoadSidebar) {
|
||||
let sidebar = document.getElementById("sidebar");
|
||||
@ -1341,7 +1343,7 @@ var gBrowserInit = {
|
||||
// If the user manually opens the download manager before the timeout, the
|
||||
// downloads will start right away, and getting the service again won't hurt.
|
||||
setTimeout(function() {
|
||||
Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
|
||||
Services.downloads;
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (Win7Features) {
|
||||
@ -1495,10 +1497,8 @@ var gBrowserInit = {
|
||||
// End startup crash tracking after a delay to catch crashes while restoring
|
||||
// tabs and to postpone saving the pref to disk.
|
||||
try {
|
||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].
|
||||
getService(Ci.nsIAppStartup);
|
||||
const startupCrashEndDelay = 30 * 1000;
|
||||
setTimeout(appStartup.trackStartupCrashEnd, startupCrashEndDelay);
|
||||
setTimeout(Services.startup.trackStartupCrashEnd, startupCrashEndDelay);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Could not end startup crash tracking: " + ex);
|
||||
}
|
||||
@ -1750,7 +1750,6 @@ var nonBrowserWindowShutdown = gBrowserInit.nonBrowserWindowShutdown.bind(
|
||||
|
||||
|
||||
function HandleAppCommandEvent(evt) {
|
||||
evt.stopPropagation();
|
||||
switch (evt.command) {
|
||||
case "Back":
|
||||
BrowserBack();
|
||||
@ -1774,9 +1773,35 @@ function HandleAppCommandEvent(evt) {
|
||||
case "Home":
|
||||
BrowserHome();
|
||||
break;
|
||||
default:
|
||||
case "New":
|
||||
BrowserOpenTab();
|
||||
break;
|
||||
case "Close":
|
||||
BrowserCloseTabOrWindow();
|
||||
break;
|
||||
case "Find":
|
||||
gFindBar.onFindCommand();
|
||||
break;
|
||||
case "Help":
|
||||
openHelpLink('firefox-help');
|
||||
break;
|
||||
case "Open":
|
||||
BrowserOpenFileWindow();
|
||||
break;
|
||||
case "Print":
|
||||
PrintUtils.print();
|
||||
break;
|
||||
case "Save":
|
||||
saveDocument(window.content.document);
|
||||
break;
|
||||
case "SendMail":
|
||||
MailIntegration.sendLinkForWindow(window.content);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
}
|
||||
|
||||
function gotoHistoryIndex(aEvent) {
|
||||
@ -2222,10 +2247,6 @@ function readFromClipboard()
|
||||
var url;
|
||||
|
||||
try {
|
||||
// Get clipboard.
|
||||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
|
||||
// Create transferable that will transfer the text.
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
@ -2234,10 +2255,10 @@ function readFromClipboard()
|
||||
trans.addDataFlavor("text/unicode");
|
||||
|
||||
// If available, use selection clipboard, otherwise global one
|
||||
if (clipboard.supportsSelectionClipboard())
|
||||
clipboard.getData(trans, clipboard.kSelectionClipboard);
|
||||
if (Services.clipboard.supportsSelectionClipboard())
|
||||
Services.clipboard.getData(trans, Services.clipboard.kSelectionClipboard);
|
||||
else
|
||||
clipboard.getData(trans, clipboard.kGlobalClipboard);
|
||||
Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
|
||||
|
||||
var data = {};
|
||||
var dataLen = {};
|
||||
@ -2303,9 +2324,7 @@ function BrowserViewSourceOfDocument(aDocument)
|
||||
// imageElement - image to load in the Media Tab of the Page Info window; can be null/omitted
|
||||
function BrowserPageInfo(doc, initialTab, imageElement) {
|
||||
var args = {doc: doc, initialTab: initialTab, imageElement: imageElement};
|
||||
var windows = Cc['@mozilla.org/appshell/window-mediator;1']
|
||||
.getService(Ci.nsIWindowMediator)
|
||||
.getEnumerator("Browser:page-info");
|
||||
var windows = Services.wm.getEnumerator("Browser:page-info");
|
||||
|
||||
var documentURL = doc ? doc.location : window.content.document.location;
|
||||
|
||||
@ -2468,7 +2487,7 @@ function PageProxyClickHandler(aEvent)
|
||||
* to the DOM for unprivileged pages.
|
||||
*/
|
||||
function BrowserOnAboutPageLoad(document) {
|
||||
if (/^about:home$/i.test(document.documentURI)) {
|
||||
if (document.documentURI.toLowerCase() == "about:home") {
|
||||
// XXX bug 738646 - when Marketplace is launched, remove this statement and
|
||||
// the hidden attribute set on the apps button in aboutHome.xhtml
|
||||
if (getBoolPref("browser.aboutHome.apps", false))
|
||||
@ -2517,16 +2536,14 @@ let BrowserOnClick = {
|
||||
else if (ownerDoc.documentURI.startsWith("about:neterror")) {
|
||||
this.onAboutNetError(originalTarget, ownerDoc);
|
||||
}
|
||||
else if (/^about:home$/i.test(ownerDoc.documentURI)) {
|
||||
else if (ownerDoc.documentURI.toLowerCase() == "about:home") {
|
||||
this.onAboutHome(originalTarget, ownerDoc);
|
||||
}
|
||||
},
|
||||
|
||||
onAboutCertError: function BrowserOnClick_onAboutCertError(aTargetElm, aOwnerDoc) {
|
||||
let elmId = aTargetElm.getAttribute("id");
|
||||
let secHistogram = Cc["@mozilla.org/base/telemetry;1"].
|
||||
getService(Ci.nsITelemetry).
|
||||
getHistogramById("SECURITY_UI");
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
|
||||
switch (elmId) {
|
||||
case "exceptionDialogButton":
|
||||
@ -2571,9 +2588,7 @@ let BrowserOnClick = {
|
||||
|
||||
onAboutBlocked: function BrowserOnClick_onAboutBlocked(aTargetElm, aOwnerDoc) {
|
||||
let elmId = aTargetElm.getAttribute("id");
|
||||
let secHistogram = Cc["@mozilla.org/base/telemetry;1"].
|
||||
getService(Ci.nsITelemetry).
|
||||
getHistogramById("SECURITY_UI");
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
|
||||
// The event came from a button on a malware/phishing block page
|
||||
// First check whether it's malware or phishing, so that we can
|
||||
@ -2743,8 +2758,7 @@ let BrowserOnClick = {
|
||||
*/
|
||||
function getMeOutOfHere() {
|
||||
// Get the start page from the *default* pref branch, not the user's
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService).getDefaultBranch(null);
|
||||
var prefs = Services.prefs.getDefaultBranch(null);
|
||||
var url = BROWSER_NEW_TAB_URL;
|
||||
try {
|
||||
url = prefs.getComplexValue("browser.startup.homepage",
|
||||
@ -3134,8 +3148,7 @@ const DOMLinkHandler = {
|
||||
].some(function (re) re.test(targetDoc.documentURI));
|
||||
|
||||
if (!isAllowedPage || !uri.schemeIs("chrome")) {
|
||||
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
|
||||
getService(Ci.nsIScriptSecurityManager);
|
||||
var ssm = Services.scriptSecurityManager;
|
||||
try {
|
||||
ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
|
||||
@ -3768,7 +3781,8 @@ function updateEditUIVisibility()
|
||||
*/
|
||||
function mimeTypeIsTextBased(aMimeType)
|
||||
{
|
||||
return /^text\/|\+xml$/.test(aMimeType) ||
|
||||
return aMimeType.startsWith("text/") ||
|
||||
aMimeType.endsWith("+xml") ||
|
||||
aMimeType == "application/x-javascript" ||
|
||||
aMimeType == "application/javascript" ||
|
||||
aMimeType == "application/xml" ||
|
||||
@ -3785,7 +3799,7 @@ var XULBrowserWindow = {
|
||||
startTime: 0,
|
||||
statusText: "",
|
||||
isBusy: false,
|
||||
inContentWhitelist: ["about:addons", "about:permissions",
|
||||
inContentWhitelist: ["about:addons", "about:downloads", "about:permissions",
|
||||
"about:sync-progress", "about:preferences"],
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
@ -4066,7 +4080,7 @@ var XULBrowserWindow = {
|
||||
let newSpec = location;
|
||||
let newIndexOfHash = newSpec.indexOf("#");
|
||||
if (newIndexOfHash != -1)
|
||||
newSpec = newSpec.substr(0, newSpec.indexOf("#"));
|
||||
newSpec = newSpec.substr(0, newIndexOfHash);
|
||||
if (newSpec != oldSpec) {
|
||||
// Remove all the notifications, except for those which want to
|
||||
// persist across the first location change.
|
||||
@ -5083,8 +5097,8 @@ var gHomeButton = {
|
||||
|
||||
// use this if we can't find the pref
|
||||
if (!url) {
|
||||
var SBS = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
|
||||
var configBundle = SBS.createBundle("chrome://branding/locale/browserconfig.properties");
|
||||
var configBundle = Services.strings
|
||||
.createBundle("chrome://branding/locale/browserconfig.properties");
|
||||
url = configBundle.GetStringFromName(this.prefDomain);
|
||||
}
|
||||
|
||||
@ -5144,9 +5158,7 @@ function getBrowserSelection(aCharLen) {
|
||||
selection = RegExp.lastMatch;
|
||||
}
|
||||
|
||||
selection = selection.replace(/^\s+/, "")
|
||||
.replace(/\s+$/, "")
|
||||
.replace(/\s+/g, " ");
|
||||
selection = selection.trim().replace(/\s+/g, " ");
|
||||
|
||||
if (selection.length > charLen)
|
||||
selection = selection.substr(0, charLen);
|
||||
@ -5278,8 +5290,8 @@ function contentAreaClick(event, isPanelClick)
|
||||
if (isPanelClick && mainTarget) {
|
||||
// javascript and data links should be executed in the current browser.
|
||||
if (linkNode.getAttribute("onclick") ||
|
||||
href.substr(0, 11) === "javascript:" ||
|
||||
href.substr(0, 5) === "data:")
|
||||
href.startsWith("javascript:") ||
|
||||
href.startsWith("data:"))
|
||||
return;
|
||||
|
||||
try {
|
||||
@ -6644,16 +6656,12 @@ var gIdentityHandler = {
|
||||
* Return the eTLD+1 version of the current hostname
|
||||
*/
|
||||
getEffectiveHost : function() {
|
||||
// Cache the eTLDService if this is our first time through
|
||||
if (!this._eTLDService)
|
||||
this._eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"]
|
||||
.getService(Ci.nsIEffectiveTLDService);
|
||||
if (!this._IDNService)
|
||||
this._IDNService = Cc["@mozilla.org/network/idn-service;1"]
|
||||
.getService(Ci.nsIIDNService);
|
||||
try {
|
||||
let baseDomain =
|
||||
this._eTLDService.getBaseDomainFromHost(this._lastLocation.hostname);
|
||||
Services.eTLD.getBaseDomainFromHost(this._lastLocation.hostname);
|
||||
return this._IDNService.convertToDisplayIDN(baseDomain, {});
|
||||
} catch (e) {
|
||||
// If something goes wrong (e.g. hostname is an IP address) just fail back
|
||||
@ -7000,8 +7008,7 @@ let gPrivateBrowsingUI = {
|
||||
}
|
||||
catch (ex) { }
|
||||
|
||||
var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService);
|
||||
var bundleService = Services.strings;
|
||||
var pbBundle = bundleService.createBundle("chrome://browser/locale/browser.properties");
|
||||
var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
|
||||
|
||||
@ -7332,9 +7339,7 @@ function safeModeRestart()
|
||||
buttonFlags, restartText, null, null,
|
||||
null, {});
|
||||
if (rv == 0) {
|
||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].
|
||||
getService(Ci.nsIAppStartup);
|
||||
appStartup.restartInSafeMode(Ci.nsIAppStartup.eAttemptQuit);
|
||||
Services.startup.restartInSafeMode(Ci.nsIAppStartup.eAttemptQuit);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7401,9 +7406,7 @@ XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() {
|
||||
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
|
||||
#ifdef XP_WIN
|
||||
// Only show resizers on Windows 2000 and XP
|
||||
let sysInfo = Components.classes["@mozilla.org/system-info;1"]
|
||||
.getService(Components.interfaces.nsIPropertyBag2);
|
||||
return parseFloat(sysInfo.getProperty("version")) < 6;
|
||||
return parseFloat(Services.sysinfo.getProperty("version")) < 6;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
@ -7473,7 +7476,7 @@ var MousePosTracker = {
|
||||
};
|
||||
|
||||
function focusNextFrame(event) {
|
||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
let fm = Services.focus;
|
||||
let dir = event.shiftKey ? fm.MOVEFOCUS_BACKWARDDOC : fm.MOVEFOCUS_FORWARDDOC;
|
||||
let element = fm.moveFocus(window, null, dir, fm.FLAG_BYKEY);
|
||||
if (element.ownerDocument == document)
|
||||
|
@ -464,6 +464,13 @@
|
||||
</menulist>
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
|
||||
<popupnotification id="geolocation-notification" hidden="true">
|
||||
<popupnotificationcontent orient="vertical" align="start">
|
||||
<separator class="thin"/>
|
||||
<label id="geolocation-learnmore-link" class="text-link"/>
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
</popupset>
|
||||
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
@ -521,7 +528,7 @@
|
||||
toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
|
||||
fullscreentoolbar="true" mode="icons" customizable="true"
|
||||
iconsize="large"
|
||||
defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,downloads-button,home-button,bookmarks-menu-button-container,window-controls"
|
||||
defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,webrtc-status-button,downloads-button,home-button,bookmarks-menu-button-container,window-controls"
|
||||
context="toolbar-context-menu">
|
||||
|
||||
<toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional"
|
||||
@ -578,6 +585,8 @@
|
||||
<image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
</box>
|
||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||
code fires onmousedown, and hence eats our favicon drag events.
|
||||
@ -653,6 +662,16 @@
|
||||
<searchbar id="searchbar" flex="1"/>
|
||||
</toolbaritem>
|
||||
|
||||
<toolbarbutton id="webrtc-status-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
type="menu"
|
||||
hidden="true"
|
||||
orient="horizontal">
|
||||
<menupopup onpopupshowing="WebrtcIndicator.fillPopup(this);"
|
||||
onpopuphiding="WebrtcIndicator.clearPopup(this);"
|
||||
oncommand="WebrtcIndicator.menuCommand(event.target);"/>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
persist="class" removable="true"
|
||||
label="&homeButton.label;"
|
||||
@ -1050,6 +1069,8 @@
|
||||
</toolbarpalette>
|
||||
</toolbox>
|
||||
|
||||
<hbox id="fullscr-toggler" collapsed="true"/>
|
||||
|
||||
<hbox flex="1" id="browser">
|
||||
<vbox id="browser-border-start" hidden="true" layer="true"/>
|
||||
<vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
|
||||
|
@ -851,11 +851,11 @@
|
||||
var oldTab = this.mCurrentTab;
|
||||
|
||||
// Preview mode should not reset the owner
|
||||
if (!this._previewMode && oldTab != this.selectedTab)
|
||||
if (!this._previewMode && !oldTab.selected)
|
||||
oldTab.owner = null;
|
||||
|
||||
if (this._lastRelatedTab) {
|
||||
if (this._lastRelatedTab != this.selectedTab)
|
||||
if (!this._lastRelatedTab.selected)
|
||||
this._lastRelatedTab.owner = null;
|
||||
this._lastRelatedTab = null;
|
||||
}
|
||||
@ -876,7 +876,7 @@
|
||||
newBrowser.docShellIsActive =
|
||||
(window.windowState != window.STATE_MINIMIZED);
|
||||
this.mCurrentBrowser = newBrowser;
|
||||
this.mCurrentTab = this.selectedTab;
|
||||
this.mCurrentTab = this.tabContainer.selectedItem;
|
||||
this.showTab(this.mCurrentTab);
|
||||
|
||||
var backForwardContainer = document.getElementById("unified-back-forward-button");
|
||||
@ -957,8 +957,7 @@
|
||||
true, false);
|
||||
}
|
||||
|
||||
if (this.mCurrentTab.selected)
|
||||
this._setCloseKeyState(!this.mCurrentTab.pinned);
|
||||
this._setCloseKeyState(!this.mCurrentTab.pinned);
|
||||
|
||||
// TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code
|
||||
// that might rely upon the other changes suppressed.
|
||||
@ -1671,7 +1670,7 @@
|
||||
const filter = this.mTabFilters[aTab._tPos];
|
||||
#ifdef MOZ_E10S_COMPAT
|
||||
// Bug 666801 - WebProgress support for e10s
|
||||
#else
|
||||
#else
|
||||
browser.webProgress.removeProgressListener(filter);
|
||||
#endif
|
||||
filter.removeProgressListener(this.mTabListeners[aTab._tPos]);
|
||||
@ -1825,7 +1824,7 @@
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.mCurrentTab != aTab)
|
||||
if (!aTab.selected)
|
||||
return;
|
||||
|
||||
if (aTab.owner &&
|
||||
@ -1875,7 +1874,7 @@
|
||||
|
||||
// The tab is definitely not loading.
|
||||
aNewTab.removeAttribute("busy");
|
||||
if (aNewTab == this.selectedTab) {
|
||||
if (aNewTab.selected) {
|
||||
this.mIsBusy = false;
|
||||
}
|
||||
|
||||
@ -1884,7 +1883,7 @@
|
||||
// Update the new tab's title.
|
||||
this.setTabTitle(aNewTab);
|
||||
|
||||
if (aNewTab == this.selectedTab) {
|
||||
if (aNewTab.selected) {
|
||||
this.updateCurrentBrowser(true);
|
||||
}
|
||||
]]>
|
||||
@ -1923,7 +1922,7 @@
|
||||
if (isBusy) {
|
||||
aOurTab.setAttribute("busy", "true");
|
||||
this._tabAttrModified(aOurTab);
|
||||
if (aOurTab == this.selectedTab)
|
||||
if (aOurTab.selected)
|
||||
this.mIsBusy = true;
|
||||
}
|
||||
|
||||
@ -1939,7 +1938,7 @@
|
||||
|
||||
// If the tab was already selected (this happpens in the scenario
|
||||
// of replaceTabWithWindow), notify onLocationChange, etc.
|
||||
if (aOurTab == this.selectedTab)
|
||||
if (aOurTab.selected)
|
||||
this.updateCurrentBrowser(true);
|
||||
]]>
|
||||
</body>
|
||||
@ -2136,7 +2135,7 @@
|
||||
|
||||
<property name="selectedTab">
|
||||
<getter>
|
||||
return this.mTabBox.selectedTab;
|
||||
return this.mCurrentTab;
|
||||
</getter>
|
||||
<setter>
|
||||
<![CDATA[
|
||||
@ -2203,6 +2202,8 @@
|
||||
this.mTabFilters.splice(aIndex, 0, this.mTabFilters.splice(aTab._tPos, 1)[0]);
|
||||
this.mTabListeners.splice(aIndex, 0, this.mTabListeners.splice(aTab._tPos, 1)[0]);
|
||||
|
||||
let wasFocused = (document.activeElement == this.mCurrentTab);
|
||||
|
||||
aIndex = aIndex < aTab._tPos ? aIndex: aIndex+1;
|
||||
this.mCurrentTab._selected = false;
|
||||
|
||||
@ -2219,6 +2220,10 @@
|
||||
this.tabs[i]._selected = false;
|
||||
}
|
||||
this.mCurrentTab._selected = true;
|
||||
|
||||
if (wasFocused)
|
||||
this.mCurrentTab.focus();
|
||||
|
||||
this.tabContainer._handleTabSelect(false);
|
||||
|
||||
if (aTab.pinned)
|
||||
@ -2234,11 +2239,12 @@
|
||||
<method name="moveTabForward">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var tabPos = this.mCurrentTab._tPos;
|
||||
if (tabPos < this.browsers.length - 1) {
|
||||
this.moveTabTo(this.mCurrentTab, tabPos + 1);
|
||||
this.mCurrentTab.focus();
|
||||
}
|
||||
let nextTab = this.mCurrentTab.nextSibling;
|
||||
while (nextTab && nextTab.hidden)
|
||||
nextTab = nextTab.nextSibling;
|
||||
|
||||
if (nextTab)
|
||||
this.moveTabTo(this.mCurrentTab, nextTab._tPos);
|
||||
else if (this.arrowKeysShouldWrap)
|
||||
this.moveTabToStart();
|
||||
]]>
|
||||
@ -2248,11 +2254,12 @@
|
||||
<method name="moveTabBackward">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var tabPos = this.mCurrentTab._tPos;
|
||||
if (tabPos > 0) {
|
||||
this.moveTabTo(this.mCurrentTab, tabPos - 1);
|
||||
this.mCurrentTab.focus();
|
||||
}
|
||||
let previousTab = this.mCurrentTab.previousSibling;
|
||||
while (previousTab && previousTab.hidden)
|
||||
previousTab = previousTab.previousSibling;
|
||||
|
||||
if (previousTab)
|
||||
this.moveTabTo(this.mCurrentTab, previousTab._tPos);
|
||||
else if (this.arrowKeysShouldWrap)
|
||||
this.moveTabToEnd();
|
||||
]]>
|
||||
@ -2263,10 +2270,8 @@
|
||||
<body>
|
||||
<![CDATA[
|
||||
var tabPos = this.mCurrentTab._tPos;
|
||||
if (tabPos > 0) {
|
||||
if (tabPos > 0)
|
||||
this.moveTabTo(this.mCurrentTab, 0);
|
||||
this.mCurrentTab.focus();
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -2275,11 +2280,8 @@
|
||||
<body>
|
||||
<![CDATA[
|
||||
var tabPos = this.mCurrentTab._tPos;
|
||||
if (tabPos < this.browsers.length - 1) {
|
||||
this.moveTabTo(this.mCurrentTab,
|
||||
this.browsers.length - 1);
|
||||
this.mCurrentTab.focus();
|
||||
}
|
||||
if (tabPos < this.browsers.length - 1)
|
||||
this.moveTabTo(this.mCurrentTab, this.browsers.length - 1);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -292,6 +292,7 @@ _BROWSER_FILES = \
|
||||
browser_bug676619.js \
|
||||
download_page.html \
|
||||
browser_URLBarSetURI.js \
|
||||
browser_bookmark_titles.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
75
browser/base/content/test/browser_bookmark_titles.js
Normal file
75
browser/base/content/test/browser_bookmark_titles.js
Normal file
@ -0,0 +1,75 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This file is tests for the default titles that new bookmarks get.
|
||||
|
||||
let tests = [
|
||||
['http://example.com/browser/browser/base/content/test/dummy_page.html',
|
||||
'Dummy test page'],
|
||||
['data:text/html;charset=utf-8,<title>test data: url</title>',
|
||||
'test data: url'],
|
||||
['http://unregistered-domain.example',
|
||||
'http://unregistered-domain.example/'],
|
||||
['https://untrusted.example.com/somepage.html',
|
||||
'https://untrusted.example.com/somepage.html']
|
||||
];
|
||||
|
||||
function generatorTest() {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
browser.addEventListener("DOMContentLoaded", nextStep, true);
|
||||
registerCleanupFunction(function () {
|
||||
browser.removeEventListener("DOMContentLoaded", nextStep, true);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
yield; // Wait for the new tab to load.
|
||||
|
||||
// Test that a bookmark of each URI gets the corresponding default title.
|
||||
for (let i = 0; i < tests.length; ++i) {
|
||||
let [uri, title] = tests[i];
|
||||
content.location = uri;
|
||||
yield;
|
||||
checkBookmark(uri, title);
|
||||
}
|
||||
|
||||
// Network failure test: now that dummy_page.html is in history, bookmarking
|
||||
// it should give the last known page title as the default bookmark title.
|
||||
|
||||
// Simulate a network outage with offline mode. (Localhost is still
|
||||
// accessible in offline mode, so disable the test proxy as well.)
|
||||
BrowserOffline.toggleOfflineStatus();
|
||||
let proxy = Services.prefs.getIntPref('network.proxy.type');
|
||||
Services.prefs.setIntPref('network.proxy.type', 0);
|
||||
registerCleanupFunction(function () {
|
||||
BrowserOffline.toggleOfflineStatus();
|
||||
Services.prefs.setIntPref('network.proxy.type', proxy);
|
||||
});
|
||||
|
||||
// LOAD_FLAGS_BYPASS_CACHE isn't good enough. So clear the cache.
|
||||
Services.cache.evictEntries(Services.cache.STORE_ANYWHERE);
|
||||
|
||||
let [uri, title] = tests[0];
|
||||
content.location = uri;
|
||||
yield;
|
||||
// The offline mode test is only good if the page failed to load.
|
||||
is(content.document.documentURI.substring(0, 14), 'about:neterror',
|
||||
"Offline mode successfully simulated network outage.");
|
||||
checkBookmark(uri, title);
|
||||
}
|
||||
|
||||
// Bookmark the current page and confirm that the new bookmark has the expected
|
||||
// title. (Then delete the bookmark.)
|
||||
function checkBookmark(uri, expected_title) {
|
||||
PlacesCommandHook.bookmarkCurrentPage(false);
|
||||
|
||||
let id = PlacesUtils.getMostRecentBookmarkForURI(PlacesUtils._uri(uri));
|
||||
let title = PlacesUtils.bookmarks.getItemTitle(id);
|
||||
|
||||
is(title, expected_title, "Bookmark got a good default title.");
|
||||
|
||||
PlacesUtils.bookmarks.removeItem(id);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ var gWebProgressListener = {
|
||||
}
|
||||
|
||||
ok(gNewTab, "There is a new tab.");
|
||||
ok(isRedirectedURI(aLocation),
|
||||
ok(isRedirectedURI(aLocation),
|
||||
"onLocationChange catches only redirected URI.");
|
||||
|
||||
if (aLocation.ref == "BG") {
|
||||
@ -97,7 +97,7 @@ var gWebProgressListener = {
|
||||
ok(false, "This URI hash is not expected:" + aLocation.ref);
|
||||
}
|
||||
|
||||
let isSelectedTab = (gNewTab == gBrowser.selectedTab);
|
||||
let isSelectedTab = gNewTab.selected;
|
||||
setTimeout(delayed, 0, isSelectedTab);
|
||||
}
|
||||
};
|
||||
|
@ -59,7 +59,7 @@ function test() {
|
||||
pressCtrlTab(true);
|
||||
pressCtrlTab(true);
|
||||
releaseCtrl();
|
||||
ok(gBrowser.selectedTab == selectedTab,
|
||||
ok(selectedTab.selected,
|
||||
"Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab");
|
||||
}
|
||||
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
|
||||
|
@ -707,13 +707,12 @@ function checkPopup(popup, notificationObj) {
|
||||
is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
|
||||
is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");
|
||||
}
|
||||
let actualSecondaryActions = notification.childNodes;
|
||||
let actualSecondaryActions = Array.filter(notification.childNodes,
|
||||
function (child) child.nodeName == "menuitem");
|
||||
let secondaryActions = notificationObj.secondaryActions || [];
|
||||
let actualSecondaryActionsCount = actualSecondaryActions.length;
|
||||
if (secondaryActions.length) {
|
||||
let lastChild = actualSecondaryActions.item(actualSecondaryActions.length - 1);
|
||||
is(lastChild.tagName, "menuseparator", "menuseparator exists");
|
||||
actualSecondaryActionsCount--;
|
||||
is(notification.lastChild.tagName, "menuseparator", "menuseparator exists");
|
||||
}
|
||||
is(actualSecondaryActionsCount, secondaryActions.length, actualSecondaryActions.length + " secondary actions");
|
||||
secondaryActions.forEach(function (a, i) {
|
||||
|
@ -903,50 +903,6 @@
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="geolocation-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
|
||||
<content align="start">
|
||||
<xul:image class="popup-notification-icon"
|
||||
xbl:inherits="popupid,src=icon"/>
|
||||
<xul:vbox flex="1">
|
||||
<xul:description class="popup-notification-description"
|
||||
xbl:inherits="xbl:text=label"/>
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:hbox class="popup-notification-button-container"
|
||||
pack="end" align="center">
|
||||
<xul:label anonid="learnmore" class="text-link geolocation-text-link"/>
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:button anonid="button"
|
||||
type="menu-button"
|
||||
class="popup-notification-menubutton"
|
||||
xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
|
||||
<xul:menupopup anonid="menupopup"
|
||||
xbl:inherits="oncommand=menucommand">
|
||||
<children/>
|
||||
<xul:menuitem class="menuitem-iconic popup-notification-closeitem"
|
||||
label="&closeNotificationItem.label;"
|
||||
xbl:inherits="oncommand=closeitemcommand"/>
|
||||
</xul:menupopup>
|
||||
</xul:button>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
<xul:vbox pack="start">
|
||||
<xul:toolbarbutton anonid="closebutton"
|
||||
class="messageCloseButton popup-notification-closebutton tabbable"
|
||||
xbl:inherits="oncommand=closebuttoncommand"
|
||||
tooltiptext="&closeNotification.tooltip;"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<constructor><![CDATA[
|
||||
let link = document.getAnonymousElementByAttribute(this, "anonid", "learnmore");
|
||||
link.value = gNavigatorBundle.getString("geolocation.learnMore");
|
||||
|
||||
let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
|
||||
link.href = formatter.formatURLPref("browser.geolocation.warning.infoURL");
|
||||
]]></constructor>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="addon-progress-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
|
||||
<content align="start">
|
||||
<xul:image class="popup-notification-icon"
|
||||
|
@ -80,6 +80,8 @@ static RedirEntry kRedirMap[] = {
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "preferences", "chrome://browser/content/preferences/in-content/preferences.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
};
|
||||
static const int kRedirTotal = NS_ARRAY_LENGTH(kRedirMap);
|
||||
|
||||
|
@ -30,7 +30,6 @@ endif
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../shell/src \
|
||||
-I$(srcdir)/../feeds/src \
|
||||
-I$(srcdir)/../privatebrowsing/src \
|
||||
-I$(srcdir)/../about \
|
||||
-I$(srcdir)/../dirprovider \
|
||||
$(NULL)
|
||||
@ -41,11 +40,15 @@ endif
|
||||
|
||||
SHARED_LIBRARY_LIBS = \
|
||||
../feeds/src/$(LIB_PREFIX)browser_feeds_s.$(LIB_SUFFIX) \
|
||||
../privatebrowsing/src/$(LIB_PREFIX)privatebrowsing_s.$(LIB_SUFFIX) \
|
||||
../about/$(LIB_PREFIX)browserabout_s.$(LIB_SUFFIX) \
|
||||
../dirprovider/$(LIB_PREFIX)browserdir_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../privatebrowsing/src
|
||||
SHARED_LIBRARY_LIBS += ../privatebrowsing/src/$(LIB_PREFIX)privatebrowsing_s.$(LIB_SUFFIX)
|
||||
endif
|
||||
|
||||
ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
|
||||
SHARED_LIBRARY_LIBS += ../shell/src/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX)
|
||||
endif
|
||||
|
@ -25,7 +25,9 @@
|
||||
#include "AboutRedirector.h"
|
||||
#include "nsIAboutModule.h"
|
||||
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
#include "nsPrivateBrowsingServiceWrapper.h"
|
||||
#endif
|
||||
#include "nsNetCID.h"
|
||||
|
||||
using namespace mozilla::browser;
|
||||
@ -47,7 +49,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
|
||||
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrivateBrowsingServiceWrapper, Init)
|
||||
#endif
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYPROVIDER_CID);
|
||||
#if defined(XP_WIN)
|
||||
@ -62,7 +66,9 @@ NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
|
||||
#elif defined(XP_MACOSX)
|
||||
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
|
||||
#endif
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID);
|
||||
#endif
|
||||
|
||||
static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
|
||||
{ &kNS_BROWSERDIRECTORYPROVIDER_CID, false, NULL, DirectoryProviderConstructor },
|
||||
@ -78,7 +84,9 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
|
||||
#elif defined(XP_MACOSX)
|
||||
{ &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
|
||||
#endif
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
{ &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor },
|
||||
#endif
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -108,12 +116,15 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#if defined(XP_WIN)
|
||||
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
|
||||
#elif defined(XP_MACOSX)
|
||||
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
|
||||
#endif
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
{ NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID },
|
||||
#endif
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -21,9 +21,10 @@ richlistitem.download {
|
||||
[state="9"]) /* Blocked (policy) */)
|
||||
.downloadRemoveFromHistoryMenuItem,
|
||||
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
|
||||
[state="5"], /* Starting (queued) */
|
||||
[state="0"], /* Downloading */
|
||||
[state="4"]) /* Paused */)
|
||||
[state="1"], /* Finished */
|
||||
[state="4"], /* Paused */
|
||||
[state="5"]) /* Starting (queued) */)
|
||||
.downloadShowMenuItem,
|
||||
|
||||
.download-state[state="7"] .downloadCommandsSeparator
|
||||
|
@ -96,7 +96,7 @@ DownloadElementShell.prototype = {
|
||||
}
|
||||
else if (this._placesNode) {
|
||||
this._wasInProgress = false;
|
||||
this._wasDone = this._state == nsIDM.DOWNLOAD_FINISHED;
|
||||
this._wasDone = this.getDownloadState(true) == nsIDM.DOWNLOAD_FINISHED;
|
||||
}
|
||||
|
||||
this._updateStatusUI();
|
||||
@ -115,7 +115,7 @@ DownloadElementShell.prototype = {
|
||||
this._placesNode = aNode;
|
||||
if (!this._dataItem && this._placesNode) {
|
||||
this._wasInProgress = false;
|
||||
this._wasDone = this._state == nsIDM.DOWNLOAD_FINISHED;
|
||||
this._wasDone = this.getDownloadState(true) == nsIDM.DOWNLOAD_FINISHED;
|
||||
this._updateStatusUI();
|
||||
}
|
||||
}
|
||||
@ -216,42 +216,53 @@ DownloadElementShell.prototype = {
|
||||
// The target's file size in bytes. If there's no target file, or If we
|
||||
// cannot determine its size, 0 is returned.
|
||||
get _fileSize() {
|
||||
if (!this._file || !this._file.exists())
|
||||
return 0;
|
||||
try {
|
||||
return this._file.fileSize;
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
return 0;
|
||||
if (!("__fileSize" in this)) {
|
||||
if (!this._file || !this._file.exists())
|
||||
this.__fileSize = 0;
|
||||
try {
|
||||
this.__fileSize = this._file.fileSize;
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
this.__fileSize = 0;
|
||||
}
|
||||
}
|
||||
return this.__fileSize;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the state of the download
|
||||
* @param [optional] aForceUpdate
|
||||
* Whether to force update the cached download state. Default: false.
|
||||
*/
|
||||
// The download state (see nsIDownloadManager).
|
||||
get _state() {
|
||||
if (this._dataItem)
|
||||
return this._dataItem.state;
|
||||
|
||||
let state = -1;
|
||||
try {
|
||||
return this._getAnnotation(DOWNLOAD_STATE_ANNO);
|
||||
}
|
||||
catch (ex) {
|
||||
// The state annotation didn't exist in past releases.
|
||||
if (!this._file) {
|
||||
state = nsIDM.DOWNLOAD_FAILED;
|
||||
}
|
||||
else if (this._file.exists()) {
|
||||
state = this._fileSize > 0 ?
|
||||
nsIDM.DOWNLOAD_FINISHED : nsIDM.DOWNLOAD_FAILED;
|
||||
getDownloadState: function DES_getDownloadState(aForceUpdate = false) {
|
||||
if (aForceUpdate || !("_state" in this)) {
|
||||
if (this._dataItem) {
|
||||
this._state = this._dataItem.state;
|
||||
}
|
||||
else {
|
||||
// XXXmano I'm not sure if this right. We should probably show no
|
||||
// status text at all in this case.
|
||||
state = nsIDM.DOWNLOAD_CANCELED;
|
||||
try {
|
||||
this._state = this._getAnnotation(DOWNLOAD_STATE_ANNO);
|
||||
}
|
||||
catch (ex) {
|
||||
// The state annotation didn't exist in past releases.
|
||||
if (!this._file) {
|
||||
this._state = nsIDM.DOWNLOAD_FAILED;
|
||||
}
|
||||
else if (this._file.exists()) {
|
||||
this._state = this._fileSize > 0 ?
|
||||
nsIDM.DOWNLOAD_FINISHED : nsIDM.DOWNLOAD_FAILED;
|
||||
}
|
||||
else {
|
||||
// XXXmano I'm not sure if this right. We should probably show no
|
||||
// status text at all in this case.
|
||||
this._state = nsIDM.DOWNLOAD_CANCELED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
return this._state;
|
||||
},
|
||||
|
||||
// The status text for the download
|
||||
@ -292,7 +303,7 @@ DownloadElementShell.prototype = {
|
||||
return s.statusSeparator(fullHost, fullDate);
|
||||
}
|
||||
|
||||
switch (this._state) {
|
||||
switch (this.getDownloadState()) {
|
||||
case nsIDM.DOWNLOAD_FAILED:
|
||||
return s.stateFailed;
|
||||
case nsIDM.DOWNLOAD_CANCELED:
|
||||
@ -331,7 +342,7 @@ DownloadElementShell.prototype = {
|
||||
// appropriate buttons and context menu items), the status text label,
|
||||
// and the progress meter.
|
||||
_updateDownloadStatusUI: function DES__updateDownloadStatusUI() {
|
||||
this._element.setAttribute("state", this._state);
|
||||
this._element.setAttribute("state", this.getDownloadState(true));
|
||||
this._element.setAttribute("status", this._statusText);
|
||||
|
||||
// For past-downloads, we're done. For session-downloads, we may also need
|
||||
@ -429,7 +440,7 @@ DownloadElementShell.prototype = {
|
||||
case "downloadsCmd_open": {
|
||||
return this._file.exists() &&
|
||||
((this._dataItem && this._dataItem.openable) ||
|
||||
(this._state == nsIDM.DOWNLOAD_FINISHED));
|
||||
(this.getDownloadState() == nsIDM.DOWNLOAD_FINISHED));
|
||||
}
|
||||
case "downloadsCmd_show": {
|
||||
return this._getTargetFileOrPartFileIfExists() != null;
|
||||
@ -547,7 +558,7 @@ DownloadElementShell.prototype = {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
let command = getDefaultCommandForState(this._state);
|
||||
let command = getDefaultCommandForState(this.getDownloadState());
|
||||
if (this.isCommandEnabled(command))
|
||||
this.doCommand(command);
|
||||
}
|
||||
@ -589,6 +600,7 @@ function DownloadsPlacesView(aRichListBox) {
|
||||
|
||||
// Make sure to unregister the view if the window is closed.
|
||||
window.addEventListener("unload", function() {
|
||||
this._richlistbox.controllers.removeController(this);
|
||||
downloadsData.removeView(this);
|
||||
this.result = null;
|
||||
}.bind(this), true);
|
||||
@ -759,6 +771,7 @@ DownloadsPlacesView.prototype = {
|
||||
// sibling first, if any.
|
||||
if (aElement.nextSibling &&
|
||||
this._richlistbox.selectedItems &&
|
||||
this._richlistbox.selectedItems.length > 0 &&
|
||||
this._richlistbox.selectedItems[0] == aElement) {
|
||||
this._richlistbox.selectItem(aElement.nextSibling);
|
||||
}
|
||||
@ -871,8 +884,8 @@ DownloadsPlacesView.prototype = {
|
||||
let placesNodes = [];
|
||||
let selectedElements = this._richlistbox.selectedItems;
|
||||
for (let elt of selectedElements) {
|
||||
if (elt.placesNode)
|
||||
placesNodes.push(elt.placesNode);
|
||||
if (elt._shell.placesNode)
|
||||
placesNodes.push(elt._shell.placesNode);
|
||||
}
|
||||
return placesNodes;
|
||||
},
|
||||
@ -1079,7 +1092,7 @@ DownloadsPlacesView.prototype = {
|
||||
|
||||
// Set the state attribute so that only the appropriate items are displayed.
|
||||
let contextMenu = document.getElementById("downloadsContextMenu");
|
||||
contextMenu.setAttribute("state", element._shell._state);
|
||||
contextMenu.setAttribute("state", element._shell.getDownloadState());
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -2,9 +2,14 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
let ContentAreaDownloadsView = {
|
||||
init: function CADV_init() {
|
||||
let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"));
|
||||
view.place = "place:transition=7&sort=4";
|
||||
// Do not display the Places downloads in private windows
|
||||
if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
view.place = "place:transition=7&sort=4";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -5,12 +5,20 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/downloads/contentAreaDownloadsView.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://browser/content/downloads/allDownloadsViewOverlay.xul"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
|
||||
%downloadsDTD;
|
||||
]>
|
||||
|
||||
<window id="contentAreaDownloadsView"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&downloads.title;"
|
||||
onload="ContentAreaDownloadsView.init();">
|
||||
|
||||
<script type="application/javascript"
|
||||
|
@ -57,9 +57,10 @@ richlistitem[type="download"]:not([selected]) button {
|
||||
.downloadRemoveFromHistoryMenuItem,
|
||||
|
||||
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
|
||||
[state="5"], /* Starting (queued) */
|
||||
[state="0"], /* Downloading */
|
||||
[state="4"]) /* Paused */)
|
||||
[state="1"], /* Finished */
|
||||
[state="4"], /* Paused */
|
||||
[state="5"]) /* Starting (queued) */)
|
||||
.downloadShowMenuItem,
|
||||
|
||||
.download-state[state="7"] .downloadCommandsSeparator
|
||||
|
@ -32,6 +32,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "gBrowserGlue",
|
||||
"nsIBrowserGlue");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||
"resource:///modules/RecentWindow.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsUI
|
||||
@ -107,50 +109,38 @@ DownloadsUI.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function that opens the right download manager UI. Either the
|
||||
* new Downloads View in Places, or the toolkit download window if the
|
||||
* Places Downloads View is not enabled.
|
||||
* Helper function that opens the download manager UI.
|
||||
*/
|
||||
_showDownloadManagerUI:
|
||||
function DUI_showDownloadManagerUI(aWindowContext, aID, aReason)
|
||||
{
|
||||
// First, determine if the Places Downloads view is preffed on.
|
||||
let usePlacesView = false;
|
||||
try {
|
||||
usePlacesView =
|
||||
Services.prefs.getBoolPref("browser.library.useNewDownloadsView");
|
||||
} catch(e) {}
|
||||
|
||||
if (!usePlacesView) {
|
||||
// If we got here, then the browser.library.useNewDownloadsView pref
|
||||
// either didn't exist or was false, so just show the toolkit downloads
|
||||
// manager.
|
||||
this._toolkitUI.show(aWindowContext, aID, aReason);
|
||||
return;
|
||||
}
|
||||
|
||||
let organizer = Services.wm.getMostRecentWindow("Places:Organizer");
|
||||
if (!organizer) {
|
||||
let parentWindow = aWindowContext;
|
||||
// If we weren't given a window context, try to find a browser window
|
||||
// to use as our parent - and if that doesn't work, error out and give
|
||||
// up.
|
||||
// If we weren't given a window context, try to find a browser window
|
||||
// to use as our parent - and if that doesn't work, error out and give up.
|
||||
let parentWindow = aWindowContext;
|
||||
if (!parentWindow) {
|
||||
parentWindow = RecentWindow.getMostRecentBrowserWindow();
|
||||
if (!parentWindow) {
|
||||
parentWindow = RecentWindow.getMostRecentBrowserWindow();
|
||||
if (!parentWindow) {
|
||||
Components.utils
|
||||
.reportError("Couldn't find a browser window to open " +
|
||||
"the Places Downloads View from.");
|
||||
return;
|
||||
}
|
||||
Components.utils.reportError(
|
||||
"Couldn't find a browser window to open the Places Downloads View " +
|
||||
"from.");
|
||||
return;
|
||||
}
|
||||
parentWindow.openDialog("chrome://browser/content/places/places.xul",
|
||||
"", "chrome,toolbar=yes,dialog=no,resizable",
|
||||
"Downloads");
|
||||
}
|
||||
else {
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery("Downloads");
|
||||
organizer.focus();
|
||||
|
||||
// If window is private then show it in a tab.
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(parentWindow)) {
|
||||
parentWindow.openUILinkIn("about:downloads", "tab");
|
||||
return;
|
||||
} else {
|
||||
let organizer = Services.wm.getMostRecentWindow("Places:Organizer");
|
||||
if (!organizer) {
|
||||
parentWindow.openDialog("chrome://browser/content/places/places.xul",
|
||||
"", "chrome,toolbar=yes,dialog=no,resizable",
|
||||
"Downloads");
|
||||
} else {
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery("Downloads");
|
||||
organizer.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -551,19 +551,21 @@ BrowserGlue.prototype = {
|
||||
// browser.startup.page == 3 or browser.sessionstore.resume_session_once == true
|
||||
// 3. browser.warnOnQuit == false
|
||||
// 4. The browser is currently in Private Browsing mode
|
||||
// 5. The browser will be restarted.
|
||||
//
|
||||
// Otherwise these are the conditions and the associated dialogs that will be shown:
|
||||
// 1. aQuitType == "lastwindow" or "quit" and browser.showQuitWarning == true
|
||||
// - The quit dialog will be shown
|
||||
// 2. aQuitType == "restart" && browser.warnOnRestart == true
|
||||
// - The restart dialog will be shown
|
||||
// 3. aQuitType == "lastwindow" && browser.tabs.warnOnClose == true
|
||||
// 2. aQuitType == "lastwindow" && browser.tabs.warnOnClose == true
|
||||
// - The "closing multiple tabs" dialog will be shown
|
||||
//
|
||||
// aQuitType == "lastwindow" is overloaded. "lastwindow" is used to indicate
|
||||
// "the last window is closing but we're not quitting (a non-browser window is open)"
|
||||
// and also "we're quitting by closing the last window".
|
||||
|
||||
if (aQuitType == "restart")
|
||||
return;
|
||||
|
||||
var windowcount = 0;
|
||||
var pagecount = 0;
|
||||
var browserEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
@ -586,12 +588,10 @@ BrowserGlue.prototype = {
|
||||
if (!aQuitType)
|
||||
aQuitType = "quit";
|
||||
|
||||
var showPrompt = false;
|
||||
var mostRecentBrowserWindow;
|
||||
|
||||
// browser.warnOnQuit is a hidden global boolean to override all quit prompts
|
||||
// browser.showQuitWarning specifically covers quitting
|
||||
// browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
|
||||
// browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
|
||||
|
||||
var sessionWillBeRestored = Services.prefs.getIntPref("browser.startup.page") == 3 ||
|
||||
@ -601,19 +601,15 @@ BrowserGlue.prototype = {
|
||||
|
||||
// On last window close or quit && showQuitWarning, we want to show the
|
||||
// quit warning.
|
||||
if (aQuitType != "restart" && Services.prefs.getBoolPref("browser.showQuitWarning")) {
|
||||
showPrompt = true;
|
||||
}
|
||||
else if (aQuitType == "restart" && Services.prefs.getBoolPref("browser.warnOnRestart")) {
|
||||
showPrompt = true;
|
||||
}
|
||||
else if (aQuitType == "lastwindow") {
|
||||
// If aQuitType is "lastwindow" and we aren't showing the quit warning,
|
||||
// we should show the window closing warning instead. warnAboutClosing
|
||||
// tabs checks browser.tabs.warnOnClose and returns if it's ok to close
|
||||
// the window. It doesn't actually close the window.
|
||||
mostRecentBrowserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
aCancelQuit.data = !mostRecentBrowserWindow.gBrowser.warnAboutClosingTabs(true);
|
||||
if (!Services.prefs.getBoolPref("browser.showQuitWarning")) {
|
||||
if (aQuitType == "lastwindow") {
|
||||
// If aQuitType is "lastwindow" and we aren't showing the quit warning,
|
||||
// we should show the window closing warning instead. warnAboutClosing
|
||||
// tabs checks browser.tabs.warnOnClose and returns if it's ok to close
|
||||
// the window. It doesn't actually close the window.
|
||||
mostRecentBrowserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
aCancelQuit.data = !mostRecentBrowserWindow.gBrowser.warnAboutClosingTabs(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -621,21 +617,15 @@ BrowserGlue.prototype = {
|
||||
if (allWindowsPrivate)
|
||||
return;
|
||||
|
||||
if (!showPrompt)
|
||||
return;
|
||||
|
||||
var quitBundle = Services.strings.createBundle("chrome://browser/locale/quitDialog.properties");
|
||||
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
|
||||
var appName = brandBundle.GetStringFromName("brandShortName");
|
||||
var quitTitleString = (aQuitType == "restart" ? "restart" : "quit") + "DialogTitle";
|
||||
var quitTitleString = "quitDialogTitle";
|
||||
var quitDialogTitle = quitBundle.formatStringFromName(quitTitleString, [appName], 1);
|
||||
|
||||
var message;
|
||||
if (aQuitType == "restart")
|
||||
message = quitBundle.formatStringFromName("messageRestart",
|
||||
[appName], 1);
|
||||
else if (windowcount == 1)
|
||||
if (windowcount == 1)
|
||||
message = quitBundle.formatStringFromName("messageNoWindows",
|
||||
[appName], 1);
|
||||
else
|
||||
@ -646,21 +636,15 @@ BrowserGlue.prototype = {
|
||||
|
||||
var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
|
||||
promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
|
||||
promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2 +
|
||||
promptService.BUTTON_POS_0_DEFAULT;
|
||||
|
||||
var neverAsk = {value:false};
|
||||
var button0Title, button2Title;
|
||||
var button0Title = quitBundle.GetStringFromName("saveTitle");
|
||||
var button1Title = quitBundle.GetStringFromName("cancelTitle");
|
||||
var button2Title = quitBundle.GetStringFromName("quitTitle");
|
||||
var neverAskText = quitBundle.GetStringFromName("neverAsk");
|
||||
|
||||
if (aQuitType == "restart")
|
||||
button0Title = quitBundle.GetStringFromName("restartTitle");
|
||||
else {
|
||||
flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
|
||||
button0Title = quitBundle.GetStringFromName("saveTitle");
|
||||
button2Title = quitBundle.GetStringFromName("quitTitle");
|
||||
}
|
||||
|
||||
// This wouldn't have been set above since we shouldn't be here for
|
||||
// aQuitType == "lastwindow"
|
||||
mostRecentBrowserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
@ -682,12 +666,8 @@ BrowserGlue.prototype = {
|
||||
case 0: // Save & Quit
|
||||
this._saveSession = true;
|
||||
if (neverAsk.value) {
|
||||
if (aQuitType == "restart")
|
||||
Services.prefs.setBoolPref("browser.warnOnRestart", false);
|
||||
else {
|
||||
// always save state when shutting down
|
||||
Services.prefs.setIntPref("browser.startup.page", 3);
|
||||
}
|
||||
// always save state when shutting down
|
||||
Services.prefs.setIntPref("browser.startup.page", 3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -930,13 +910,13 @@ BrowserGlue.prototype = {
|
||||
*
|
||||
* - The last accepted/refused policy (either by accepting the prompt or by
|
||||
* manually flipping the telemetry preference) is already at version
|
||||
* TELEMETRY_DISPLAY_REV.
|
||||
* TELEMETRY_DISPLAY_REV or higher (to avoid the prompt in tests).
|
||||
*/
|
||||
var telemetryDisplayed;
|
||||
try {
|
||||
telemetryDisplayed = Services.prefs.getIntPref(PREF_TELEMETRY_DISPLAYED);
|
||||
} catch(e) {}
|
||||
if (telemetryDisplayed === TELEMETRY_DISPLAY_REV)
|
||||
if (telemetryDisplayed >= TELEMETRY_DISPLAY_REV)
|
||||
return;
|
||||
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
@ -945,7 +925,8 @@ BrowserGlue.prototype = {
|
||||
*
|
||||
* - Telemetry is disabled
|
||||
* - Telemetry was explicitly refused through the UI
|
||||
* - Opt-in telemetry was enabled and this is the first run with opt-out.
|
||||
* - Opt-in telemetry was already enabled, don't notify the user until next
|
||||
* policy update. (Do the check only at first run with opt-out builds)
|
||||
*/
|
||||
|
||||
var telemetryEnabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
|
||||
@ -1791,6 +1772,10 @@ ContentPermissionPrompt.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
var link = chromeWin.document.getElementById("geolocation-learnmore-link");
|
||||
link.value = browserBundle.GetStringFromName("geolocation.learnMore");
|
||||
link.href = Services.urlFormatter.formatURLPref("browser.geolocation.warning.infoURL");
|
||||
|
||||
var browser = chromeWin.gBrowser.getBrowserForDocument(requestingWindow.document);
|
||||
|
||||
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST);
|
||||
|
29
browser/components/places/content/downloadsViewOverlay.xul
Normal file
29
browser/components/places/content/downloadsViewOverlay.xul
Normal file
@ -0,0 +1,29 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?xul-overlay href="chrome://browser/content/downloads/allDownloadsViewOverlay.xul"?>
|
||||
|
||||
<overlay id="downloadsViewOverlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript"><![CDATA[
|
||||
const DOWNLOADS_QUERY = "place:transition=" +
|
||||
Components.interfaces.nsINavHistoryService.TRANSITION_DOWNLOAD +
|
||||
"&sort=" +
|
||||
Components.interfaces.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
|
||||
|
||||
ContentArea.setContentViewForQueryString(DOWNLOADS_QUERY,
|
||||
function() new DownloadsPlacesView(document.getElementById("downloadsRichListBox")),
|
||||
{ showDetailsPane: false });
|
||||
]]></script>
|
||||
|
||||
<window id="places">
|
||||
<commandset id="downloadCommands"/>
|
||||
<menupopup id="downloadsContextMenu"/>
|
||||
</window>
|
||||
|
||||
<deck id="placesViewsDeck">
|
||||
<richlistbox id="downloadsRichListBox"/>
|
||||
</deck>
|
||||
</overlay>
|
@ -5,11 +5,6 @@
|
||||
|
||||
Components.utils.import("resource:///modules/MigrationUtils.jsm");
|
||||
|
||||
const DOWNLOADS_QUERY = "place:transition=" +
|
||||
Components.interfaces.nsINavHistoryService.TRANSITION_DOWNLOAD +
|
||||
"&sort=" +
|
||||
Components.interfaces.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
|
||||
|
||||
var PlacesOrganizer = {
|
||||
_places: null,
|
||||
|
||||
@ -87,7 +82,7 @@ var PlacesOrganizer = {
|
||||
// Select the first item in the content area view.
|
||||
let view = ContentArea.currentView;
|
||||
let root = view.result ? view.result.root : null;
|
||||
if (root && root.containerOpen && root.childCount >= 0)
|
||||
if (root && root.containerOpen && root.childCount > 0)
|
||||
view.selectNode(root.getChild(0));
|
||||
ContentArea.focus();
|
||||
},
|
||||
@ -279,6 +274,13 @@ var PlacesOrganizer = {
|
||||
* Handle focus changes on the places list and the current content view.
|
||||
*/
|
||||
updateDetailsPane: function PO_updateDetailsPane() {
|
||||
let detailsDeck = document.getElementById("detailsDeck");
|
||||
let detailsPaneDisabled = detailsDeck.hidden =
|
||||
!ContentArea.currentViewOptions.showDetailsPane;
|
||||
if (detailsPaneDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
let view = PlacesUIUtils.getViewForNode(document.activeElement);
|
||||
if (view) {
|
||||
let selectedNodes = view.selectedNode ?
|
||||
@ -1246,35 +1248,60 @@ let gPrivateBrowsingListener = {
|
||||
#endif
|
||||
|
||||
let ContentArea = {
|
||||
_specialViews: new Map(),
|
||||
|
||||
init: function CA_init() {
|
||||
this._deck = document.getElementById("placesViewsDeck");
|
||||
this._specialViews = new Map();
|
||||
ContentTree.init();
|
||||
},
|
||||
|
||||
_shouldUseNewDownloadsView: function CA_shouldUseNewDownloadsView() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref("browser.library.useNewDownloadsView");
|
||||
}
|
||||
catch(ex) { }
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the content view to be used for loading the given query.
|
||||
* If a custom view was set by setContentViewForQueryString, that
|
||||
* view would be returned, else the default tree view is returned
|
||||
*
|
||||
* @param aQueryString
|
||||
* a query string
|
||||
* @return the view to be used for loading aQueryString.
|
||||
*/
|
||||
getContentViewForQueryString:
|
||||
function CA_getContentViewForQueryString(aQueryString) {
|
||||
if (this._specialViews.has(aQueryString))
|
||||
return this._specialViews.get(aQueryString);
|
||||
if (aQueryString == DOWNLOADS_QUERY && this._shouldUseNewDownloadsView()) {
|
||||
let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"));
|
||||
this.setContentViewForQueryString(aQueryString, view);
|
||||
return view;
|
||||
try {
|
||||
if (this._specialViews.has(aQueryString)) {
|
||||
let { view, options } = this._specialViews.get(aQueryString);
|
||||
if (typeof view == "function") {
|
||||
view = view();
|
||||
this._specialViews.set(aQueryString, { view: view, options: options });
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
return ContentTree.view;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a custom view to be used rather than the default places tree
|
||||
* whenever the given query is selected in the left pane.
|
||||
* @param aQueryString
|
||||
* a query string
|
||||
* @param aView
|
||||
* Either the custom view or a function that will return the view
|
||||
* the first (and only) time it's called.
|
||||
* @param [optional] aOptions
|
||||
* Object defining special options for the view.
|
||||
* @see ContentTree.viewOptions for supported options and default values.
|
||||
*/
|
||||
setContentViewForQueryString:
|
||||
function CA_setContentViewForQueryString(aQueryString, aView) {
|
||||
this._specialViews.set(aQueryString, aView);
|
||||
function CA_setContentViewForQueryString(aQueryString, aView, aOptions) {
|
||||
if (!aQueryString ||
|
||||
typeof aView != "object" && typeof aView != "function")
|
||||
throw new Error("Invalid arguments");
|
||||
|
||||
this._specialViews.set(aQueryString, { view: aView,
|
||||
options: aOptions || new Object() });
|
||||
},
|
||||
|
||||
get currentView() PlacesUIUtils.getViewForNode(this._deck.selectedPanel),
|
||||
@ -1291,6 +1318,23 @@ let ContentArea = {
|
||||
return aQueryString;
|
||||
},
|
||||
|
||||
/**
|
||||
* Options for the current view.
|
||||
*
|
||||
* @see ContentTree.viewOptions for supported options and default values.
|
||||
*/
|
||||
get currentViewOptions() {
|
||||
// Use ContentTree options as default.
|
||||
let viewOptions = ContentTree.viewOptions;
|
||||
if (this._specialViews.has(this.currentPlace)) {
|
||||
let { view, options } = this._specialViews.get(this.currentPlace);
|
||||
for (let option in options) {
|
||||
viewOptions[option] = options[option];
|
||||
}
|
||||
}
|
||||
return viewOptions;
|
||||
},
|
||||
|
||||
focus: function() {
|
||||
this._deck.selectedPanel.focus();
|
||||
}
|
||||
@ -1303,6 +1347,8 @@ let ContentTree = {
|
||||
|
||||
get view() this._view,
|
||||
|
||||
get viewOptions() Object.seal({ showDetailsPane: true }),
|
||||
|
||||
openSelectedNode: function CT_openSelectedNode(aEvent) {
|
||||
let view = this.view;
|
||||
PlacesUIUtils.openNodeWithEvent(view.selectedNode, aEvent, view);
|
||||
|
@ -12,7 +12,6 @@
|
||||
<?xml-stylesheet href="chrome://browser/skin/places/organizer.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://browser/content/downloads/allDownloadsViewOverlay.xul"?>
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
|
||||
@ -405,7 +404,6 @@
|
||||
</treecols>
|
||||
<treechildren flex="1"/>
|
||||
</tree>
|
||||
<richlistbox id="downloadsRichListBox"/>
|
||||
</deck>
|
||||
<deck id="detailsDeck" style="height: 11em;">
|
||||
<vbox id="itemsCountBox" align="center">
|
||||
@ -440,7 +438,4 @@
|
||||
</deck>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<commandset id="downloadCommands"/>
|
||||
<menupopup id="downloadsContextMenu"/>
|
||||
</window>
|
||||
|
@ -3,6 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
browser.jar:
|
||||
% overlay chrome://browser/content/places/places.xul chrome://browser/content/places/downloadsViewOverlay.xul
|
||||
# Provide another URI for the bookmarkProperties dialog so we can persist the
|
||||
# attributes separately
|
||||
content/browser/places/bookmarkProperties2.xul (content/bookmarkProperties.xul)
|
||||
@ -30,3 +31,4 @@ browser.jar:
|
||||
content/browser/places/moveBookmarks.js (content/moveBookmarks.js)
|
||||
content/browser/places/editBookmarkOverlay.xul (content/editBookmarkOverlay.xul)
|
||||
content/browser/places/editBookmarkOverlay.js (content/editBookmarkOverlay.js)
|
||||
content/browser/places/downloadsViewOverlay.xul (content/downloadsViewOverlay.xul)
|
||||
|
@ -15,42 +15,56 @@ let now = Date.now();
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
function onLibraryReady(win) {
|
||||
let onLibraryReady = function(win) {
|
||||
// Add visits to compare contents with.
|
||||
fastAddVisit("http://mozilla.com",
|
||||
PlacesUtils.history.TRANSITION_TYPED);
|
||||
fastAddVisit("http://google.com",
|
||||
PlacesUtils.history.TRANSITION_DOWNLOAD);
|
||||
fastAddVisit("http://en.wikipedia.org",
|
||||
PlacesUtils.history.TRANSITION_TYPED);
|
||||
fastAddVisit("http://ubuntu.org",
|
||||
PlacesUtils.history.TRANSITION_DOWNLOAD);
|
||||
let places = [
|
||||
{ uri: NetUtil.newURI("http://mozilla.com"),
|
||||
visits: [ new VisitInfo(PlacesUtils.history.TRANSITION_TYPED) ]
|
||||
},
|
||||
{ uri: NetUtil.newURI("http://google.com"),
|
||||
visits: [ new VisitInfo(PlacesUtils.history.TRANSITION_DOWNLOAD) ]
|
||||
},
|
||||
{ uri: NetUtil.newURI("http://en.wikipedia.org"),
|
||||
visits: [ new VisitInfo(PlacesUtils.history.TRANSITION_TYPED) ]
|
||||
},
|
||||
{ uri: NetUtil.newURI("http://ubuntu.org"),
|
||||
visits: [ new VisitInfo(PlacesUtils.history.TRANSITION_DOWNLOAD) ]
|
||||
},
|
||||
]
|
||||
PlacesUtils.asyncHistory.updatePlaces(places, {
|
||||
handleResult: function () {},
|
||||
handleError: function () {
|
||||
ok(false, "gHistory.updatePlaces() failed");
|
||||
},
|
||||
handleCompletion: function () {
|
||||
// Make sure Downloads is present.
|
||||
isnot(win.PlacesOrganizer._places.selectedNode, null,
|
||||
"Downloads is present and selected");
|
||||
|
||||
// Make sure Downloads is present.
|
||||
isnot(win.PlacesOrganizer._places.selectedNode, null,
|
||||
"Downloads is present and selected");
|
||||
|
||||
// Make sure content in right pane exists.
|
||||
let tree = win.document.getElementById("placeContent");
|
||||
isnot(tree, null, "placeContent tree exists");
|
||||
// Check results.
|
||||
let contentRoot = win.ContentArea.currentView.result.root;
|
||||
let len = contentRoot.childCount;
|
||||
const TEST_URIS = ["http://ubuntu.org/", "http://google.com/"];
|
||||
for (let i = 0; i < len; i++) {
|
||||
is(contentRoot.getChild(i).uri, TEST_URIS[i],
|
||||
"Comparing downloads shown at index " + i);
|
||||
}
|
||||
|
||||
// Check results.
|
||||
var contentRoot = tree.result.root;
|
||||
var len = contentRoot.childCount;
|
||||
var testUris = ["http://ubuntu.org/", "http://google.com/"];
|
||||
for (var i = 0; i < len; i++) {
|
||||
is(contentRoot.getChild(i).uri, testUris[i],
|
||||
"Comparing downloads shown at index " + i);
|
||||
}
|
||||
|
||||
win.close();
|
||||
waitForClearHistory(finish);
|
||||
win.close();
|
||||
waitForClearHistory(finish);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
openLibrary(onLibraryReady, "Downloads");
|
||||
}
|
||||
|
||||
function fastAddVisit(uri, transition) {
|
||||
PlacesUtils.history.addVisit(PlacesUtils._uri(uri), now++ * 1000,
|
||||
null, transition, false, 0);
|
||||
function VisitInfo(aTransitionType)
|
||||
{
|
||||
this.transitionType =
|
||||
aTransitionType === undefined ?
|
||||
PlacesUtils.history.TRANSITION_LINK : aTransitionType;
|
||||
this.visitDate = now++ * 1000;
|
||||
}
|
||||
VisitInfo.prototype = {}
|
||||
|
@ -11,7 +11,7 @@ browser.jar:
|
||||
* content/browser/preferences/in-content/tabs.xul
|
||||
* content/browser/preferences/in-content/tabs.js
|
||||
content/browser/preferences/in-content/privacy.xul
|
||||
content/browser/preferences/in-content/privacy.js
|
||||
* content/browser/preferences/in-content/privacy.js
|
||||
* content/browser/preferences/in-content/advanced.xul
|
||||
* content/browser/preferences/in-content/advanced.js
|
||||
content/browser/preferences/in-content/applications.xul
|
||||
|
@ -2,6 +2,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||
"resource:///modules/DownloadsCommon.jsm");
|
||||
|
||||
var gMainPane = {
|
||||
_pane: null,
|
||||
|
||||
@ -18,12 +21,25 @@ var gMainPane = {
|
||||
|
||||
this.updateBrowserStartupLastSession();
|
||||
|
||||
this.setupDownloadsWindowOptions();
|
||||
|
||||
// Notify observers that the UI is now ready
|
||||
Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService)
|
||||
.notifyObservers(window, "main-pane-loaded", null);
|
||||
},
|
||||
|
||||
setupDownloadsWindowOptions: function ()
|
||||
{
|
||||
let showWhenDownloading = document.getElementById("showWhenDownloading");
|
||||
let closeWhenDone = document.getElementById("closeWhenDone");
|
||||
|
||||
// These radio buttons should be hidden when the Downloads Panel is enabled.
|
||||
let shouldHide = !DownloadsCommon.useToolkitUI;
|
||||
showWhenDownloading.hidden = shouldHide;
|
||||
closeWhenDone.hidden = shouldHide;
|
||||
},
|
||||
|
||||
// HOME PAGE
|
||||
|
||||
/*
|
||||
|
@ -9,6 +9,11 @@ var gPrivacyPane = {
|
||||
*/
|
||||
_autoStartPrivateBrowsing: false,
|
||||
|
||||
/**
|
||||
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
|
||||
*/
|
||||
_shouldPromptForRestart: true,
|
||||
|
||||
/**
|
||||
* Sets up the UI for the number of days of history to keep, and updates the
|
||||
* label of the "Clear Now..." button.
|
||||
@ -127,7 +132,8 @@ var gPrivacyPane = {
|
||||
let pref = document.getElementById("browser.privatebrowsing.autostart");
|
||||
switch (document.getElementById("historyMode").value) {
|
||||
case "remember":
|
||||
pref.value = false;
|
||||
if (pref.value)
|
||||
pref.value = false;
|
||||
|
||||
// select the remember history option if needed
|
||||
let rememberHistoryCheckbox = document.getElementById("rememberHistory");
|
||||
@ -146,7 +152,8 @@ var gPrivacyPane = {
|
||||
document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false;
|
||||
break;
|
||||
case "dontremember":
|
||||
pref.value = true;
|
||||
if (!pref.value)
|
||||
pref.value = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -219,19 +226,65 @@ var gPrivacyPane = {
|
||||
|
||||
observe: function PPP_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Components.interfaces.nsIPrivateBrowsingService);
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
if (!gPrivacyPane._shouldPromptForRestart) {
|
||||
// We're performing a revert. Just let it happen.
|
||||
gPrivacyPane._shouldPromptForRestart = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const Cc = Components.classes, Ci = Components.interfaces;
|
||||
let pref = document.getElementById("browser.privatebrowsing.autostart");
|
||||
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
|
||||
let bundle = document.getElementById("bundlePreferences");
|
||||
let msg = bundle.getFormattedString(pref.value ?
|
||||
"featureEnableRequiresRestart" : "featureDisableRequiresRestart",
|
||||
[brandName]);
|
||||
let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
|
||||
let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
|
||||
let shouldProceed = prompts.confirm(window, title, msg)
|
||||
if (shouldProceed) {
|
||||
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
|
||||
"restart");
|
||||
shouldProceed = !cancelQuit.data;
|
||||
|
||||
if (shouldProceed) {
|
||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Ci.nsIAppStartup);
|
||||
appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
gPrivacyPane._shouldPromptForRestart = false;
|
||||
pref.value = !pref.value;
|
||||
|
||||
let mode = document.getElementById("historyMode");
|
||||
if (mode.value != "custom") {
|
||||
mode.selectedIndex = pref.value ? 1 : 0;
|
||||
mode.doCommand();
|
||||
} else {
|
||||
let rememberHistoryCheckbox = document.getElementById("rememberHistory");
|
||||
rememberHistory.checked = pref.value;
|
||||
}
|
||||
#else
|
||||
// Toggle the private browsing mode without switching the session
|
||||
let prefValue = document.getElementById("browser.privatebrowsing.autostart").value;
|
||||
let keepCurrentSession = document.getElementById("browser.privatebrowsing.keep_current_session");
|
||||
keepCurrentSession.value = true;
|
||||
|
||||
let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Components.interfaces.nsIPrivateBrowsingService);
|
||||
|
||||
// If activating from within the private browsing mode, reset the
|
||||
// private session
|
||||
if (prefValue && privateBrowsingService.privateBrowsingEnabled)
|
||||
privateBrowsingService.privateBrowsingEnabled = false;
|
||||
privateBrowsingService.privateBrowsingEnabled = prefValue;
|
||||
|
||||
keepCurrentSession.reset();
|
||||
#endif
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -15,22 +15,31 @@ _BROWSER_FILES = \
|
||||
head.js \
|
||||
browser_advanced_update.js \
|
||||
browser_bug410900.js \
|
||||
browser_bug567487.js \
|
||||
browser_bug731866.js \
|
||||
browser_connection.js \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += \
|
||||
privacypane_tests.js \
|
||||
browser_bug567487.js \
|
||||
browser_privacypane_1.js \
|
||||
browser_privacypane_2.js \
|
||||
browser_privacypane_3.js \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_8.js \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += \
|
||||
browser_privacypane_6.js \
|
||||
browser_privacypane_7.js \
|
||||
browser_privacypane_8.js \
|
||||
$(NULL)
|
||||
else
|
||||
_BROWSER_FILES += \
|
||||
privacypane_tests_perwindow.js \
|
||||
browser_privacypane_1.js \
|
||||
browser_privacypane_3.js \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_8.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_pane_visibility,
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_historymode_retention("remember", undefined),
|
||||
|
@ -10,7 +10,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_custom_retention("rememberHistory", "remember"),
|
||||
|
@ -10,7 +10,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_custom_retention("acceptCookies", "remember"),
|
||||
|
@ -10,7 +10,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_locbar_suggestion_retention(-1, undefined),
|
||||
|
@ -10,7 +10,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_privatebrowsing_toggle,
|
||||
|
@ -10,7 +10,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_privatebrowsing_ui,
|
||||
|
@ -10,7 +10,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
// history mode should be initialized to remember
|
||||
|
@ -0,0 +1,344 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTestOnPrivacyPrefPane(testFunc) {
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", function(aEvent) {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", arguments.callee, true);
|
||||
let browser = aEvent.originalTarget.linkedBrowser;
|
||||
browser.addEventListener("Initialized", function(aEvent) {
|
||||
browser.removeEventListener("Initialized", arguments.callee, true);
|
||||
is(browser.contentWindow.location.href, "about:preferences", "Checking if the preferences tab was opened");
|
||||
testFunc(browser.contentWindow);
|
||||
gBrowser.removeCurrentTab();
|
||||
testRunner.runNext();
|
||||
}, true);
|
||||
}, true);
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:preferences");
|
||||
}
|
||||
|
||||
function controlChanged(element) {
|
||||
element.doCommand();
|
||||
}
|
||||
|
||||
// We can only test the panes that don't trigger a preference update
|
||||
function test_pane_visibility(win) {
|
||||
let modes = {
|
||||
"remember": "historyRememberPane",
|
||||
"custom": "historyCustomPane"
|
||||
};
|
||||
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let historypane = win.document.getElementById("historyPane");
|
||||
ok(historypane, "history mode pane should exist");
|
||||
|
||||
for (let mode in modes) {
|
||||
historymode.value = mode;
|
||||
controlChanged(historymode);
|
||||
is(historypane.selectedPanel, win.document.getElementById(modes[mode]),
|
||||
"The correct pane should be selected for the " + mode + " mode");
|
||||
}
|
||||
}
|
||||
|
||||
function test_dependent_elements(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("rememberHistory"),
|
||||
win.document.getElementById("rememberForms"),
|
||||
win.document.getElementById("keepUntil"),
|
||||
win.document.getElementById("keepCookiesUntil"),
|
||||
win.document.getElementById("alwaysClear"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the dependent controls should exist");
|
||||
});
|
||||
let independents = [
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
];
|
||||
independents.forEach(function(control) {
|
||||
ok(control, "the independent controls should exist");
|
||||
});
|
||||
let cookieexceptions = win.document.getElementById("cookieExceptions");
|
||||
ok(cookieexceptions, "the cookie exceptions button should exist");
|
||||
let keepuntil = win.document.getElementById("keepCookiesUntil");
|
||||
ok(keepuntil, "the keep cookies until menulist should exist");
|
||||
let alwaysclear = win.document.getElementById("alwaysClear");
|
||||
ok(alwaysclear, "the clear data on close checkbox should exist");
|
||||
let rememberhistory = win.document.getElementById("rememberHistory");
|
||||
ok(rememberhistory, "the remember history checkbox should exist");
|
||||
let rememberforms = win.document.getElementById("rememberForms");
|
||||
ok(rememberforms, "the remember forms checkbox should exist");
|
||||
let alwaysclearsettings = win.document.getElementById("clearDataSettings");
|
||||
ok(alwaysclearsettings, "the clear data settings button should exist");
|
||||
|
||||
function expect_disabled(disabled) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.disabled, disabled,
|
||||
control.getAttribute("id") + " should " + (disabled ? "" : "not ") + "be disabled");
|
||||
});
|
||||
is(keepuntil.value, disabled ? 2 : 0,
|
||||
"the keep cookies until menulist value should be as expected");
|
||||
if (disabled) {
|
||||
ok(!alwaysclear.checked,
|
||||
"the clear data on close checkbox value should be as expected");
|
||||
ok(!rememberhistory.checked,
|
||||
"the remember history checkbox value should be as expected");
|
||||
ok(!rememberforms.checked,
|
||||
"the remember forms checkbox value should be as expected");
|
||||
}
|
||||
}
|
||||
function check_independents(expected) {
|
||||
independents.forEach(function(control) {
|
||||
is(control.disabled, expected,
|
||||
control.getAttribute("id") + " should " + (expected ? "" : "not ") + "be disabled");
|
||||
});
|
||||
|
||||
ok(!cookieexceptions.disabled,
|
||||
"the cookie exceptions button should never be disabled");
|
||||
ok(alwaysclearsettings.disabled,
|
||||
"the clear data settings button should always be disabled");
|
||||
}
|
||||
|
||||
// controls should only change in custom mode
|
||||
historymode.value = "remember";
|
||||
controlChanged(historymode);
|
||||
expect_disabled(false);
|
||||
check_independents(false);
|
||||
|
||||
// setting the mode to custom shouldn't change anything
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
expect_disabled(false);
|
||||
check_independents(false);
|
||||
}
|
||||
|
||||
function test_dependent_cookie_elements(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("keepUntil"),
|
||||
win.document.getElementById("keepCookiesUntil"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the dependent cookie controls should exist");
|
||||
});
|
||||
let acceptcookies = win.document.getElementById("acceptCookies");
|
||||
ok(acceptcookies, "the accept cookies checkbox should exist");
|
||||
|
||||
function expect_disabled(disabled) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.disabled, disabled,
|
||||
control.getAttribute("id") + " should " + (disabled ? "" : "not ") + "be disabled");
|
||||
});
|
||||
}
|
||||
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
pbautostart.checked = false;
|
||||
controlChanged(pbautostart);
|
||||
expect_disabled(false);
|
||||
|
||||
acceptcookies.checked = false;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(true);
|
||||
|
||||
acceptcookies.checked = true;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(false);
|
||||
|
||||
let accessthirdparty = controls.shift();
|
||||
acceptcookies.checked = false;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(true);
|
||||
ok(accessthirdparty.disabled, "access third party button should be disabled");
|
||||
|
||||
pbautostart.checked = false;
|
||||
controlChanged(pbautostart);
|
||||
expect_disabled(true);
|
||||
ok(accessthirdparty.disabled, "access third party button should be disabled");
|
||||
|
||||
acceptcookies.checked = true;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(false);
|
||||
ok(!accessthirdparty.disabled, "access third party button should be enabled");
|
||||
}
|
||||
|
||||
function test_dependent_clearonclose_elements(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let alwaysclear = win.document.getElementById("alwaysClear");
|
||||
ok(alwaysclear, "the clear data on close checkbox should exist");
|
||||
let alwaysclearsettings = win.document.getElementById("clearDataSettings");
|
||||
ok(alwaysclearsettings, "the clear data settings button should exist");
|
||||
|
||||
function expect_disabled(disabled) {
|
||||
is(alwaysclearsettings.disabled, disabled,
|
||||
"the clear data settings should " + (disabled ? "" : "not ") + "be disabled");
|
||||
}
|
||||
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
pbautostart.checked = false;
|
||||
controlChanged(pbautostart);
|
||||
alwaysclear.checked = false;
|
||||
controlChanged(alwaysclear);
|
||||
expect_disabled(true);
|
||||
|
||||
alwaysclear.checked = true;
|
||||
controlChanged(alwaysclear);
|
||||
expect_disabled(false);
|
||||
|
||||
alwaysclear.checked = false;
|
||||
controlChanged(alwaysclear);
|
||||
expect_disabled(true);
|
||||
}
|
||||
|
||||
function test_dependent_prefs(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("rememberHistory"),
|
||||
win.document.getElementById("rememberForms"),
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the micro-management controls should exist");
|
||||
});
|
||||
|
||||
function expect_checked(checked) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.checked, checked,
|
||||
control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
|
||||
});
|
||||
}
|
||||
|
||||
// controls should be checked in remember mode
|
||||
historymode.value = "remember";
|
||||
controlChanged(historymode);
|
||||
expect_checked(true);
|
||||
|
||||
// even if they're unchecked in custom mode
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
controls.forEach(function(control) {
|
||||
control.checked = false;
|
||||
controlChanged(control);
|
||||
});
|
||||
expect_checked(false);
|
||||
historymode.value = "remember";
|
||||
controlChanged(historymode);
|
||||
expect_checked(true);
|
||||
}
|
||||
|
||||
function test_historymode_retention(mode, expect) {
|
||||
return function(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
|
||||
if ((historymode.value == "remember" && mode == "dontremember") ||
|
||||
(historymode.value == "dontremember" && mode == "remember") ||
|
||||
(historymode.value == "custom" && mode == "dontremember")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expect !== undefined) {
|
||||
is(historymode.value, expect,
|
||||
"history mode is expected to remain " + expect);
|
||||
}
|
||||
|
||||
historymode.value = mode;
|
||||
controlChanged(historymode);
|
||||
};
|
||||
}
|
||||
|
||||
function test_custom_retention(controlToChange, expect, valueIncrement) {
|
||||
return function(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
|
||||
if (expect !== undefined) {
|
||||
is(historymode.value, expect,
|
||||
"history mode is expected to remain " + expect);
|
||||
}
|
||||
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
|
||||
controlToChange = win.document.getElementById(controlToChange);
|
||||
ok(controlToChange, "the control to change should exist");
|
||||
switch (controlToChange.localName) {
|
||||
case "checkbox":
|
||||
controlToChange.checked = !controlToChange.checked;
|
||||
break;
|
||||
case "textbox":
|
||||
controlToChange.value = parseInt(controlToChange.value) + valueIncrement;
|
||||
break;
|
||||
case "menulist":
|
||||
controlToChange.value = valueIncrement;
|
||||
break;
|
||||
}
|
||||
controlChanged(controlToChange);
|
||||
};
|
||||
}
|
||||
|
||||
function test_locbar_suggestion_retention(mode, expect) {
|
||||
return function(win) {
|
||||
let locbarsuggest = win.document.getElementById("locationBarSuggestion");
|
||||
ok(locbarsuggest, "location bar suggestion menulist should exist");
|
||||
|
||||
if (expect !== undefined) {
|
||||
is(locbarsuggest.value, expect,
|
||||
"location bar suggestion is expected to remain " + expect);
|
||||
}
|
||||
|
||||
locbarsuggest.value = mode;
|
||||
controlChanged(locbarsuggest);
|
||||
};
|
||||
}
|
||||
|
||||
function reset_preferences(win) {
|
||||
let prefs = win.document.querySelectorAll("#privacyPreferences > preference");
|
||||
for (let i = 0; i < prefs.length; ++i)
|
||||
if (prefs[i].hasUserValue)
|
||||
prefs[i].reset();
|
||||
}
|
||||
|
||||
let testRunner;
|
||||
function run_test_subset(subset) {
|
||||
Services.prefs.setBoolPref("browser.preferences.instantApply", true);
|
||||
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
// Reset pref to its default
|
||||
Services.prefs.clearUserPref("browser.preferences.instantApply");
|
||||
});
|
||||
|
||||
testRunner = {
|
||||
tests: subset,
|
||||
counter: 0,
|
||||
runNext: function() {
|
||||
if (this.counter == this.tests.length) {
|
||||
finish();
|
||||
} else {
|
||||
let self = this;
|
||||
setTimeout(function() {
|
||||
runTestOnPrivacyPrefPane(self.tests[self.counter++]);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
testRunner.runNext();
|
||||
}
|
@ -23,12 +23,25 @@ var gMainPane = {
|
||||
|
||||
this.updateBrowserStartupLastSession();
|
||||
|
||||
this.setupDownloadsWindowOptions();
|
||||
|
||||
// Notify observers that the UI is now ready
|
||||
Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService)
|
||||
.notifyObservers(window, "main-pane-loaded", null);
|
||||
},
|
||||
|
||||
setupDownloadsWindowOptions: function ()
|
||||
{
|
||||
let showWhenDownloading = document.getElementById("showWhenDownloading");
|
||||
let closeWhenDone = document.getElementById("closeWhenDone");
|
||||
|
||||
// These radio buttons should be hidden when the Downloads Panel is enabled.
|
||||
let shouldHide = !DownloadsCommon.useToolkitUI;
|
||||
showWhenDownloading.hidden = shouldHide;
|
||||
closeWhenDone.hidden = shouldHide;
|
||||
},
|
||||
|
||||
// HOME PAGE
|
||||
|
||||
/*
|
||||
|
@ -12,6 +12,11 @@ var gPrivacyPane = {
|
||||
*/
|
||||
_autoStartPrivateBrowsing: false,
|
||||
|
||||
/**
|
||||
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
|
||||
*/
|
||||
_shouldPromptForRestart: true,
|
||||
|
||||
/**
|
||||
* Sets up the UI for the number of days of history to keep, and updates the
|
||||
* label of the "Clear Now..." button.
|
||||
@ -130,7 +135,8 @@ var gPrivacyPane = {
|
||||
let pref = document.getElementById("browser.privatebrowsing.autostart");
|
||||
switch (document.getElementById("historyMode").value) {
|
||||
case "remember":
|
||||
pref.value = false;
|
||||
if (pref.value)
|
||||
pref.value = false;
|
||||
|
||||
// select the remember history option if needed
|
||||
let rememberHistoryCheckbox = document.getElementById("rememberHistory");
|
||||
@ -149,7 +155,8 @@ var gPrivacyPane = {
|
||||
document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false;
|
||||
break;
|
||||
case "dontremember":
|
||||
pref.value = true;
|
||||
if (!pref.value)
|
||||
pref.value = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -222,12 +229,54 @@ var gPrivacyPane = {
|
||||
|
||||
observe: function PPP_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
if (!gPrivacyPane._shouldPromptForRestart) {
|
||||
// We're performing a revert. Just let it happen.
|
||||
gPrivacyPane._shouldPromptForRestart = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const Cc = Components.classes, Ci = Components.interfaces;
|
||||
let pref = document.getElementById("browser.privatebrowsing.autostart");
|
||||
let brandName = document.getElementById("bundleBrand").getString("brandShortName");
|
||||
let bundle = document.getElementById("bundlePreferences");
|
||||
let msg = bundle.getFormattedString(pref.value ?
|
||||
"featureEnableRequiresRestart" : "featureDisableRequiresRestart",
|
||||
[brandName]);
|
||||
let title = bundle.getFormattedString("shouldRestartTitle", [brandName]);
|
||||
let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
|
||||
let shouldProceed = prompts.confirm(window, title, msg)
|
||||
if (shouldProceed) {
|
||||
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
|
||||
.createInstance(Ci.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
|
||||
"restart");
|
||||
shouldProceed = !cancelQuit.data;
|
||||
|
||||
if (shouldProceed) {
|
||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Ci.nsIAppStartup);
|
||||
appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
gPrivacyPane._shouldPromptForRestart = false;
|
||||
pref.value = !pref.value;
|
||||
|
||||
let mode = document.getElementById("historyMode");
|
||||
if (mode.value != "custom") {
|
||||
mode.selectedIndex = pref.value ? 1 : 0;
|
||||
mode.doCommand();
|
||||
} else {
|
||||
let rememberHistoryCheckbox = document.getElementById("rememberHistory");
|
||||
rememberHistory.checked = pref.value;
|
||||
}
|
||||
#else
|
||||
// Toggle the private browsing mode without switching the session
|
||||
let prefValue = document.getElementById("browser.privatebrowsing.autostart").value;
|
||||
let keepCurrentSession = document.getElementById("browser.privatebrowsing.keep_current_session");
|
||||
keepCurrentSession.value = true;
|
||||
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
let privateBrowsingService = Components.classes["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Components.interfaces.nsIPrivateBrowsingService);
|
||||
|
||||
@ -236,9 +285,9 @@ var gPrivacyPane = {
|
||||
if (prefValue && privateBrowsingService.privateBrowsingEnabled)
|
||||
privateBrowsingService.privateBrowsingEnabled = false;
|
||||
privateBrowsingService.privateBrowsingEnabled = prefValue;
|
||||
#endif
|
||||
|
||||
keepCurrentSession.reset();
|
||||
#endif
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -14,23 +14,32 @@ include $(topsrcdir)/config/rules.mk
|
||||
_BROWSER_FILES = \
|
||||
browser_advanced_update.js \
|
||||
browser_bug410900.js \
|
||||
browser_bug567487.js \
|
||||
browser_bug705422.js \
|
||||
privacypane_tests.js \
|
||||
browser_privacypane_1.js \
|
||||
browser_privacypane_2.js \
|
||||
browser_privacypane_3.js \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_8.js \
|
||||
browser_permissions.js \
|
||||
browser_chunk_permissions.js \
|
||||
$(NULL)
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += \
|
||||
privacypane_tests.js \
|
||||
browser_bug567487.js \
|
||||
browser_privacypane_1.js \
|
||||
browser_privacypane_2.js \
|
||||
browser_privacypane_3.js \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_6.js \
|
||||
browser_privacypane_7.js \
|
||||
browser_privacypane_8.js \
|
||||
$(NULL)
|
||||
else
|
||||
_BROWSER_FILES += \
|
||||
privacypane_tests_perwindow.js \
|
||||
browser_privacypane_1.js \
|
||||
browser_privacypane_3.js \
|
||||
browser_privacypane_4.js \
|
||||
browser_privacypane_5.js \
|
||||
browser_privacypane_8.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -12,7 +12,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_pane_visibility,
|
||||
|
@ -12,7 +12,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_historymode_retention("remember", undefined),
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_custom_retention("rememberHistory", "remember"),
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_custom_retention("acceptCookies", "remember"),
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_locbar_suggestion_retention(-1, undefined),
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_privatebrowsing_toggle,
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
test_privatebrowsing_ui,
|
||||
|
@ -11,7 +11,11 @@ function test() {
|
||||
let tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
try {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
|
||||
} catch(x) {
|
||||
loader.loadSubScript(rootDir + "privacypane_tests.js", this);
|
||||
}
|
||||
|
||||
run_test_subset([
|
||||
// history mode should be initialized to remember
|
||||
|
@ -0,0 +1,352 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function runTestOnPrivacyPrefPane(testFunc) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
Services.ww.unregisterNotification(this);
|
||||
|
||||
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
|
||||
win.addEventListener("load", function() {
|
||||
win.removeEventListener("load", arguments.callee, false);
|
||||
testFunc(dialog.document.defaultView);
|
||||
|
||||
Services.ww.registerNotification(observer);
|
||||
dialog.close();
|
||||
}, false);
|
||||
} else if (aTopic == "domwindowclosed") {
|
||||
Services.ww.unregisterNotification(this);
|
||||
testRunner.runNext();
|
||||
}
|
||||
}
|
||||
};
|
||||
Services.ww.registerNotification(observer);
|
||||
|
||||
let dialog = openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences",
|
||||
"chrome,titlebar,toolbar,centerscreen,dialog=no", "panePrivacy");
|
||||
}
|
||||
|
||||
function controlChanged(element) {
|
||||
element.doCommand();
|
||||
}
|
||||
|
||||
// We can only test the panes that don't trigger a preference update
|
||||
function test_pane_visibility(win) {
|
||||
let modes = {
|
||||
"remember": "historyRememberPane",
|
||||
"custom": "historyCustomPane"
|
||||
};
|
||||
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let historypane = win.document.getElementById("historyPane");
|
||||
ok(historypane, "history mode pane should exist");
|
||||
|
||||
for (let mode in modes) {
|
||||
historymode.value = mode;
|
||||
controlChanged(historymode);
|
||||
is(historypane.selectedPanel, win.document.getElementById(modes[mode]),
|
||||
"The correct pane should be selected for the " + mode + " mode");
|
||||
}
|
||||
}
|
||||
|
||||
function test_dependent_elements(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("rememberHistory"),
|
||||
win.document.getElementById("rememberForms"),
|
||||
win.document.getElementById("keepUntil"),
|
||||
win.document.getElementById("keepCookiesUntil"),
|
||||
win.document.getElementById("alwaysClear"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the dependent controls should exist");
|
||||
});
|
||||
let independents = [
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
];
|
||||
independents.forEach(function(control) {
|
||||
ok(control, "the independent controls should exist");
|
||||
});
|
||||
let cookieexceptions = win.document.getElementById("cookieExceptions");
|
||||
ok(cookieexceptions, "the cookie exceptions button should exist");
|
||||
let keepuntil = win.document.getElementById("keepCookiesUntil");
|
||||
ok(keepuntil, "the keep cookies until menulist should exist");
|
||||
let alwaysclear = win.document.getElementById("alwaysClear");
|
||||
ok(alwaysclear, "the clear data on close checkbox should exist");
|
||||
let rememberhistory = win.document.getElementById("rememberHistory");
|
||||
ok(rememberhistory, "the remember history checkbox should exist");
|
||||
let rememberforms = win.document.getElementById("rememberForms");
|
||||
ok(rememberforms, "the remember forms checkbox should exist");
|
||||
let alwaysclearsettings = win.document.getElementById("clearDataSettings");
|
||||
ok(alwaysclearsettings, "the clear data settings button should exist");
|
||||
|
||||
function expect_disabled(disabled) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.disabled, disabled,
|
||||
control.getAttribute("id") + " should " + (disabled ? "" : "not ") + "be disabled");
|
||||
});
|
||||
is(keepuntil.value, disabled ? 2 : 0,
|
||||
"the keep cookies until menulist value should be as expected");
|
||||
if (disabled) {
|
||||
ok(!alwaysclear.checked,
|
||||
"the clear data on close checkbox value should be as expected");
|
||||
ok(!rememberhistory.checked,
|
||||
"the remember history checkbox value should be as expected");
|
||||
ok(!rememberforms.checked,
|
||||
"the remember forms checkbox value should be as expected");
|
||||
}
|
||||
}
|
||||
function check_independents(expected) {
|
||||
independents.forEach(function(control) {
|
||||
is(control.disabled, expected,
|
||||
control.getAttribute("id") + " should " + (expected ? "" : "not ") + "be disabled");
|
||||
});
|
||||
ok(!cookieexceptions.disabled,
|
||||
"the cookie exceptions button should never be disabled");
|
||||
ok(alwaysclearsettings.disabled,
|
||||
"the clear data settings button should always be disabled");
|
||||
}
|
||||
|
||||
// controls should only change in custom mode
|
||||
historymode.value = "remember";
|
||||
controlChanged(historymode);
|
||||
expect_disabled(false);
|
||||
check_independents(false);
|
||||
|
||||
// setting the mode to custom shouldn't change anything
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
expect_disabled(false);
|
||||
check_independents(false);
|
||||
}
|
||||
|
||||
function test_dependent_cookie_elements(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
win.document.getElementById("keepUntil"),
|
||||
win.document.getElementById("keepCookiesUntil"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the dependent cookie controls should exist");
|
||||
});
|
||||
let acceptcookies = win.document.getElementById("acceptCookies");
|
||||
ok(acceptcookies, "the accept cookies checkbox should exist");
|
||||
|
||||
function expect_disabled(disabled) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.disabled, disabled,
|
||||
control.getAttribute("id") + " should " + (disabled ? "" : "not ") + "be disabled");
|
||||
});
|
||||
}
|
||||
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
pbautostart.checked = false;
|
||||
controlChanged(pbautostart);
|
||||
expect_disabled(false);
|
||||
|
||||
acceptcookies.checked = false;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(true);
|
||||
|
||||
acceptcookies.checked = true;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(false);
|
||||
|
||||
let accessthirdparty = controls.shift();
|
||||
acceptcookies.checked = false;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(true);
|
||||
ok(accessthirdparty.disabled, "access third party button should be disabled");
|
||||
|
||||
pbautostart.checked = false;
|
||||
controlChanged(pbautostart);
|
||||
expect_disabled(true);
|
||||
ok(accessthirdparty.disabled, "access third party button should be disabled");
|
||||
|
||||
acceptcookies.checked = true;
|
||||
controlChanged(acceptcookies);
|
||||
expect_disabled(false);
|
||||
ok(!accessthirdparty.disabled, "access third party button should be enabled");
|
||||
}
|
||||
|
||||
function test_dependent_clearonclose_elements(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
|
||||
ok(pbautostart, "the private browsing auto-start checkbox should exist");
|
||||
let alwaysclear = win.document.getElementById("alwaysClear");
|
||||
ok(alwaysclear, "the clear data on close checkbox should exist");
|
||||
let alwaysclearsettings = win.document.getElementById("clearDataSettings");
|
||||
ok(alwaysclearsettings, "the clear data settings button should exist");
|
||||
|
||||
function expect_disabled(disabled) {
|
||||
is(alwaysclearsettings.disabled, disabled,
|
||||
"the clear data settings should " + (disabled ? "" : "not ") + "be disabled");
|
||||
}
|
||||
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
pbautostart.checked = false;
|
||||
controlChanged(pbautostart);
|
||||
alwaysclear.checked = false;
|
||||
controlChanged(alwaysclear);
|
||||
expect_disabled(true);
|
||||
|
||||
alwaysclear.checked = true;
|
||||
controlChanged(alwaysclear);
|
||||
expect_disabled(false);
|
||||
|
||||
alwaysclear.checked = false;
|
||||
controlChanged(alwaysclear);
|
||||
expect_disabled(true);
|
||||
}
|
||||
|
||||
function test_dependent_prefs(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
let controls = [
|
||||
win.document.getElementById("rememberHistory"),
|
||||
win.document.getElementById("rememberForms"),
|
||||
win.document.getElementById("acceptCookies"),
|
||||
win.document.getElementById("acceptThirdParty"),
|
||||
];
|
||||
controls.forEach(function(control) {
|
||||
ok(control, "the micro-management controls should exist");
|
||||
});
|
||||
|
||||
function expect_checked(checked) {
|
||||
controls.forEach(function(control) {
|
||||
is(control.checked, checked,
|
||||
control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
|
||||
});
|
||||
}
|
||||
|
||||
// controls should be checked in remember mode
|
||||
historymode.value = "remember";
|
||||
controlChanged(historymode);
|
||||
expect_checked(true);
|
||||
|
||||
// even if they're unchecked in custom mode
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
controls.forEach(function(control) {
|
||||
control.checked = false;
|
||||
controlChanged(control);
|
||||
});
|
||||
expect_checked(false);
|
||||
historymode.value = "remember";
|
||||
controlChanged(historymode);
|
||||
expect_checked(true);
|
||||
}
|
||||
|
||||
function test_historymode_retention(mode, expect) {
|
||||
return function(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
|
||||
if ((historymode.value == "remember" && mode == "dontremember") ||
|
||||
(historymode.value == "dontremember" && mode == "remember") ||
|
||||
(historymode.value == "custom" && mode == "dontremember")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expect !== undefined) {
|
||||
is(historymode.value, expect,
|
||||
"history mode is expected to remain " + expect);
|
||||
}
|
||||
|
||||
historymode.value = mode;
|
||||
controlChanged(historymode);
|
||||
};
|
||||
}
|
||||
|
||||
function test_custom_retention(controlToChange, expect, valueIncrement) {
|
||||
return function(win) {
|
||||
let historymode = win.document.getElementById("historyMode");
|
||||
ok(historymode, "history mode menulist should exist");
|
||||
|
||||
if (expect !== undefined) {
|
||||
is(historymode.value, expect,
|
||||
"history mode is expected to remain " + expect);
|
||||
}
|
||||
|
||||
historymode.value = "custom";
|
||||
controlChanged(historymode);
|
||||
|
||||
controlToChange = win.document.getElementById(controlToChange);
|
||||
ok(controlToChange, "the control to change should exist");
|
||||
switch (controlToChange.localName) {
|
||||
case "checkbox":
|
||||
controlToChange.checked = !controlToChange.checked;
|
||||
break;
|
||||
case "textbox":
|
||||
controlToChange.value = parseInt(controlToChange.value) + valueIncrement;
|
||||
break;
|
||||
case "menulist":
|
||||
controlToChange.value = valueIncrement;
|
||||
break;
|
||||
}
|
||||
controlChanged(controlToChange);
|
||||
};
|
||||
}
|
||||
|
||||
function test_locbar_suggestion_retention(mode, expect) {
|
||||
return function(win) {
|
||||
let locbarsuggest = win.document.getElementById("locationBarSuggestion");
|
||||
ok(locbarsuggest, "location bar suggestion menulist should exist");
|
||||
|
||||
if (expect !== undefined) {
|
||||
is(locbarsuggest.value, expect,
|
||||
"location bar suggestion is expected to remain " + expect);
|
||||
}
|
||||
|
||||
locbarsuggest.value = mode;
|
||||
controlChanged(locbarsuggest);
|
||||
};
|
||||
}
|
||||
|
||||
function reset_preferences(win) {
|
||||
let prefs = win.document.getElementsByTagName("preference");
|
||||
for (let i = 0; i < prefs.length; ++i)
|
||||
if (prefs[i].hasUserValue)
|
||||
prefs[i].reset();
|
||||
}
|
||||
|
||||
let testRunner;
|
||||
function run_test_subset(subset) {
|
||||
let instantApplyOrig = Services.prefs.getBoolPref("browser.preferences.instantApply");
|
||||
Services.prefs.setBoolPref("browser.preferences.instantApply", true);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
testRunner = {
|
||||
tests: subset,
|
||||
counter: 0,
|
||||
runNext: function() {
|
||||
if (this.counter == this.tests.length) {
|
||||
// cleanup
|
||||
Services.prefs.setBoolPref("browser.preferences.instantApply", instantApplyOrig);
|
||||
finish();
|
||||
} else {
|
||||
let self = this;
|
||||
setTimeout(function() {
|
||||
runTestOnPrivacyPrefPane(self.tests[self.counter++]);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
testRunner.runNext();
|
||||
}
|
@ -11,7 +11,9 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = privatebrowsing
|
||||
|
||||
ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
DIRS = src
|
||||
endif
|
||||
|
||||
TEST_DIRS += test
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user