Merge mozilla-central into build-system
@ -41,9 +41,8 @@
|
||||
|
||||
#include "nsMaiInterfaceText.h"
|
||||
|
||||
#include "nsHyperTextAccessible.h"
|
||||
#include "nsRoleMap.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
|
||||
|
||||
@ -374,14 +373,9 @@ getCharacterCountCB(AtkText *aText)
|
||||
if (!accWrap)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIAccessibleText> accText;
|
||||
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
|
||||
getter_AddRefs(accText));
|
||||
NS_ENSURE_TRUE(accText, 0);
|
||||
|
||||
PRInt32 count = 0;
|
||||
nsresult rv = accText->GetCharacterCount(&count);
|
||||
return (NS_FAILED(rv)) ? 0 : static_cast<gint>(count);
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(accWrap));
|
||||
return textAcc->IsDefunct() ?
|
||||
0 : static_cast<gint>(textAcc->CharacterCount());
|
||||
}
|
||||
|
||||
gint
|
||||
|
@ -54,8 +54,10 @@
|
||||
NotificationController::NotificationController(nsDocAccessible* aDocument,
|
||||
nsIPresShell* aPresShell) :
|
||||
mObservingState(eNotObservingRefresh), mDocument(aDocument),
|
||||
mPresShell(aPresShell)
|
||||
mPresShell(aPresShell), mTreeConstructedState(eTreeConstructionPending)
|
||||
{
|
||||
// Schedule initial accessible tree construction.
|
||||
ScheduleProcessing();
|
||||
}
|
||||
|
||||
NotificationController::~NotificationController()
|
||||
@ -80,6 +82,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController)
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDocument");
|
||||
cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mDocument.get()));
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(mHangingChildDocuments,
|
||||
nsDocAccessible)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(mContentInsertions,
|
||||
ContentInsertion)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(mEvents, AccEvent)
|
||||
@ -99,8 +103,16 @@ NotificationController::Shutdown()
|
||||
mObservingState = eNotObservingRefresh;
|
||||
}
|
||||
|
||||
// Shutdown handling child documents.
|
||||
PRInt32 childDocCount = mHangingChildDocuments.Length();
|
||||
for (PRInt32 idx = childDocCount - 1; idx >= 0; idx--)
|
||||
mHangingChildDocuments[idx]->Shutdown();
|
||||
|
||||
mHangingChildDocuments.Clear();
|
||||
|
||||
mDocument = nsnull;
|
||||
mPresShell = nsnull;
|
||||
|
||||
mContentInsertions.Clear();
|
||||
mNotifications.Clear();
|
||||
mEvents.Clear();
|
||||
@ -124,11 +136,23 @@ NotificationController::QueueEvent(AccEvent* aEvent)
|
||||
ScheduleProcessing();
|
||||
}
|
||||
|
||||
void
|
||||
NotificationController::ScheduleChildDocBinding(nsDocAccessible* aDocument)
|
||||
{
|
||||
// Schedule child document binding to the tree.
|
||||
mHangingChildDocuments.AppendElement(aDocument);
|
||||
ScheduleProcessing();
|
||||
}
|
||||
|
||||
void
|
||||
NotificationController::ScheduleContentInsertion(nsAccessible* aContainer,
|
||||
nsIContent* aStartChildNode,
|
||||
nsIContent* aEndChildNode)
|
||||
{
|
||||
// Ignore content insertions until we constructed accessible tree.
|
||||
if (mTreeConstructedState == eTreeConstructionPending)
|
||||
return;
|
||||
|
||||
nsRefPtr<ContentInsertion> insertion =
|
||||
new ContentInsertion(mDocument, aContainer, aStartChildNode, aEndChildNode);
|
||||
|
||||
@ -177,6 +201,20 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
// insertions or generic notifications.
|
||||
mObservingState = eRefreshProcessingForUpdate;
|
||||
|
||||
// Initial accessible tree construction.
|
||||
if (mTreeConstructedState == eTreeConstructionPending) {
|
||||
// If document is not bound to parent at this point then the document is not
|
||||
// ready yet (process notifications later).
|
||||
if (!mDocument->IsBoundToParent())
|
||||
return;
|
||||
|
||||
mTreeConstructedState = eTreeConstructed;
|
||||
mDocument->CacheChildrenInSubtree(mDocument);
|
||||
|
||||
NS_ASSERTION(mContentInsertions.Length() == 0,
|
||||
"Pending content insertions while initial accessible tree isn't created!");
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -197,6 +235,36 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind hanging child documents.
|
||||
PRUint32 childDocCount = mHangingChildDocuments.Length();
|
||||
for (PRUint32 idx = 0; idx < childDocCount; idx++) {
|
||||
nsDocAccessible* childDoc = mHangingChildDocuments[idx];
|
||||
|
||||
nsIContent* ownerContent = mDocument->GetDocumentNode()->
|
||||
FindContentForSubDocument(childDoc->GetDocumentNode());
|
||||
if (ownerContent) {
|
||||
nsAccessible* outerDocAcc = mDocument->GetCachedAccessible(ownerContent);
|
||||
if (outerDocAcc && outerDocAcc->AppendChild(childDoc)) {
|
||||
if (mDocument->AppendChildDocument(childDoc)) {
|
||||
// Fire reorder event to notify new accessible document has been
|
||||
// attached to the tree.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, outerDocAcc,
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
if (reorderEvent)
|
||||
QueueEvent(reorderEvent);
|
||||
|
||||
continue;
|
||||
}
|
||||
outerDocAcc->RemoveChild(childDoc);
|
||||
}
|
||||
|
||||
// Failed to bind the child document, destroy it.
|
||||
childDoc->Shutdown();
|
||||
}
|
||||
}
|
||||
mHangingChildDocuments.Clear();
|
||||
|
||||
// Process only currently queued generic notifications.
|
||||
nsTArray < nsRefPtr<Notification> > notifications;
|
||||
notifications.SwapElements(mNotifications);
|
||||
|
@ -126,6 +126,14 @@ public:
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
|
||||
|
||||
/**
|
||||
* Return true when tree is constructed.
|
||||
*/
|
||||
inline bool IsTreeConstructed()
|
||||
{
|
||||
return mTreeConstructedState == eTreeConstructed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the notification controller.
|
||||
*/
|
||||
@ -136,6 +144,11 @@ public:
|
||||
*/
|
||||
void QueueEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Schedule binding the child document to the tree of this document.
|
||||
*/
|
||||
void ScheduleChildDocBinding(nsDocAccessible* aDocument);
|
||||
|
||||
/**
|
||||
* Pend accessible tree update for content insertion.
|
||||
*/
|
||||
@ -256,6 +269,22 @@ private:
|
||||
*/
|
||||
nsIPresShell* mPresShell;
|
||||
|
||||
/**
|
||||
* Indicate whether initial construction of the document's accessible tree
|
||||
* performed or pending. When the document accessible is created then
|
||||
* we construct its initial accessible tree.
|
||||
*/
|
||||
enum eTreeConstructedState {
|
||||
eTreeConstructed,
|
||||
eTreeConstructionPending
|
||||
};
|
||||
eTreeConstructedState mTreeConstructedState;
|
||||
|
||||
/**
|
||||
* Child documents that needs to be bound to the tree.
|
||||
*/
|
||||
nsTArray<nsRefPtr<nsDocAccessible> > mHangingChildDocuments;
|
||||
|
||||
/**
|
||||
* Storage for content inserted notification information.
|
||||
*/
|
||||
|
@ -429,32 +429,20 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
||||
|
||||
PRBool isRootDoc = nsCoreUtils::IsRootDocument(aDocument);
|
||||
|
||||
// Ensure the document container node is accessible, otherwise do not create
|
||||
// document accessible.
|
||||
nsAccessible *outerDocAcc = nsnull;
|
||||
if (isRootDoc) {
|
||||
outerDocAcc = nsAccessNode::GetApplicationAccessible();
|
||||
|
||||
} else {
|
||||
nsIDocument* parentDoc = aDocument->GetParentDocument();
|
||||
if (!parentDoc)
|
||||
return nsnull;
|
||||
|
||||
nsIContent* ownerContent = parentDoc->FindContentForSubDocument(aDocument);
|
||||
if (!ownerContent)
|
||||
return nsnull;
|
||||
|
||||
nsDocAccessible* parentDocAcc = nsnull;
|
||||
if (!isRootDoc) {
|
||||
// XXXaaronl: ideally we would traverse the presshell chain. Since there's
|
||||
// no easy way to do that, we cheat and use the document hierarchy.
|
||||
// GetAccessible() is bad because it doesn't support our concept of multiple
|
||||
// presshells per doc. It should be changed to use
|
||||
// GetAccessibleInWeakShell().
|
||||
outerDocAcc = GetAccService()->GetAccessible(ownerContent);
|
||||
parentDocAcc = GetDocAccessible(aDocument->GetParentDocument());
|
||||
NS_ASSERTION(parentDocAcc,
|
||||
"Can't create an accessible for the document!");
|
||||
if (!parentDocAcc)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!outerDocAcc)
|
||||
return nsnull;
|
||||
|
||||
// We only create root accessibles for the true root, otherwise create a
|
||||
// doc accessible.
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
@ -466,21 +454,33 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
||||
if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc))
|
||||
return nsnull;
|
||||
|
||||
// Bind the document accessible into tree.
|
||||
if (!outerDocAcc->AppendChild(docAcc)) {
|
||||
mDocAccessibleCache.Remove(aDocument);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Initialize the document accessible. Note, Init() should be called after
|
||||
// the document accessible is bound to the tree.
|
||||
// Initialize the document accessible.
|
||||
if (!docAcc->Init()) {
|
||||
docAcc->Shutdown();
|
||||
mDocAccessibleCache.Remove(aDocument);
|
||||
return nsnull;
|
||||
}
|
||||
docAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aDocument));
|
||||
|
||||
// Bind the document to the tree.
|
||||
if (isRootDoc) {
|
||||
nsAccessible* appAcc = nsAccessNode::GetApplicationAccessible();
|
||||
if (!appAcc->AppendChild(docAcc)) {
|
||||
docAcc->Shutdown();
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Fire reorder event to notify new accessible document has been attached to
|
||||
// the tree.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, appAcc, eAutoDetect,
|
||||
AccEvent::eCoalesceFromSameSubtree);
|
||||
if (reorderEvent)
|
||||
docAcc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
|
||||
} else {
|
||||
parentDocAcc->BindChildDocument(docAcc);
|
||||
}
|
||||
|
||||
NS_LOG_ACCDOCCREATE("document creation finished", aDocument)
|
||||
|
||||
AddListeners(aDocument, isRootDoc);
|
||||
|
@ -143,26 +143,14 @@ nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
|
||||
// nsIAccessibilityService
|
||||
void
|
||||
nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent *aTarget)
|
||||
nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent* aTargetNode)
|
||||
{
|
||||
nsIDocument *document = aTarget->GetCurrentDoc();
|
||||
if (!document)
|
||||
return;
|
||||
|
||||
// If the jump target is not accessible then fire an event for nearest
|
||||
// accessible in parent chain.
|
||||
nsCOMPtr<nsIWeakReference> weakShell(nsCoreUtils::GetWeakShellFor(aTarget));
|
||||
nsAccessible* targetAcc = GetAccessibleOrContainer(aTarget, weakShell);
|
||||
if (!targetAcc)
|
||||
return;
|
||||
|
||||
nsINode* targetNode = targetAcc->GetNode();
|
||||
|
||||
// XXX note in rare cases the node could go away before we flush the queue,
|
||||
// for example if the node becomes inaccessible, or is removed from the DOM.
|
||||
GetDocAccessible(document)->
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
|
||||
targetNode);
|
||||
nsIDocument* documentNode = aTargetNode->GetCurrentDoc();
|
||||
if (documentNode) {
|
||||
nsDocAccessible* document = GetDocAccessible(documentNode);
|
||||
if (document)
|
||||
document->HandleAnchorJump(aTargetNode);
|
||||
}
|
||||
}
|
||||
|
||||
// nsIAccessibilityService
|
||||
@ -1259,7 +1247,7 @@ nsAccessibilityService::GetAccessibleByRule(nsINode* aNode,
|
||||
|
||||
if (aWhatToGet & eGetAccForNode) {
|
||||
nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (cachedAcc && cachedAcc->IsBoundToParent())
|
||||
if (cachedAcc && (cachedAcc->IsBoundToParent() || cachedAcc->IsDocument()))
|
||||
return cachedAcc;
|
||||
}
|
||||
|
||||
|
@ -320,7 +320,8 @@ nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
*aState |= nsIAccessibleStates::STATE_FOCUSED;
|
||||
}
|
||||
|
||||
if (!mIsLoaded) {
|
||||
// Expose state busy until the document is loaded or tree is constructed.
|
||||
if (!mIsLoaded || !mNotificationController->IsTreeConstructed()) {
|
||||
*aState |= nsIAccessibleStates::STATE_BUSY;
|
||||
if (aExtraState) {
|
||||
*aExtraState |= nsIAccessibleStates::EXT_STATE_STALE;
|
||||
@ -629,22 +630,7 @@ nsDocAccessible::Init()
|
||||
return PR_FALSE;
|
||||
|
||||
AddEventListeners();
|
||||
|
||||
nsDocAccessible* parentDocument = mParent->GetDocAccessible();
|
||||
if (parentDocument)
|
||||
parentDocument->AppendChildDocument(this);
|
||||
|
||||
// Fire reorder event to notify new accessible document has been created and
|
||||
// attached to the tree.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mParent, eAutoDetect,
|
||||
AccEvent::eCoalesceFromSameSubtree);
|
||||
if (reorderEvent) {
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1833,6 +1819,23 @@ nsDocAccessible::ProcessPendingEvent(AccEvent* aEvent)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocAccessible::ProcessAnchorJump(nsIContent* aTargetNode)
|
||||
{
|
||||
// If the jump target is not accessible then fire an event for nearest
|
||||
// accessible in parent chain.
|
||||
nsAccessible* target = GetAccService()->GetAccessibleOrContainer(aTargetNode,
|
||||
mWeakShell);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
// XXX: bug 625699, note in some cases the node could go away before we flush
|
||||
// the queue, for example if the node becomes inaccessible, or is removed from
|
||||
// the DOM.
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
|
||||
target->GetNode());
|
||||
}
|
||||
|
||||
void
|
||||
nsDocAccessible::ProcessContentInserted(nsAccessible* aContainer,
|
||||
const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent)
|
||||
|
@ -189,6 +189,23 @@ public:
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Handle anchor jump when page is loaded.
|
||||
*/
|
||||
inline void HandleAnchorJump(nsIContent* aTargetNode)
|
||||
{
|
||||
HandleNotification<nsDocAccessible, nsIContent>
|
||||
(this, &nsDocAccessible::ProcessAnchorJump, aTargetNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the child document to the tree.
|
||||
*/
|
||||
inline void BindChildDocument(nsDocAccessible* aDocument)
|
||||
{
|
||||
mNotificationController->ScheduleChildDocBinding(aDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the generic notification.
|
||||
*
|
||||
@ -390,6 +407,11 @@ protected:
|
||||
*/
|
||||
void ProcessPendingEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Process anchor jump notification and fire scrolling end event.
|
||||
*/
|
||||
void ProcessAnchorJump(nsIContent* aTargetNode);
|
||||
|
||||
/**
|
||||
* Update the accessible tree for inserted content.
|
||||
*/
|
||||
|
@ -282,13 +282,13 @@ nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset,
|
||||
nsAccessible **aEndAcc)
|
||||
{
|
||||
if (aStartOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
|
||||
GetCharacterCount(&aStartOffset);
|
||||
aStartOffset = CharacterCount();
|
||||
}
|
||||
if (aStartOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
|
||||
GetCaretOffset(&aStartOffset);
|
||||
}
|
||||
if (aEndOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
|
||||
GetCharacterCount(&aEndOffset);
|
||||
aEndOffset = CharacterCount();
|
||||
}
|
||||
if (aEndOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
|
||||
GetCaretOffset(&aEndOffset);
|
||||
@ -492,14 +492,7 @@ NS_IMETHODIMP nsHyperTextAccessible::GetCharacterCount(PRInt32 *aCharacterCount)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 childCount = GetChildCount();
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible *childAcc = mChildren[childIdx];
|
||||
|
||||
PRInt32 textLength = nsAccUtils::TextLength(childAcc);
|
||||
NS_ENSURE_TRUE(textLength >= 0, nsnull);
|
||||
*aCharacterCount += textLength;
|
||||
}
|
||||
*aCharacterCount = CharacterCount();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -874,7 +867,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
|
||||
}
|
||||
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT) {
|
||||
GetCharacterCount(&aOffset);
|
||||
aOffset = CharacterCount();
|
||||
}
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
|
||||
GetCaretOffset(&aOffset);
|
||||
@ -958,8 +951,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
|
||||
nsnull, getter_AddRefs(startAcc));
|
||||
|
||||
if (!startFrame) {
|
||||
PRInt32 textLength;
|
||||
GetCharacterCount(&textLength);
|
||||
PRInt32 textLength = CharacterCount();
|
||||
if (aBoundaryType == BOUNDARY_LINE_START && aOffset > 0 && aOffset == textLength) {
|
||||
// Asking for start of line, while on last character
|
||||
if (startAcc)
|
||||
@ -1023,8 +1015,7 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
|
||||
// that the first character is in
|
||||
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, aText);
|
||||
}
|
||||
PRInt32 textLength;
|
||||
GetCharacterCount(&textLength);
|
||||
PRInt32 textLength = CharacterCount();
|
||||
if (finalEndOffset < textLength) {
|
||||
// This happens sometimes when current character at finalStartOffset
|
||||
// is an embedded object character representing another hypertext, that
|
||||
@ -1419,8 +1410,7 @@ NS_IMETHODIMP nsHyperTextAccessible::SetAttributes(PRInt32 aStartPos, PRInt32 aE
|
||||
|
||||
NS_IMETHODIMP nsHyperTextAccessible::SetTextContents(const nsAString &aText)
|
||||
{
|
||||
PRInt32 numChars;
|
||||
GetCharacterCount(&numChars);
|
||||
PRInt32 numChars = CharacterCount();
|
||||
if (numChars == 0 || NS_SUCCEEDED(DeleteText(0, numChars))) {
|
||||
return InsertText(aText, 0);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
|
||||
virtual void InvalidateChildren();
|
||||
|
||||
// nsHyperTextAccessible
|
||||
// nsHyperTextAccessible (static helper method)
|
||||
|
||||
// Convert content offset to rendered text offset
|
||||
static nsresult ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
|
||||
@ -101,6 +101,9 @@ public:
|
||||
static nsresult RenderedToContentOffset(nsIFrame *aFrame, PRUint32 aRenderedOffset,
|
||||
PRInt32 *aContentOffset);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// HyperLinkAccessible
|
||||
|
||||
/**
|
||||
* Return link count within this hypertext accessible.
|
||||
*/
|
||||
@ -134,6 +137,9 @@ public:
|
||||
return child ? GetLinkIndex(child) : -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// nsHyperTextAccessible: DOM point to text offset conversions.
|
||||
|
||||
/**
|
||||
* Turn a DOM Node and offset into a character offset into this hypertext.
|
||||
* Will look for closest match when the DOM node does not have an accessible
|
||||
@ -192,6 +198,17 @@ public:
|
||||
nsIDOMNode **aEndNode,
|
||||
PRInt32 *aEndOffset);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// TextAccessible
|
||||
|
||||
/**
|
||||
* Return character count within the hypertext accessible.
|
||||
*/
|
||||
inline PRUint32 CharacterCount()
|
||||
{
|
||||
return GetChildOffset(GetChildCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return text offset of the given child accessible within hypertext
|
||||
* accessible.
|
||||
|
@ -1,13 +1,12 @@
|
||||
#import "mozAccessible.h"
|
||||
|
||||
#import "nsIAccessibleText.h"
|
||||
#import "nsIAccessibleEditableText.h"
|
||||
#import "nsHyperTextAccessible.h"
|
||||
|
||||
@interface mozTextAccessible : mozAccessible
|
||||
{
|
||||
// both of these are the same old mGeckoAccessible, but already
|
||||
// QI'd for us, to the right type, for convenience.
|
||||
nsIAccessibleText *mGeckoTextAccessible; // strong
|
||||
nsHyperTextAccessible *mGeckoTextAccessible; // strong
|
||||
nsIAccessibleEditableText *mGeckoEditableTextAccessible; // strong
|
||||
}
|
||||
@end
|
||||
|
@ -164,12 +164,7 @@ extern const NSString *kTopLevelUIElementAttribute; // NSAccessibilityTopLevel
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
||||
|
||||
if (mGeckoTextAccessible) {
|
||||
PRInt32 charCount = 0;
|
||||
mGeckoTextAccessible->GetCharacterCount(&charCount);
|
||||
return charCount;
|
||||
}
|
||||
return 0;
|
||||
return mGeckoTextAccessible ? mGeckoTextAccessible->CharacterCount() : 0;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
|
||||
}
|
||||
|
@ -43,23 +43,7 @@
|
||||
#include "Accessible2.h"
|
||||
#include "AccessibleText_i.c"
|
||||
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsIAccessibleText.h"
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "nsIWinAccessNode.h"
|
||||
#include "nsAccessNodeWrap.h"
|
||||
#include "nsAccessibleWrap.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define GET_NSIACCESSIBLETEXT \
|
||||
nsCOMPtr<nsIAccessibleText> textAcc(do_QueryObject(this));\
|
||||
NS_ASSERTION(textAcc,\
|
||||
"Subclass of CAccessibleText doesn't implement nsIAccessibleText");\
|
||||
if (!textAcc)\
|
||||
return E_FAIL;\
|
||||
#include "nsHyperTextAccessible.h"
|
||||
|
||||
// IUnknown
|
||||
|
||||
@ -87,8 +71,7 @@ STDMETHODIMP
|
||||
CAccessibleText::addSelection(long aStartOffset, long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
GET_NSIACCESSIBLETEXT
|
||||
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
nsresult rv = textAcc->AddSelection(aStartOffset, aEndOffset);
|
||||
return GetHRESULT(rv);
|
||||
|
||||
@ -108,7 +91,7 @@ __try {
|
||||
*aEndOffset = 0;
|
||||
*aTextAttributes = NULL;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
nsCOMPtr<nsIPersistentProperties> attributes;
|
||||
@ -138,7 +121,7 @@ CAccessibleText::get_caretOffset(long *aOffset)
|
||||
__try {
|
||||
*aOffset = -1;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRInt32 offset = 0;
|
||||
nsresult rv = textAcc->GetCaretOffset(&offset);
|
||||
@ -164,7 +147,7 @@ __try {
|
||||
*aWidth = 0;
|
||||
*aHeight = 0;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
|
||||
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
|
||||
@ -192,7 +175,7 @@ CAccessibleText::get_nSelections(long *aNSelections)
|
||||
__try {
|
||||
*aNSelections = 0;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRInt32 selCount = 0;
|
||||
nsresult rv = textAcc->GetSelectionCount(&selCount);
|
||||
@ -214,7 +197,7 @@ CAccessibleText::get_offsetAtPoint(long aX, long aY,
|
||||
__try {
|
||||
*aOffset = 0;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
|
||||
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
|
||||
@ -240,7 +223,7 @@ __try {
|
||||
*aStartOffset = 0;
|
||||
*aEndOffset = 0;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
nsresult rv = textAcc->GetSelectionBounds(aSelectionIndex,
|
||||
@ -262,7 +245,7 @@ CAccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
|
||||
__try {
|
||||
*aText = NULL;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
nsAutoString text;
|
||||
nsresult rv = textAcc->GetText(aStartOffset, aEndOffset, text);
|
||||
@ -290,7 +273,9 @@ __try {
|
||||
*aEndOffset = 0;
|
||||
*aText = NULL;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
if (textAcc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoString text;
|
||||
@ -298,7 +283,7 @@ __try {
|
||||
|
||||
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
|
||||
startOffset = 0;
|
||||
textAcc->GetCharacterCount(&endOffset);
|
||||
endOffset = textAcc->CharacterCount();
|
||||
rv = textAcc->GetText(startOffset, endOffset, text);
|
||||
} else {
|
||||
nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
|
||||
@ -335,7 +320,9 @@ __try {
|
||||
*aEndOffset = 0;
|
||||
*aText = NULL;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
if (textAcc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoString text;
|
||||
@ -343,7 +330,7 @@ __try {
|
||||
|
||||
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
|
||||
startOffset = 0;
|
||||
textAcc->GetCharacterCount(&endOffset);
|
||||
endOffset = textAcc->CharacterCount();
|
||||
rv = textAcc->GetText(startOffset, endOffset, text);
|
||||
} else {
|
||||
nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
|
||||
@ -380,7 +367,9 @@ __try {
|
||||
*aEndOffset = 0;
|
||||
*aText = NULL;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
if (textAcc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoString text;
|
||||
@ -388,7 +377,7 @@ __try {
|
||||
|
||||
if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
|
||||
startOffset = 0;
|
||||
textAcc->GetCharacterCount(&endOffset);
|
||||
endOffset = textAcc->CharacterCount();
|
||||
rv = textAcc->GetText(startOffset, endOffset, text);
|
||||
} else {
|
||||
nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
|
||||
@ -418,7 +407,7 @@ STDMETHODIMP
|
||||
CAccessibleText::removeSelection(long aSelectionIndex)
|
||||
{
|
||||
__try {
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
nsresult rv = textAcc->RemoveSelection(aSelectionIndex);
|
||||
return GetHRESULT(rv);
|
||||
@ -431,7 +420,7 @@ STDMETHODIMP
|
||||
CAccessibleText::setCaretOffset(long aOffset)
|
||||
{
|
||||
__try {
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
nsresult rv = textAcc->SetCaretOffset(aOffset);
|
||||
return GetHRESULT(rv);
|
||||
@ -445,7 +434,7 @@ CAccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
|
||||
long aEndOffset)
|
||||
{
|
||||
__try {
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
nsresult rv = textAcc->SetSelectionBounds(aSelectionIndex,
|
||||
aStartOffset, aEndOffset);
|
||||
@ -461,14 +450,11 @@ CAccessibleText::get_nCharacters(long *aNCharacters)
|
||||
__try {
|
||||
*aNCharacters = 0;
|
||||
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
if (textAcc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
PRInt32 charCount = 0;
|
||||
nsresult rv = textAcc->GetCharacterCount(&charCount);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*aNCharacters = charCount;
|
||||
*aNCharacters = textAcc->CharacterCount();
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
@ -480,7 +466,7 @@ CAccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
|
||||
enum IA2ScrollType aScrollType)
|
||||
{
|
||||
__try {
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
nsresult rv = textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
|
||||
return GetHRESULT(rv);
|
||||
@ -495,7 +481,7 @@ CAccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
|
||||
long aX, long aY)
|
||||
{
|
||||
__try {
|
||||
GET_NSIACCESSIBLETEXT
|
||||
nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
|
||||
|
||||
PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
|
||||
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
|
||||
|
@ -430,7 +430,7 @@ function eventQueue(aEventType)
|
||||
msg += " unexpected";
|
||||
|
||||
msg += ": event type: " + this.getEventTypeAsString(idx) +
|
||||
", target: " + prettyName(this.getEventTarget(idx));
|
||||
", target: " + this.getEventTargetDescr(idx);
|
||||
|
||||
gLogger.logToConsole(msg);
|
||||
gLogger.logToDOM(msg, true);
|
||||
@ -487,6 +487,12 @@ function eventQueue(aEventType)
|
||||
return this.mEventSeq[aIdx].target;
|
||||
}
|
||||
|
||||
this.getEventTargetDescr = function eventQueue_getEventTargetDescr(aIdx)
|
||||
{
|
||||
var descr = this.mEventSeq[aIdx].targetDescr;
|
||||
return descr ? descr : "no target description";
|
||||
}
|
||||
|
||||
this.getEventPhase = function eventQueue_getEventPhase(aIdx)
|
||||
{
|
||||
var eventItem = this.mEventSeq[aIdx];
|
||||
@ -895,6 +901,16 @@ function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
|
||||
return this.mTarget;
|
||||
}
|
||||
|
||||
this.__defineGetter__("targetDescr", invokerChecker_targetDescrGetter);
|
||||
|
||||
function invokerChecker_targetDescrGetter()
|
||||
{
|
||||
if (typeof this.mTarget == "function")
|
||||
return this.mTarget.toSource() + this.mTargetFuncArg;
|
||||
|
||||
return prettyName(this.mTarget);
|
||||
}
|
||||
|
||||
this.mTarget = aTargetOrFunc;
|
||||
this.mTargetFuncArg = aTargetFuncArg;
|
||||
}
|
||||
|
@ -2,20 +2,38 @@
|
||||
<head>
|
||||
<title>Accessible events testing for document</title>
|
||||
<script>
|
||||
const STATE_BUSY = Components.interfaces.nsIAccessibleStates.STATE_BUSY;
|
||||
|
||||
var gRetrieval = null;
|
||||
function waitForDocLoad()
|
||||
{
|
||||
if (!gRetrieval) {
|
||||
gRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
||||
getService(Components.interfaces.nsIAccessibleRetrieval);
|
||||
}
|
||||
|
||||
var accDoc = gRetrieval.getAccessibleFor(document);
|
||||
|
||||
var state = {};
|
||||
accDoc.getState(state, {});
|
||||
if (state.value & STATE_BUSY) {
|
||||
window.setTimeout(waitForDocLoad, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
hideIFrame();
|
||||
}
|
||||
|
||||
function hideIFrame()
|
||||
{
|
||||
var iframe = document.getElementById("iframe");
|
||||
|
||||
var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
|
||||
getService(Components.interfaces.nsIAccessibleRetrieval);
|
||||
accRetrieval.getAccessibleFor(iframe.contentDocument);
|
||||
|
||||
gRetrieval.getAccessibleFor(iframe.contentDocument);
|
||||
iframe.style.display = 'none';
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="hideIFrame();">
|
||||
<body onload="waitForDocLoad();">
|
||||
<iframe id="iframe"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -197,6 +197,10 @@
|
||||
this.invoker.iframeDoc = iframe.contentDocument;
|
||||
return iframe;
|
||||
},
|
||||
get targetDescr()
|
||||
{
|
||||
return "inner iframe of docload_wnd.html document";
|
||||
},
|
||||
invoker: thisObj
|
||||
};
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
var gScrollHandler = {
|
||||
handleEvent: function gScrollHandler_handleEvent(aEvent) {
|
||||
if (aEvent.DOMNode.getAttribute("name") == "link1") {
|
||||
ok(true, "scrolling start event was handled on link1");
|
||||
unregisterA11yEventListener(EVENT_SCROLLING_START, this);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -107,11 +107,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">
|
||||
Mozilla Bug 418368
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Cache links within hypertext accessible"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572394">
|
||||
Mozilla Bug 572394
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -106,6 +106,11 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Cache links within hypertext accessible"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572394">
|
||||
Mozilla Bug 572394
|
||||
</a>
|
||||
<a target="_blank"
|
||||
title="Text offsets don't get updated when text of first child text accessible is changed"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=625009">
|
||||
|
@ -11,6 +11,21 @@ const BOUNDARY_ATTRIBUTE_RANGE = nsIAccessibleText.BOUNDARY_ATTRIBUTE_RANGE;
|
||||
const kTodo = 1;
|
||||
const kOk = 2;
|
||||
|
||||
/**
|
||||
* Test characterCount for the given array of accessibles.
|
||||
*
|
||||
* @param aCount [in] the expected character count
|
||||
* @param aIDs [in] array of accessible identifiers to test
|
||||
*/
|
||||
function testCharacterCount(aIDs, aCount)
|
||||
{
|
||||
for (var i = 1; i < aIDs.length; i++) {
|
||||
var textacc = getAccessible(aIDs[i], [nsIAccessibleText]);
|
||||
is(textacc.characterCount, aCount,
|
||||
"Wrong character count for " + prettyName(aIDs[i]));
|
||||
}
|
||||
}
|
||||
|
||||
function testText(aIDs, aStartOffset, aEndOffset, aText)
|
||||
{
|
||||
for (var i = 0; i < aIDs.length; i++)
|
||||
|
@ -17,7 +17,9 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
testText([getNode("iframe").contentDocument], 0, 14, "outbody inbody");
|
||||
var iframeDoc = [ getNode("iframe").contentDocument ];
|
||||
testCharacterCount(iframeDoc, 15);
|
||||
testText(iframeDoc, 0, 15, "outbody inbody ");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -16,14 +16,19 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var IDs = ["input", "div", "textarea"];
|
||||
|
||||
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// characterCount
|
||||
|
||||
testCharacterCount(["input", "div"], 15);
|
||||
testCharacterCount(["textarea"], 16);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// getText
|
||||
|
||||
var IDs = ["input", "div", "textarea"];
|
||||
testText(IDs, 0, 1, "h");
|
||||
testText(IDs, 1, 3, "el");
|
||||
testText(IDs, 14, 15, "d");
|
||||
|
@ -18,15 +18,20 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// Tests for elements rendering the original sring
|
||||
var IDs = ["input", "div", "editable", "textarea"];
|
||||
|
||||
// __B__r__a__v__e__ __S__i__r__ __ __R__o__b__i__n__ __ __ __r__a__n
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// characterCount
|
||||
|
||||
testCharacterCount(["input", "div", "editable"], 22);
|
||||
testCharacterCount(["textarea"], 23);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// getText
|
||||
|
||||
var IDs = ["input", "div", "editable", "textarea"];
|
||||
|
||||
testText(IDs, 0, 1, "B");
|
||||
testText(IDs, 5, 6, " ");
|
||||
testText(IDs, 9, 11, " ");
|
||||
|
@ -56,6 +56,9 @@
|
||||
<emItem id="{3f963a5b-e555-4543-90e2-c3908898db71}">
|
||||
<versionRange minVersion=" " maxVersion="8.5"/>
|
||||
</emItem>
|
||||
<emItem id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
|
||||
<versionRange minVersion="1.1b1" maxVersion="1.1b1"/>
|
||||
</emItem>
|
||||
<emItem id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
|
||||
<versionRange minVersion="1.2" maxVersion="1.2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
@ -64,8 +67,11 @@
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem id="{8CE11043-9A15-4207-A565-0C94C42D590D}"/>
|
||||
<emItem id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
|
||||
<versionRange severity="1"/>
|
||||
</emItem>
|
||||
<emItem id="{B13721C7-F507-4982-B2E5-502A71474FED}">
|
||||
<versionRange minVersion=" " maxVersion="3.3.0.3970" severity="1"/>
|
||||
<versionRange severity="1"/>
|
||||
</emItem>
|
||||
<emItem id="{E8E88AB0-7182-11DF-904E-6045E0D72085}"/>
|
||||
</emItems>
|
||||
|
@ -40,6 +40,8 @@ topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
DISTROEXT = $(call core_abspath,$(DIST))/bin/distribution/extensions
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = {972ce4c6-7e08-4474-a285-3208198ce6fd}
|
||||
@ -51,11 +53,13 @@ EXTENSIONS = \
|
||||
testpilot@labs.mozilla.com \
|
||||
$(NULL)
|
||||
|
||||
define _INSTALL_EXTENSIONS
|
||||
$(PYTHON) $(topsrcdir)/config/nsinstall.py $(wildcard $(srcdir)/$(dir)/*) $(DIST)/bin/extensions/$(dir)
|
||||
define _INSTALL_EXTENSION
|
||||
cd $(srcdir)/$(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi *
|
||||
|
||||
endef # do not remove the blank line!
|
||||
|
||||
libs::
|
||||
$(foreach dir,$(EXTENSIONS),$(_INSTALL_EXTENSIONS))
|
||||
$(NSINSTALL) -D $(DISTROEXT)
|
||||
$(foreach dir,$(EXTENSIONS),$(_INSTALL_EXTENSION))
|
||||
endif
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>testpilot@labs.mozilla.com</em:id>
|
||||
<em:version>1.0.3</em:version>
|
||||
<em:version>1.0.4</em:version>
|
||||
<em:type>2</em:type>
|
||||
|
||||
<!-- Target Application this extension can install into,
|
||||
|
@ -687,22 +687,28 @@ let TestPilotSetup = {
|
||||
},
|
||||
|
||||
_experimentRequirementsAreMet: function TPS__requirementsMet(experiment) {
|
||||
// Returns true if we we meet the requirements to run this experiment
|
||||
// (e.g. meet the minimum Test Pilot version and Firefox version)
|
||||
// false if not.
|
||||
// If the experiment doesn't specify minimum versions, attempt to run it.
|
||||
/* Returns true if we we meet the requirements to run this experiment
|
||||
* (e.g. meet the minimum Test Pilot version and Firefox version)
|
||||
* false if not.
|
||||
* Default is always to run the study - return true UNLESS the study
|
||||
* specifies a requirement that we don't meet. */
|
||||
let logger = this._logger;
|
||||
try {
|
||||
let minTpVer, minFxVer, expName;
|
||||
if (experiment.experimentInfo) {
|
||||
minTpVer = experiment.experimentInfo.minTPVersion;
|
||||
minFxVer = experiment.experimentInfo.minFXVersion;
|
||||
expName = experiment.experimentInfo.testName;
|
||||
} else if (experiment.surveyInfo) {
|
||||
minTpVer = experiment.surveyInfo.minTPVersion;
|
||||
minFxVer = experiment.surveyInfo.minFXVersion;
|
||||
expName = experiment.surveyInfo.surveyName;
|
||||
let minTpVer, minFxVer, expName, runOrNotFunc;
|
||||
/* Could be an experiment, which specifies experimentInfo, or survey,
|
||||
* which specifies surveyInfo. */
|
||||
let info = experiment.experimentInfo ?
|
||||
experiment.experimentInfo :
|
||||
experiment.surveyInfo;
|
||||
if (!info) {
|
||||
// If neither one is supplied, study lacks metadata required to run
|
||||
logger.warn("Study lacks minimum metadata to run.");
|
||||
return false;
|
||||
}
|
||||
minTpVer = info.minTPVersion;
|
||||
minFxVer = info.minFXVersion;
|
||||
expName = info.testName;
|
||||
runOrNotFunc = info.runOrNotFunc;
|
||||
|
||||
// Minimum test pilot version:
|
||||
if (minTpVer && this._isNewerThanMe(minTpVer)) {
|
||||
@ -728,6 +734,12 @@ let TestPilotSetup = {
|
||||
logger.warn("Because it requires Firefox version " + minFxVer);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The all-purpose, arbitrary code "Should this study run?" function - if
|
||||
* provided, use its return value. */
|
||||
if (runOrNotFunc) {
|
||||
return runOrNotFunc();
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn("Error in requirements check " + e);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ pref("extensions.logging.enabled", false);
|
||||
// Preferences for AMO integration
|
||||
pref("extensions.getAddons.cache.enabled", true);
|
||||
pref("extensions.getAddons.maxResults", 15);
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%?src=firefox");
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
|
||||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/%APP%/search?q=%TERMS%");
|
||||
pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%?src=firefox");
|
||||
pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/%APP%/discovery/%VERSION%/%OS%");
|
||||
@ -244,8 +244,8 @@ pref("browser.aboutHomeSnippets.updateUrl", "http://snippets.mozilla.com/%STARTP
|
||||
pref("browser.enable_automatic_image_resizing", true);
|
||||
pref("browser.chrome.site_icons", true);
|
||||
pref("browser.chrome.favicons", true);
|
||||
pref("browser.warnOnQuit", true);
|
||||
pref("browser.warnOnRestart", true);
|
||||
pref("browser.warnOnQuit", false);
|
||||
pref("browser.warnOnRestart", false);
|
||||
pref("browser.fullscreen.autohide", true);
|
||||
pref("browser.fullscreen.animateUp", 1);
|
||||
|
||||
@ -539,9 +539,6 @@ pref("alerts.totalOpenTime", 4000);
|
||||
pref("browser.xul.error_pages.enabled", true);
|
||||
pref("browser.xul.error_pages.expert_bad_cert", false);
|
||||
|
||||
// Work Offline is best manually managed by the user.
|
||||
pref("network.manage-offline-status", false);
|
||||
|
||||
// We want to make sure mail URLs are handled externally...
|
||||
pref("network.protocol-handler.external.mailto", true); // for mail
|
||||
pref("network.protocol-handler.external.news", true); // for news
|
||||
|
@ -39,17 +39,20 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
<menupopup id="appmenu-popup"
|
||||
onpopupshowing="if (event.target == this) {
|
||||
updateEditUIVisibility();
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
onpopupshowing="updateEditUIVisibility();gSyncUI.updateUI();">
|
||||
#else
|
||||
onpopupshowing="updateEditUIVisibility();">
|
||||
gSyncUI.updateUI();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (event.target.parentNode.parentNode.parentNode.parentNode == this)
|
||||
this._currentPopup = event.target;">
|
||||
<hbox>
|
||||
<vbox id="appmenuPrimaryPane">
|
||||
<splitmenu id="appmenu_newTab"
|
||||
label="&tabCmd.label;"
|
||||
command="cmd_newNavigatorTab"
|
||||
key="key_newNavigatorTab">
|
||||
command="cmd_newNavigatorTab">
|
||||
<menupopup>
|
||||
<menuitem id="appmenu_newTab_popup"
|
||||
label="&tabCmd.label;"
|
||||
@ -116,8 +119,7 @@
|
||||
<splitmenu id="appmenu_print"
|
||||
iconic="true"
|
||||
label="&printCmd.label;"
|
||||
command="cmd_print"
|
||||
key="printKb">
|
||||
command="cmd_print">
|
||||
<menupopup>
|
||||
<menuitem id="appmenu_print_popup"
|
||||
class="menuitem-iconic"
|
||||
@ -203,8 +205,7 @@
|
||||
<splitmenu id="appmenu_bookmarks"
|
||||
iconic="true"
|
||||
label="&bookmarksMenu.label;"
|
||||
command="Browser:ShowAllBookmarks"
|
||||
key="manBookmarkKb">
|
||||
command="Browser:ShowAllBookmarks">
|
||||
<menupopup id="appmenu_bookmarksPopup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
@ -267,8 +268,7 @@
|
||||
<splitmenu id="appmenu_history"
|
||||
iconic="true"
|
||||
label="&historyMenu.label;"
|
||||
command="Browser:ShowAllHistory"
|
||||
key="showAllHistoryKb">
|
||||
command="Browser:ShowAllHistory">
|
||||
<menupopup id="appmenu_historyMenupopup"
|
||||
placespopup="true"
|
||||
oncommand="this.parentNode._placesView._onCommand(event);"
|
||||
|
@ -348,10 +348,8 @@ var PlacesCommandHook = {
|
||||
if (starIcon && isElementVisible(starIcon)) {
|
||||
// Make sure the bookmark properties dialog hangs toward the middle of
|
||||
// the location bar in RTL builds
|
||||
var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ?
|
||||
'bottomcenter topleft' : 'bottomcenter topright';
|
||||
if (aShowEditUI)
|
||||
StarUI.showEditBookmarkPopup(itemId, starIcon, position);
|
||||
StarUI.showEditBookmarkPopup(itemId, starIcon, "bottomcenter topright");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -117,8 +117,6 @@
|
||||
<command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);"/>
|
||||
<command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/>
|
||||
<command id="Browser:ToggleTabView" oncommand="TabView.toggle();"/>
|
||||
<command id="Browser:ShowTabView" oncommand="TabView.show();"/>
|
||||
<command id="Browser:HideTabView" oncommand="TabView.hide();"/>
|
||||
<command id="cmd_fullZoomReduce" oncommand="FullZoom.reduce()"/>
|
||||
<command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
|
||||
<command id="cmd_fullZoomReset" oncommand="FullZoom.reset()"/>
|
||||
|
@ -249,6 +249,7 @@ let gSyncUI = {
|
||||
},
|
||||
|
||||
onStartOver: function SUI_onStartOver() {
|
||||
Weave.Notifications.removeAll();
|
||||
this.updateUI();
|
||||
},
|
||||
|
||||
|
@ -155,13 +155,18 @@ splitmenu {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#splitmenu");
|
||||
}
|
||||
|
||||
.split-menuitem-item {
|
||||
.splitmenu-menuitem {
|
||||
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem");
|
||||
list-style-image: inherit;
|
||||
-moz-image-region: inherit;
|
||||
}
|
||||
|
||||
.split-menuitem-menu > .menu-text,
|
||||
.split-menuitem-menu > .menu-accel-container {
|
||||
.splitmenu-menuitem[iconic="true"] {
|
||||
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
|
||||
}
|
||||
|
||||
.splitmenu-menu > .menu-text,
|
||||
:-moz-any(.splitmenu-menu, .splitmenu-menuitem) > .menu-accel-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -279,7 +284,7 @@ panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .a
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#urlbar:not([actiontype]) > #urlbar-display {
|
||||
#urlbar:not([actiontype]) > #urlbar-display-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -719,11 +719,11 @@ const gXPInstallObserver = {
|
||||
options.installs = installInfo.installs;
|
||||
options.contentWindow = browser.contentWindow;
|
||||
options.sourceURI = browser.currentURI;
|
||||
options.eventCallback = function(aNotification, aEvent) {
|
||||
options.eventCallback = function(aEvent) {
|
||||
if (aEvent != "removed")
|
||||
return;
|
||||
aNotification.options.contentWindow = null;
|
||||
aNotification.options.sourceURI = null;
|
||||
options.contentWindow = null;
|
||||
options.sourceURI = null;
|
||||
};
|
||||
PopupNotifications.show(browser, notificationID, messageString, anchorID,
|
||||
null, null, options);
|
||||
@ -1736,7 +1736,8 @@ function nonBrowserWindowStartup()
|
||||
'Browser:SendLink', 'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain',
|
||||
'viewToolbarsMenu', 'viewSidebarMenuMenu', 'Browser:Reload',
|
||||
'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
|
||||
'viewHistorySidebar', 'Browser:AddBookmarkAs', 'View:PageInfo', 'Tasks:InspectPage'];
|
||||
'viewHistorySidebar', 'Browser:AddBookmarkAs', 'View:PageInfo', 'Tasks:InspectPage',
|
||||
'Browser:ToggleTabView'];
|
||||
var element;
|
||||
|
||||
for (var id in disabledItems)
|
||||
@ -3542,6 +3543,12 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
|
||||
#ifndef XP_MACOSX
|
||||
updateEditUIVisibility();
|
||||
#endif
|
||||
|
||||
// Hacky: update the PopupNotifications' object's reference to the iconBox,
|
||||
// if it already exists, since it may have changed if the URL bar was
|
||||
// added/removed.
|
||||
if (!__lookupGetter__("PopupNotifications"))
|
||||
PopupNotifications.iconBox = document.getElementById("notification-popup-box");
|
||||
}
|
||||
|
||||
PlacesToolbarHelper.customizeDone();
|
||||
@ -4319,6 +4326,21 @@ var XULBrowserWindow = {
|
||||
document.documentElement.setAttribute("disablechrome", "true");
|
||||
else
|
||||
document.documentElement.removeAttribute("disablechrome");
|
||||
|
||||
// Disable find commands in documents that ask for them to be disabled.
|
||||
let docElt = content.document.documentElement;
|
||||
let disableFind = aLocationURI &&
|
||||
(docElt && docElt.getAttribute("disablefastfind") == "true") &&
|
||||
(aLocationURI.schemeIs("about") || aLocationURI.schemeIs("chrome"));
|
||||
let findCommands = [document.getElementById("cmd_find"),
|
||||
document.getElementById("cmd_findAgain"),
|
||||
document.getElementById("cmd_findPrevious")];
|
||||
findCommands.forEach(function (elt) {
|
||||
if (disableFind)
|
||||
elt.setAttribute("disabled", "true");
|
||||
else
|
||||
elt.removeAttribute("disabled");
|
||||
});
|
||||
}
|
||||
UpdateBackForwardCommands(gBrowser.webNavigation);
|
||||
|
||||
|
@ -571,7 +571,9 @@
|
||||
</hbox>
|
||||
</hbox>
|
||||
</box>
|
||||
<label id="urlbar-display" value="&urlbar.switchToTab.label;"/>
|
||||
<box id="urlbar-display-box" align="center">
|
||||
<label id="urlbar-display" value="&urlbar.switchToTab.label;"/>
|
||||
</box>
|
||||
<hbox id="urlbar-icons">
|
||||
<image id="page-report-button"
|
||||
class="urlbar-icon"
|
||||
|
@ -79,6 +79,9 @@ let Change = {
|
||||
this._firstBox = document.getElementById("textBox1");
|
||||
this._secondBox = document.getElementById("textBox2");
|
||||
|
||||
this._dialog.getButton("finish").disabled = true;
|
||||
this._dialog.getButton("back").hidden = true;
|
||||
|
||||
this._stringBundle =
|
||||
Services.strings.createBundle("chrome://browser/locale/syncGenericChange.properties");
|
||||
|
||||
@ -87,34 +90,35 @@ let Change = {
|
||||
case "ResetPassphrase":
|
||||
document.getElementById("textBox1Row").hidden = true;
|
||||
document.getElementById("textBox2Row").hidden = true;
|
||||
let passphraseLabel = document.getElementById("passphraseLabel");
|
||||
passphraseLabel.value = this._str("new.synckey.label");
|
||||
document.getElementById("passphraseLabel").value
|
||||
= this._str("new.synckey.label");
|
||||
document.getElementById("passphraseSpacer").hidden = false;
|
||||
|
||||
if (this._updatingPassphrase) {
|
||||
document.getElementById("passphraseBackupButtons").hidden = true;
|
||||
document.getElementById("generatePassphraseButton").hidden = true;
|
||||
document.getElementById("passphraseHelpBox").hidden = false;
|
||||
document.title = this._str("new.synckey.title");
|
||||
introText.textContent = this._str("new.synckey2.introText");
|
||||
this._dialog.getButton("accept")
|
||||
.setAttribute("label", this._str("new.synckey.acceptButton"));
|
||||
this._dialog.getButton("finish").label
|
||||
= this._str("new.synckey.acceptButton");
|
||||
}
|
||||
else {
|
||||
document.getElementById("generatePassphraseButton").hidden = false;
|
||||
document.getElementById("generatePassphraseButton").hidden = false;
|
||||
this._passphraseBox.setAttribute("readonly", "true");
|
||||
let pp = Weave.Service.passphrase;
|
||||
if (Weave.Utils.isPassphrase(pp))
|
||||
pp = Weave.Utils.hyphenatePassphrase(pp);
|
||||
document.getElementById("passphraseBox").value = pp;
|
||||
this._passphraseBox.value = pp;
|
||||
this._passphraseBox.focus();
|
||||
document.title = this._str("change.synckey.title");
|
||||
introText.innerHTML = this._str("change.synckey.introText");
|
||||
introText2.innerHTML = this._str("change.synckey.introText2");
|
||||
warningText.innerHTML = this._str("change.synckey2.warningText");
|
||||
this._dialog.getButton("accept")
|
||||
.setAttribute("label", this._str("change.synckey.acceptButton"));
|
||||
introText.textContent = this._str("change.synckey.introText2");
|
||||
warningText.textContent = this._str("change.synckey2.warningText");
|
||||
this._dialog.getButton("finish").label
|
||||
= this._str("change.synckey.acceptButton");
|
||||
}
|
||||
break;
|
||||
case "ChangePassword":
|
||||
document.getElementById("passphraseRow").hidden = true;
|
||||
document.getElementById("passphraseBackupButtons").hidden = true;
|
||||
let box1label = document.getElementById("textBox1Label");
|
||||
let box2label = document.getElementById("textBox2Label");
|
||||
box1label.value = this._str("new.password.label");
|
||||
@ -122,8 +126,8 @@ let Change = {
|
||||
if (this._currentPasswordInvalid) {
|
||||
document.title = this._str("new.password.title");
|
||||
introText.textContent = this._str("new.password.introText");
|
||||
this._dialog.getButton("accept")
|
||||
.setAttribute("label", this._str("new.password.acceptButton"));
|
||||
this._dialog.getButton("finish").label
|
||||
= this._str("new.password.acceptButton");
|
||||
document.getElementById("textBox2Row").hidden = true;
|
||||
}
|
||||
else {
|
||||
@ -131,11 +135,13 @@ let Change = {
|
||||
box2label.value = this._str("new.password.confirm");
|
||||
introText.textContent = this._str("change.password2.introText");
|
||||
warningText.textContent = this._str("change.password.warningText");
|
||||
this._dialog.getButton("accept")
|
||||
.setAttribute("label", this._str("change.password.acceptButton"));
|
||||
this._dialog.getButton("finish").label
|
||||
= this._str("change.password.acceptButton");
|
||||
}
|
||||
break;
|
||||
}
|
||||
document.getElementById("change-page")
|
||||
.setAttribute("label", document.title);
|
||||
},
|
||||
|
||||
_clearStatus: function _clearStatus() {
|
||||
@ -153,8 +159,8 @@ let Change = {
|
||||
this._statusIcon.setAttribute("status", state);
|
||||
|
||||
let error = state == "error";
|
||||
this._dialog.getButton("cancel").setAttribute("disabled", !error);
|
||||
this._dialog.getButton("accept").setAttribute("disabled", !error);
|
||||
this._dialog.getButton("cancel").disabled = !error;
|
||||
this._dialog.getButton("finish").disabled = !error;
|
||||
document.getElementById("printSyncKeyButton").disabled = !error;
|
||||
document.getElementById("saveSyncKeyButton").disabled = !error;
|
||||
|
||||
@ -176,9 +182,8 @@ let Change = {
|
||||
|
||||
doGeneratePassphrase: function () {
|
||||
let passphrase = Weave.Utils.generatePassphrase();
|
||||
let el = document.getElementById("passphraseBox");
|
||||
el.value = Weave.Utils.hyphenatePassphrase(passphrase);
|
||||
this._dialog.getButton("accept").disabled = false;
|
||||
this._passphraseBox.value = Weave.Utils.hyphenatePassphrase(passphrase);
|
||||
this._dialog.getButton("finish").disabled = false;
|
||||
},
|
||||
|
||||
doChangePassphrase: function Change_doChangePassphrase() {
|
||||
@ -251,7 +256,7 @@ let Change = {
|
||||
this._updateStatusWithString(errorString, "error");
|
||||
|
||||
this._statusRow.hidden = valid;
|
||||
this._dialog.getButton("accept").disabled = !valid;
|
||||
this._dialog.getButton("finish").disabled = !valid;
|
||||
},
|
||||
|
||||
_str: function Change__string(str) {
|
||||
|
@ -40,6 +40,7 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/syncSetup.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/syncCommon.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
@ -50,15 +51,12 @@
|
||||
%syncBrandDTD;
|
||||
%syncSetupDTD;
|
||||
]>
|
||||
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
<wizard xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
id="change-dialog"
|
||||
windowtype="Weave:ChangeSomething"
|
||||
buttons="accept,cancel"
|
||||
onload="Change.onLoad()"
|
||||
buttondisabledaccept="true"
|
||||
ondialogaccept="return Change.onDialogAccept();"
|
||||
defaultButton="accept">
|
||||
onwizardnext="Change.onLoad()"
|
||||
onwizardfinish="return Change.onDialogAccept();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/syncGenericChange.js"/>
|
||||
@ -67,55 +65,65 @@
|
||||
<script type="application/javascript"
|
||||
src="chrome://global/content/printUtils.js"/>
|
||||
|
||||
<hbox align="top">
|
||||
<image id="syncIcon"/>
|
||||
<spacer style="width: 1em"/>
|
||||
<description flex="1">
|
||||
<html:p id="introText"/>
|
||||
<html:p id="introText2"/>
|
||||
<wizardpage id="change-page"
|
||||
label="">
|
||||
|
||||
<description id="introText">
|
||||
</description>
|
||||
</hbox>
|
||||
<separator class="thin"/>
|
||||
<vbox>
|
||||
<grid>
|
||||
<columns>
|
||||
<column align="right"/>
|
||||
<column flex="3"/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="textBox1Row" align="center">
|
||||
<label id="textBox1Label" control="textBox1"/>
|
||||
<textbox id="textBox1" type="password" oninput="Change.validate()"/>
|
||||
<spacer/>
|
||||
</row>
|
||||
<row id="textBox2Row" align="center">
|
||||
<label id="textBox2Label" control="textBox2"/>
|
||||
<textbox id="textBox2" type="password" oninput="Change.validate()"/>
|
||||
<spacer/>
|
||||
</row>
|
||||
<row id="passphraseRow" align="center">
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<groupbox>
|
||||
<grid>
|
||||
<columns>
|
||||
<column align="right"/>
|
||||
<column flex="3"/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row id="textBox1Row" align="center">
|
||||
<label id="textBox1Label" control="textBox1"/>
|
||||
<textbox id="textBox1" type="password" oninput="Change.validate()"/>
|
||||
<spacer/>
|
||||
</row>
|
||||
<row id="textBox2Row" align="center">
|
||||
<label id="textBox2Label" control="textBox2"/>
|
||||
<textbox id="textBox2" type="password" oninput="Change.validate()"/>
|
||||
<spacer/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
||||
<vbox id="passphraseRow">
|
||||
<hbox flex="1">
|
||||
<label id="passphraseLabel" control="passphraseBox"/>
|
||||
<textbox id="passphraseBox"
|
||||
onfocus="this.select()"
|
||||
oninput="Change.validate()"/>
|
||||
<spacer flex="1"/>
|
||||
<label id="generatePassphraseButton"
|
||||
hidden="true"
|
||||
value="&syncKeyGenerate.label;"
|
||||
class="text-link inline-link"
|
||||
onclick="event.stopPropagation();
|
||||
Change.doGeneratePassphrase();"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</hbox>
|
||||
<textbox id="passphraseBox"
|
||||
flex="1"
|
||||
onfocus="this.select()"
|
||||
oninput="Change.validate()"/>
|
||||
</vbox>
|
||||
|
||||
<vbox id="feedback" pack="center">
|
||||
<hbox id="statusRow" align="center">
|
||||
<image id="statusIcon" class="statusIcon"/>
|
||||
<label id="status" class="status" value=" "/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox id="feedback" pack="center">
|
||||
<hbox id="statusRow" align="center">
|
||||
<image id="statusIcon" class="statusIcon"/>
|
||||
<label id="status" class="status" value=" "/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
|
||||
<hbox id="passphraseBackupButtons" pack="center">
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox id="passphraseBackupButtons"
|
||||
hidden="true"
|
||||
pack="center">
|
||||
<button id="printSyncKeyButton"
|
||||
label="&button.syncKeyBackup.print.label;"
|
||||
accesskey="&button.syncKeyBackup.print.accesskey;"
|
||||
@ -126,8 +134,24 @@
|
||||
oncommand="gSyncUtils.passphraseSave('passphraseBox');"/>
|
||||
</hbox>
|
||||
|
||||
<description>
|
||||
<html:p class="data" id="warningText"/>
|
||||
<vbox id="passphraseHelpBox"
|
||||
hidden="true">
|
||||
<description>
|
||||
&existingSyncKey.description;
|
||||
<label class="text-link"
|
||||
href="https://services.mozilla.com/sync/help/manual-setup">
|
||||
&addDevice.showMeHow.label;
|
||||
</label>
|
||||
</description>
|
||||
</vbox>
|
||||
|
||||
<spacer id="passphraseSpacer"
|
||||
flex="1"
|
||||
hidden="true"/>
|
||||
|
||||
<description id="warningText" class="data">
|
||||
</description>
|
||||
</vbox>
|
||||
</dialog>
|
||||
|
||||
<spacer flex="1"/>
|
||||
</wizardpage>
|
||||
</wizard>
|
||||
|
@ -880,9 +880,9 @@ var gSyncSetup = {
|
||||
// if no property string is passed in, we clear label/style
|
||||
_setFeedback: function (element, success, string) {
|
||||
element.hidden = success || !string;
|
||||
let class = success ? "success" : "error";
|
||||
let classname = success ? "success" : "error";
|
||||
let image = element.getElementsByAttribute("class", "statusIcon")[0];
|
||||
image.setAttribute("status", class);
|
||||
image.setAttribute("status", classname);
|
||||
let label = element.getElementsByAttribute("class", "status")[0];
|
||||
label.value = string;
|
||||
},
|
||||
|
@ -320,7 +320,7 @@
|
||||
<label class="text-link"
|
||||
value="&resetPassword.label;"
|
||||
onclick="gSyncUtils.resetPassword(); return false;"/>
|
||||
</row>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label control="existingServer"
|
||||
value="&server.label;"/>
|
||||
@ -370,11 +370,14 @@
|
||||
<description>
|
||||
&existingSyncKey.description;
|
||||
<label class="text-link"
|
||||
value="&addDevice.showMeHow.label;"
|
||||
href="https://services.mozilla.com/sync/help/manual-setup"/>
|
||||
href="https://services.mozilla.com/sync/help/manual-setup">
|
||||
&addDevice.showMeHow.label;
|
||||
</label>
|
||||
<spacer id="passphraseHelpSpacer"/>
|
||||
<label class="text-link"
|
||||
value="&resetSyncKey.label;"
|
||||
onclick="gSyncUtils.resetPassphrase(); return false;"/>
|
||||
onclick="gSyncUtils.resetPassphrase(); return false;">
|
||||
&resetSyncKey.label;
|
||||
</label>
|
||||
</description>
|
||||
</vbox>
|
||||
</wizardpage>
|
||||
|
@ -77,7 +77,7 @@ let gSyncUtils = {
|
||||
|
||||
// Open up the change dialog
|
||||
let changeXUL = "chrome://browser/content/syncGenericChange.xul";
|
||||
let changeOpt = "centerscreen,chrome,dialog,modal,resizable=no";
|
||||
let changeOpt = "centerscreen,chrome,resizable=no";
|
||||
Weave.Svc.WinWatcher.activeWindow.openDialog(changeXUL, "", changeOpt, type);
|
||||
},
|
||||
|
||||
|
@ -182,7 +182,8 @@
|
||||
if (!window.gShowPageResizers)
|
||||
return;
|
||||
|
||||
var show = document.getElementById("addon-bar").collapsed;
|
||||
var show = document.getElementById("addon-bar").collapsed &&
|
||||
window.windowState == window.STATE_NORMAL;
|
||||
for (let i = 0; i < this.browsers.length; i++) {
|
||||
this.browsers[i].showWindowResizer = show;
|
||||
}
|
||||
@ -2864,6 +2865,7 @@
|
||||
this._handleTabSelect();
|
||||
this.mTabstripWidth = width;
|
||||
}
|
||||
this.tabbrowser.updateWindowResizers();
|
||||
break;
|
||||
}
|
||||
]]></body>
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Ehsan Akhgari <ehsan@mozilla.com>
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -491,6 +492,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
this.adjustTitleSize();
|
||||
|
||||
UI.clearShouldResizeItems();
|
||||
|
||||
this._updateDebugBounds();
|
||||
this.setTrenches(rect);
|
||||
|
||||
@ -564,7 +567,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Function: closeAll
|
||||
// Closes the groupItem and all of its children.
|
||||
closeAll: function GroupItem_closeAll() {
|
||||
let closeCenter = this.getBounds().center();
|
||||
if (this._children.length > 0) {
|
||||
this._children.forEach(function(child) {
|
||||
iQ(child.container).hide();
|
||||
@ -585,6 +587,16 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
if (!this.locked.close)
|
||||
this.close();
|
||||
}
|
||||
|
||||
this._makeClosestTabActive();
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _makeClosestTabActive
|
||||
// Make the closest tab external to this group active.
|
||||
// Used when closing the group.
|
||||
_makeClosestTabActive: function GroupItem__makeClosestTabActive() {
|
||||
let closeCenter = this.getBounds().center();
|
||||
// Find closest tab to make active
|
||||
let closestTabItem = UI.getClosestTab(closeCenter);
|
||||
UI.setActiveTab(closestTabItem);
|
||||
@ -638,6 +650,20 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
this._cancelFadeAwayUndoButtonTimer();
|
||||
|
||||
// When the last non-empty groupItem is closed and there are no orphan or
|
||||
// pinned tabs then create a new group with a blank tab.
|
||||
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && groupItem.getChildren().length);
|
||||
});
|
||||
if (!gBrowser._numPinnedTabs && !GroupItems.getOrphanedTabs().length &&
|
||||
!remainingGroups.length) {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && !groupItem.getChildren().length);
|
||||
});
|
||||
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
group.newTab();
|
||||
}
|
||||
|
||||
// when "TabClose" event is fired, the browser tab is about to close and our
|
||||
// item "close" event is fired. And then, the browser tab gets closed.
|
||||
// In other words, the group "close" event is fired before all browser
|
||||
@ -926,6 +952,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
!options.dontClose) {
|
||||
if (!GroupItems.getUnclosableGroupItemId()) {
|
||||
this.close();
|
||||
this._makeClosestTabActive();
|
||||
} else {
|
||||
// this.close(); this line is causing the leak but the leak doesn't happen after re-enabling it
|
||||
}
|
||||
@ -1478,8 +1505,15 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
addTab: drag.info.item.parent != self,
|
||||
animate: true});
|
||||
}
|
||||
|
||||
// remove the item from its parent if that's not the current groupItem.
|
||||
// this may occur when dragging too quickly so the out event is not fired.
|
||||
var groupItem = drag.info.item.parent;
|
||||
if (groupItem && self !== groupItem)
|
||||
groupItem.remove(drag.info.$el, {dontClose: true});
|
||||
|
||||
if (dropIndex !== false)
|
||||
options = {index: dropIndex}
|
||||
options = {index: dropIndex};
|
||||
this.add(drag.info.$el, options);
|
||||
GroupItems.setActiveGroupItem(this);
|
||||
dropIndex = false;
|
||||
@ -1556,34 +1590,21 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Reorders the tabs in the tab bar based on the arrangment of the tabs
|
||||
// shown in the groupItem.
|
||||
reorderTabsBasedOnTabItemOrder: function GroupItem_reorderTabsBasedOnTabItemOrder() {
|
||||
let targetIndices = null;
|
||||
let indices;
|
||||
let tabs = this._children.map(function (tabItem) tabItem.tab);
|
||||
|
||||
let self = this;
|
||||
this._children.some(function(tabItem, index) {
|
||||
// if no targetIndices, or it was reset, recompute
|
||||
if (!targetIndices) {
|
||||
let currentIndices = [tabItem.tab._tPos for each (tabItem in self._children)];
|
||||
targetIndices = currentIndices.concat().sort();
|
||||
// if no resorting is required, we're done!
|
||||
if (currentIndices == targetIndices)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute a target range for this tab's index
|
||||
let originalIndex = tabItem.tab._tPos;
|
||||
let targetRange = new Range(index ? targetIndices[index - 1] : -1,
|
||||
targetIndices[index + 1] || Infinity);
|
||||
tabs.forEach(function (tab, index) {
|
||||
if (!indices)
|
||||
indices = tabs.map(function (tab) tab._tPos);
|
||||
|
||||
// If the originalIndex of this tab is not within its target,
|
||||
// let's move it to the targetIndex.
|
||||
if (!targetRange.contains(originalIndex)) {
|
||||
let targetIndex = targetIndices[index];
|
||||
gBrowser.moveTabTo(tabItem.tab, targetIndex);
|
||||
// force recomputing targetIndices
|
||||
targetIndices = null;
|
||||
let start = index ? indices[index - 1] + 1 : 0;
|
||||
let end = index + 1 < indices.length ? indices[index + 1] - 1 : Infinity;
|
||||
let targetRange = new Range(start, end);
|
||||
|
||||
if (!targetRange.contains(tab._tPos)) {
|
||||
gBrowser.moveTabTo(tab, start);
|
||||
indices = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
@ -1676,6 +1697,14 @@ let GroupItems = {
|
||||
this.groupItems = null;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: newGroup
|
||||
// Creates a new empty group.
|
||||
newGroup: function () {
|
||||
let bounds = new Rect(20, 20, 250, 200);
|
||||
return new GroupItem([], {bounds: bounds, immediately: true});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: pauseArrange
|
||||
// Bypass arrange() calls and collect for resolution in
|
||||
@ -1909,7 +1938,6 @@ let GroupItems = {
|
||||
let groupItemsData = Storage.readGroupItemsData(gWindow);
|
||||
let groupItemData = Storage.readGroupItemData(gWindow);
|
||||
this.reconstitute(groupItemsData, groupItemData);
|
||||
this.killNewTabGroup(); // temporary?
|
||||
|
||||
return (groupItemsData && !Utils.isEmptyObject(groupItemsData));
|
||||
},
|
||||
@ -2316,21 +2344,6 @@ let GroupItems = {
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: killNewTabGroup
|
||||
// Removes the New Tab Group, which is now defunct. See bug 575851 and comments therein.
|
||||
killNewTabGroup: function GroupItems_killNewTabGroup() {
|
||||
// not localized as the original "New Tabs" group title was never localized
|
||||
// to begin with
|
||||
let newTabGroupTitle = "New Tabs";
|
||||
this.groupItems.forEach(function(groupItem) {
|
||||
if (groupItem.getTitle() == newTabGroupTitle && groupItem.locked.title) {
|
||||
groupItem.removeAll();
|
||||
groupItem.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: removeHiddenGroups
|
||||
// Removes all hidden groups' data and its browser tabs.
|
||||
|
@ -509,8 +509,9 @@ function hideSearch(event){
|
||||
|
||||
iQ("#searchbutton").css({ opacity:.8 });
|
||||
|
||||
let mainWindow = gWindow.document.getElementById("main-window");
|
||||
mainWindow.setAttribute("activetitlebarcolor", "#C4C4C4");
|
||||
#ifdef XP_MACOSX
|
||||
UI.setTitlebarColors(true);
|
||||
#endif
|
||||
|
||||
performSearch();
|
||||
SearchEventHandler.switchToBeforeMode();
|
||||
@ -550,8 +551,10 @@ function ensureSearchShown(){
|
||||
if (!isSearchEnabled()) {
|
||||
$searchShade.show();
|
||||
$search.show();
|
||||
var mainWindow = gWindow.document.getElementById("main-window");
|
||||
mainWindow.setAttribute("activetitlebarcolor", "#717171");
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
UI.setTitlebarColors({active: "#717171", inactive: "#EDEDED"});
|
||||
#endif
|
||||
|
||||
$searchbox[0].focus();
|
||||
$searchbox[0].val = '0';
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Ehsan Akhgari <ehsan@mozilla.com>
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -62,7 +63,7 @@ function TabItem(tab, options) {
|
||||
var $div = iQ('<div>')
|
||||
.addClass('tab')
|
||||
.html("<div class='thumb'>" +
|
||||
"<img class='cached-thumb' style='display:none'/><canvas moz-opaque='true'/></div>" +
|
||||
"<img class='cached-thumb' style='display:none'/><canvas moz-opaque/></div>" +
|
||||
"<div class='favicon'><img/></div>" +
|
||||
"<span class='tab-title'> </span>"
|
||||
)
|
||||
@ -496,6 +497,8 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this._hasBeenDrawn = true;
|
||||
}
|
||||
|
||||
UI.clearShouldResizeItems();
|
||||
|
||||
this._updateDebugBounds();
|
||||
rect = this.getBounds(); // ensure that it's a <Rect>
|
||||
|
||||
@ -806,7 +809,7 @@ let TabItems = {
|
||||
this.minTabHeight = this.minTabWidth * this.tabHeight / this.tabWidth;
|
||||
|
||||
let $canvas = iQ("<canvas>")
|
||||
.attr('moz-opaque', true);
|
||||
.attr('moz-opaque', '');
|
||||
$canvas.appendTo(iQ("body"));
|
||||
$canvas.hide();
|
||||
this.tempCanvas = $canvas[0];
|
||||
@ -901,8 +904,6 @@ let TabItems = {
|
||||
);
|
||||
|
||||
if (shouldDefer) {
|
||||
if (!this.reconnectingPaused() && !tab._tabViewTabItem._reconnected)
|
||||
this._reconnect(tab._tabViewTabItem);
|
||||
if (this._tabsWaitingForUpdate.indexOf(tab) == -1)
|
||||
this._tabsWaitingForUpdate.push(tab);
|
||||
this.startHeartbeat();
|
||||
@ -1017,6 +1018,9 @@ let TabItems = {
|
||||
Utils.assertThrow(tab._tabViewTabItem, "should already be linked");
|
||||
// note that it's ok to unlink an app tab; see .handleTabUnpin
|
||||
|
||||
if (tab._tabViewTabItem == GroupItems.getActiveOrphanTab())
|
||||
GroupItems.setActiveOrphanTab(null);
|
||||
|
||||
this.unregister(tab._tabViewTabItem);
|
||||
tab._tabViewTabItem._sendToSubscribers("close");
|
||||
iQ(tab._tabViewTabItem.container).remove();
|
||||
|
@ -25,6 +25,7 @@
|
||||
* Ehsan Akhgari <ehsan@mozilla.com>
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
* Sean Dunn <seanedunn@yahoo.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -200,11 +201,6 @@ let UI = {
|
||||
}
|
||||
});
|
||||
|
||||
iQ(window).bind("beforeunload", function() {
|
||||
Array.forEach(gBrowser.tabs, function(tab) {
|
||||
gBrowser.showTab(tab);
|
||||
});
|
||||
});
|
||||
iQ(window).bind("unload", function() {
|
||||
self.uninit();
|
||||
});
|
||||
@ -342,13 +338,15 @@ let UI = {
|
||||
item.parent.remove(item);
|
||||
groupItem.add(item, {immediately: true});
|
||||
});
|
||||
|
||||
GroupItems.setActiveGroupItem(groupItem);
|
||||
|
||||
if (firstTime) {
|
||||
gPrefBranch.setBoolPref("experienced_first_run", true);
|
||||
// ensure that the first run pref is flushed to the file, in case a crash
|
||||
// or force quit happens before the pref gets flushed automatically.
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
/* DISABLED BY BUG 626754. To be reenabled via bug 626926.
|
||||
let url = gPrefBranch.getCharPref("welcome_url");
|
||||
let newTab = gBrowser.loadOneTab(url, {inBackground: true});
|
||||
let newTabItem = newTab._tabViewTabItem;
|
||||
@ -360,11 +358,11 @@ let UI = {
|
||||
let welcomeBounds = new Rect(UI.rtl ? pageBounds.left : box.right, box.top,
|
||||
welcomeWidth, welcomeWidth * aspect);
|
||||
newTabItem.setBounds(welcomeBounds, true);
|
||||
GroupItems.setActiveGroupItem(groupItem);
|
||||
|
||||
// Remove the newly created welcome-tab from the tab bar
|
||||
if (!this.isTabViewVisible())
|
||||
GroupItems._updateTabBar();
|
||||
*/
|
||||
}
|
||||
},
|
||||
|
||||
@ -476,7 +474,7 @@ let UI = {
|
||||
|
||||
gBrowser.updateTitlebar();
|
||||
#ifdef XP_MACOSX
|
||||
this._setActiveTitleColor(true);
|
||||
this.setTitlebarColors(true);
|
||||
#endif
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewshown", true, false);
|
||||
@ -553,7 +551,7 @@ let UI = {
|
||||
|
||||
gBrowser.updateTitlebar();
|
||||
#ifdef XP_MACOSX
|
||||
this._setActiveTitleColor(false);
|
||||
this.setTitlebarColors(false);
|
||||
#endif
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewhidden", true, false);
|
||||
@ -564,19 +562,27 @@ let UI = {
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// ----------
|
||||
// Function: _setActiveTitleColor
|
||||
// Function: setTitlebarColors
|
||||
// Used on the Mac to make the title bar match the gradient in the rest of the
|
||||
// TabView UI.
|
||||
//
|
||||
// Parameters:
|
||||
// set - true for the special TabView color, false for the normal color.
|
||||
_setActiveTitleColor: function UI__setActiveTitleColor(set) {
|
||||
// colors - (bool or object) true for the special TabView color, false for
|
||||
// the normal color, and an object with "active" and "inactive"
|
||||
// properties to specify directly.
|
||||
setTitlebarColors: function UI_setTitlebarColors(colors) {
|
||||
// Mac Only
|
||||
var mainWindow = gWindow.document.getElementById("main-window");
|
||||
if (set)
|
||||
if (colors === true) {
|
||||
mainWindow.setAttribute("activetitlebarcolor", "#C4C4C4");
|
||||
else
|
||||
mainWindow.setAttribute("inactivetitlebarcolor", "#EDEDED");
|
||||
} else if (colors && "active" in colors && "inactive" in colors) {
|
||||
mainWindow.setAttribute("activetitlebarcolor", colors.active);
|
||||
mainWindow.setAttribute("inactivetitlebarcolor", colors.inactive);
|
||||
} else {
|
||||
mainWindow.removeAttribute("activetitlebarcolor");
|
||||
mainWindow.removeAttribute("inactivetitlebarcolor");
|
||||
}
|
||||
},
|
||||
#endif
|
||||
|
||||
@ -1202,16 +1208,21 @@ let UI = {
|
||||
if (!this._pageBounds)
|
||||
return;
|
||||
|
||||
// If TabView isn't focused and is not showing, don't perform a resize.
|
||||
// This resize really slows things down.
|
||||
// Here are reasons why we *won't* resize:
|
||||
// 1. Panorama isn't visible (in which case we will resize when we do display)
|
||||
// 2. the screen dimensions haven't changed
|
||||
// 3. everything on the screen fits and nothing feels cramped
|
||||
if (!force && !this.isTabViewVisible())
|
||||
return;
|
||||
|
||||
var oldPageBounds = new Rect(this._pageBounds);
|
||||
var newPageBounds = Items.getPageBounds();
|
||||
let oldPageBounds = new Rect(this._pageBounds);
|
||||
let newPageBounds = Items.getPageBounds();
|
||||
if (newPageBounds.equals(oldPageBounds))
|
||||
return;
|
||||
|
||||
if (!this.shouldResizeItems())
|
||||
return;
|
||||
|
||||
var items = Items.getTopLevelItems();
|
||||
|
||||
// compute itemBounds: the union of all the top-level items' bounds.
|
||||
@ -1279,6 +1290,58 @@ let UI = {
|
||||
this._pageBounds = Items.getPageBounds();
|
||||
this._save();
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: shouldResizeItems
|
||||
// Returns whether we should resize the items on the screen, based on whether
|
||||
// the top-level items fit in the screen or not and whether they feel
|
||||
// "cramped" or not.
|
||||
// These computations may be done using cached values. The cache can be
|
||||
// cleared with UI.clearShouldResizeItems().
|
||||
shouldResizeItems: function UI_shouldResizeItems() {
|
||||
|
||||
let newPageBounds = Items.getPageBounds();
|
||||
|
||||
// If we don't have cached cached values...
|
||||
if (this._minimalRect === undefined || this._feelsCramped === undefined) {
|
||||
|
||||
// Loop through every top-level Item for two operations:
|
||||
// 1. check if it is feeling "cramped" due to squishing (a technical term),
|
||||
// 2. union its bounds with the minimalRect
|
||||
let feelsCramped = false;
|
||||
let minimalRect = new Rect(0, 0, 1, 1);
|
||||
|
||||
Items.getTopLevelItems()
|
||||
.forEach(function UI_shouldResizeItems_checkItem(item) {
|
||||
let bounds = new Rect(item.getBounds());
|
||||
feelsCramped = feelsCramped || (item.userSize &&
|
||||
(item.userSize.x > bounds.width || item.userSize.y > bounds.height));
|
||||
bounds.inset(-Trenches.defaultRadius, -Trenches.defaultRadius);
|
||||
minimalRect = minimalRect.union(bounds);
|
||||
});
|
||||
|
||||
// ensure the minimalRect extends to, but not beyond, the origin
|
||||
minimalRect.left = 0;
|
||||
minimalRect.top = 0;
|
||||
|
||||
this._minimalRect = minimalRect;
|
||||
this._feelsCramped = feelsCramped;
|
||||
}
|
||||
|
||||
return this._minimalRect.width > newPageBounds.width ||
|
||||
this._minimalRect.height > newPageBounds.height ||
|
||||
this._feelsCramped;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: clearShouldResizeItems
|
||||
// Clear the cache of whether we should resize the items on the Panorama
|
||||
// screen, forcing a recomputation on the next UI.shouldResizeItems()
|
||||
// call.
|
||||
clearShouldResizeItems: function UI_clearShouldResizeItems() {
|
||||
delete this._minimalRect;
|
||||
delete this._feelsCramped;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: exit
|
||||
@ -1302,14 +1365,17 @@ let UI = {
|
||||
let unhiddenGroups = GroupItems.groupItems.filter(function(groupItem) {
|
||||
return (!groupItem.hidden && groupItem.getChildren().length > 0);
|
||||
});
|
||||
// no visible groups, no orphaned tabs and no apps tabs, open a new group
|
||||
// with a blank tab
|
||||
if (unhiddenGroups.length == 0 && GroupItems.getOrphanedTabs().length == 0 &&
|
||||
gBrowser._numPinnedTabs == 0) {
|
||||
let box = new Rect(20, 20, 250, 200);
|
||||
let groupItem = new GroupItem([], { bounds: box, immediately: true });
|
||||
groupItem.newTab();
|
||||
return;
|
||||
// no pinned tabs, no visible groups and no orphaned tabs: open a new
|
||||
// group. open a blank tab and return
|
||||
if (!unhiddenGroups.length && !GroupItems.getOrphanedTabs().length) {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (!groupItem.hidden && !groupItem.getChildren().length);
|
||||
});
|
||||
let group = (emptyGroups.length ? emptyGroups[0] : GroupItems.newGroup());
|
||||
if (!gBrowser._numPinnedTabs) {
|
||||
group.newTab();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's an active TabItem, zoom into it. If not (for instance when the
|
||||
|
@ -170,6 +170,7 @@ _BROWSER_FILES = \
|
||||
browser_bug624734.js \
|
||||
browser_contextSearchTabPosition.js \
|
||||
browser_ctrlTab.js \
|
||||
browser_customize_popupNotification.js \
|
||||
browser_disablechrome.js \
|
||||
browser_discovery.js \
|
||||
browser_duplicateIDs.js \
|
||||
|
@ -110,14 +110,6 @@ function test_blocked_install() {
|
||||
"software on your computer.",
|
||||
"Should have seen the right message");
|
||||
|
||||
// Click on Allow
|
||||
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
|
||||
|
||||
// Notification should have changed to progress notification
|
||||
ok(PopupNotifications.isPanelOpen, "Notification should still be open");
|
||||
notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
|
||||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
// Wait for the complete notification
|
||||
@ -140,6 +132,15 @@ function test_blocked_install() {
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
// Click on Allow
|
||||
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
|
||||
|
||||
// Notification should have changed to progress notification
|
||||
ok(PopupNotifications.isPanelOpen, "Notification should still be open");
|
||||
notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
|
||||
|
||||
});
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
@ -705,15 +706,6 @@ function test_cancel_restart() {
|
||||
notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
|
||||
|
||||
// Restart the download
|
||||
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
|
||||
|
||||
// Should be back to a progress notification
|
||||
ok(PopupNotifications.isPanelOpen, "Notification should still be open");
|
||||
is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
|
||||
notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
|
||||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
// Wait for the complete notification
|
||||
@ -737,6 +729,16 @@ function test_cancel_restart() {
|
||||
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
});
|
||||
|
||||
// Restart the download
|
||||
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
|
||||
|
||||
// Should be back to a progress notification
|
||||
ok(PopupNotifications.isPanelOpen, "Notification should still be open");
|
||||
is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
|
||||
notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
var newWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank");
|
||||
registerCleanupFunction(function () {
|
||||
newWin.close();
|
||||
});
|
||||
newWin.addEventListener("load", function test_win_onLoad() {
|
||||
// Remove the URL bar
|
||||
newWin.gURLBar.parentNode.removeChild(newWin.gURLBar);
|
||||
|
||||
waitForFocus(function () {
|
||||
let PN = newWin.PopupNotifications;
|
||||
try {
|
||||
let notification = PN.show(newWin.gBrowser.selectedBrowser, "some-notification", "Some message");
|
||||
ok(notification, "showed the notification");
|
||||
ok(PN.isPanelOpen, "panel is open");
|
||||
is(PN.panel.anchorNode, newWin.gBrowser.selectedTab, "notification is correctly anchored to the tab");
|
||||
} catch (ex) {
|
||||
ok(false, "threw exception: " + ex);
|
||||
}
|
||||
finish();
|
||||
}, newWin);
|
||||
}, false);
|
||||
}
|
@ -58,6 +58,7 @@ function cleanUp() {
|
||||
|
||||
var gActiveListeners = {};
|
||||
var gActiveObservers = {};
|
||||
var gShownState = {};
|
||||
|
||||
function runNextTest() {
|
||||
let nextTest = tests[gTestIndex];
|
||||
@ -91,6 +92,7 @@ function runNextTest() {
|
||||
info("[Test #" + gTestIndex + "] popup showing");
|
||||
});
|
||||
doOnPopupEvent("popupshown", function () {
|
||||
gShownState[gTestIndex] = true;
|
||||
info("[Test #" + gTestIndex + "] popup shown");
|
||||
nextTest.onShown(this);
|
||||
});
|
||||
@ -101,6 +103,11 @@ function runNextTest() {
|
||||
nextTest.onHidden :
|
||||
[nextTest.onHidden];
|
||||
doOnPopupEvent("popuphidden", function () {
|
||||
if (!gShownState[gTestIndex]) {
|
||||
// This is expected to happen for test 9, so let's not treat it as a failure.
|
||||
info("Popup from test " + gTestIndex + " was hidden before its popupshown fired");
|
||||
}
|
||||
|
||||
let onHidden = onHiddenArray.shift();
|
||||
info("[Test #" + gTestIndex + "] popup hidden (" + onHiddenArray.length + " hides remaining)");
|
||||
onHidden.call(nextTest, this);
|
||||
|
@ -4,45 +4,60 @@
|
||||
|
||||
var gTab = null;
|
||||
|
||||
function cleanUp() {
|
||||
gBrowser.removeTab(gTab);
|
||||
finish();
|
||||
}
|
||||
|
||||
// function borrowed from browser_bug386835.js
|
||||
function load(tab, url, cb) {
|
||||
tab.linkedBrowser.addEventListener("load", function (event) {
|
||||
event.currentTarget.removeEventListener("load", arguments.callee, true);
|
||||
function load(url, cb) {
|
||||
gTab = gBrowser.addTab(url);
|
||||
gBrowser.addEventListener("load", function (event) {
|
||||
gBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// Trigger onLocationChange by switching tabs.
|
||||
gBrowser.selectedTab = gTab;
|
||||
cb();
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gTab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
|
||||
run_test_1();
|
||||
}
|
||||
|
||||
function run_test_1() {
|
||||
load(gTab, "about:config", function() {
|
||||
load("about:config", function() {
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
EventUtils.synthesizeKey("/", {}, gTab.linkedBrowser.contentWindow);
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
EventUtils.synthesizeKey("f", { accelKey: true });
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
ok(document.getElementById("cmd_find").getAttribute("disabled"),
|
||||
"Find command should be disabled");
|
||||
|
||||
gBrowser.removeTab(gTab);
|
||||
run_test_2();
|
||||
});
|
||||
}
|
||||
|
||||
function run_test_2() {
|
||||
load(gTab, "about:addons", function() {
|
||||
load("about:addons", function() {
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
EventUtils.synthesizeKey("/", {}, gTab.linkedBrowser.contentWindow);
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
EventUtils.synthesizeKey("f", { accelKey: true });
|
||||
ok(gFindBar.hidden, "Find bar should not be visible");
|
||||
ok(document.getElementById("cmd_find").getAttribute("disabled"),
|
||||
"Find command should be disabled");
|
||||
|
||||
cleanUp();
|
||||
gBrowser.removeTab(gTab);
|
||||
run_test_3();
|
||||
});
|
||||
}
|
||||
|
||||
function run_test_3() {
|
||||
load("about:blank", function() {
|
||||
ok(!document.getElementById("cmd_find").getAttribute("disabled"),
|
||||
"Find command should not be disabled");
|
||||
|
||||
gBrowser.removeTab(gTab);
|
||||
finish();
|
||||
});
|
||||
}
|
@ -72,6 +72,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug598600.js \
|
||||
browser_tabview_bug599626.js \
|
||||
browser_tabview_bug600645.js \
|
||||
browser_tabview_bug600812.js \
|
||||
browser_tabview_bug604098.js \
|
||||
browser_tabview_bug606657.js \
|
||||
browser_tabview_bug606905.js \
|
||||
@ -79,12 +80,17 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug608184.js \
|
||||
browser_tabview_bug608158.js \
|
||||
browser_tabview_bug610242.js \
|
||||
browser_tabview_bug613541.js \
|
||||
browser_tabview_bug616729.js \
|
||||
browser_tabview_bug616967.js \
|
||||
browser_tabview_bug618828.js \
|
||||
browser_tabview_bug619937.js \
|
||||
browser_tabview_bug622835.js \
|
||||
browser_tabview_bug622872.js \
|
||||
browser_tabview_bug624265.js \
|
||||
browser_tabview_bug624953.js \
|
||||
browser_tabview_bug625269.js \
|
||||
browser_tabview_bug627736.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
browser_tabview_expander.js \
|
||||
|
@ -83,10 +83,10 @@ function onTabViewWindowHidden() {
|
||||
|
||||
is(moves, 1, "Only one move should be necessary for this basic move.");
|
||||
|
||||
is(originalTab._tPos, 1, "Original tab is in position 0");
|
||||
is(newTabs[0]._tPos, 2, "Robots is in position 1");
|
||||
is(newTabs[1]._tPos, 3, "Mozilla is in position 2");
|
||||
is(newTabs[2]._tPos, 0, "Credits is in position 3");
|
||||
is(newTabs[2]._tPos, 0, "Credits is in position 0");
|
||||
is(originalTab._tPos, 1, "Original tab is in position 1");
|
||||
is(newTabs[0]._tPos, 2, "Robots is in position 2");
|
||||
is(newTabs[1]._tPos, 3, "Mozilla is in position 3");
|
||||
|
||||
gBrowser.removeTab(newTabs[0]);
|
||||
gBrowser.removeTab(newTabs[1]);
|
||||
|
@ -11,14 +11,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Weave.
|
||||
* The Original Code is a test for bug 600812.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jono DiCarlo <jdicarlo@mozilla.com>
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -34,25 +35,45 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const EXPORTED_SYMBOLS = ['TabSetRecord'];
|
||||
function test() {
|
||||
let cw;
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
let createGroupItem = function () {
|
||||
let bounds = new cw.Rect(20, 20, 150, 150);
|
||||
let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
|
||||
|
||||
Cu.import("resource://services-sync/base_records/crypto.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
cw.GroupItems.setActiveGroupItem(groupItem);
|
||||
gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
|
||||
const TABS_TTL = 604800; // 7 days
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
function TabSetRecord(collection, id) {
|
||||
CryptoWrapper.call(this, collection, id);
|
||||
let testVeryQuickDragAndDrop = function () {
|
||||
let sourceGroup = cw.GroupItems.groupItems[0];
|
||||
let targetGroup = createGroupItem();
|
||||
|
||||
sourceGroup.pushAway(true);
|
||||
targetGroup.pushAway(true);
|
||||
|
||||
let sourceTab = sourceGroup.getChild(0).container;
|
||||
EventUtils.synthesizeMouseAtCenter(sourceTab, {type: 'mousedown'}, cw);
|
||||
|
||||
let targetTab = targetGroup.getChild(0).container;
|
||||
EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mouseup'}, cw);
|
||||
|
||||
is(targetGroup.getChildren().length, 2, 'target group has two tabs');
|
||||
is(cw.GroupItems.groupItems.length, 1, 'sourceGroup was closed');
|
||||
isnot(cw.GroupItems.groupItems[0], sourceGroup, 'sourceGroup was closed');
|
||||
|
||||
targetGroup.getChild(0).close();
|
||||
hideTabView(finish);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
cw = TabView.getContentWindow();
|
||||
afterAllTabsLoaded(testVeryQuickDragAndDrop);
|
||||
});
|
||||
}
|
||||
TabSetRecord.prototype = {
|
||||
__proto__: CryptoWrapper.prototype,
|
||||
_logName: "Record.Tabs",
|
||||
ttl: TABS_TTL
|
||||
};
|
||||
|
||||
Utils.deferGetSet(TabSetRecord, "cleartext", ["clientName", "tabs"]);
|
396
browser/base/content/test/tabview/browser_tabview_bug613541.js
Normal file
@ -0,0 +1,396 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is a test for bug 613541.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
let cw;
|
||||
let currentTest;
|
||||
|
||||
let getGroupItem = function (index) {
|
||||
return cw.GroupItems.groupItems[index];
|
||||
}
|
||||
|
||||
let createGroupItem = function (numTabs) {
|
||||
let bounds = new cw.Rect(20, 20, 200, 200);
|
||||
let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
|
||||
cw.GroupItems.setActiveGroupItem(groupItem);
|
||||
|
||||
for (let i=0; i<numTabs || 0; i++)
|
||||
gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
let hideGroupItem = function (groupItem, callback) {
|
||||
groupItem.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'groupHidden');
|
||||
callback();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
||||
let closeGroupItem = function (groupItem, callback) {
|
||||
afterAllTabsLoaded(function () {
|
||||
hideGroupItem(groupItem, function () {
|
||||
groupItem.closeHidden();
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let tests = [];
|
||||
|
||||
let next = function () {
|
||||
let test = tests.shift();
|
||||
|
||||
if (test) {
|
||||
// check that the previous test left things as expected
|
||||
if (currentTest) {
|
||||
currentTest += ' (post-check)';
|
||||
assertTabViewIsHidden();
|
||||
assertNumberOfGroupItems(1);
|
||||
assertNumberOfTabs(1);
|
||||
}
|
||||
|
||||
currentTest = test.name;
|
||||
showTabView(test.func);
|
||||
} else
|
||||
hideTabView(finish);
|
||||
}
|
||||
|
||||
let assertTabViewIsHidden = function () {
|
||||
ok(!TabView.isVisible(), currentTest + ': tabview is hidden');
|
||||
}
|
||||
|
||||
let assertNumberOfGroupItems = function (num) {
|
||||
is(cw.GroupItems.groupItems.length, num, currentTest + ': number of groupItems is equal to ' + num);
|
||||
}
|
||||
|
||||
let assertNumberOfTabs = function (num) {
|
||||
is(gBrowser.tabs.length, num, currentTest + ': number of tabs is equal to ' + num);
|
||||
}
|
||||
|
||||
let assertGroupItemRemoved = function (groupItem) {
|
||||
is(cw.GroupItems.groupItems.indexOf(groupItem), -1, currentTest + ': groupItem was removed');
|
||||
}
|
||||
|
||||
let assertGroupItemExists = function (groupItem) {
|
||||
isnot(cw.GroupItems.groupItems.indexOf(groupItem), -1, currentTest + ': groupItem still exists');
|
||||
}
|
||||
|
||||
// setup: 1 non-empty group
|
||||
// action: close the group
|
||||
// expected: new group with blank tab is created and zoomed into
|
||||
let testSingleGroup1 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemRemoved(groupItem);
|
||||
whenTabViewIsHidden(next);
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 non-empty group
|
||||
// action: hide the group, exit panorama
|
||||
// expected: new group with blank tab is created and zoomed into
|
||||
let testSingleGroup2 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
hideGroupItem(groupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemRemoved(groupItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 2 non-empty groups
|
||||
// action: close one group
|
||||
// expected: nothing should happen
|
||||
let testNonEmptyGroup1 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemExists(newGroupItem);
|
||||
hideTabView(next);
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 2 non-empty groups
|
||||
// action: hide one group, exit panorama
|
||||
// expected: nothing should happen
|
||||
let testNonEmptyGroup2 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemRemoved(groupItem);
|
||||
assertGroupItemExists(newGroupItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 pinned tab, 1 empty group
|
||||
// action: exit panorama
|
||||
// expected: nothing should happen
|
||||
let testPinnedTab1 = function () {
|
||||
gBrowser.pinTab(gBrowser.selectedTab);
|
||||
|
||||
let groupItem = getGroupItem(0);
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemExists(groupItem);
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 pinned tab
|
||||
// action: exit panorama
|
||||
// expected: new blank group is created
|
||||
let testPinnedTab2 = function () {
|
||||
gBrowser.pinTab(gBrowser.selectedTab);
|
||||
getGroupItem(0).close();
|
||||
|
||||
hideTabView(function () {
|
||||
assertNumberOfTabs(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 pinned tab, 1 empty group, 1 non-empty group
|
||||
// action: close non-empty group
|
||||
// expected: nothing should happen
|
||||
let testPinnedTab3 = function () {
|
||||
gBrowser.pinTab(gBrowser.selectedTab);
|
||||
|
||||
let groupItem = getGroupItem(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
closeGroupItem(newGroupItem, function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemExists(groupItem);
|
||||
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
hideTabView(next);
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 pinned tab, 1 empty group, 1 non-empty group
|
||||
// action: hide non-empty group, exit panorama
|
||||
// expected: nothing should happen
|
||||
let testPinnedTab4 = function () {
|
||||
gBrowser.pinTab(gBrowser.selectedTab);
|
||||
|
||||
let groupItem = getGroupItem(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
hideGroupItem(newGroupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemExists(groupItem);
|
||||
assertGroupItemRemoved(newGroupItem);
|
||||
gBrowser.unpinTab(gBrowser.selectedTab);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 orphan tab
|
||||
// action: exit panorama
|
||||
// expected: nothing should happen
|
||||
let testOrphanTab1 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 orphan tab, 1 non-empty group
|
||||
// action: close the group
|
||||
// expected: nothing should happen
|
||||
let testOrphanTab2 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
assertNumberOfGroupItems(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
closeGroupItem(newGroupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
hideTabView(next);
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 orphan tab, 1 non-empty group
|
||||
// action: hide the group, exit panorama
|
||||
// expected: nothing should happen
|
||||
let testOrphanTab3 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
assertNumberOfGroupItems(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
hideGroupItem(newGroupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 non-empty group, 1 empty group
|
||||
// action: close non-empty group
|
||||
// expected: empty group is re-used, new tab is created and zoomed into
|
||||
let testEmptyGroup1 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let newGroupItem = createGroupItem(0);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemExists(newGroupItem);
|
||||
whenTabViewIsHidden(next);
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 non-empty group, 1 empty group
|
||||
// action: hide non-empty group, exit panorama
|
||||
// expected: empty group is re-used, new tab is created and zoomed into
|
||||
let testEmptyGroup2 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let newGroupItem = createGroupItem(0);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemRemoved(groupItem);
|
||||
assertGroupItemExists(newGroupItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 hidden group, 1 non-empty group
|
||||
// action: close non-empty group
|
||||
// expected: nothing should happen
|
||||
let testHiddenGroup1 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let hiddenGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
hideGroupItem(hiddenGroupItem, function () {
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemRemoved(groupItem);
|
||||
assertGroupItemExists(hiddenGroupItem);
|
||||
hideTabView(next);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 hidden group, 1 non-empty group
|
||||
// action: hide non-empty group, exit panorama
|
||||
// expected: new group with blank tab is created and zoomed into
|
||||
let testHiddenGroup2 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let hiddenGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
hideGroupItem(hiddenGroupItem, function () {
|
||||
hideGroupItem(groupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(1);
|
||||
assertGroupItemRemoved(groupItem);
|
||||
assertGroupItemRemoved(hiddenGroupItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
tests.push({name: 'testSingleGroup1', func: testSingleGroup1});
|
||||
tests.push({name: 'testSingleGroup2', func: testSingleGroup2});
|
||||
|
||||
tests.push({name: 'testNonEmptyGroup1', func: testNonEmptyGroup1});
|
||||
tests.push({name: 'testNonEmptyGroup2', func: testNonEmptyGroup2});
|
||||
|
||||
tests.push({name: 'testPinnedTab1', func: testPinnedTab1});
|
||||
tests.push({name: 'testPinnedTab2', func: testPinnedTab2});
|
||||
tests.push({name: 'testPinnedTab3', func: testPinnedTab3});
|
||||
tests.push({name: 'testPinnedTab4', func: testPinnedTab4});
|
||||
|
||||
tests.push({name: 'testOrphanTab1', func: testOrphanTab1});
|
||||
tests.push({name: 'testOrphanTab2', func: testOrphanTab2});
|
||||
tests.push({name: 'testOrphanTab3', func: testOrphanTab3});
|
||||
|
||||
tests.push({name: 'testEmptyGroup1', func: testEmptyGroup1});
|
||||
tests.push({name: 'testEmptyGroup2', func: testEmptyGroup2});
|
||||
|
||||
tests.push({name: 'testHiddenGroup1', func: testHiddenGroup1});
|
||||
tests.push({name: 'testHiddenGroup2', func: testHiddenGroup2}),
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
cw = TabView.getContentWindow();
|
||||
next();
|
||||
});
|
||||
}
|
157
browser/base/content/test/tabview/browser_tabview_bug616729.js
Normal file
@ -0,0 +1,157 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is a test for bug 616729.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Tim Taubert <tim.taubert@gmx.de>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
let cw;
|
||||
|
||||
let createGroupItem = function () {
|
||||
let bounds = new cw.Rect(20, 20, 400, 200);
|
||||
let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
|
||||
cw.GroupItems.setActiveGroupItem(groupItem);
|
||||
|
||||
for (let i=0; i<5; i++)
|
||||
gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
let assertCorrectItemOrder = function (items) {
|
||||
for (let i=1; i<items.length; i++) {
|
||||
if (items[i-1].tab._tPos > items[i].tab._tPos) {
|
||||
ok(false, 'tabs were correctly reordered');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let testVariousTabOrders = function () {
|
||||
let groupItem = createGroupItem();
|
||||
let [tab1, tab2, tab3, tab4, tab5] = groupItem.getChildren();
|
||||
|
||||
// prepare tests
|
||||
let tests = [];
|
||||
tests.push([tab1, tab2, tab3, tab4, tab5]);
|
||||
tests.push([tab5, tab4, tab3, tab2, tab1]);
|
||||
tests.push([tab1, tab2, tab3, tab4]);
|
||||
tests.push([tab4, tab3, tab2, tab1]);
|
||||
tests.push([tab1, tab2, tab3]);
|
||||
tests.push([tab1, tab2, tab3]);
|
||||
tests.push([tab1, tab3, tab2]);
|
||||
tests.push([tab2, tab1, tab3]);
|
||||
tests.push([tab2, tab3, tab1]);
|
||||
tests.push([tab3, tab1, tab2]);
|
||||
tests.push([tab3, tab2, tab1]);
|
||||
tests.push([tab1, tab2]);
|
||||
tests.push([tab2, tab1]);
|
||||
tests.push([tab1]);
|
||||
|
||||
// test reordering of empty groups - removes the last tab and causes
|
||||
// the groupItem to close
|
||||
tests.push([]);
|
||||
|
||||
while (tests.length) {
|
||||
let test = tests.shift();
|
||||
|
||||
// prepare
|
||||
let items = groupItem.getChildren();
|
||||
while (test.length < items.length)
|
||||
items[items.length-1].close();
|
||||
|
||||
let orig = cw.Utils.copy(items);
|
||||
items.sort(function (a, b) test.indexOf(a) - test.indexOf(b));
|
||||
|
||||
// order and check
|
||||
groupItem.reorderTabsBasedOnTabItemOrder();
|
||||
assertCorrectItemOrder(items);
|
||||
|
||||
// revert to original item order
|
||||
items.sort(function (a, b) orig.indexOf(a) - orig.indexOf(b));
|
||||
groupItem.reorderTabsBasedOnTabItemOrder();
|
||||
}
|
||||
|
||||
testMoveBetweenGroups();
|
||||
}
|
||||
|
||||
let testMoveBetweenGroups = function () {
|
||||
let groupItem = createGroupItem();
|
||||
let groupItem2 = createGroupItem();
|
||||
|
||||
afterAllTabsLoaded(function () {
|
||||
// move item from group1 to group2
|
||||
let child = groupItem.getChild(2);
|
||||
groupItem.remove(child);
|
||||
|
||||
groupItem2.add(child, {index: 3});
|
||||
groupItem2.reorderTabsBasedOnTabItemOrder();
|
||||
|
||||
assertCorrectItemOrder(groupItem.getChildren());
|
||||
assertCorrectItemOrder(groupItem2.getChildren());
|
||||
|
||||
// move item from group2 to group1
|
||||
child = groupItem2.getChild(1);
|
||||
groupItem2.remove(child);
|
||||
|
||||
groupItem.add(child, {index: 1});
|
||||
groupItem.reorderTabsBasedOnTabItemOrder();
|
||||
|
||||
assertCorrectItemOrder(groupItem.getChildren());
|
||||
assertCorrectItemOrder(groupItem2.getChildren());
|
||||
|
||||
// cleanup
|
||||
groupItem.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'groupHidden');
|
||||
groupItem.closeHidden();
|
||||
groupItem2.closeAll();
|
||||
});
|
||||
|
||||
groupItem2.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem2.removeSubscriber(groupItem, 'groupHidden');
|
||||
groupItem2.closeHidden();
|
||||
hideTabView(finish);
|
||||
});
|
||||
|
||||
groupItem.closeAll();
|
||||
});
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
showTabView(function () {
|
||||
cw = TabView.getContentWindow();
|
||||
afterAllTabsLoaded(testVariousTabOrders);
|
||||
});
|
||||
}
|
156
browser/base/content/test/tabview/browser_tabview_bug622872.js
Normal file
@ -0,0 +1,156 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is bug 622872 test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
newWindowWithTabView(part1);
|
||||
}
|
||||
|
||||
// PART 1:
|
||||
// 1. Create a new tab (called newTab)
|
||||
// 2. Orphan it. Activate this orphan tab.
|
||||
// 3. Zoom into it.
|
||||
function part1(win) {
|
||||
ok(win.TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
is(win.gBrowser.tabs.length, 1, "In the beginning, there was one tab.");
|
||||
let [originalTab] = win.gBrowser.visibleTabs;
|
||||
let originalGroup = contentWindow.GroupItems.getActiveGroupItem();
|
||||
ok(originalGroup.getChildren().some(function(child) {
|
||||
return child == originalTab._tabViewTabItem;
|
||||
}),"The current active group is the one with the original tab in it.");
|
||||
|
||||
// Create a new tab and orphan it
|
||||
let newTab = win.gBrowser.loadOneTab("about:mozilla", {inBackground: true});
|
||||
|
||||
let newTabItem = newTab._tabViewTabItem;
|
||||
ok(originalGroup.getChildren().some(function(child) child == newTabItem),"The new tab was made in the current group");
|
||||
contentWindow.GroupItems.getActiveGroupItem().remove(newTabItem);
|
||||
ok(!originalGroup.getChildren().some(function(child) child == newTabItem),"The new tab was orphaned");
|
||||
newTabItem.pushAway();
|
||||
// activate this tab item
|
||||
contentWindow.UI.setActiveTab(newTabItem);
|
||||
|
||||
// PART 2: close this orphan tab (newTab)
|
||||
let part2 = function part2() {
|
||||
win.removeEventListener("tabviewhidden", part2, false);
|
||||
|
||||
is(win.gBrowser.selectedTab, newTab, "We zoomed into that new tab.");
|
||||
ok(!win.TabView.isVisible(), "Tab View is hidden, because we're looking at the new tab");
|
||||
|
||||
newTab.addEventListener("TabClose", function() {
|
||||
newTab.removeEventListener("TabClose", arguments.callee, false);
|
||||
|
||||
win.addEventListener("tabviewshown", part3, false);
|
||||
executeSoon(function() { win.TabView.toggle(); });
|
||||
}, false);
|
||||
win.gBrowser.removeTab(newTab);
|
||||
}
|
||||
|
||||
let secondNewTab;
|
||||
// PART 3: now back in Panorama, open a new tab via the "new tab" menu item (or equivalent)
|
||||
// We call this secondNewTab.
|
||||
let part3 = function part3() {
|
||||
win.removeEventListener("tabviewshown", part3, false);
|
||||
|
||||
ok(win.TabView.isVisible(), "Tab View is visible.");
|
||||
|
||||
is(win.gBrowser.tabs.length, 1, "Only one tab again.");
|
||||
is(win.gBrowser.tabs[0], originalTab, "That one tab is the original tab.");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "Only one group");
|
||||
|
||||
ok(!contentWindow.GroupItems.getActiveOrphanTab(), "There is no active orphan tab.");
|
||||
ok(win.TabView.isVisible(), "Tab View is visible.");
|
||||
|
||||
win.gBrowser.tabContainer.addEventListener("TabSelect", function() {
|
||||
win.gBrowser.tabContainer.removeEventListener("TabSelect", arguments.callee, false);
|
||||
executeSoon(part4);
|
||||
}, false);
|
||||
win.document.getElementById("cmd_newNavigatorTab").doCommand();
|
||||
}
|
||||
|
||||
// PART 4: verify it opened in the original group, and go back into Panorama
|
||||
let part4 = function part4() {
|
||||
ok(!win.TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
is(win.gBrowser.tabs.length, 2, "There are two tabs total now.");
|
||||
is(win.gBrowser.visibleTabs.length, 2, "We're looking at both of them.");
|
||||
|
||||
let foundOriginalTab = false;
|
||||
// we can't use forEach because win.gBrowser.tabs is only array-like.
|
||||
for (let i = 0; i < win.gBrowser.tabs.length; i++) {
|
||||
let tab = win.gBrowser.tabs[i];
|
||||
if (tab === originalTab)
|
||||
foundOriginalTab = true;
|
||||
else
|
||||
secondNewTab = tab;
|
||||
}
|
||||
ok(foundOriginalTab, "One of those tabs is the original tab.");
|
||||
ok(secondNewTab, "We found another tab... this is secondNewTab");
|
||||
|
||||
is(win.gBrowser.selectedTab, secondNewTab, "This second new tab is what we're looking at.");
|
||||
|
||||
win.addEventListener("tabviewshown", part5, false);
|
||||
win.TabView.toggle();
|
||||
}
|
||||
|
||||
// PART 5: make sure we only have one group with both tabs now, and finish.
|
||||
let part5 = function part5() {
|
||||
win.removeEventListener("tabviewshown", part5, false);
|
||||
|
||||
is(win.gBrowser.tabs.length, 2, "There are of course still two tabs.");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There is one group now");
|
||||
is(groupItems[0], originalGroup, "It's the original group.");
|
||||
is(originalGroup.getChildren().length, 2, "It has two children.");
|
||||
|
||||
// finish!
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
// Okay, all set up now. Let's get this party started!
|
||||
afterAllTabItemsUpdated(function() {
|
||||
win.addEventListener("tabviewhidden", part2, false);
|
||||
win.TabView.toggle();
|
||||
}, win);
|
||||
}
|
111
browser/base/content/test/tabview/browser_tabview_bug625269.js
Normal file
@ -0,0 +1,111 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is bug 625269 test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded(win) {
|
||||
win.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
ok(win.TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let [originalTab] = win.gBrowser.visibleTabs;
|
||||
|
||||
let currentGroup = contentWindow.GroupItems.getActiveGroupItem();
|
||||
|
||||
currentGroup.setSize(600, 600, true);
|
||||
currentGroup.setUserSize();
|
||||
|
||||
let down1 = function down1(resized) {
|
||||
checkResized(currentGroup, 50, 50, false, "A little bigger", up1, contentWindow, win);
|
||||
};
|
||||
|
||||
let up1 = function up1(resized) {
|
||||
checkResized(currentGroup, -400, -400, true, "Much smaller", down2, contentWindow, win);
|
||||
}
|
||||
|
||||
let down2 = function down2(resized) {
|
||||
checkResized(currentGroup, 400, 400, undefined,
|
||||
"Bigger after much smaller: TODO (bug 625668): the group should be resized!",
|
||||
up2, contentWindow, win);
|
||||
};
|
||||
|
||||
let up2 = function up2(resized) {
|
||||
checkResized(currentGroup, -400, -400, undefined,
|
||||
"Much smaller: TODO (bug 625668): the group should be resized!",
|
||||
down3, contentWindow, win);
|
||||
}
|
||||
|
||||
let down3 = function down3(resized) {
|
||||
// reset the usersize of the group, so this should clear the "cramped" feeling.
|
||||
currentGroup.setSize(100,100,true);
|
||||
currentGroup.setUserSize();
|
||||
checkResized(currentGroup, 400, 400, false,
|
||||
"After clearing the cramp",
|
||||
up3, contentWindow, win);
|
||||
};
|
||||
|
||||
let up3 = function up3(resized) {
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
// start by making it a little smaller.
|
||||
checkResized(currentGroup, -50, -50, false, "A little smaller", down1, contentWindow, win);
|
||||
}
|
||||
|
||||
function simulateResizeBy(xDiff, yDiff, win) {
|
||||
win = win || window;
|
||||
|
||||
win.resizeBy(xDiff, yDiff);
|
||||
}
|
||||
|
||||
function checkResized(item, xDiff, yDiff, expectResized, note, callback, contentWindow, win) {
|
||||
let originalBounds = new contentWindow.Rect(item.getBounds());
|
||||
simulateResizeBy(xDiff, yDiff, win);
|
||||
|
||||
let newBounds = item.getBounds();
|
||||
let resized = !newBounds.equals(originalBounds);
|
||||
if (expectResized !== undefined)
|
||||
is(resized, expectResized, note + ": The group should " +
|
||||
(expectResized ? "" : "not ") + "be resized");
|
||||
callback(resized);
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Panorama bug 627736 (post-group close focus) test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
newWindowWithTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded(win) {
|
||||
ok(win.TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let [originalTab] = win.gBrowser.visibleTabs;
|
||||
let originalGroup = contentWindow.GroupItems.getActiveGroupItem();
|
||||
|
||||
// open a group with a tab, and close either the group or the tab.
|
||||
function openAndClose(groupOrTab, callback) {
|
||||
// let's create a group with a tab.
|
||||
let group = new contentWindow.GroupItem([], {
|
||||
immediately: true,
|
||||
bounds: {left: 20, top: 20, width: 400, height: 400}
|
||||
});
|
||||
contentWindow.GroupItems.setActiveGroupItem(group);
|
||||
win.gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
|
||||
is(group.getChildren().length, 1, "The group has one child now.");
|
||||
let tab = group.getChild(0);
|
||||
|
||||
function check() {
|
||||
if (groupOrTab == 'group') {
|
||||
group.removeSubscriber(group, "groupHidden", check);
|
||||
group.closeHidden();
|
||||
} else
|
||||
tab.removeSubscriber(tab, "tabRemoved", check);
|
||||
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
|
||||
"The original group is active.");
|
||||
is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
|
||||
"The original tab is active");
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
if (groupOrTab == 'group') {
|
||||
group.addSubscriber(group, "groupHidden", check);
|
||||
group.closeAll();
|
||||
} else {
|
||||
tab.addSubscriber(tab, "tabRemoved", check);
|
||||
tab.close();
|
||||
}
|
||||
}
|
||||
|
||||
// PHASE 1: create a group with a tab and close the group.
|
||||
openAndClose("group", function postPhase1() {
|
||||
// PHASE 2: create a group with a tab and close the tab.
|
||||
openAndClose("tab", function postPhase2() {
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
@ -60,14 +60,16 @@ function experienced() {
|
||||
function checkFirstRun(win) {
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
is(win.gBrowser.tabs.length, 2, "There should be two tabs");
|
||||
// Welcome tab disabled by bug 626754. To be fixed via bug 626926.
|
||||
todo_is(win.gBrowser.tabs.length, 2, "There should be two tabs");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There should be one group");
|
||||
is(groupItems[0].getChildren().length, 1, "...with one child");
|
||||
|
||||
let orphanTabCount = contentWindow.GroupItems.getOrphanedTabs().length;
|
||||
is(orphanTabCount, 1, "There should also be an orphaned tab");
|
||||
// Welcome tab disabled by bug 626754. To be fixed via bug 626926.
|
||||
todo_is(orphanTabCount, 1, "There should also be an orphaned tab");
|
||||
|
||||
ok(experienced(), "we're now experienced");
|
||||
}
|
||||
|
@ -783,7 +783,8 @@
|
||||
overLink.style.maxWidth = maxWidth + "px";
|
||||
}
|
||||
|
||||
this._originLabel.value = this.value;
|
||||
var action = this._parseActionUrl(this._value);
|
||||
this._originLabel.value = action ? action.param : this._value;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -1298,27 +1299,85 @@
|
||||
|
||||
<binding id="splitmenu">
|
||||
<content>
|
||||
<xul:menuitem anonid="item" flex="1"
|
||||
class="menuitem-tooltip split-menuitem-item"
|
||||
xbl:inherits="label,key"/>
|
||||
<xul:menu anonid="menu" class="split-menuitem-menu"
|
||||
<xul:hbox anonid="menuitem" flex="1"
|
||||
class="splitmenu-menuitem"
|
||||
xbl:inherits="iconic,label,disabled,onclick=oncommand,_moz-menuactive=active"/>
|
||||
<xul:menu anonid="menu" class="splitmenu-menu"
|
||||
xbl:inherits="disabled"
|
||||
oncommand="event.stopPropagation();">
|
||||
<children includes="menupopup"/>
|
||||
</xul:menu>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<constructor><![CDATA[
|
||||
if (this.getAttribute("iconic") == "true") {
|
||||
this.item.classList.remove("menuitem-tooltip");
|
||||
this.item.classList.add("menuitem-iconic-tooltip");
|
||||
this.item.classList.add("menuitem-iconic");
|
||||
}
|
||||
]]></constructor>
|
||||
<field name="item" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "item");
|
||||
<field name="menuitem" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "menuitem");
|
||||
</field>
|
||||
<field name="menu" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "menu");
|
||||
</field>
|
||||
|
||||
<field name="_menuDelay">600</field>
|
||||
|
||||
<field name="_parentMenupopup"><![CDATA[
|
||||
let node = this.parentNode;
|
||||
while (node) {
|
||||
if (node.localName == "menupopup")
|
||||
break;
|
||||
node = node.parentNode;
|
||||
}
|
||||
node;
|
||||
]]></field>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="mouseover"><![CDATA[
|
||||
if (this.getAttribute("active") != "true" &&
|
||||
this.getAttribute("disabled") != "true") {
|
||||
if (this._parentMenupopup._currentPopup)
|
||||
this._parentMenupopup._currentPopup.hidePopup();
|
||||
|
||||
this.setAttribute("active", "true");
|
||||
|
||||
let self = this;
|
||||
setTimeout(function () {
|
||||
if (self.getAttribute("active") == "true")
|
||||
self.menu.open = true;
|
||||
}, this._menuDelay);
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="mouseout"><![CDATA[
|
||||
if (this.menu.open)
|
||||
return;
|
||||
|
||||
let node = event.relatedTarget;
|
||||
while (node) {
|
||||
if (node == this)
|
||||
return;
|
||||
node = node.parentNode;
|
||||
}
|
||||
this.removeAttribute("active");
|
||||
]]></handler>
|
||||
|
||||
<handler event="popuphidden"><![CDATA[
|
||||
if (event.target == this.firstChild)
|
||||
this.removeAttribute("active");
|
||||
]]></handler>
|
||||
|
||||
<handler event="click" phase="capturing"><![CDATA[
|
||||
let node = event.originalTarget;
|
||||
while (true) {
|
||||
if (node == this.menuitem)
|
||||
break;
|
||||
if (node == this)
|
||||
return;
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
this._parentMenupopup.hidePopup();
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<binding id="menuitem-tooltip" extends="chrome://global/content/bindings/menu.xml#menuitem">
|
||||
@ -1342,5 +1401,5 @@
|
||||
]]></constructor>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
</bindings>
|
||||
|
@ -146,9 +146,9 @@ BrowserGlue.prototype = {
|
||||
// delays are in seconds
|
||||
const MAX_DELAY = 300;
|
||||
let delay = 3;
|
||||
let enum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (enum.hasMoreElements()) {
|
||||
delay += enum.getNext().gBrowser.tabs.length;
|
||||
let browserEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (browserEnum.hasMoreElements()) {
|
||||
delay += browserEnum.getNext().gBrowser.tabs.length;
|
||||
}
|
||||
delay = delay <= MAX_DELAY ? delay : MAX_DELAY;
|
||||
|
||||
|
@ -167,7 +167,7 @@ SessionStartup.prototype = {
|
||||
win.tabs.every(function (tab) tab.pinned)))
|
||||
Services.obs.addObserver(this, "domwindowopened", true);
|
||||
|
||||
Services.obs.addObserver(this, "browser:purge-session-history", true);
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
||||
}
|
||||
},
|
||||
|
||||
@ -198,6 +198,14 @@ SessionStartup.prototype = {
|
||||
window.removeEventListener("load", arguments.callee, false);
|
||||
}, false);
|
||||
break;
|
||||
case "sessionstore-windows-restored":
|
||||
Services.obs.removeObserver(this, "sessionstore-windows-restored");
|
||||
// We only want to start listening for the purge notification after we've
|
||||
// sessionstore has finished its initial startup. That way we won't observe
|
||||
// the purge notification & clear the old session before sessionstore loads
|
||||
// it (in the case of a crash).
|
||||
Services.obs.addObserver(this, "browser:purge-session-history", true);
|
||||
break;
|
||||
case "browser:purge-session-history":
|
||||
// reset all state on sanitization
|
||||
this._iniString = null;
|
||||
|
@ -769,41 +769,36 @@ SessionStoreService.prototype = {
|
||||
|
||||
if (closedWindowState) {
|
||||
let newWindowState;
|
||||
#ifndef XP_MACOSX
|
||||
if (!this._doResumeSession()) {
|
||||
#endif
|
||||
// We want to split the window up into pinned tabs and unpinned tabs.
|
||||
// Pinned tabs should be restored. If there are any remaining tabs,
|
||||
// they should be added back to _closedWindows.
|
||||
// We'll cheat a little bit and reuse _prepDataForDeferredRestore
|
||||
// even though it wasn't built exactly for this.
|
||||
let [appTabsState, normalTabsState] =
|
||||
this._prepDataForDeferredRestore(JSON.stringify({ windows: [closedWindowState] }));
|
||||
#ifdef XP_MACOSX
|
||||
// We want to split the window up into pinned tabs and unpinned tabs.
|
||||
// Pinned tabs should be restored. If there are any remaining tabs,
|
||||
// they should be added back to _closedWindows.
|
||||
// We'll cheat a little bit and reuse _prepDataForDeferredRestore
|
||||
// even though it wasn't built exactly for this.
|
||||
let [appTabsState, normalTabsState] =
|
||||
this._prepDataForDeferredRestore(JSON.stringify({ windows: [closedWindowState] }));
|
||||
|
||||
// These are our pinned tabs, which we should restore
|
||||
if (appTabsState.windows.length) {
|
||||
newWindowState = appTabsState.windows[0];
|
||||
delete newWindowState.__lastSessionWindowID;
|
||||
}
|
||||
|
||||
// In case there were no unpinned tabs, remove the window from _closedWindows
|
||||
if (!normalTabsState.windows.length) {
|
||||
this._closedWindows.splice(closedWindowIndex, 1);
|
||||
}
|
||||
// Or update _closedWindows with the modified state
|
||||
else {
|
||||
delete normalTabsState.windows[0].__lastSessionWindowID;
|
||||
this._closedWindows[closedWindowIndex] = normalTabsState.windows[0];
|
||||
}
|
||||
#ifndef XP_MACOSX
|
||||
// These are our pinned tabs, which we should restore
|
||||
if (appTabsState.windows.length) {
|
||||
newWindowState = appTabsState.windows[0];
|
||||
delete newWindowState.__lastSessionWindowID;
|
||||
}
|
||||
else {
|
||||
// If we're just restoring the window, make sure it gets removed from
|
||||
// _closedWindows.
|
||||
|
||||
// In case there were no unpinned tabs, remove the window from _closedWindows
|
||||
if (!normalTabsState.windows.length) {
|
||||
this._closedWindows.splice(closedWindowIndex, 1);
|
||||
newWindowState = closedWindowState;
|
||||
delete newWindowState.hidden;
|
||||
}
|
||||
// Or update _closedWindows with the modified state
|
||||
else {
|
||||
delete normalTabsState.windows[0].__lastSessionWindowID;
|
||||
this._closedWindows[closedWindowIndex] = normalTabsState.windows[0];
|
||||
}
|
||||
#else
|
||||
// If we're just restoring the window, make sure it gets removed from
|
||||
// _closedWindows.
|
||||
this._closedWindows.splice(closedWindowIndex, 1);
|
||||
newWindowState = closedWindowState;
|
||||
delete newWindowState.hidden;
|
||||
#endif
|
||||
if (newWindowState) {
|
||||
// Ensure that the window state isn't hidden
|
||||
@ -1513,6 +1508,7 @@ SessionStoreService.prototype = {
|
||||
// data even when we shouldn't (e.g. Back, different anchor)
|
||||
if (history && browser.__SS_data &&
|
||||
browser.__SS_data.entries[history.index] &&
|
||||
browser.__SS_data.entries[history.index].url == browser.currentURI.spec &&
|
||||
history.index < this._sessionhistory_max_entries - 1 && !aFullData) {
|
||||
tabData = browser.__SS_data;
|
||||
tabData.index = history.index + 1;
|
||||
|
@ -137,6 +137,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_615394-SSWindowState_events.js \
|
||||
browser_618151.js \
|
||||
browser_623779.js \
|
||||
browser_625257.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
|
@ -21,7 +21,14 @@ function closeFirstWin(win) {
|
||||
win.BrowserTryToCloseWindow();
|
||||
ok(win.closed, "window closed");
|
||||
|
||||
openWinWithCb(checkSecondWin, URIS_NORMAL_B, URIS_PINNED.concat(URIS_NORMAL_B));
|
||||
|
||||
// The second check will be platform dependent. After bug 592833, Win/Linux
|
||||
// will restore all tabs from the last close window while OSX will just
|
||||
// reopen pinned tabs.
|
||||
let expectedURIs = URIS_PINNED.concat(URIS_NORMAL_B);
|
||||
if (!navigator.platform.match(/Mac/))
|
||||
expectedURIs = expectedURIs.concat(URIS_NORMAL_A);
|
||||
openWinWithCb(checkSecondWin, URIS_NORMAL_B, expectedURIs);
|
||||
}
|
||||
|
||||
function checkSecondWin(win) {
|
||||
|
@ -344,7 +344,7 @@ function test_undoCloseWindow() {
|
||||
function firstWindowObserver(aSubject, aTopic, aData) {
|
||||
if (aTopic == "domwindowopened") {
|
||||
newWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
Services.ww.unregisterNotification(windowObserver);
|
||||
Services.ww.unregisterNotification(firstWindowObserver);
|
||||
}
|
||||
}
|
||||
Services.ww.registerNotification(firstWindowObserver);
|
||||
|
121
browser/components/sessionstore/test/browser/browser_625257.js
Normal file
@ -0,0 +1,121 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mehdi Mulani <mmmulani@uwaterloo.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****/
|
||||
|
||||
// This tests that a tab which is closed while loading is not lost.
|
||||
// Specifically, that session store does not rely on an invalid cache when
|
||||
// constructing data for a tab which is loading.
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
|
||||
// The newly created tab which we load a URL into and try closing/undoing.
|
||||
let tab;
|
||||
|
||||
// This test steps through the following parts:
|
||||
// 1. Tab has been created is loading URI_TO_LOAD.
|
||||
// 2. Before URI_TO_LOAD finishes loading, browser.currentURI has changed and
|
||||
// tab is scheduled to be removed.
|
||||
// 3. After the tab has been closed, undoCloseTab() has been called and the tab
|
||||
// should fully load.
|
||||
const URI_TO_LOAD = "about:home";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.addTabsProgressListener(tabsListener);
|
||||
|
||||
tab = gBrowser.addTab();
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", firstOnLoad, true);
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabClose", onTabClose, true);
|
||||
}
|
||||
|
||||
function firstOnLoad(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", firstOnLoad, true);
|
||||
|
||||
let uri = aEvent.target.location;
|
||||
is(uri, "about:blank", "first load should be for about:blank");
|
||||
|
||||
// Trigger a save state.
|
||||
ss.getBrowserState();
|
||||
|
||||
is(gBrowser.tabs[1], tab, "newly created tab should exist by now");
|
||||
ok(tab.linkedBrowser.__SS_data, "newly created tab should be in save state");
|
||||
|
||||
tab.linkedBrowser.loadURI(URI_TO_LOAD);
|
||||
}
|
||||
|
||||
let tabsListener = {
|
||||
onLocationChange: function onLocationChange(aBrowser) {
|
||||
gBrowser.removeTabsProgressListener(tabsListener);
|
||||
|
||||
is(aBrowser.currentURI.spec, URI_TO_LOAD,
|
||||
"should occur after about:blank load and be loading next page");
|
||||
|
||||
// Since we are running in the context of tabs listeners, we do not
|
||||
// want to disrupt other tabs listeners.
|
||||
executeSoon(function() {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function onTabClose(aEvent) {
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, true);
|
||||
|
||||
is(tab.linkedBrowser.currentURI.spec, URI_TO_LOAD,
|
||||
"should only remove when loading page");
|
||||
|
||||
executeSoon(function() {
|
||||
tab = ss.undoCloseTab(window, 0);
|
||||
tab.linkedBrowser.addEventListener("load", secondOnLoad, true);
|
||||
});
|
||||
}
|
||||
|
||||
function secondOnLoad(aEvent) {
|
||||
let uri = aEvent.target.location;
|
||||
is(uri, URI_TO_LOAD, "should load page from undoCloseTab");
|
||||
done();
|
||||
}
|
||||
|
||||
function done() {
|
||||
tab.linkedBrowser.removeEventListener("load", secondOnLoad, true);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
executeSoon(finish);
|
||||
}
|
@ -1 +1 @@
|
||||
4.0b10pre
|
||||
4.0b11pre
|
||||
|
@ -703,10 +703,10 @@ Application.prototype = {
|
||||
|
||||
get windows() {
|
||||
var win = [];
|
||||
var enum = Utilities.windowMediator.getEnumerator("navigator:browser");
|
||||
var browserEnum = Utilities.windowMediator.getEnumerator("navigator:browser");
|
||||
|
||||
while (enum.hasMoreElements())
|
||||
win.push(new Window(enum.getNext()));
|
||||
while (browserEnum.hasMoreElements())
|
||||
win.push(new Window(browserEnum.getNext()));
|
||||
|
||||
return win;
|
||||
},
|
||||
|
@ -421,7 +421,7 @@
|
||||
@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
|
||||
@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png
|
||||
#if MOZ_UPDATE_CHANNEL == beta
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/*
|
||||
@BINPATH@/distribution/extensions/testpilot@labs.mozilla.com.xpi
|
||||
#endif
|
||||
@BINPATH@/chrome/toolkit@JAREXT@
|
||||
@BINPATH@/chrome/toolkit.manifest
|
||||
|
@ -87,6 +87,9 @@ defaults/profile/extensions/installed-extensions.txt
|
||||
defaults/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/
|
||||
defaults/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
|
||||
defaults/profile/search.rdf
|
||||
#if MOZ_UPDATE_CHANNEL != beta
|
||||
distribution/extensions/testpilot@labs.mozilla.com.xpi
|
||||
#endif
|
||||
extensions/talkback@mozilla.org/
|
||||
extensions/talkback@mozilla.org/chrome.manifest
|
||||
extensions/talkback@mozilla.org/components/@DLL_PREFIX@qfaservices@DLL_SUFFIX@
|
||||
@ -94,6 +97,122 @@ extensions/talkback@mozilla.org/components/qfaservices.xpt
|
||||
extensions/talkback@mozilla.org/install.rdf
|
||||
extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/
|
||||
extensions/{641d8d09-7dda-4850-8228-ac0ab65e2ac9}/install.rdf
|
||||
extensions/testpilot@labs.mozilla.com/chrome.manifest
|
||||
extensions/testpilot@labs.mozilla.com/components/TestPilot.js
|
||||
extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
|
||||
extensions/testpilot@labs.mozilla.com/content/all-studies-window.xul
|
||||
extensions/testpilot@labs.mozilla.com/content/browser.css
|
||||
extensions/testpilot@labs.mozilla.com/content/browser.js
|
||||
extensions/testpilot@labs.mozilla.com/content/debug.html
|
||||
extensions/testpilot@labs.mozilla.com/content/experiment-page.js
|
||||
extensions/testpilot@labs.mozilla.com/content/feedback-browser.xul
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.js
|
||||
extensions/testpilot@labs.mozilla.com/content/flot/jquery.min.js
|
||||
extensions/testpilot@labs.mozilla.com/content/raw-data-dialog.js
|
||||
extensions/testpilot@labs.mozilla.com/content/raw-data-dialog.xul
|
||||
extensions/testpilot@labs.mozilla.com/content/screen.css
|
||||
extensions/testpilot@labs.mozilla.com/content/status-quit.html
|
||||
extensions/testpilot@labs.mozilla.com/content/status.html
|
||||
extensions/testpilot@labs.mozilla.com/content/survey-generator.js
|
||||
extensions/testpilot@labs.mozilla.com/content/take-survey.html
|
||||
extensions/testpilot@labs.mozilla.com/content/tp-browser.xul
|
||||
extensions/testpilot@labs.mozilla.com/content/welcome-page.js
|
||||
extensions/testpilot@labs.mozilla.com/content/welcome.html
|
||||
extensions/testpilot@labs.mozilla.com/content/window-utils.js
|
||||
extensions/testpilot@labs.mozilla.com/defaults/preferences/preferences.js
|
||||
extensions/testpilot@labs.mozilla.com/install.rdf
|
||||
extensions/testpilot@labs.mozilla.com/instrument/chrome.manifest
|
||||
extensions/testpilot@labs.mozilla.com/instrument/install.rdf
|
||||
extensions/testpilot@labs.mozilla.com/instrument/instrument.jsm
|
||||
extensions/testpilot@labs.mozilla.com/instrument/instrument.xul
|
||||
extensions/testpilot@labs.mozilla.com/modules/dbutils.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/experiment_data_store.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/extension-update.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/feedback.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/jar-code-store.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/cuddlefish.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/memory.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/observer-service.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/plain-text-console.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/preferences-service.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/securable-module.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/timer.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/traceback.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/unit-test.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/unload.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/lib/url.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/log4moz.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/metadata.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/Observers.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/setup.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/string_sanitizer.js
|
||||
extensions/testpilot@labs.mozilla.com/modules/tasks.js
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/badge-default.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/bg.jpg
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/css/screen-standalone.css
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/dino_32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/bg-status.jpg
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/callout.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/callout_continue.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/data1.jpg
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/data2.jpg
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_comments.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_computer.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_continue.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_quit.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_results.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_twitter.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/images/home_upcoming.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/logo.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/mozilla-logo.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/status-completed.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/status-ejected.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/status-missed.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/testpilot_16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/testPilot_200x200.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/testpilot_32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-completedstudies-32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-currentstudies-32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-generic-32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-learned-32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-results-48x48.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-settings-32x32.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-study-48x48.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/all/tp-submit-48x48.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/linux/close_button.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/linux/feedback-frown-16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/linux/feedback-smile-16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/linux/feedback.css
|
||||
extensions/testpilot@labs.mozilla.com/skin/mac/close_button.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/mac/feedback-frown-16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/mac/feedback-smile-16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/mac/feedback.css
|
||||
extensions/testpilot@labs.mozilla.com/skin/mac/notification-tail-down.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/mac/notification-tail-up.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/win/close_button.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/win/feedback-frown-16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/win/feedback-smile-16x16.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/win/feedback.css
|
||||
extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-down.png
|
||||
extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-up.png
|
||||
extensions/testpilot@labs.mozilla.com/tests/test_data_store.js
|
||||
greprefs/all.js
|
||||
greprefs/security-prefs.js
|
||||
greprefs/xpinstall.js
|
||||
|
@ -54,13 +54,17 @@ RequestExecutionLevel user
|
||||
!addplugindir ./
|
||||
|
||||
Var TmpVal
|
||||
Var StartMenuDir
|
||||
Var InstallType
|
||||
Var AddStartMenuSC
|
||||
Var AddQuickLaunchSC
|
||||
Var AddDesktopSC
|
||||
Var PageName
|
||||
|
||||
; By defining NO_STARTMENU_DIR an installer that doesn't provide an option for
|
||||
; an application's Start Menu PROGRAMS directory and doesn't define the
|
||||
; StartMenuDir variable can use the common InstallOnInitCommon macro.
|
||||
!define NO_STARTMENU_DIR
|
||||
|
||||
; On Vista and above attempt to elevate Standard Users in addition to users that
|
||||
; are a member of the Administrators group.
|
||||
!define NONADMIN_ELEVATE
|
||||
@ -95,19 +99,18 @@ VIAddVersionKey "OriginalFilename" "setup.exe"
|
||||
; Must be inserted before other macros that use logging
|
||||
!insertmacro _LoggingCommon
|
||||
|
||||
; Most commonly used macros for managing shortcuts
|
||||
!insertmacro _LoggingShortcutsCommon
|
||||
|
||||
!insertmacro AddDDEHandlerValues
|
||||
!insertmacro ChangeMUIHeaderImage
|
||||
!insertmacro CheckForFilesInUse
|
||||
!insertmacro CleanUpdatesDir
|
||||
!insertmacro CopyFilesFromDir
|
||||
!insertmacro CreateRegKey
|
||||
!insertmacro FindSMProgramsDir
|
||||
!insertmacro GetPathFromString
|
||||
!insertmacro GetParent
|
||||
!insertmacro IsHandlerForInstallDir
|
||||
!insertmacro LogDesktopShortcut
|
||||
!insertmacro LogQuickLaunchShortcut
|
||||
!insertmacro LogStartMenuShortcut
|
||||
!insertmacro ManualCloseAppPrompt
|
||||
!insertmacro RegCleanAppHandler
|
||||
!insertmacro RegCleanMain
|
||||
@ -178,12 +181,6 @@ Page custom preOptions leaveOptions
|
||||
; Custom Shortcuts Page
|
||||
Page custom preShortcuts leaveShortcuts
|
||||
|
||||
; Start Menu Folder Page Configuration
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE preStartMenu
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE leaveStartMenu
|
||||
!define MUI_STARTMENUPAGE_NODISABLE
|
||||
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuDir
|
||||
|
||||
; Custom Summary Page
|
||||
Page custom preSummary leaveSummary
|
||||
|
||||
@ -274,7 +271,7 @@ Section "-Application" APP_IDX
|
||||
|
||||
ClearErrors
|
||||
|
||||
; Default for creating Start Menu folder and shortcuts
|
||||
; Default for creating Start Menu shortcut
|
||||
; (1 = create, 0 = don't create)
|
||||
${If} $AddStartMenuSC == ""
|
||||
StrCpy $AddStartMenuSC "1"
|
||||
@ -382,15 +379,16 @@ Section "-Application" APP_IDX
|
||||
; Create shortcuts
|
||||
${LogHeader} "Adding Shortcuts"
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
; Remove the start menu shortcuts and directory if the SMPROGRAMS section
|
||||
; exists in the shortcuts_log.ini and the SMPROGRAMS. The installer's shortcut
|
||||
; creation code will create the shortcut in the root of the Start Menu
|
||||
; Programs directory.
|
||||
${RemoveStartMenuDir}
|
||||
|
||||
; Always add the relative path to the application's Start Menu directory and
|
||||
; the application's shortcuts to the shortcuts log ini file. The
|
||||
; DeleteShortcuts macro will do the right thing on uninstall if they don't
|
||||
; exist.
|
||||
${LogSMProgramsDirRelPath} "$StartMenuDir"
|
||||
${LogSMProgramsShortcut} "${BrandFullName}.lnk"
|
||||
${LogSMProgramsShortcut} "${BrandFullName} ($(SAFE_MODE)).lnk"
|
||||
; Always add the application's shortcuts to the shortcuts log ini file. The
|
||||
; DeleteShortcuts macro will do the right thing on uninstall if the
|
||||
; shortcuts don't exist.
|
||||
${LogStartMenuShortcut} "${BrandFullName}.lnk"
|
||||
${LogQuickLaunchShortcut} "${BrandFullName}.lnk"
|
||||
${LogDesktopShortcut} "${BrandFullName}.lnk"
|
||||
|
||||
@ -399,22 +397,19 @@ Section "-Application" APP_IDX
|
||||
; since this will either add it for the user if unelevated or All Users if
|
||||
; elevated.
|
||||
${If} $AddStartMenuSC == 1
|
||||
${Unless} ${FileExists} "$SMPROGRAMS\$StartMenuDir"
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuDir"
|
||||
${LogMsg} "Added Start Menu Directory: $SMPROGRAMS\$StartMenuDir"
|
||||
${EndUnless}
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
ApplicationID::Set "$SMPROGRAMS\$StartMenuDir\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
CreateShortCut "$SMPROGRAMS\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" \
|
||||
"" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\${BrandFullName}.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullName} ($(SAFE_MODE)).lnk" "$INSTDIR\${FileMainEXE}" "-safe-mode" "$INSTDIR\${FileMainEXE}" 0
|
||||
ApplicationID::Set "$SMPROGRAMS\$StartMenuDir\${BrandFullName} ($(SAFE_MODE)).lnk" "${AppUserModelID}"
|
||||
${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\${BrandFullName} ($(SAFE_MODE)).lnk"
|
||||
${EndIf}
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
|
||||
${If} $AddDesktopSC == 1
|
||||
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" \
|
||||
"" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
${LogMsg} "Added Shortcut: $DESKTOP\${BrandFullName}.lnk"
|
||||
${EndIf}
|
||||
@ -523,8 +518,6 @@ Function CustomAbort
|
||||
GetFunctionAddress $0 AbortSurveyDirectory
|
||||
${ElseIf} "$PageName" == "Shortcuts"
|
||||
GetFunctionAddress $0 AbortSurveyShortcuts
|
||||
${ElseIf} "$PageName" == "StartMenu"
|
||||
GetFunctionAddress $0 AbortSurveyStartMenu
|
||||
${ElseIf} "$PageName" == "Summary"
|
||||
GetFunctionAddress $0 AbortSurveySummary
|
||||
${EndIf}
|
||||
@ -564,19 +557,18 @@ Function AbortSurveyShortcuts
|
||||
ExecShell "open" "${AbortSurveyURL}step4"
|
||||
FunctionEnd
|
||||
|
||||
Function AbortSurveyStartMenu
|
||||
ExecShell "open" "${AbortSurveyURL}step5"
|
||||
FunctionEnd
|
||||
|
||||
Function AbortSurveySummary
|
||||
ExecShell "open" "${AbortSurveyURL}step6"
|
||||
ExecShell "open" "${AbortSurveyURL}step5"
|
||||
FunctionEnd
|
||||
|
||||
################################################################################
|
||||
# Helper Functions
|
||||
|
||||
Function AddQuickLaunchShortcut
|
||||
CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" \
|
||||
"" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$QUICKLAUNCH\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
FunctionEnd
|
||||
|
||||
@ -746,49 +738,6 @@ Function leaveShortcuts
|
||||
${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State"
|
||||
${MUI_INSTALLOPTIONS_READ} $AddQuickLaunchSC "shortcuts.ini" "Field 4" "State"
|
||||
|
||||
; If Start Menu shortcuts won't be created call CheckExistingInstall here
|
||||
; since leaveStartMenu will not be called.
|
||||
${If} $AddStartMenuSC != 1
|
||||
${AndIf} $InstallType == ${INSTALLTYPE_CUSTOM}
|
||||
Call CheckExistingInstall
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function preStartMenu
|
||||
StrCpy $PageName "StartMenu"
|
||||
; With the Unicode installer the path to the application's Start Menu
|
||||
; directory relative to the Start Menu's Programs directory is written to the
|
||||
; shortcuts log ini file and is used to set the default Start Menu directory.
|
||||
${GetSMProgramsDirRelPath} $0
|
||||
${If} "$0" != ""
|
||||
StrCpy $StartMenuDir "$0"
|
||||
${Else}
|
||||
; Prior to the Unicode installer the path to the application's Start Menu
|
||||
; directory relative to the Start Menu's Programs directory was written to
|
||||
; the registry and use this value to set the default Start Menu directory.
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKLM "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main" "Start Menu Folder"
|
||||
${If} ${Errors}
|
||||
; Use the FindSMProgramsDir macro to find a previously used path to the
|
||||
; application's Start Menu directory relative to the Start Menu's Programs
|
||||
; directory in the uninstall log and use this value to set the default
|
||||
; Start Menu directory.
|
||||
${FindSMProgramsDir} $0
|
||||
${If} "$0" != ""
|
||||
StrCpy $StartMenuDir "$0"
|
||||
${EndIf}
|
||||
${Else}
|
||||
StrCpy $StartMenuDir "$0"
|
||||
${EndUnless}
|
||||
${EndIf}
|
||||
|
||||
${CheckCustomCommon}
|
||||
${If} $AddStartMenuSC != 1
|
||||
Abort
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function leaveStartMenu
|
||||
${If} $InstallType == ${INSTALLTYPE_CUSTOM}
|
||||
Call CheckExistingInstall
|
||||
${EndIf}
|
||||
|
@ -78,6 +78,10 @@
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
; Migrate the application's Start Menu directory to a single shortcut in the
|
||||
; root of the Start Menu Programs directory.
|
||||
${MigrateStartMenuShortcut}
|
||||
|
||||
${RemoveDeprecatedKeys}
|
||||
|
||||
${SetAppKeys}
|
||||
@ -126,20 +130,39 @@
|
||||
${If} "$0" == ""
|
||||
ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
|
||||
Pop $0
|
||||
; Needs to handle short paths
|
||||
${GetLongPath} "$0" $0
|
||||
${If} "$0" == "$INSTDIR\${FileMainEXE}"
|
||||
Delete "$DESKTOP\${BrandFullName}.lnk"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
SetShellVarContext all ; Set $SMPROGRAMS to All Users
|
||||
${Unless} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
SetShellVarContext current ; Set $SMPROGRAMS to the current user's Start
|
||||
; Menu Programs directory
|
||||
${EndUnless}
|
||||
|
||||
${If} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
ShellLink::GetShortCutArgs "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
Pop $0
|
||||
${If} "$0" == ""
|
||||
ShellLink::GetShortCutTarget "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
Pop $0
|
||||
${GetLongPath} "$0" $0
|
||||
${If} "$0" == "$INSTDIR\${FileMainEXE}"
|
||||
Delete "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
|
||||
ShellLink::GetShortCutArgs "$QUICKLAUNCH\${BrandFullName}.lnk"
|
||||
Pop $0
|
||||
${If} "$0" == ""
|
||||
ShellLink::GetShortCutTarget "$QUICKLAUNCH\${BrandFullName}.lnk"
|
||||
Pop $0
|
||||
; Needs to handle short paths
|
||||
${GetLongPath} "$0" $0
|
||||
${If} "$0" == "$INSTDIR\${FileMainEXE}"
|
||||
Delete "$QUICKLAUNCH\${BrandFullName}.lnk"
|
||||
${EndIf}
|
||||
@ -154,24 +177,51 @@
|
||||
${StrFilter} "${FileMainEXE}" "+" "" "" $0
|
||||
StrCpy $R1 "Software\Clients\StartMenuInternet\$0\InstallInfo"
|
||||
WriteRegDWORD HKLM "$R1" "IconsVisible" 1
|
||||
|
||||
SetShellVarContext all ; Set $DESKTOP to All Users
|
||||
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
|
||||
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" \
|
||||
"" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR"
|
||||
ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
|
||||
SetShellVarContext current ; Set $DESKTOP to the current user's desktop
|
||||
${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
|
||||
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
CreateShortCut "$DESKTOP\${BrandFullName}.lnk" \
|
||||
"$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$DESKTOP\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR"
|
||||
${EndUnless}
|
||||
${EndUnless}
|
||||
${EndUnless}
|
||||
|
||||
SetShellVarContext all ; Set $DESKTOP to All Users
|
||||
${Unless} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
${Unless} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
SetShellVarContext current ; Set $SMPROGRAMS to the current user's Start
|
||||
; Menu Programs directory
|
||||
${Unless} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
${EndUnless}
|
||||
${EndUnless}
|
||||
${EndUnless}
|
||||
|
||||
${Unless} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
|
||||
CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" \
|
||||
"$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$QUICKLAUNCH\${BrandFullName}.lnk" "${AppUserModelID}"
|
||||
ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR"
|
||||
${EndUnless}
|
||||
!macroend
|
||||
!define ShowShortcuts "!insertmacro ShowShortcuts"
|
||||
@ -612,29 +662,114 @@
|
||||
!macroend
|
||||
!define RemoveDeprecatedFiles "!insertmacro RemoveDeprecatedFiles"
|
||||
|
||||
; Adds a shortcut to the root of the Start Menu Programs directory if the
|
||||
; application's Start Menu Programs directory exists with a shortcut pointing to
|
||||
; this installation directory. This will also remove the old shortcuts and the
|
||||
; application's Start Menu Programs directory by calling the RemoveStartMenuDir
|
||||
; macro.
|
||||
!macro MigrateStartMenuShortcut
|
||||
${GetShortcutsLogPath} $0
|
||||
${If} ${FileExists} "$0"
|
||||
ClearErrors
|
||||
ReadINIStr $5 "$0" "SMPROGRAMS" "RelativePathToDir"
|
||||
${Unless} ${Errors}
|
||||
ClearErrors
|
||||
ReadINIStr $1 "$0" "STARTMENU" "Shortcut0"
|
||||
${If} ${Errors}
|
||||
; The STARTMENU ini section doesn't exist.
|
||||
${LogStartMenuShortcut} "${BrandFullName}.lnk"
|
||||
${GetLongPath} "$SMPROGRAMS" $2
|
||||
${GetLongPath} "$2\$5" $1
|
||||
${If} "$1" != ""
|
||||
ClearErrors
|
||||
ReadINIStr $3 "$0" "SMPROGRAMS" "Shortcut0"
|
||||
${Unless} ${Errors}
|
||||
${If} ${FileExists} "$1\$3"
|
||||
ShellLink::GetShortCutTarget "$1\$3"
|
||||
Pop $4
|
||||
${If} "$INSTDIR\${FileMainEXE}" == "$4"
|
||||
CreateShortCut "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR\${FileMainEXE}" "" \
|
||||
"$INSTDIR\${FileMainEXE}" 0
|
||||
ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"$INSTDIR"
|
||||
ApplicationID::Set "$SMPROGRAMS\${BrandFullName}.lnk" \
|
||||
"${AppUserModelID}"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
${EndUnless}
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
; Remove the application's Start Menu Programs directory, shortcuts, and
|
||||
; ini section.
|
||||
${RemoveStartMenuDir}
|
||||
${EndUnless}
|
||||
${EndIf}
|
||||
!macroend
|
||||
!define MigrateStartMenuShortcut "!insertmacro MigrateStartMenuShortcut"
|
||||
|
||||
; Removes the application's start menu directory along with its shortcuts if
|
||||
; they exist and if they exist creates a start menu shortcut in the root of the
|
||||
; start menu directory (bug 598779). If the application's start menu directory
|
||||
; is not empty after removing the shortucts the directory will not be removed
|
||||
; since these additional items were not created by the installer (uses SHCTX).
|
||||
!macro RemoveStartMenuDir
|
||||
${GetShortcutsLogPath} $0
|
||||
${If} ${FileExists} "$0"
|
||||
; Delete Start Menu Programs shortcuts, directory if it is empty, and
|
||||
; parent directories if they are empty up to but not including the start
|
||||
; menu directory.
|
||||
${GetLongPath} "$SMPROGRAMS" $1
|
||||
ClearErrors
|
||||
ReadINIStr $2 "$0" "SMPROGRAMS" "RelativePathToDir"
|
||||
${Unless} ${Errors}
|
||||
${GetLongPath} "$1\$2" $2
|
||||
${If} "$2" != ""
|
||||
; Delete shortucts in the Start Menu Programs directory.
|
||||
StrCpy $3 0
|
||||
${Do}
|
||||
ClearErrors
|
||||
ReadINIStr $4 "$0" "SMPROGRAMS" "Shortcut$3"
|
||||
; Stop if there are no more entries
|
||||
${If} ${Errors}
|
||||
${ExitDo}
|
||||
${EndIf}
|
||||
${If} ${FileExists} "$2\$4"
|
||||
ShellLink::GetShortCutTarget "$2\$4"
|
||||
Pop $5
|
||||
${If} "$INSTDIR\${FileMainEXE}" == "$5"
|
||||
Delete "$2\$4"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
IntOp $3 $3 + 1 ; Increment the counter
|
||||
${Loop}
|
||||
; Delete Start Menu Programs directory and parent directories
|
||||
${Do}
|
||||
; Stop if the current directory is the start menu directory
|
||||
${If} "$1" == "$2"
|
||||
${ExitDo}
|
||||
${EndIf}
|
||||
ClearErrors
|
||||
RmDir "$2"
|
||||
; Stop if removing the directory failed
|
||||
${If} ${Errors}
|
||||
${ExitDo}
|
||||
${EndIf}
|
||||
${GetParent} "$2" $2
|
||||
${Loop}
|
||||
${EndIf}
|
||||
DeleteINISec "$0" "SMPROGRAMS"
|
||||
${EndUnless}
|
||||
${EndIf}
|
||||
!macroend
|
||||
!define RemoveStartMenuDir "!insertmacro RemoveStartMenuDir"
|
||||
|
||||
; Creates the shortcuts log ini file with the appropriate entries if it doesn't
|
||||
; already exist.
|
||||
!macro CreateShortcutsLog
|
||||
${GetShortcutsLogPath} $0
|
||||
${Unless} ${FileExists} "$0"
|
||||
; Default to ${BrandFullName} for the Start Menu Folder
|
||||
StrCpy $TmpVal "${BrandFullName}"
|
||||
; Prior to Firefox 3.1 the Start Menu directory was written to the registry and
|
||||
; this value can be used to set the Start Menu directory.
|
||||
ClearErrors
|
||||
ReadRegStr $0 SHCTX "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main" "Start Menu Folder"
|
||||
${If} ${Errors}
|
||||
${FindSMProgramsDir} $0
|
||||
${If} "$0" != ""
|
||||
StrCpy $TmpVal "$0"
|
||||
${EndIf}
|
||||
${Else}
|
||||
StrCpy $TmpVal "$0"
|
||||
${EndUnless}
|
||||
|
||||
${LogSMProgramsDirRelPath} "$TmpVal"
|
||||
${LogSMProgramsShortcut} "${BrandFullName}.lnk"
|
||||
${LogSMProgramsShortcut} "${BrandFullName} ($(SAFE_MODE)).lnk"
|
||||
${LogStartMenuShortcut} "${BrandFullName}.lnk"
|
||||
${LogQuickLaunchShortcut} "${BrandFullName}.lnk"
|
||||
${LogDesktopShortcut} "${BrandFullName}.lnk"
|
||||
${EndUnless}
|
||||
|
@ -87,16 +87,15 @@ Var TmpVal
|
||||
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
|
||||
VIAddVersionKey "OriginalFilename" "helper.exe"
|
||||
|
||||
; Most commonly used macros for managing shortcuts
|
||||
!insertmacro _LoggingShortcutsCommon
|
||||
|
||||
!insertmacro AddDDEHandlerValues
|
||||
!insertmacro CleanVirtualStore
|
||||
!insertmacro ElevateUAC
|
||||
!insertmacro FindSMProgramsDir
|
||||
!insertmacro GetLongPath
|
||||
!insertmacro GetPathFromString
|
||||
!insertmacro IsHandlerForInstallDir
|
||||
!insertmacro LogDesktopShortcut
|
||||
!insertmacro LogQuickLaunchShortcut
|
||||
!insertmacro LogStartMenuShortcut
|
||||
!insertmacro RegCleanAppHandler
|
||||
!insertmacro RegCleanMain
|
||||
!insertmacro RegCleanUninstall
|
||||
|
@ -312,17 +312,6 @@ endif
|
||||
# Set the permissions that the folders will have in ftp once uploaded
|
||||
chmod -vR 775 $(UPLOAD_DIR)
|
||||
|
||||
l10n-upload-%: AB_CD=$*
|
||||
l10n-upload-%:
|
||||
$(PYTHON) $(topsrcdir)/build/upload.py --base-path $(DIST) "$(DIST)/$(PACKAGE)" $(DIST)/$(LANGPACK)
|
||||
ifdef MOZ_MAKE_COMPLETE_MAR
|
||||
$(PYTHON) $(topsrcdir)/build/upload.py --base-path $(DIST) $(DIST)/$(COMPLETE_MAR) $(call QUOTED_WILDCARD,$(wildcard $(DIST)/$(PARTIAL_MAR)))
|
||||
endif
|
||||
ifneq (,$(filter WINNT WINCE,$(OS_ARCH)))
|
||||
$(PYTHON) $(topsrcdir)/build/upload.py --base-path $(DIST) "$(INSTALLER_PACKAGE)"
|
||||
endif
|
||||
|
||||
|
||||
merge-%:
|
||||
ifdef LOCALE_MERGEDIR
|
||||
$(RM) -rf $(LOCALE_MERGEDIR)
|
||||
|
@ -86,8 +86,6 @@
|
||||
% override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd
|
||||
% override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
|
||||
% override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd
|
||||
#if MOZ_UPDATE_CHANNEL == beta
|
||||
% locale testpilot @AB_CD@ %locale/feedback/
|
||||
locale/feedback/main.dtd (%feedback/main.dtd)
|
||||
locale/feedback/main.properties (%feedback/main.properties)
|
||||
#endif
|
||||
|
@ -1,6 +1,7 @@
|
||||
af
|
||||
ak
|
||||
ar
|
||||
ast
|
||||
be
|
||||
bg
|
||||
bn-BD
|
||||
@ -8,6 +9,7 @@ bn-IN
|
||||
br
|
||||
ca
|
||||
cs
|
||||
cy
|
||||
da
|
||||
de
|
||||
el
|
||||
|
@ -943,17 +943,19 @@ toolbar[iconsize="small"] #feed-button {
|
||||
-moz-margin-start: 0;
|
||||
}
|
||||
|
||||
#urlbar-display {
|
||||
margin-top: -2px;
|
||||
margin-bottom: -2px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 2px;
|
||||
-moz-padding-end: 3px;
|
||||
color: GrayText;
|
||||
#urlbar-display-box {
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
-moz-border-end: 1px solid #AAA;
|
||||
-moz-margin-end: 3px;
|
||||
}
|
||||
|
||||
#urlbar-display {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
#PopupAutoComplete,
|
||||
#PopupAutoCompleteRichResult {
|
||||
direction: ltr !important;
|
||||
@ -1120,14 +1122,6 @@ toolbar[iconsize="small"] #feed-button {
|
||||
min-width: 280px;
|
||||
}
|
||||
|
||||
/* Invalid form popup */
|
||||
#invalid-form-popup {
|
||||
-moz-appearance: none;
|
||||
background-color: #fffcd6;
|
||||
border: 1px solid #dad8b6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Notification popup */
|
||||
#notification-popup {
|
||||
min-width: 280px;
|
||||
|
@ -78,7 +78,6 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/tab.png (tabbrowser/tab.png)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png)
|
||||
skin/classic/browser/tabview/edit.png (tabview/edit.png)
|
||||
skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png)
|
||||
skin/classic/browser/tabview/search.png (tabview/search.png)
|
||||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
|
@ -105,6 +105,10 @@ description > .text-link:focus {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#passphraseHelpSpacer {
|
||||
width: 0.5em;
|
||||
}
|
||||
|
||||
#add-device-throbber > image,
|
||||
#login-throbber > image {
|
||||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
|
Before Width: | Height: | Size: 238 B |
@ -501,8 +501,10 @@ html[dir=rtl] .resizer {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
padding-right: 3px;
|
||||
padding-bottom: 3px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
}
|
||||
|
||||
html[dir=rtl] .iq-resizable-se {
|
||||
|
@ -757,28 +757,22 @@ toolbar[mode="icons"] #zoom-in-button {
|
||||
width: 7em;
|
||||
min-width: 7em;
|
||||
-moz-appearance: none;
|
||||
border: 0;
|
||||
box-shadow: 0 1px rgba(255, 255, 255, 0.2);
|
||||
box-shadow: 0 1px rgba(255, 255, 255, 0.2), inset 0 1px #d6d6d6;
|
||||
margin: 0 4px;
|
||||
padding: 0;
|
||||
border: 1px solid transparent;
|
||||
background: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF),
|
||||
-moz-linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.2));
|
||||
background-origin: padding-box, border-box;
|
||||
background-clip: padding-box, border-box;
|
||||
border: 1px solid;
|
||||
border-color: #626262 #787878 #8c8c8c;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#urlbar:-moz-window-inactive,
|
||||
.searchbar-textbox:-moz-window-inactive {
|
||||
background-image: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF),
|
||||
-moz-linear-gradient(@toolbarbuttonInactiveBorderColor@, @toolbarbuttonInactiveBorderColor@);
|
||||
border-color: @toolbarbuttonInactiveBorderColor@;
|
||||
}
|
||||
|
||||
#urlbar[focused="true"],
|
||||
.searchbar-textbox[focused="true"] {
|
||||
background-color: -moz-mac-focusring;
|
||||
background-image: -moz-linear-gradient(#D6D6D6, #D6D6D6 1px, #F7F7F7 1px, #F7F7F7 2px, #FFF 2px, #FFF),
|
||||
-moz-linear-gradient(rgba(0,0,0,.1), rgba(0,0,0,.1));
|
||||
border-color: -moz-mac-focusring;
|
||||
box-shadow: @focusRingShadow@;
|
||||
}
|
||||
|
||||
@ -892,17 +886,17 @@ toolbar[mode="icons"] #zoom-in-button {
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
#urlbar-display {
|
||||
margin-top: -3px;
|
||||
margin-bottom: -2px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 2px;
|
||||
-moz-padding-end: 3px;
|
||||
color: GrayText;
|
||||
#urlbar-display-box {
|
||||
-moz-border-end: 1px solid #AAA;
|
||||
-moz-margin-end: 3px;
|
||||
}
|
||||
|
||||
#urlbar-display {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
#PopupAutoCompleteRichResult {
|
||||
direction: ltr !important;
|
||||
margin-top: 2px;
|
||||
@ -1427,12 +1421,12 @@ sidebarheader {
|
||||
-moz-border-end: 1px solid #404040;
|
||||
min-width: 1px;
|
||||
width: 1px;
|
||||
background-image: none !important;
|
||||
}
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
#sidebar-title {
|
||||
color: #535f6d;
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#sidebar-throbber[loading="true"] {
|
||||
|
@ -117,7 +117,6 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/tab-top-selected-active.png (tabbrowser/tab-top-selected-active.png)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png)
|
||||
skin/classic/browser/tabview/edit.png (tabview/edit.png)
|
||||
skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png)
|
||||
skin/classic/browser/tabview/search.png (tabview/search.png)
|
||||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
|
@ -104,6 +104,10 @@ description > .text-link:focus {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#passphraseHelpSpacer {
|
||||
width: 0.5em;
|
||||
}
|
||||
|
||||
#add-device-throbber > image,
|
||||
#login-throbber > image {
|
||||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
|
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 691 B After Width: | Height: | Size: 611 B |
Before Width: | Height: | Size: 156 B After Width: | Height: | Size: 291 B |
Before Width: | Height: | Size: 238 B |
@ -7,7 +7,11 @@ body {
|
||||
}
|
||||
|
||||
#bg {
|
||||
background: -moz-linear-gradient(top,#C4C4C4,#9E9E9E);
|
||||
background: -moz-linear-gradient(#C4C4C4,#9E9E9E);
|
||||
}
|
||||
|
||||
#bg:-moz-window-inactive {
|
||||
background: -moz-linear-gradient(rgb(237,237,237),rgb(216,216,216));
|
||||
}
|
||||
|
||||
/* Tabs
|
||||
@ -132,7 +136,7 @@ html[dir=rtl] .expander {
|
||||
width: 94.5%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-shadow: 0 1px rgba(255, 255, 255, 0.6);
|
||||
text-shadow: 0 1px rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.stacked {
|
||||
@ -419,7 +423,7 @@ input.name:focus {
|
||||
|
||||
input.name:-moz-placeholder {
|
||||
font-style: italic !important;
|
||||
color: transparent;
|
||||
color: transparent;
|
||||
background-image: url(chrome://browser/skin/tabview/edit-light.png);
|
||||
background-image-opacity: .1;
|
||||
background-repeat: no-repeat;
|
||||
@ -493,8 +497,10 @@ html[dir=rtl] .resizer {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
padding-right: 3px;
|
||||
padding-bottom: 3px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
}
|
||||
|
||||
html[dir=rtl] .iq-resizable-se {
|
||||
@ -540,6 +546,10 @@ html[dir=rtl] .iq-resizable-se {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#searchshade:-moz-window-inactive {
|
||||
background: -moz-linear-gradient(rgba(237,237,237,.42),rgba(216,216,216,.42));
|
||||
}
|
||||
|
||||
#search{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -558,6 +568,11 @@ html[dir=rtl] .iq-resizable-se {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#searchbox:-moz-window-inactive {
|
||||
background-color: #BBBBBB;
|
||||
box-shadow: 0px 1px 0px rgba(255,255,255,.1), 0px -1px 0px rgba(0,0,0,0.3), 0px 0px 13px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
#actions {
|
||||
width: 29px;
|
||||
text-align: center;
|
||||
|
@ -121,22 +121,22 @@
|
||||
text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
|
||||
}
|
||||
|
||||
#main-window[sizemode="normal"] #navigator-toolbox:not([inFullscreen="true"])::after,
|
||||
#main-window[sizemode="normal"] #navigator-toolbox[tabsontop="true"] > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not([inFullscreen="true"]):not(:-moz-lwtheme) {
|
||||
border-left: 1px solid @glassToolbarBorderColor@;
|
||||
border-right: 1px solid @glassToolbarBorderColor@;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
#navigator-toolbox[tabsontop="false"],
|
||||
#main-window[disablechrome] #navigator-toolbox[tabsontop="true"],
|
||||
#navigator-toolbox > toolbar {
|
||||
border-color: @glassToolbarBorderColor@ !important;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
#main-window[sizemode="normal"]:not([disablechrome]) #navigator-toolbox[tabsontop="true"] {
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
#navigator-toolbox[tabsontop="false"]::after,
|
||||
#main-window[disablechrome] #navigator-toolbox[tabsontop="true"]::after {
|
||||
background-color: @glassToolbarBorderColor@;
|
||||
}
|
||||
#main-window[sizemode="normal"] #browser-border-start,
|
||||
#main-window[sizemode="normal"] #browser-border-end {
|
||||
#main-window[sizemode="normal"]:not([inFullscreen="true"]) #browser-border-start,
|
||||
#main-window[sizemode="normal"]:not([inFullscreen="true"]) #browser-border-end {
|
||||
display: -moz-box;
|
||||
background-color: @glassToolbarBorderColor@;
|
||||
width: 1px;
|
||||
@ -231,6 +231,12 @@
|
||||
color: black;
|
||||
text-shadow: white -1px -1px .35em, white -1px 1px .35em, white 1px 1px .35em, white 1px -1px .35em;
|
||||
}
|
||||
|
||||
#tab-view:-moz-lwtheme {
|
||||
background-image: url("chrome://browser/skin/tabview/grain.png"),
|
||||
-moz-linear-gradient(rgba(255,255,255,0), #CCD9EA 200px, #C7D5E7);
|
||||
background-attachment: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
@media not all and (-moz-windows-compositor) {
|
||||
|
@ -67,7 +67,14 @@
|
||||
-moz-appearance: none;
|
||||
background-color: transparent;
|
||||
border-top: none;
|
||||
border-bottom: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
||||
#navigator-toolbox::after {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
-moz-box-ordinal-group: 101; /* tabs toolbar is 100 */
|
||||
height: 1px;
|
||||
background-color: ThreeDShadow;
|
||||
}
|
||||
|
||||
#navigator-toolbox > toolbar:not(:-moz-lwtheme) {
|
||||
@ -219,7 +226,7 @@
|
||||
-moz-margin-start: .5em;
|
||||
}
|
||||
|
||||
.split-menuitem-menu {
|
||||
.splitmenu-menu {
|
||||
-moz-box-pack: end;
|
||||
}
|
||||
|
||||
@ -669,12 +676,10 @@ menuitem.bookmark-item {
|
||||
.toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
.toolbarbutton-1 > .toolbarbutton-icon {
|
||||
-moz-margin-end: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
toolbar[iconsize="small"] .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
toolbar[iconsize="small"] .toolbarbutton-1 > .toolbarbutton-icon {
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-icon {
|
||||
margin: 1px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@ -1130,17 +1135,19 @@ html|*.urlbar-input:-moz-lwtheme:-moz-placeholder,
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
#urlbar-display {
|
||||
#urlbar-display-box {
|
||||
margin-top: -2px;
|
||||
margin-bottom: -2px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 2px;
|
||||
-moz-padding-end: 3px;
|
||||
color: GrayText;
|
||||
-moz-border-end: 1px solid #AAA;
|
||||
-moz-margin-end: 3px;
|
||||
}
|
||||
|
||||
#urlbar-display {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
/* over-link in location bar */
|
||||
|
||||
.urlbar-origin-label {
|
||||
|
@ -94,7 +94,6 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png)
|
||||
skin/classic/browser/tabview/edit.png (tabview/edit.png)
|
||||
skin/classic/browser/tabview/grain.png (tabview/grain.png)
|
||||
skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png)
|
||||
skin/classic/browser/tabview/search.png (tabview/search.png)
|
||||
@ -209,7 +208,6 @@ browser.jar:
|
||||
skin/classic/aero/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
skin/classic/aero/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/aero/browser/tabview/edit-light.png (tabview/edit-light.png)
|
||||
skin/classic/aero/browser/tabview/edit.png (tabview/edit.png)
|
||||
skin/classic/aero/browser/tabview/grain.png (tabview/grain.png)
|
||||
skin/classic/aero/browser/tabview/new-tab.png (tabview/new-tab.png)
|
||||
skin/classic/aero/browser/tabview/search.png (tabview/search.png)
|
||||
|
@ -105,6 +105,10 @@ description > .text-link:focus {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#passphraseHelpSpacer {
|
||||
width: 0.5em;
|
||||
}
|
||||
|
||||
#add-device-throbber > image,
|
||||
#login-throbber > image {
|
||||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
|
Before Width: | Height: | Size: 238 B |
@ -5,7 +5,7 @@ body {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
#bg {
|
||||
#bg:not(:-moz-system-metric(windows-compositor)) {
|
||||
background: url("chrome://browser/skin/tabview/grain.png") repeat scroll center top,
|
||||
-moz-linear-gradient(center top , #CCD9EA, #C7D5E7) repeat scroll 0 0 transparent;
|
||||
}
|
||||
@ -520,8 +520,10 @@ html[dir=rtl] .resizer {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
padding-right: 3px;
|
||||
padding-bottom: 3px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
}
|
||||
|
||||
html[dir=rtl] .iq-resizable-se {
|
||||
|
@ -339,6 +339,7 @@ user_pref("dom.disable_open_during_load", false);
|
||||
user_pref("dom.max_script_run_time", 0); // no slow script dialogs
|
||||
user_pref("dom.max_chrome_script_run_time", 0);
|
||||
user_pref("dom.popup_maximum", -1);
|
||||
user_pref("dom.send_after_paint_to_content", true);
|
||||
user_pref("dom.successive_dialog_time_limit", 0);
|
||||
user_pref("signed.applets.codebase_principal_support", true);
|
||||
user_pref("security.warn_submit_insecure", false);
|
||||
|
@ -81,11 +81,7 @@ genpgocert.py: genpgocert.py.in
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
|
||||
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@
|
||||
|
||||
profileserver.py: profileserver.py.in
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@
|
||||
chmod +x $@
|
||||
|
||||
GARBAGE += profileserver.py genpgocert.py
|
||||
GARBAGE += genpgocert.py
|
||||
|
||||
libs:: $(_PGO_FILES)
|
||||
$(INSTALL) $^ $(_PROFILE_DIR)
|
||||
|
@ -16,7 +16,7 @@
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# the Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
@ -45,6 +45,10 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = build
|
||||
|
||||
ifeq ($(USE_ELF_HACK)$(HOST_OS_ARCH)$(OS_ARCH)$(OS_TARGET),1LinuxLinuxLinux)
|
||||
DIRS = elfhack
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs:: $(srcdir)/run-mozilla.sh
|
||||
|
112
build/unix/elfhack/Makefile.in
Normal file
@ -0,0 +1,112 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is elfhack
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mike Hommey <mh@glandium.org>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
INTERNAL_TOOLS = 1
|
||||
|
||||
HOST_PROGRAM = elfhack
|
||||
NO_DIST_INSTALL = 1
|
||||
|
||||
HOST_CPPSRCS = \
|
||||
elf.cpp \
|
||||
elfhack.cpp \
|
||||
$(NULL)
|
||||
|
||||
OS_CXXFLAGS += -fexceptions
|
||||
|
||||
ifneq (,$(filter %86,$(TARGET_CPU)))
|
||||
CPU := x86
|
||||
else
|
||||
CPU := $(TARGET_CPU)
|
||||
endif
|
||||
|
||||
CSRCS := \
|
||||
inject/$(CPU).c \
|
||||
inject/$(CPU)-noinit.c \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
|
||||
ifndef CROSS_COMPILE
|
||||
test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) elfhack $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
$(MKSHLIB) $<
|
||||
rm -f $@.bak
|
||||
$(CURDIR)/elfhack -b $@
|
||||
# Fail if the backup file doesn't exist
|
||||
[ -f "$@.bak" ]
|
||||
# Fail if the new library doesn't contain less relocations
|
||||
[ $$(objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
|
||||
|
||||
dummy: dummy.$(OBJ_SUFFIX) test$(DLL_SUFFIX)
|
||||
$(CC) -o $@ $^
|
||||
|
||||
libs:: dummy
|
||||
# Will either crash or return exit code 1 if elfhack is broken
|
||||
LD_LIBRARY_PATH=$(CURDIR) $(CURDIR)/dummy
|
||||
|
||||
CSRCS += test.c dummy.c
|
||||
|
||||
GARBAGE += dummy test$(DLL_SUFFIX) test$(DLL_SUFFIX).bak
|
||||
endif
|
||||
|
||||
inject:
|
||||
$(NSINSTALL) -D $@
|
||||
|
||||
inject/%.c: inject.c | inject
|
||||
cp $< $@
|
||||
|
||||
GARBAGE_DIRS += inject
|
||||
|
||||
inject/%.$(OBJ_SUFFIX): DEFINES += -DBITS=$(if $(HAVE_64BIT_OS),64,32)
|
||||
inject/$(CPU)-noinit.$(OBJ_SUFFIX): DEFINES += -DNOINIT
|
||||
|
||||
# need this to suppress errors due to /usr/include/linux/byteorder/swab.h
|
||||
# on mozilla buildbots
|
||||
OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
|
||||
|
||||
# Avoid building as thumb code, this is not supported yet
|
||||
COMMA := ,
|
||||
OS_CFLAGS := $(filter-out -mthumb -Wa$(COMMA)-mthumb,$(OS_CFLAGS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|