mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Merge MC -> JM
This commit is contained in:
commit
f631882466
@ -111,97 +111,53 @@ getActionNameCB(AtkAction *aAction, gint aActionIndex)
|
||||
const gchar *
|
||||
getKeyBindingCB(AtkAction *aAction, gint aActionIndex)
|
||||
{
|
||||
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
nsAccessibleWrap* acc = GetAccessibleWrap(ATK_OBJECT(aAction));
|
||||
if (!acc)
|
||||
return nsnull;
|
||||
|
||||
//return all KeyBindings including accesskey and shortcut
|
||||
nsAutoString allKeyBinding;
|
||||
// Return all key bindings including access key and keyboard shortcut.
|
||||
nsAutoString keyBindingsStr;
|
||||
|
||||
//get accesskey
|
||||
nsAutoString accessKey;
|
||||
nsresult rv = accWrap->GetKeyboardShortcut(accessKey);
|
||||
// Get access key.
|
||||
KeyBinding keyBinding = acc->AccessKey();
|
||||
if (!keyBinding.IsEmpty()) {
|
||||
keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !accessKey.IsEmpty()) {
|
||||
nsAccessible* parent = accWrap->GetParent();
|
||||
if (parent) {
|
||||
PRUint32 atkRole = atkRoleMap[parent->NativeRole()];
|
||||
nsAccessible* parent = acc->GetParent();
|
||||
PRUint32 role = parent ? parent->Role() : 0;
|
||||
if (role == nsIAccessibleRole::ROLE_PARENT_MENUITEM ||
|
||||
role == nsIAccessibleRole::ROLE_MENUITEM ||
|
||||
role == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM ||
|
||||
role == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM) {
|
||||
// It is submenu, expose keyboard shortcuts from menu hierarchy like
|
||||
// "s;<Alt>f:s"
|
||||
nsAutoString keysInHierarchyStr = keyBindingsStr;
|
||||
do {
|
||||
KeyBinding parentKeyBinding = parent->AccessKey();
|
||||
if (!parentKeyBinding.IsEmpty()) {
|
||||
nsAutoString str;
|
||||
parentKeyBinding.ToString(str, KeyBinding::eAtkFormat);
|
||||
str.Append(':');
|
||||
|
||||
if (atkRole == ATK_ROLE_MENU_BAR) {
|
||||
//it is topmenu, change from "Alt+f" to "f;<Alt>f"
|
||||
nsAutoString rightChar;
|
||||
accessKey.Right(rightChar, 1);
|
||||
allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") +
|
||||
rightChar;
|
||||
}
|
||||
else if ((atkRole == ATK_ROLE_MENU) || (atkRole == ATK_ROLE_MENU_ITEM)) {
|
||||
//it is submenu, change from "s" to "s;<Alt>f:s"
|
||||
nsAutoString allKey = accessKey;
|
||||
nsAccessible* grandParent = parent;
|
||||
|
||||
do {
|
||||
nsAutoString grandParentKey;
|
||||
grandParent->GetKeyboardShortcut(grandParentKey);
|
||||
|
||||
if (!grandParentKey.IsEmpty()) {
|
||||
nsAutoString rightChar;
|
||||
grandParentKey.Right(rightChar, 1);
|
||||
allKey = rightChar + NS_LITERAL_STRING(":") + allKey;
|
||||
}
|
||||
|
||||
} while ((grandParent = grandParent->GetParent()) &&
|
||||
atkRoleMap[grandParent->NativeRole()] != ATK_ROLE_MENU_BAR);
|
||||
|
||||
allKeyBinding = accessKey + NS_LITERAL_STRING(";<Alt>") +
|
||||
allKey;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//default process, rarely happens.
|
||||
nsAutoString rightChar;
|
||||
accessKey.Right(rightChar, 1);
|
||||
allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") + rightChar;
|
||||
keysInHierarchyStr.Insert(str, 0);
|
||||
}
|
||||
} while ((parent = parent->GetParent()) &&
|
||||
parent->Role() != nsIAccessibleRole::ROLE_MENUBAR);
|
||||
|
||||
keyBindingsStr.Append(';');
|
||||
keyBindingsStr.Append(keysInHierarchyStr);
|
||||
}
|
||||
else //don't have accesskey
|
||||
allKeyBinding.AssignLiteral(";");
|
||||
} else {
|
||||
// No access key, add ';' to point this.
|
||||
keyBindingsStr.Append(';');
|
||||
}
|
||||
|
||||
//get shortcut
|
||||
nsAutoString subShortcut;
|
||||
nsCOMPtr<nsIDOMDOMStringList> keyBindings;
|
||||
rv = accWrap->GetKeyBindings(aActionIndex, getter_AddRefs(keyBindings));
|
||||
// Get keyboard shortcut.
|
||||
keyBindingsStr.Append(';');
|
||||
keyBinding = acc->KeyboardShortcut();
|
||||
if (!keyBinding.IsEmpty()) {
|
||||
keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && keyBindings) {
|
||||
PRUint32 length = 0;
|
||||
keyBindings->GetLength(&length);
|
||||
for (PRUint32 i = 0; i < length; i++) {
|
||||
nsAutoString keyBinding;
|
||||
keyBindings->Item(i, keyBinding);
|
||||
|
||||
//change the shortcut from "Ctrl+Shift+L" to "<Control><Shift>L"
|
||||
PRInt32 oldPos, curPos=0;
|
||||
while ((curPos != -1) && (curPos < (PRInt32)keyBinding.Length())) {
|
||||
oldPos = curPos;
|
||||
nsAutoString subString;
|
||||
curPos = keyBinding.FindChar('+', oldPos);
|
||||
if (curPos == -1) {
|
||||
keyBinding.Mid(subString, oldPos, keyBinding.Length() - oldPos);
|
||||
subShortcut += subString;
|
||||
} else {
|
||||
keyBinding.Mid(subString, oldPos, curPos - oldPos);
|
||||
|
||||
//change "Ctrl" to "Control"
|
||||
if (subString.LowerCaseEqualsLiteral("ctrl"))
|
||||
subString.AssignLiteral("Control");
|
||||
|
||||
subShortcut += NS_LITERAL_STRING("<") + subString +
|
||||
NS_LITERAL_STRING(">");
|
||||
curPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allKeyBinding += NS_LITERAL_STRING(";") + subShortcut;
|
||||
return nsAccessibleWrap::ReturnString(allKeyBinding);
|
||||
return nsAccessibleWrap::ReturnString(keyBindingsStr);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "nsEventShell.h"
|
||||
#include "nsTextAccessible.h"
|
||||
#include "TextUpdater.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -258,17 +259,9 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
if (ownerContent) {
|
||||
nsAccessible* outerDocAcc = mDocument->GetAccessible(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);
|
||||
|
||||
if (mDocument->AppendChildDocument(childDoc))
|
||||
continue;
|
||||
}
|
||||
|
||||
outerDocAcc->RemoveChild(childDoc);
|
||||
}
|
||||
|
||||
|
@ -468,12 +468,13 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
||||
}
|
||||
|
||||
// Fire reorder event to notify new accessible document has been attached to
|
||||
// the tree.
|
||||
// the tree. The reorder event is delivered after the document tree is
|
||||
// constructed because event processing and tree construction are done by
|
||||
// the same document.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, appAcc, eAutoDetect,
|
||||
AccEvent::eCoalesceFromSameSubtree);
|
||||
if (reorderEvent)
|
||||
docAcc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
docAcc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
|
||||
} else {
|
||||
parentDocAcc->BindChildDocument(docAcc);
|
||||
|
@ -76,7 +76,6 @@
|
||||
*/
|
||||
|
||||
nsIStringBundle *nsAccessNode::gStringBundle = 0;
|
||||
nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
|
||||
nsINode *nsAccessNode::gLastFocusedNode = nsnull;
|
||||
|
||||
PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
|
||||
@ -210,8 +209,6 @@ void nsAccessNode::InitXPAccessibility()
|
||||
// Static variables are released in ShutdownAllXPAccessibility();
|
||||
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL,
|
||||
&gStringBundle);
|
||||
stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL,
|
||||
&gKeyStringBundle);
|
||||
}
|
||||
|
||||
nsAccessibilityAtoms::AddRefAtoms();
|
||||
@ -246,7 +243,6 @@ void nsAccessNode::ShutdownXPAccessibility()
|
||||
// at exit of program
|
||||
|
||||
NS_IF_RELEASE(gStringBundle);
|
||||
NS_IF_RELEASE(gKeyStringBundle);
|
||||
NS_IF_RELEASE(gLastFocusedNode);
|
||||
|
||||
// Release gApplicationAccessible after everything else is shutdown
|
||||
|
@ -215,7 +215,6 @@ protected:
|
||||
|
||||
// Static data, we do our own refcounting for our static data
|
||||
static nsIStringBundle *gStringBundle;
|
||||
static nsIStringBundle *gKeyStringBundle;
|
||||
|
||||
static PRBool gIsFormFillEnabled;
|
||||
|
||||
|
@ -105,6 +105,7 @@
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -329,55 +330,6 @@ nsAccessible::Description(nsString& aDescription)
|
||||
aDescription.CompressWhitespace();
|
||||
}
|
||||
|
||||
// mask values for ui.key.chromeAccess and ui.key.contentAccess
|
||||
#define NS_MODIFIER_SHIFT 1
|
||||
#define NS_MODIFIER_CONTROL 2
|
||||
#define NS_MODIFIER_ALT 4
|
||||
#define NS_MODIFIER_META 8
|
||||
|
||||
// returns the accesskey modifier mask used in the given node's context
|
||||
// (i.e. chrome or content), or 0 if an error occurs
|
||||
static PRInt32
|
||||
GetAccessModifierMask(nsIContent* aContent)
|
||||
{
|
||||
// use ui.key.generalAccessKey (unless it is -1)
|
||||
switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
|
||||
case -1: break;
|
||||
case nsIDOMKeyEvent::DOM_VK_SHIFT: return NS_MODIFIER_SHIFT;
|
||||
case nsIDOMKeyEvent::DOM_VK_CONTROL: return NS_MODIFIER_CONTROL;
|
||||
case nsIDOMKeyEvent::DOM_VK_ALT: return NS_MODIFIER_ALT;
|
||||
case nsIDOMKeyEvent::DOM_VK_META: return NS_MODIFIER_META;
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
// get the docShell to this DOMNode, return 0 on failure
|
||||
nsCOMPtr<nsIDocument> document = aContent->GetCurrentDoc();
|
||||
if (!document)
|
||||
return 0;
|
||||
nsCOMPtr<nsISupports> container = document->GetContainer();
|
||||
if (!container)
|
||||
return 0;
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
|
||||
if (!treeItem)
|
||||
return 0;
|
||||
|
||||
// determine the access modifier used in this context
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
PRInt32 itemType, accessModifierMask = 0;
|
||||
treeItem->GetItemType(&itemType);
|
||||
switch (itemType) {
|
||||
case nsIDocShellTreeItem::typeChrome:
|
||||
rv = Preferences::GetInt("ui.key.chromeAccess", &accessModifierMask);
|
||||
break;
|
||||
|
||||
case nsIDocShellTreeItem::typeContent:
|
||||
rv = Preferences::GetInt("ui.key.contentAccess", &accessModifierMask);
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(rv) ? accessModifierMask : 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
|
||||
{
|
||||
@ -386,6 +338,13 @@ nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
AccessKey().ToString(aAccessKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
KeyBinding
|
||||
nsAccessible::AccessKey() const
|
||||
{
|
||||
PRUint32 key = nsCoreUtils::GetAccessKeyFor(mContent);
|
||||
if (!key && mContent->IsElement()) {
|
||||
nsAccessible* label = nsnull;
|
||||
@ -408,32 +367,54 @@ nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
|
||||
}
|
||||
|
||||
if (!key)
|
||||
return NS_OK;
|
||||
return KeyBinding();
|
||||
|
||||
nsAutoString accesskey(key);
|
||||
|
||||
// Append the modifiers in reverse order, result: Control+Alt+Shift+Meta+<key>
|
||||
nsAutoString propertyKey;
|
||||
PRInt32 modifierMask = GetAccessModifierMask(mContent);
|
||||
if (modifierMask & NS_MODIFIER_META) {
|
||||
propertyKey.AssignLiteral("VK_META");
|
||||
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
|
||||
}
|
||||
if (modifierMask & NS_MODIFIER_SHIFT) {
|
||||
propertyKey.AssignLiteral("VK_SHIFT");
|
||||
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
|
||||
}
|
||||
if (modifierMask & NS_MODIFIER_ALT) {
|
||||
propertyKey.AssignLiteral("VK_ALT");
|
||||
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
|
||||
}
|
||||
if (modifierMask & NS_MODIFIER_CONTROL) {
|
||||
propertyKey.AssignLiteral("VK_CONTROL");
|
||||
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
|
||||
// Get modifier mask. Use ui.key.generalAccessKey (unless it is -1).
|
||||
switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
|
||||
case -1:
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_SHIFT:
|
||||
return KeyBinding(key, KeyBinding::kShift);
|
||||
case nsIDOMKeyEvent::DOM_VK_CONTROL:
|
||||
return KeyBinding(key, KeyBinding::kControl);
|
||||
case nsIDOMKeyEvent::DOM_VK_ALT:
|
||||
return KeyBinding(key, KeyBinding::kAlt);
|
||||
case nsIDOMKeyEvent::DOM_VK_META:
|
||||
return KeyBinding(key, KeyBinding::kMeta);
|
||||
default:
|
||||
return KeyBinding();
|
||||
}
|
||||
|
||||
aAccessKey = accesskey;
|
||||
return NS_OK;
|
||||
// Determine the access modifier used in this context.
|
||||
nsIDocument* document = mContent->GetCurrentDoc();
|
||||
if (!document)
|
||||
return KeyBinding();
|
||||
nsCOMPtr<nsISupports> container = document->GetContainer();
|
||||
if (!container)
|
||||
return KeyBinding();
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
|
||||
if (!treeItem)
|
||||
return KeyBinding();
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
PRInt32 itemType = 0, modifierMask = 0;
|
||||
treeItem->GetItemType(&itemType);
|
||||
switch (itemType) {
|
||||
case nsIDocShellTreeItem::typeChrome:
|
||||
rv = Preferences::GetInt("ui.key.chromeAccess", &modifierMask);
|
||||
break;
|
||||
case nsIDocShellTreeItem::typeContent:
|
||||
rv = Preferences::GetInt("ui.key.contentAccess", &modifierMask);
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(rv) ? KeyBinding(key, modifierMask) : KeyBinding();
|
||||
}
|
||||
|
||||
KeyBinding
|
||||
nsAccessible::KeyboardShortcut() const
|
||||
{
|
||||
return KeyBinding();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -604,22 +585,6 @@ nsresult nsAccessible::GetTranslatedString(const nsAString& aKey, nsAString& aSt
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsAccessible::GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut)
|
||||
{
|
||||
nsXPIDLString modifierName, separator;
|
||||
|
||||
if (!gKeyStringBundle ||
|
||||
NS_FAILED(gKeyStringBundle->GetStringFromName(PromiseFlatString(aModifierName).get(),
|
||||
getter_Copies(modifierName))) ||
|
||||
NS_FAILED(gKeyStringBundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(),
|
||||
getter_Copies(separator)))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aStringOut = modifierName + separator + aKeyName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccessible::IsVisible(PRBool* aIsOffscreen)
|
||||
{
|
||||
@ -1788,6 +1753,10 @@ NS_IMETHODIMP
|
||||
nsAccessible::GetDefaultKeyBinding(nsAString& aKeyBinding)
|
||||
{
|
||||
aKeyBinding.Truncate();
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
KeyboardShortcut().ToString(aKeyBinding);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3359,3 +3328,79 @@ nsAccessible::GetLevelInternal()
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// KeyBinding class
|
||||
|
||||
void
|
||||
KeyBinding::ToPlatformFormat(nsAString& aValue) const
|
||||
{
|
||||
nsCOMPtr<nsIStringBundle> keyStringBundle;
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleService =
|
||||
mozilla::services::GetStringBundleService();
|
||||
if (stringBundleService)
|
||||
stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL,
|
||||
getter_AddRefs(keyStringBundle));
|
||||
|
||||
if (!keyStringBundle)
|
||||
return;
|
||||
|
||||
nsAutoString separator;
|
||||
keyStringBundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(),
|
||||
getter_Copies(separator));
|
||||
|
||||
nsAutoString modifierName;
|
||||
if (mModifierMask & kControl) {
|
||||
keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(),
|
||||
getter_Copies(modifierName));
|
||||
|
||||
aValue.Append(modifierName);
|
||||
aValue.Append(separator);
|
||||
}
|
||||
|
||||
if (mModifierMask & kAlt) {
|
||||
keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(),
|
||||
getter_Copies(modifierName));
|
||||
|
||||
aValue.Append(modifierName);
|
||||
aValue.Append(separator);
|
||||
}
|
||||
|
||||
if (mModifierMask & kShift) {
|
||||
keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(),
|
||||
getter_Copies(modifierName));
|
||||
|
||||
aValue.Append(modifierName);
|
||||
aValue.Append(separator);
|
||||
}
|
||||
|
||||
if (mModifierMask & kMeta) {
|
||||
keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(),
|
||||
getter_Copies(modifierName));
|
||||
|
||||
aValue.Append(modifierName);
|
||||
aValue.Append(separator);
|
||||
}
|
||||
|
||||
aValue.Append(mKey);
|
||||
}
|
||||
|
||||
void
|
||||
KeyBinding::ToAtkFormat(nsAString& aValue) const
|
||||
{
|
||||
nsAutoString modifierName;
|
||||
if (mModifierMask & kControl)
|
||||
aValue.Append(NS_LITERAL_STRING("<Control>"));
|
||||
|
||||
if (mModifierMask & kAlt)
|
||||
aValue.Append(NS_LITERAL_STRING("<Alt>"));
|
||||
|
||||
if (mModifierMask & kShift)
|
||||
aValue.Append(NS_LITERAL_STRING("<Shift>"));
|
||||
|
||||
if (mModifierMask & kMeta)
|
||||
aValue.Append(NS_LITERAL_STRING("<Meta>"));
|
||||
|
||||
aValue.Append(mKey);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@
|
||||
class AccEvent;
|
||||
class AccGroupInfo;
|
||||
class EmbeddedObjCollector;
|
||||
class KeyBinding;
|
||||
class nsAccessible;
|
||||
class nsHyperTextAccessible;
|
||||
class nsHTMLLIAccessible;
|
||||
@ -401,6 +402,20 @@ public:
|
||||
inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
|
||||
nsTextAccessible* AsTextLeaf();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ActionAccessible
|
||||
|
||||
/**
|
||||
* Return access key, such as Alt+D.
|
||||
*/
|
||||
virtual KeyBinding AccessKey() const;
|
||||
|
||||
/**
|
||||
* Return global keyboard shortcut for default action, such as Ctrl+O for
|
||||
* Open file menuitem.
|
||||
*/
|
||||
virtual KeyBinding KeyboardShortcut() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// HyperLinkAccessible
|
||||
|
||||
@ -692,4 +707,61 @@ protected:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible,
|
||||
NS_ACCESSIBLE_IMPL_IID)
|
||||
|
||||
|
||||
/**
|
||||
* Represent key binding associated with accessible (such as access key and
|
||||
* global keyboard shortcuts).
|
||||
*/
|
||||
class KeyBinding
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Modifier mask values.
|
||||
*/
|
||||
static const PRUint32 kShift = 1;
|
||||
static const PRUint32 kControl = 2;
|
||||
static const PRUint32 kAlt = 4;
|
||||
static const PRUint32 kMeta = 8;
|
||||
|
||||
KeyBinding() : mKey(0), mModifierMask(0) {}
|
||||
KeyBinding(PRUint32 aKey, PRUint32 aModifierMask) :
|
||||
mKey(aKey), mModifierMask(aModifierMask) {};
|
||||
|
||||
inline bool IsEmpty() const { return !mKey; }
|
||||
inline PRUint32 Key() const { return mKey; }
|
||||
inline PRUint32 ModifierMask() const { return mModifierMask; }
|
||||
|
||||
enum Format {
|
||||
ePlatformFormat,
|
||||
eAtkFormat
|
||||
};
|
||||
|
||||
/**
|
||||
* Return formatted string for this key binding depending on the given format.
|
||||
*/
|
||||
inline void ToString(nsAString& aValue,
|
||||
Format aFormat = ePlatformFormat) const
|
||||
{
|
||||
aValue.Truncate();
|
||||
AppendToString(aValue, aFormat);
|
||||
}
|
||||
inline void AppendToString(nsAString& aValue,
|
||||
Format aFormat = ePlatformFormat) const
|
||||
{
|
||||
if (mKey) {
|
||||
if (aFormat == ePlatformFormat)
|
||||
ToPlatformFormat(aValue);
|
||||
else
|
||||
ToAtkFormat(aValue);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void ToPlatformFormat(nsAString& aValue) const;
|
||||
void ToAtkFormat(nsAString& aValue) const;
|
||||
|
||||
PRUint32 mKey;
|
||||
PRUint32 mModifierMask;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -133,13 +133,6 @@ nsApplicationAccessible::Description(nsString &aDescription)
|
||||
aDescription.Truncate();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetKeyboardShortcut(nsAString &aKeyboardShortcut)
|
||||
{
|
||||
aKeyboardShortcut.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsApplicationAccessible::State()
|
||||
{
|
||||
@ -384,6 +377,12 @@ nsApplicationAccessible::InvalidateChildren()
|
||||
// and RemoveChild() method calls.
|
||||
}
|
||||
|
||||
KeyBinding
|
||||
nsApplicationAccessible::AccessKey() const
|
||||
{
|
||||
return KeyBinding();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible protected methods
|
||||
|
||||
|
@ -91,7 +91,6 @@ public:
|
||||
NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
|
||||
NS_IMETHOD GetName(nsAString &aName);
|
||||
NS_IMETHOD GetValue(nsAString &aValue);
|
||||
NS_IMETHOD GetKeyboardShortcut(nsAString &aKeyboardShortcut);
|
||||
NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
|
||||
NS_IMETHOD GroupPosition(PRInt32 *aGroupLevel, PRInt32 *aSimilarItemsInGroup,
|
||||
PRInt32 *aPositionInGroup);
|
||||
@ -130,6 +129,9 @@ public:
|
||||
|
||||
virtual void InvalidateChildren();
|
||||
|
||||
// ActionAccessible
|
||||
virtual KeyBinding AccessKey() const;
|
||||
|
||||
protected:
|
||||
|
||||
// nsAccessible
|
||||
|
@ -175,13 +175,11 @@ nsLinkableAccessible::DoAction(PRUint8 aIndex)
|
||||
nsAccessibleWrap::DoAction(aIndex);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
|
||||
KeyBinding
|
||||
nsLinkableAccessible::AccessKey() const
|
||||
{
|
||||
aKeyboardShortcut.Truncate();
|
||||
|
||||
return mActionAcc ? mActionAcc->GetKeyboardShortcut(aKeyboardShortcut) :
|
||||
nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
|
||||
return mActionAcc ?
|
||||
mActionAcc->AccessKey() : nsAccessible::AccessKey();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -92,7 +92,6 @@ public:
|
||||
NS_IMETHOD DoAction(PRUint8 index);
|
||||
NS_IMETHOD GetValue(nsAString& _retval);
|
||||
NS_IMETHOD TakeFocus();
|
||||
NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
@ -100,6 +99,9 @@ public:
|
||||
// nsAccessible
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// ActionAccessible
|
||||
virtual KeyBinding AccessKey() const;
|
||||
|
||||
// HyperLinkAccessible
|
||||
virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
|
||||
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "nsContentCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
|
@ -1494,6 +1494,17 @@ nsDocAccessible::NotifyOfInitialUpdate()
|
||||
|
||||
// Build initial tree.
|
||||
CacheChildrenInSubtree(this);
|
||||
|
||||
// Fire reorder event after the document tree is constructed. Note, since
|
||||
// this reorder event is processed by parent document then events targeted to
|
||||
// this document may be fired prior to this reorder event. If this is
|
||||
// a problem then consider to keep event processing per tab document.
|
||||
if (!IsRoot()) {
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, GetParent(),
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
ParentDocument()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nsCoreUtils.h"
|
||||
|
||||
#include "nsEventStates.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLinkAccessible
|
||||
|
@ -42,11 +42,7 @@
|
||||
|
||||
#include "AccessibleAction_i.c"
|
||||
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsAccessNodeWrap.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIDOMDOMStringList.h"
|
||||
#include "nsAccessible.h"
|
||||
|
||||
// IUnknown
|
||||
|
||||
@ -137,54 +133,44 @@ CAccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
|
||||
long *aNumBinding)
|
||||
{
|
||||
__try {
|
||||
if (!aKeyBinding)
|
||||
return E_INVALIDARG;
|
||||
*aKeyBinding = NULL;
|
||||
|
||||
if (!aNumBinding)
|
||||
return E_INVALIDARG;
|
||||
*aNumBinding = 0;
|
||||
|
||||
nsCOMPtr<nsIAccessible> acc(do_QueryObject(this));
|
||||
if (!acc)
|
||||
if (aActionIndex != 0 || aNumMaxBinding < 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
||||
if (!acc || acc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIDOMDOMStringList> keys;
|
||||
PRUint8 index = static_cast<PRUint8>(aActionIndex);
|
||||
nsresult rv = acc->GetKeyBindings(index, getter_AddRefs(keys));
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
PRUint32 length = 0;
|
||||
keys->GetLength(&length);
|
||||
if (length == 0)
|
||||
// Expose keyboard shortcut if it's not exposed via MSAA keyboard shortcut.
|
||||
KeyBinding keyBinding = acc->AccessKey();
|
||||
if (keyBinding.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
PRUint32 maxBinding = static_cast<PRUint32>(aNumMaxBinding);
|
||||
PRUint32 numBinding = length > maxBinding ? maxBinding : length;
|
||||
*aNumBinding = numBinding;
|
||||
keyBinding = acc->KeyboardShortcut();
|
||||
if (keyBinding.IsEmpty())
|
||||
return S_FALSE;
|
||||
|
||||
*aKeyBinding = static_cast<BSTR*>(nsMemory::Alloc((numBinding) * sizeof(BSTR*)));
|
||||
nsAutoString keyStr;
|
||||
keyBinding.ToString(keyStr);
|
||||
|
||||
*aKeyBinding = static_cast<BSTR*>(::CoTaskMemAlloc(sizeof(BSTR*)));
|
||||
if (!*aKeyBinding)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
PRBool outOfMemory = PR_FALSE;
|
||||
PRUint32 i = 0;
|
||||
for (; i < numBinding; i++) {
|
||||
nsAutoString key;
|
||||
keys->Item(i, key);
|
||||
*(aKeyBinding[i]) = ::SysAllocStringLen(key.get(), key.Length());
|
||||
|
||||
if (!*(aKeyBinding[i])) {
|
||||
outOfMemory = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outOfMemory) {
|
||||
for (PRUint32 j = 0; j < i; j++)
|
||||
::SysFreeString(*(aKeyBinding[j]));
|
||||
|
||||
nsMemory::Free(*aKeyBinding);
|
||||
*aKeyBinding = NULL;
|
||||
|
||||
*(aKeyBinding[0]) = ::SysAllocStringLen(keyStr.get(), keyStr.Length());
|
||||
if (!*(aKeyBinding[0])) {
|
||||
::CoTaskMemFree(*aKeyBinding);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
*aNumBinding = 1;
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
@ -486,16 +486,18 @@ STDMETHODIMP nsAccessibleWrap::get_accKeyboardShortcut(
|
||||
__try {
|
||||
if (!pszKeyboardShortcut)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*pszKeyboardShortcut = NULL;
|
||||
nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
|
||||
if (!xpAccessible || xpAccessible->IsDefunct())
|
||||
|
||||
nsAccessible* acc = GetXPAccessibleFor(varChild);
|
||||
if (!acc || acc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
KeyBinding keyBinding = acc->AccessKey();
|
||||
if (keyBinding.IsEmpty())
|
||||
keyBinding = acc->KeyboardShortcut();
|
||||
|
||||
nsAutoString shortcut;
|
||||
nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
keyBinding.ToString(shortcut);
|
||||
|
||||
*pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
|
||||
shortcut.Length());
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -387,14 +388,10 @@ nsXULMenuitemAccessible::Description(nsString& aDescription)
|
||||
aDescription);
|
||||
}
|
||||
|
||||
//return menu accesskey: N or Alt+F
|
||||
NS_IMETHODIMP
|
||||
nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
|
||||
KeyBinding
|
||||
nsXULMenuitemAccessible::AccessKey() const
|
||||
{
|
||||
aAccessKey.Truncate();
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Return menu accesskey: N or Alt+F.
|
||||
static PRInt32 gMenuAccesskeyModifier = -1; // magic value of -1 indicates unitialized state
|
||||
|
||||
// We do not use nsCoreUtils::GetAccesskeyFor() because accesskeys for
|
||||
@ -403,7 +400,9 @@ nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
|
||||
mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::accesskey,
|
||||
accesskey);
|
||||
if (accesskey.IsEmpty())
|
||||
return NS_OK;
|
||||
return KeyBinding();
|
||||
|
||||
PRUint32 modifierKey = 0;
|
||||
|
||||
nsAccessible* parentAcc = GetParent();
|
||||
if (parentAcc) {
|
||||
@ -415,44 +414,89 @@ nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
|
||||
gMenuAccesskeyModifier = Preferences::GetInt("ui.key.menuAccessKey", 0);
|
||||
}
|
||||
|
||||
nsAutoString propertyKey;
|
||||
switch (gMenuAccesskeyModifier) {
|
||||
case nsIDOMKeyEvent::DOM_VK_CONTROL:
|
||||
propertyKey.AssignLiteral("VK_CONTROL");
|
||||
modifierKey = KeyBinding::kControl;
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_ALT:
|
||||
propertyKey.AssignLiteral("VK_ALT");
|
||||
modifierKey = KeyBinding::kAlt;
|
||||
break;
|
||||
case nsIDOMKeyEvent::DOM_VK_META:
|
||||
propertyKey.AssignLiteral("VK_META");
|
||||
modifierKey = KeyBinding::kMeta;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!propertyKey.IsEmpty())
|
||||
nsAccessible::GetFullKeyName(propertyKey, accesskey, aAccessKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (aAccessKey.IsEmpty())
|
||||
aAccessKey = accesskey;
|
||||
|
||||
return NS_OK;
|
||||
return KeyBinding(accesskey[0], modifierKey);
|
||||
}
|
||||
|
||||
//return menu shortcut: Ctrl+F or Ctrl+Shift+L
|
||||
NS_IMETHODIMP
|
||||
nsXULMenuitemAccessible::GetDefaultKeyBinding(nsAString& aKeyBinding)
|
||||
KeyBinding
|
||||
nsXULMenuitemAccessible::KeyboardShortcut() const
|
||||
{
|
||||
aKeyBinding.Truncate();
|
||||
nsAutoString keyElmId;
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyElmId);
|
||||
if (keyElmId.IsEmpty())
|
||||
return KeyBinding();
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
nsIDocument* document = mContent->GetOwnerDoc();
|
||||
if (!document)
|
||||
return KeyBinding();
|
||||
|
||||
nsAutoString accelText;
|
||||
mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::acceltext,
|
||||
aKeyBinding);
|
||||
nsIContent* keyElm = document->GetElementById(keyElmId);
|
||||
if (!keyElm)
|
||||
return KeyBinding();
|
||||
|
||||
return NS_OK;
|
||||
PRUint32 key = 0;
|
||||
|
||||
nsAutoString keyStr;
|
||||
keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyStr);
|
||||
if (keyStr.IsEmpty()) {
|
||||
nsAutoString keyCodeStr;
|
||||
keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCodeStr);
|
||||
PRUint32 errorCode;
|
||||
key = keyStr.ToInteger(&errorCode, kAutoDetect);
|
||||
} else {
|
||||
key = keyStr[0];
|
||||
}
|
||||
|
||||
nsAutoString modifiersStr;
|
||||
keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr);
|
||||
|
||||
PRUint32 modifierMask = 0;
|
||||
if (modifiersStr.Find("shift") != -1)
|
||||
modifierMask != KeyBinding::kShift;
|
||||
if (modifiersStr.Find("alt") != -1)
|
||||
modifierMask |= KeyBinding::kAlt;
|
||||
if (modifiersStr.Find("meta") != -1)
|
||||
modifierMask |= KeyBinding::kMeta;
|
||||
if (modifiersStr.Find("control") != -1)
|
||||
modifierMask |= KeyBinding::kControl;
|
||||
if (modifiersStr.Find("accel") != -1) {
|
||||
// Get the accelerator key value from prefs, overriding the default.
|
||||
switch (Preferences::GetInt("ui.key.accelKey", 0)) {
|
||||
case nsIDOMKeyEvent::DOM_VK_META:
|
||||
modifierMask |= KeyBinding::kMeta;
|
||||
break;
|
||||
|
||||
case nsIDOMKeyEvent::DOM_VK_ALT:
|
||||
modifierMask |= KeyBinding::kAlt;
|
||||
break;
|
||||
|
||||
case nsIDOMKeyEvent::DOM_VK_CONTROL:
|
||||
modifierMask |= KeyBinding::kControl;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef XP_MACOSX
|
||||
modifierMask |= KeyBinding::kMeta;
|
||||
#else
|
||||
modifierMask |= KeyBinding::kControl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return KeyBinding(key, modifierMask);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
|
@ -82,8 +82,6 @@ public:
|
||||
nsXULMenuitemAccessible(nsIContent *aContent, nsIWeakReference *aShell);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
|
||||
NS_IMETHOD GetDefaultKeyBinding(nsAString& aKeyBinding);
|
||||
NS_IMETHOD DoAction(PRUint8 index);
|
||||
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
|
||||
NS_IMETHOD GetNumActions(PRUint8 *_retval);
|
||||
@ -98,6 +96,10 @@ public:
|
||||
PRInt32 *aSetSize);
|
||||
|
||||
virtual PRBool GetAllowsAnonChildAccessibles();
|
||||
|
||||
// ActionAccessible
|
||||
virtual KeyBinding AccessKey() const;
|
||||
virtual KeyBinding KeyboardShortcut() const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -97,7 +97,6 @@ _TEST_FILES =\
|
||||
test_elm_listbox.xul \
|
||||
test_elm_nsApplicationAcc.html \
|
||||
test_elm_plugin.html \
|
||||
test_keys.html \
|
||||
test_nsIAccessible_selects.html \
|
||||
test_nsIAccessibleDocument.html \
|
||||
test_nsIAccessibleImage.html \
|
||||
|
@ -51,6 +51,8 @@ _TEST_FILES =\
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_inputs.html \
|
||||
test_keys_menu.xul \
|
||||
test_keys.html \
|
||||
test_link.html \
|
||||
test_media.html \
|
||||
test_tree.xul \
|
||||
|
@ -12,7 +12,7 @@
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="common.js"></script>
|
||||
src="../common.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function testKeyboardShortcut(aAccOrElmOrID, aKey)
|
||||
@ -29,6 +29,7 @@
|
||||
{
|
||||
testKeyboardShortcut("input1", "");
|
||||
testKeyboardShortcut("input2", MAC ? "⌃b" : "Alt+Shift+b");
|
||||
testKeyboardShortcut("link", MAC ? "⌃l" : "Alt+Shift+l");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
@ -56,5 +57,6 @@
|
||||
</label>
|
||||
<label accesskey="b" for="input2">
|
||||
<input id="input2"/>
|
||||
<a id="link" accesskey="l">link</a>
|
||||
</body>
|
||||
</html>
|
101
accessible/tests/mochitest/actions/test_keys_menu.xul
Normal file
101
accessible/tests/mochitest/actions/test_keys_menu.xul
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Accessible XUL access keys and shortcut keys tests">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js" />
|
||||
<script type="application/javascript"
|
||||
src="../events.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function openMenu(aMenuID, aMenuitemID)
|
||||
{
|
||||
this.menuNode = getNode(aMenuID),
|
||||
this.menuitemNode = getNode(aMenuitemID),
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, this.menuNode)
|
||||
];
|
||||
|
||||
this.invoke = function openMenu_invoke()
|
||||
{
|
||||
// Show menu.
|
||||
this.menuNode.open = true;
|
||||
}
|
||||
|
||||
this.finalCheck = function openMenu_finalCheck()
|
||||
{
|
||||
var menu = getAccessible(aMenuID);
|
||||
is(menu.keyboardShortcut, (MAC ? "u" : "Alt+u"),
|
||||
"Wrong accesskey on " + prettyName(this.menuitemNode));
|
||||
|
||||
var menuitem = getAccessible(aMenuitemID);
|
||||
is(menuitem.keyboardShortcut, "p",
|
||||
"Wrong accesskey on " + prettyName(this.menuitemNode));
|
||||
is(menuitem.defaultKeyBinding, (MAC ? "⌃l" : "Ctrl+l"),
|
||||
"Wrong keyboard shortcut on " + prettyName(this.menuitemNode));
|
||||
}
|
||||
|
||||
this.getID = function openMenu_getID()
|
||||
{
|
||||
return "menuitem accesskey and shortcut test " +
|
||||
prettyName(this.menuItemNode);
|
||||
}
|
||||
}
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new openMenu("menu", "menuitem"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=672092"
|
||||
title="Reorganize access key and keyboard shortcut handling code">
|
||||
Mozilla Bug 672092
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
<keyset>
|
||||
<key key="l" modifiers="control" id="key1"/>
|
||||
</keyset>
|
||||
|
||||
<menubar>
|
||||
<menu label="menu" id="menu" accesskey="u">
|
||||
<menupopup>
|
||||
<menuitem accesskey="p" key="key1" label="item1" id="menuitem"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
||||
<vbox id="debug"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
||||
|
@ -159,11 +159,23 @@ const DO_NOT_FINISH_TEST = 1;
|
||||
* // Checker object interface:
|
||||
* //
|
||||
* // var checker = {
|
||||
* // type getter: function() {}, // DOM or a11y event type
|
||||
* // target getter: function() {}, // DOM node or accessible
|
||||
* // phase getter: function() {}, // DOM event phase (false - bubbling)
|
||||
* // * DOM or a11y event type. *
|
||||
* // type getter: function() {},
|
||||
* //
|
||||
* // * DOM node or accessible. *
|
||||
* // target getter: function() {},
|
||||
* //
|
||||
* // * DOM event phase (false - bubbling). *
|
||||
* // phase getter: function() {},
|
||||
* //
|
||||
* // * Callback, called when event is handled
|
||||
* // check: function(aEvent) {},
|
||||
* // getID: function() {}
|
||||
* //
|
||||
* // * Checker ID *
|
||||
* // getID: function() {},
|
||||
* //
|
||||
* // * Event that don't have predefined order relative other events. *
|
||||
* // async getter: function() {}
|
||||
* // };
|
||||
* eventSeq getter() {},
|
||||
*
|
||||
@ -327,10 +339,11 @@ function eventQueue(aEventType)
|
||||
if ("debugCheck" in invoker)
|
||||
invoker.debugCheck(aEvent);
|
||||
|
||||
// Search through handled expected events if one of them was handled again.
|
||||
// Search through handled expected events to report error if one of them is
|
||||
// handled for a second time.
|
||||
var idx = 0;
|
||||
for (; idx < this.mEventSeq.length; idx++) {
|
||||
if (!this.isEventUnexpected(idx) && (invoker.wasCaught[idx] == true) &&
|
||||
if (this.isEventExpected(idx) && (invoker.wasCaught[idx] == true) &&
|
||||
this.isAlreadyCaught(idx, aEvent)) {
|
||||
|
||||
var msg = "Doubled event { event type: " +
|
||||
@ -341,52 +354,85 @@ function eventQueue(aEventType)
|
||||
}
|
||||
}
|
||||
|
||||
// Search through unexpected events to ensure no one of them was handled.
|
||||
// Search through unexpected events, any matches result in error report
|
||||
// after this invoker processing.
|
||||
for (idx = 0; idx < this.mEventSeq.length; idx++) {
|
||||
if (this.isEventUnexpected(idx) && this.compareEvents(idx, aEvent))
|
||||
invoker.wasCaught[idx] = true;
|
||||
}
|
||||
|
||||
// We've handled all expected events, next invoker processing is pending.
|
||||
if (this.mEventSeqIdx == this.mEventSeq.length)
|
||||
// Nothing left, proceed next invoker in timeout. Otherwise check if
|
||||
// handled event is matched.
|
||||
var idxObj = {};
|
||||
if (!this.prepareForExpectedEvent(invoker, idxObj))
|
||||
return;
|
||||
|
||||
// Compute next expected event index.
|
||||
for (idx = this.mEventSeqIdx + 1;
|
||||
idx < this.mEventSeq.length && this.mEventSeq[idx].unexpected;
|
||||
idx++);
|
||||
|
||||
// No expected events were registered, proceed to next invoker to ensure
|
||||
// unexpected events for current invoker won't be handled.
|
||||
if (idx == this.mEventSeq.length) {
|
||||
this.mEventSeqIdx = idx;
|
||||
this.processNextInvokerInTimeout();
|
||||
return;
|
||||
// Check if handled event matches expected sync event.
|
||||
var matched = false;
|
||||
idx = idxObj.value;
|
||||
if (idx < this.mEventSeq.length) {
|
||||
matched = this.compareEvents(idx, aEvent);
|
||||
if (matched)
|
||||
this.mEventSeqIdx = idx;
|
||||
}
|
||||
|
||||
// Check if handled event matches expected event.
|
||||
var matched = this.compareEvents(idx, aEvent);
|
||||
// Check if handled event matches any expected async events.
|
||||
if (!matched) {
|
||||
for (idx = 0; idx < this.mEventSeq.length; idx++) {
|
||||
if (this.mEventSeq[idx].async) {
|
||||
matched = this.compareEvents(idx, aEvent);
|
||||
if (matched)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.dumpEventToDOM(aEvent, idx, matched);
|
||||
|
||||
if (matched) {
|
||||
this.checkEvent(idx, aEvent);
|
||||
invoker.wasCaught[idx] = true;
|
||||
this.mEventSeqIdx = idx;
|
||||
|
||||
// Get next expected event index.
|
||||
while (++idx < this.mEventSeq.length && this.mEventSeq[idx].unexpected);
|
||||
|
||||
// If the last expected event was processed, proceed next invoker in
|
||||
// timeout to ensure unexpected events for current invoker won't be
|
||||
// handled.
|
||||
if (idx == this.mEventSeq.length) {
|
||||
this.mEventSeqIdx = idx;
|
||||
this.processNextInvokerInTimeout();
|
||||
}
|
||||
this.prepareForExpectedEvent(invoker);
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
this.prepareForExpectedEvent =
|
||||
function eventQueue_prepareForExpectedEvent(aInvoker, aIdxObj)
|
||||
{
|
||||
// Nothing left, wait for next invoker.
|
||||
if (this.mEventSeqFinished)
|
||||
return false;
|
||||
|
||||
// Compute next expected sync event index.
|
||||
for (var idx = this.mEventSeqIdx + 1;
|
||||
idx < this.mEventSeq.length &&
|
||||
(this.mEventSeq[idx].unexpected || this.mEventSeq[idx].async);
|
||||
idx++);
|
||||
|
||||
// If no expected events were left, proceed to next invoker in timeout
|
||||
// to make sure unexpected events for current invoker aren't be handled.
|
||||
if (idx == this.mEventSeq.length) {
|
||||
var allHandled = true;
|
||||
for (var jdx = 0; jdx < this.mEventSeq.length; jdx++) {
|
||||
if (this.isEventExpected(jdx) && !aInvoker.wasCaught[jdx])
|
||||
allHandled = false;
|
||||
}
|
||||
|
||||
if (allHandled) {
|
||||
this.mEventSeqIdx = this.mEventSeq.length;
|
||||
this.mEventFinished = true;
|
||||
this.processNextInvokerInTimeout();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aIdxObj)
|
||||
aIdxObj.value = idx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
this.getInvoker = function eventQueue_getInvoker()
|
||||
{
|
||||
return this.mInvokers[this.mIndex];
|
||||
@ -405,18 +451,24 @@ function eventQueue(aEventType)
|
||||
aInvoker.eventSeq :
|
||||
[ new invokerChecker(this.mDefEventType, aInvoker.DOMNode) ];
|
||||
|
||||
for (var idx = 0; idx < this.mEventSeq.length; idx++)
|
||||
for (var idx = 0; idx < this.mEventSeq.length; idx++) {
|
||||
this.mEventSeq[idx].unexpected = false;
|
||||
if (!("async" in this.mEventSeq[idx]))
|
||||
this.mEventSeq[idx].async = false;
|
||||
}
|
||||
|
||||
var unexpectedSeq = aInvoker.unexpectedEventSeq;
|
||||
if (unexpectedSeq) {
|
||||
for (var idx = 0; idx < unexpectedSeq.length; idx++)
|
||||
for (var idx = 0; idx < unexpectedSeq.length; idx++) {
|
||||
unexpectedSeq[idx].unexpected = true;
|
||||
unexpectedSeq[idx].async = false;
|
||||
}
|
||||
|
||||
this.mEventSeq = this.mEventSeq.concat(unexpectedSeq);
|
||||
}
|
||||
|
||||
this.mEventSeqIdx = -1;
|
||||
this.mEventSeqFinished = false;
|
||||
|
||||
// Register event listeners
|
||||
if (this.mEventSeq) {
|
||||
@ -517,6 +569,10 @@ function eventQueue(aEventType)
|
||||
{
|
||||
return this.mEventSeq[aIdx].unexpected;
|
||||
}
|
||||
this.isEventExpected = function eventQueue_isEventExpected(aIdx)
|
||||
{
|
||||
return !this.mEventSeq[aIdx].unexpected;
|
||||
}
|
||||
|
||||
this.compareEvents = function eventQueue_compareEvents(aIdx, aEvent)
|
||||
{
|
||||
@ -598,20 +654,17 @@ function eventQueue(aEventType)
|
||||
gLogger.logToDOM(info);
|
||||
}
|
||||
|
||||
var currType = this.getEventTypeAsString(aExpectedEventIdx);
|
||||
var currTarget = this.getEventTarget(aExpectedEventIdx);
|
||||
if (!aMatch)
|
||||
return;
|
||||
|
||||
var msg = "EQ: ";
|
||||
var emphText = "";
|
||||
if (aMatch) {
|
||||
emphText = "matched ";
|
||||
var emphText = "matched ";
|
||||
|
||||
var consoleMsg = "*****\nEQ matched: " + currType + "\n*****";
|
||||
gLogger.logToConsole(consoleMsg);
|
||||
var currType = this.getEventTypeAsString(aExpectedEventIdx);
|
||||
var currTarget = this.getEventTarget(aExpectedEventIdx);
|
||||
var consoleMsg = "*****\nEQ matched: " + currType + "\n*****";
|
||||
gLogger.logToConsole(consoleMsg);
|
||||
|
||||
} else {
|
||||
msg += "expected";
|
||||
}
|
||||
msg += " event, type: " + currType + ", target: " + prettyName(currTarget);
|
||||
|
||||
gLogger.logToDOM(msg, true, emphText);
|
||||
@ -624,6 +677,7 @@ function eventQueue(aEventType)
|
||||
|
||||
this.mEventSeq = null;
|
||||
this.mEventSeqIdx = -1;
|
||||
this.mEventSeqFinished = false;
|
||||
}
|
||||
|
||||
|
||||
@ -896,9 +950,10 @@ function synthSelectAll(aNodeOrID, aCheckerOrEventSeq, aEventType)
|
||||
/**
|
||||
* Common invoker checker (see eventSeq of eventQueue).
|
||||
*/
|
||||
function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
|
||||
function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg, aIsAsync)
|
||||
{
|
||||
this.type = aEventType;
|
||||
this.async = aIsAsync;
|
||||
|
||||
this.__defineGetter__("target", invokerChecker_targetGetter);
|
||||
this.__defineSetter__("target", invokerChecker_targetSetter);
|
||||
@ -932,6 +987,15 @@ function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
|
||||
this.mTargetFuncArg = aTargetFuncArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common invoker checker for async events.
|
||||
*/
|
||||
function asyncInvokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
|
||||
{
|
||||
this.__proto__ = new invokerChecker(aEventType, aTargetOrFunc,
|
||||
aTargetFuncArg, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Text inserted/removed events checker.
|
||||
*/
|
||||
|
@ -36,6 +36,7 @@
|
||||
}
|
||||
|
||||
var invokerChecker = gOpenerWnd.invokerChecker;
|
||||
var asyncInvokerChecker = gOpenerWnd.asyncInvokerChecker;
|
||||
|
||||
const STATE_BUSY = gOpenerWnd.STATE_BUSY;
|
||||
const EVENT_DOCUMENT_LOAD_COMPLETE =
|
||||
@ -48,6 +49,8 @@
|
||||
const nsIAccessibleStateChangeEvent =
|
||||
gOpenerWnd.nsIAccessibleStateChangeEvent;
|
||||
|
||||
//gOpenerWnd.gA11yEventDumpToConsole = true; // debug
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Hacks to make xul:tabbrowser work.
|
||||
|
||||
@ -132,7 +135,7 @@
|
||||
this.eventSeq = [
|
||||
// We don't expect state change event for busy true since things happen
|
||||
// quickly and it's coalesced.
|
||||
new invokerChecker(EVENT_REORDER, getContainer),
|
||||
new asyncInvokerChecker(EVENT_REORDER, getContainer),
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
|
||||
new stateBusyChecker(false)
|
||||
];
|
||||
@ -155,7 +158,7 @@
|
||||
|
||||
this.eventSeq = [
|
||||
new documentReloadChecker(true),
|
||||
new invokerChecker(EVENT_REORDER, getContainer),
|
||||
new asyncInvokerChecker(EVENT_REORDER, getContainer),
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
|
||||
new stateBusyChecker(false)
|
||||
];
|
||||
@ -178,7 +181,7 @@
|
||||
|
||||
this.eventSeq = [
|
||||
new documentReloadChecker(false),
|
||||
new invokerChecker(EVENT_REORDER, getContainer),
|
||||
new asyncInvokerChecker(EVENT_REORDER, getContainer),
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
|
||||
new stateBusyChecker(false)
|
||||
];
|
||||
@ -202,7 +205,7 @@
|
||||
this.eventSeq = [
|
||||
// We don't expect state change for busy true, load stopped events since
|
||||
// things happen quickly and it's coalesced.
|
||||
new invokerChecker(EVENT_REORDER, getContainer),
|
||||
new asyncInvokerChecker(EVENT_REORDER, getContainer),
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
|
||||
new stateBusyChecker(false)
|
||||
];
|
||||
|
@ -357,6 +357,36 @@
|
||||
}
|
||||
}
|
||||
|
||||
function changeSrc(aID)
|
||||
{
|
||||
this.containerNode = getNode(aID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, this.containerNode)
|
||||
];
|
||||
|
||||
this.invoke = function changeSrc_invoke()
|
||||
{
|
||||
this.containerNode.src = "data:text/html,<html><input></html>";
|
||||
}
|
||||
|
||||
this.finalCheck = function changeSrc_finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ INTERNAL_FRAME: [
|
||||
{ DOCUMENT: [
|
||||
{ ENTRY: [ ] }
|
||||
] };
|
||||
] };
|
||||
testAccessibleTree(this.containerNode, tree);
|
||||
}
|
||||
|
||||
this.getID() = function changeSrc_getID()
|
||||
{
|
||||
return "change src on iframe";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
@ -378,6 +408,7 @@
|
||||
gQueue.push(new removeBodyFromIFrameDoc("iframe"));
|
||||
gQueue.push(new insertElmUnderDocElmWhileBodyMissed("iframe"));
|
||||
gQueue.push(new insertBodyToIFrameDoc("iframe"));
|
||||
gQueue.push(new changeSrc("iframe"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
@ -394,6 +425,9 @@
|
||||
<a target="_blank"
|
||||
title="Elements inserted outside the body aren't accessible"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=608887">Mozilla Bug 608887</a>
|
||||
<a target="_blank"
|
||||
title="Reorder event for document must be fired after document initial tree creation"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=669263">Mozilla Bug 669263</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
@ -6797,9 +6797,9 @@ var gPluginHandler = {
|
||||
submitReport : function(pluginDumpID, browserDumpID) {
|
||||
// The crash reporter wants a DOM element it can append an IFRAME to,
|
||||
// which it uses to submit a form. Let's just give it gBrowser.
|
||||
this.CrashSubmit.submit(pluginDumpID, gBrowser, null, null);
|
||||
this.CrashSubmit.submit(pluginDumpID);
|
||||
if (browserDumpID)
|
||||
this.CrashSubmit.submit(browserDumpID, gBrowser, null, null);
|
||||
this.CrashSubmit.submit(browserDumpID);
|
||||
},
|
||||
|
||||
// Callback for user clicking a "reload page" link
|
||||
|
@ -42,11 +42,11 @@ const Cu = Components.utils;
|
||||
|
||||
// Bug 671101 - directly using webNavigation in this context
|
||||
// causes docshells to leak
|
||||
__defineGetter__("webNavigation", function() {
|
||||
__defineGetter__("webNavigation", function () {
|
||||
return docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
});
|
||||
|
||||
addMessageListener("WebNavigation:LoadURI", function(message) {
|
||||
addMessageListener("WebNavigation:LoadURI", function (message) {
|
||||
let flags = message.json.flags || webNavigation.LOAD_FLAGS_NONE;
|
||||
|
||||
webNavigation.loadURI(message.json.uri, flags, null, null, null);
|
||||
|
@ -45,6 +45,7 @@
|
||||
# Justin Dolske <dolske@mozilla.com>
|
||||
# Kathleen Brade <brade@pearlcrescent.com>
|
||||
# Mark Smith <mcs@pearlcrescent.com>
|
||||
# Kailas Patil <patilkr24@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -879,17 +880,12 @@ nsContextMenu.prototype = {
|
||||
saveDocument(this.target.ownerDocument);
|
||||
},
|
||||
|
||||
// Save URL of clicked-on link.
|
||||
saveLink: function() {
|
||||
// Helper function to wait for appropriate MIME-type headers and
|
||||
// then prompt the user with a file picker
|
||||
saveHelper: function(linkURL, linkText, dialogTitle, bypassCache, doc) {
|
||||
// canonical def in nsURILoader.h
|
||||
const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
|
||||
|
||||
var doc = this.target.ownerDocument;
|
||||
urlSecurityCheck(this.linkURL, doc.nodePrincipal);
|
||||
var linkText = this.linkText();
|
||||
var linkURL = this.linkURL;
|
||||
|
||||
|
||||
// an object to proxy the data through to
|
||||
// nsIExternalHelperAppService.doContent, which will wait for the
|
||||
// appropriate MIME-type headers and then prompt the user with a
|
||||
@ -941,7 +937,7 @@ nsContextMenu.prototype = {
|
||||
if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
|
||||
// do it the old fashioned way, which will pick the best filename
|
||||
// it can without waiting.
|
||||
saveURL(linkURL, linkText, null, true, false, doc.documentURIObject);
|
||||
saveURL(linkURL, linkText, dialogTitle, bypassCache, false, doc.documentURIObject);
|
||||
}
|
||||
if (this.extListener)
|
||||
this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
|
||||
@ -985,10 +981,19 @@ nsContextMenu.prototype = {
|
||||
// set up a channel to do the saving
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var channel = ioService.newChannelFromURI(this.getLinkURI());
|
||||
var channel = ioService.newChannelFromURI(makeURI(linkURL));
|
||||
channel.notificationCallbacks = new callbacks();
|
||||
channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE |
|
||||
Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
|
||||
|
||||
let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
|
||||
|
||||
if (bypassCache)
|
||||
flags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
|
||||
|
||||
if (channel instanceof Ci.nsICachingChannel)
|
||||
flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;
|
||||
|
||||
channel.loadFlags |= flags;
|
||||
|
||||
if (channel instanceof Ci.nsIHttpChannel) {
|
||||
channel.referrer = doc.documentURIObject;
|
||||
if (channel instanceof Ci.nsIHttpChannelInternal)
|
||||
@ -1006,6 +1011,14 @@ nsContextMenu.prototype = {
|
||||
channel.asyncOpen(new saveAsListener(), null);
|
||||
},
|
||||
|
||||
// Save URL of clicked-on link.
|
||||
saveLink: function() {
|
||||
var doc = this.target.ownerDocument;
|
||||
urlSecurityCheck(this.linkURL, doc.nodePrincipal);
|
||||
|
||||
this.saveHelper(this.linkURL, this.linkText(), null, true, doc);
|
||||
},
|
||||
|
||||
sendLink: function() {
|
||||
// we don't know the title of the link so pass in an empty string
|
||||
MailIntegration.sendMessage( this.linkURL, "" );
|
||||
@ -1033,8 +1046,7 @@ nsContextMenu.prototype = {
|
||||
else if (this.onVideo || this.onAudio) {
|
||||
urlSecurityCheck(this.mediaURL, doc.nodePrincipal);
|
||||
var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
|
||||
saveURL(this.mediaURL, null, dialogTitle, false,
|
||||
false, doc.documentURIObject);
|
||||
this.saveHelper(this.mediaURL, null, dialogTitle, false, doc);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1372,15 +1372,19 @@
|
||||
// aReferrerURI is null or undefined if the tab is opened from
|
||||
// an external application or bookmark, i.e. somewhere other
|
||||
// than the current tab.
|
||||
if ((aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) &&
|
||||
Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) {
|
||||
if (aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) {
|
||||
let newTabPos = (this._lastRelatedTab ||
|
||||
this.selectedTab)._tPos + 1;
|
||||
|
||||
if (this._lastRelatedTab)
|
||||
this._lastRelatedTab.owner = null;
|
||||
else
|
||||
t.owner = this.selectedTab;
|
||||
this.moveTabTo(t, newTabPos);
|
||||
|
||||
if (!this.selectedTab.pinned &&
|
||||
Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent"))
|
||||
this.moveTabTo(t, newTabPos);
|
||||
|
||||
this._lastRelatedTab = t;
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,8 @@ function GroupItem(listOfEls, options) {
|
||||
this.keepProportional = false;
|
||||
this._frozenItemSizeData = {};
|
||||
|
||||
this._onChildClose = this._onChildClose.bind(this);
|
||||
|
||||
// Variable: _activeTab
|
||||
// The <TabItem> for the groupItem's active tab.
|
||||
this._activeTab = null;
|
||||
@ -122,15 +124,6 @@ function GroupItem(listOfEls, options) {
|
||||
.css({zIndex: -100})
|
||||
.appendTo("body");
|
||||
|
||||
// ___ New Tab Button
|
||||
this.$ntb = iQ("<div>")
|
||||
.addClass('newTabButton')
|
||||
.click(function() {
|
||||
self.newTab();
|
||||
})
|
||||
.attr('title', tabviewString('groupItem.newTabButton'))
|
||||
.appendTo($container);
|
||||
|
||||
// ___ Resizer
|
||||
this.$resizer = iQ("<div>")
|
||||
.addClass('resizer')
|
||||
@ -818,7 +811,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let shouldRemoveTabItems = [];
|
||||
let toClose = this._children.concat();
|
||||
toClose.forEach(function(child) {
|
||||
child.removeSubscriber(self, "close");
|
||||
child.removeSubscriber("close", self._onChildClose);
|
||||
|
||||
let removed = child.close(true);
|
||||
if (removed) {
|
||||
@ -826,7 +819,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
} else {
|
||||
// child.removeSubscriber() must be called before child.close(),
|
||||
// therefore we call child.addSubscriber() if the tab is not removed.
|
||||
child.addSubscriber(self, "close", self._onChildClose.bind(self));
|
||||
child.addSubscriber("close", self._onChildClose);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1009,7 +1002,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
item.droppable(false);
|
||||
item.groupItemData = {};
|
||||
|
||||
item.addSubscriber(this, "close", this._onChildClose.bind(this));
|
||||
item.addSubscriber("close", this._onChildClose);
|
||||
item.setParent(this);
|
||||
|
||||
if (typeof item.setResizable == 'function')
|
||||
@ -1110,7 +1103,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
item.setBounds(item.getBounds(), true, {force: true});
|
||||
|
||||
item.droppable(true);
|
||||
item.removeSubscriber(this, "close");
|
||||
item.removeSubscriber("close", this._onChildClose);
|
||||
|
||||
if (typeof item.setResizable == 'function')
|
||||
item.setResizable(true, options.immediately);
|
||||
@ -1658,9 +1651,45 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Helper routine for the constructor; adds various event handlers to the container.
|
||||
_addHandlers: function GroupItem__addHandlers(container) {
|
||||
let self = this;
|
||||
let lastMouseDownTarget;
|
||||
|
||||
var dropIndex = false;
|
||||
var dropSpaceTimer = null;
|
||||
container.mousedown(function(e) {
|
||||
let target = e.target;
|
||||
// only set the last mouse down target if it is a left click, not on the
|
||||
// close button, not on the new tab button, not on the title bar and its
|
||||
// element
|
||||
if (Utils.isLeftClick(e) &&
|
||||
self.$closeButton[0] != target &&
|
||||
self.$titlebar[0] != target &&
|
||||
!self.$titlebar.contains(target) &&
|
||||
!self.$appTabTray.contains(target)) {
|
||||
lastMouseDownTarget = target;
|
||||
} else {
|
||||
lastMouseDownTarget = null;
|
||||
}
|
||||
});
|
||||
container.mouseup(function(e) {
|
||||
let same = (e.target == lastMouseDownTarget);
|
||||
lastMouseDownTarget = null;
|
||||
|
||||
if (same && !self.isDragging) {
|
||||
if (gBrowser.selectedTab.pinned &&
|
||||
UI.getActiveTab() != self.getActiveTab() &&
|
||||
self.getChildren().length > 0) {
|
||||
UI.setActive(self, { dontSetActiveTabInGroup: true });
|
||||
UI.goToTab(gBrowser.selectedTab);
|
||||
} else {
|
||||
let tabItem = self.getTopChild();
|
||||
if (tabItem)
|
||||
tabItem.zoomIn();
|
||||
else
|
||||
self.newTab();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let dropIndex = false;
|
||||
let dropSpaceTimer = null;
|
||||
|
||||
// When the _dropSpaceActive flag is turned on on a group, and a tab is
|
||||
// dragged on top, a space will open up.
|
||||
|
@ -405,10 +405,8 @@ Subscribable.prototype = {
|
||||
// ----------
|
||||
// Function: addSubscriber
|
||||
// The given callback will be called when the Subscribable fires the given event.
|
||||
// The refObject is used to facilitate removal if necessary.
|
||||
addSubscriber: function Subscribable_addSubscriber(refObject, eventName, callback) {
|
||||
addSubscriber: function Subscribable_addSubscriber(eventName, callback) {
|
||||
try {
|
||||
Utils.assertThrow(refObject, "refObject");
|
||||
Utils.assertThrow(typeof callback == "function", "callback must be a function");
|
||||
Utils.assertThrow(eventName && typeof eventName == "string",
|
||||
"eventName must be a non-empty string");
|
||||
@ -423,28 +421,17 @@ Subscribable.prototype = {
|
||||
if (!this.subscribers[eventName])
|
||||
this.subscribers[eventName] = [];
|
||||
|
||||
var subs = this.subscribers[eventName];
|
||||
var existing = subs.filter(function(element) {
|
||||
return element.refObject == refObject;
|
||||
});
|
||||
|
||||
if (existing.length) {
|
||||
Utils.assert(existing.length == 1, 'should only ever be one');
|
||||
existing[0].callback = callback;
|
||||
} else {
|
||||
subs.push({
|
||||
refObject: refObject,
|
||||
callback: callback
|
||||
});
|
||||
}
|
||||
let subscribers = this.subscribers[eventName];
|
||||
if (subscribers.indexOf(callback) == -1)
|
||||
subscribers.push(callback);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: removeSubscriber
|
||||
// Removes the callback associated with refObject for the given event.
|
||||
removeSubscriber: function Subscribable_removeSubscriber(refObject, eventName) {
|
||||
// Removes the subscriber associated with the event for the given callback.
|
||||
removeSubscriber: function Subscribable_removeSubscriber(eventName, callback) {
|
||||
try {
|
||||
Utils.assertThrow(refObject, "refObject");
|
||||
Utils.assertThrow(typeof callback == "function", "callback must be a function");
|
||||
Utils.assertThrow(eventName && typeof eventName == "string",
|
||||
"eventName must be a non-empty string");
|
||||
} catch(e) {
|
||||
@ -455,9 +442,11 @@ Subscribable.prototype = {
|
||||
if (!this.subscribers || !this.subscribers[eventName])
|
||||
return;
|
||||
|
||||
this.subscribers[eventName] = this.subscribers[eventName].filter(function(element) {
|
||||
return element.refObject != refObject;
|
||||
});
|
||||
let subscribers = this.subscribers[eventName];
|
||||
let index = subscribers.indexOf(callback);
|
||||
|
||||
if (index > -1)
|
||||
subscribers.splice(index, 1);
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -475,10 +464,10 @@ Subscribable.prototype = {
|
||||
if (!this.subscribers || !this.subscribers[eventName])
|
||||
return;
|
||||
|
||||
var subsCopy = this.subscribers[eventName].concat();
|
||||
subsCopy.forEach(function(object) {
|
||||
let subsCopy = this.subscribers[eventName].concat();
|
||||
subsCopy.forEach(function (callback) {
|
||||
try {
|
||||
object.callback(this, eventInfo);
|
||||
callback(this, eventInfo);
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
|
@ -144,11 +144,6 @@ body {
|
||||
/* Other
|
||||
----------------------------------*/
|
||||
|
||||
.newTabButton {
|
||||
position: absolute !important;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
position: absolute;
|
||||
}
|
||||
|
@ -400,21 +400,28 @@ let UI = {
|
||||
|
||||
if (this._activeTab) {
|
||||
this._activeTab.makeDeactive();
|
||||
this._activeTab.removeSubscriber(this, "close");
|
||||
this._activeTab.removeSubscriber("close", this._onActiveTabClosed);
|
||||
}
|
||||
|
||||
this._activeTab = tabItem;
|
||||
|
||||
if (this._activeTab) {
|
||||
let self = this;
|
||||
this._activeTab.addSubscriber(this, "close", function(closedTabItem) {
|
||||
if (self._activeTab == closedTabItem)
|
||||
self._setActiveTab(null);
|
||||
});
|
||||
|
||||
this._activeTab.addSubscriber("close", this._onActiveTabClosed);
|
||||
this._activeTab.makeActive();
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _onActiveTabClosed
|
||||
// Handles when the currently active tab gets closed.
|
||||
//
|
||||
// Parameters:
|
||||
// - the <TabItem> that is closed
|
||||
_onActiveTabClosed: function UI__onActiveTabClosed(tabItem){
|
||||
if (UI._activeTab == tabItem)
|
||||
UI._setActiveTab(null);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setActive
|
||||
// Sets the active tab item or group item
|
||||
@ -438,6 +445,13 @@ let UI = {
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: clearActiveTab
|
||||
// Sets the active tab to 'null'.
|
||||
clearActiveTab: function UI_clearActiveTab() {
|
||||
this._setActiveTab(null);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isTabViewVisible
|
||||
// Returns true if the TabView UI is currently shown.
|
||||
@ -470,7 +484,6 @@ let UI = {
|
||||
|
||||
var self = this;
|
||||
var currentTab = this._currentTab;
|
||||
var item = null;
|
||||
|
||||
this._reorderTabItemsOnShow.forEach(function(groupItem) {
|
||||
groupItem.reorderTabItemsBasedOnTabOrder();
|
||||
@ -495,7 +508,7 @@ let UI = {
|
||||
Storage.saveVisibilityData(gWindow, "true");
|
||||
|
||||
if (zoomOut && currentTab && currentTab._tabViewTabItem) {
|
||||
item = currentTab._tabViewTabItem;
|
||||
let item = currentTab._tabViewTabItem;
|
||||
// If there was a previous currentTab we want to animate
|
||||
// its thumbnail (canvas) for the zoom out.
|
||||
// Note that we start the animation on the chrome thread.
|
||||
@ -516,6 +529,7 @@ let UI = {
|
||||
TabItems.resumePainting();
|
||||
});
|
||||
} else {
|
||||
self.clearActiveTab();
|
||||
dispatchEvent(event);
|
||||
|
||||
// Flush pending updates
|
||||
|
@ -212,6 +212,10 @@ _BROWSER_FILES = \
|
||||
browser_clearplugindata_noage.html \
|
||||
browser_popupUI.js \
|
||||
browser_sanitizeDialog.js \
|
||||
browser_save_video.js \
|
||||
bug564387.html \
|
||||
bug564387_video1.ogv \
|
||||
bug564387_video1.ogv^headers^ \
|
||||
browser_scope.js \
|
||||
browser_selectTabAtIndex.js \
|
||||
browser_tab_dragdrop.js \
|
||||
|
@ -46,6 +46,10 @@ function testURL(url, loadFunc, endFunc) {
|
||||
loadFunc(url);
|
||||
|
||||
addPageShowListener(function () {
|
||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
is(fm.focusedElement, null, "should be no focused element");
|
||||
is(fm.focusedWindow, gBrowser.contentWindow, "content window should be focused");
|
||||
|
||||
ok(!gBrowser.contentPrincipal.equals(pagePrincipal),
|
||||
"load of " + url + " by " + loadFunc.name + " should produce a page with a different principal");
|
||||
endFunc();
|
||||
|
@ -78,5 +78,14 @@ function test() {
|
||||
testPosition(7, 8, "blank tab without referrer opens at the end");
|
||||
testPosition(8, 9, "tab without referrer opens at the end");
|
||||
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
gBrowser.pinTab(gBrowser.selectedTab);
|
||||
addTab("http://mochi.test:8888/#8", gBrowser.currentURI);
|
||||
testPosition(9, 10, "tab with referrer should open at the end when the selected tab is pinned");
|
||||
gBrowser.selectedTab = tabs[9];
|
||||
gBrowser.removeTab(tabs.pop());
|
||||
is(gBrowser.selectedTab, tabs[0],
|
||||
"opening a tab from a pinned tab, selecting it and closing it should go back to the pinned tab");
|
||||
|
||||
tabs.forEach(gBrowser.removeTab, gBrowser);
|
||||
}
|
||||
|
90
browser/base/content/test/browser_save_video.js
Normal file
90
browser/base/content/test/browser_save_video.js
Normal file
@ -0,0 +1,90 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* TestCase for bug 564387
|
||||
* <https://bugzilla.mozilla.org/show_bug.cgi?id=564387>
|
||||
*/
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/bug564387.html");
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.addTab();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
gBrowser.addEventListener("pageshow", function pageShown(event) {
|
||||
if (event.target.location == "about:blank")
|
||||
return;
|
||||
gBrowser.removeEventListener("pageshow", pageShown);
|
||||
|
||||
executeSoon(function () {
|
||||
document.addEventListener("popupshown", contextMenuOpened);
|
||||
|
||||
var video1 = gBrowser.contentDocument.getElementById("video1");
|
||||
EventUtils.synthesizeMouseAtCenter(video1,
|
||||
{ type: "contextmenu", button: 2 },
|
||||
gBrowser.contentWindow);
|
||||
});
|
||||
});
|
||||
|
||||
function contextMenuOpened(event) {
|
||||
event.currentTarget.removeEventListener("popupshown", contextMenuOpened);
|
||||
|
||||
// Create the folder the video will be saved into.
|
||||
var destDir = createTemporarySaveDirectory();
|
||||
|
||||
mockFilePickerSettings.destDir = destDir;
|
||||
mockFilePickerSettings.filterIndex = 1; // kSaveAsType_URL
|
||||
mockFilePickerRegisterer.register();
|
||||
|
||||
mockTransferCallback = onTransferComplete;
|
||||
mockTransferRegisterer.register();
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
mockTransferRegisterer.unregister();
|
||||
mockFilePickerRegisterer.unregister();
|
||||
destDir.remove(true);
|
||||
});
|
||||
|
||||
// Select "Save Video As" option from context menu
|
||||
var saveVideoCommand = document.getElementById("context-savevideo");
|
||||
saveVideoCommand.doCommand();
|
||||
|
||||
event.target.hidePopup();
|
||||
}
|
||||
|
||||
function onTransferComplete(downloadSuccess) {
|
||||
ok(downloadSuccess, "Video file should have been downloaded successfully");
|
||||
|
||||
// Read the name of the saved file.
|
||||
var fileName = mockFilePickerResults.selectedFile.leafName;
|
||||
|
||||
is(fileName, "Bug564387-expectedName.ogv",
|
||||
"Video file name is correctly retrieved from Content-Disposition http header");
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
|
||||
this);
|
||||
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockFilePicker.js",
|
||||
this);
|
||||
|
||||
function createTemporarySaveDirectory() {
|
||||
var saveDir = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
.get("TmpD", Ci.nsIFile);
|
||||
saveDir.append("testsavedir");
|
||||
if (!saveDir.exists())
|
||||
saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
return saveDir;
|
||||
}
|
11
browser/base/content/test/bug564387.html
Normal file
11
browser/base/content/test/bug564387.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=564387 -->
|
||||
<head>
|
||||
<title> Bug 564387 test</title>
|
||||
</head>
|
||||
<body>
|
||||
Testing for Mozilla Bug: 564387
|
||||
<br>
|
||||
<video src="bug564387_video1.ogv" id="video1"> </video>
|
||||
</body>
|
||||
</html>
|
BIN
browser/base/content/test/bug564387_video1.ogv
Normal file
BIN
browser/base/content/test/bug564387_video1.ogv
Normal file
Binary file not shown.
3
browser/base/content/test/bug564387_video1.ogv^headers^
Normal file
3
browser/base/content/test/bug564387_video1.ogv^headers^
Normal file
@ -0,0 +1,3 @@
|
||||
Content-Disposition: filename="Bug564387-expectedName.ogv"
|
||||
Content-Type: video/ogg
|
||||
|
@ -149,6 +149,8 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug662266.js \
|
||||
browser_tabview_bug663421.js \
|
||||
browser_tabview_bug665502.js \
|
||||
browser_tabview_bug669694.js \
|
||||
browser_tabview_click_group.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
browser_tabview_expander.js \
|
||||
@ -166,7 +168,6 @@ _BROWSER_FILES = \
|
||||
head.js \
|
||||
search1.html \
|
||||
search2.html \
|
||||
test_bug599626.html \
|
||||
test_bug600645.html \
|
||||
test_bug644097.html \
|
||||
$(NULL)
|
||||
|
@ -1,53 +1,37 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let contentWindow;
|
||||
let groupItemTwoId;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", setup, false);
|
||||
TabView.toggle();
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
while (gBrowser.tabs[1])
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
hideTabView(function() {});
|
||||
});
|
||||
gBrowser.loadOneTab("about:blank", { inBackground: true });
|
||||
showTabView(setup);
|
||||
}
|
||||
|
||||
function setup() {
|
||||
window.removeEventListener("tabviewshown", setup, false);
|
||||
registerCleanupFunction(function() {
|
||||
let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId);
|
||||
if (groupItem)
|
||||
closeGroupItem(groupItem, function() {});
|
||||
});
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
|
||||
|
||||
let groupItemOne = contentWindow.GroupItems.groupItems[0];
|
||||
// add a blank tab to group one.
|
||||
createNewTabItemInGroupItem(groupItemOne, contentWindow, function() {
|
||||
is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items");
|
||||
is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items");
|
||||
|
||||
// create group two with a blank tab.
|
||||
let groupItemTwo = createEmptyGroupItem(contentWindow, 250, 250, 40);
|
||||
createNewTabItemInGroupItem(groupItemTwo, contentWindow, function() {
|
||||
// start the first test.
|
||||
testGroups(groupItemOne, groupItemTwo, contentWindow);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createNewTabItemInGroupItem(groupItem, contentWindow, callback) {
|
||||
// click on the + button to create a blank tab in group item
|
||||
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
|
||||
TabView.toggle();
|
||||
};
|
||||
let onTabViewShown = function() {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
callback();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
|
||||
let groupItemTwo = createGroupItemWithBlankTabs(window, 250, 250, 40, 1);
|
||||
groupItemTwoId = groupItemTwo.id;
|
||||
testGroups(groupItemOne, groupItemTwo, contentWindow);
|
||||
}
|
||||
|
||||
function testGroups(groupItemOne, groupItemTwo, contentWindow) {
|
||||
@ -58,8 +42,8 @@ function testGroups(groupItemOne, groupItemTwo, contentWindow) {
|
||||
"The first tab item in group two is active");
|
||||
|
||||
let tabItem = groupItemOne.getChild(1);
|
||||
tabItem.addSubscriber(tabItem, "tabRemoved", function() {
|
||||
tabItem.removeSubscriber(tabItem, "tabRemoved");
|
||||
tabItem.addSubscriber("tabRemoved", function onTabRemoved() {
|
||||
tabItem.removeSubscriber("tabRemoved", onTabRemoved);
|
||||
|
||||
is(groupItemOne.getChildren().length, 1,
|
||||
"The num of childen in group one is 1");
|
||||
@ -70,15 +54,12 @@ function testGroups(groupItemOne, groupItemTwo, contentWindow) {
|
||||
is(contentWindow.UI.getActiveTab(), groupItemOne.getChild(0),
|
||||
"The first tab item in group one is active");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
whenTabViewIsHidden(function() {
|
||||
is(groupItemOne.getChildren().length, 2,
|
||||
"The num of childen in group one is 2");
|
||||
|
||||
// clean up and finish
|
||||
groupItemTwo.addSubscriber(groupItemTwo, "close", function() {
|
||||
groupItemTwo.removeSubscriber(groupItemTwo, "close");
|
||||
|
||||
closeGroupItem(groupItemTwo, function() {
|
||||
gBrowser.removeTab(groupItemOne.getChild(1).tab);
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
|
||||
is(groupItemOne.getChildren().length, 1,
|
||||
@ -87,10 +68,7 @@ function testGroups(groupItemOne, groupItemTwo, contentWindow) {
|
||||
|
||||
finish();
|
||||
});
|
||||
gBrowser.removeTab(groupItemTwo.getChild(0).tab);
|
||||
groupItemTwo.close();
|
||||
}
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
});
|
||||
EventUtils.synthesizeKey("t", { accelKey: true });
|
||||
});
|
||||
// close a tab item in group one
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
let originalTab;
|
||||
let newTabOne;
|
||||
let groupItemTwoId;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
@ -11,10 +12,20 @@ function test() {
|
||||
// add a tab to the existing group.
|
||||
newTabOne = gBrowser.addTab();
|
||||
|
||||
let onTabviewShown = function() {
|
||||
window.removeEventListener("tabviewshown", onTabviewShown, false);
|
||||
registerCleanupFunction(function() {
|
||||
while (gBrowser.tabs[1])
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
hideTabView(function() {});
|
||||
});
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
showTabView(function() {
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId);
|
||||
if (groupItem)
|
||||
closeGroupItem(groupItem, function() {});
|
||||
});
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"There is one group item on startup");
|
||||
@ -25,22 +36,13 @@ function test() {
|
||||
"The currently selected tab should be the first tab in the groupItemOne");
|
||||
|
||||
// create another group with a tab.
|
||||
let groupItemTwo = createEmptyGroupItem(contentWindow, 300, 300, 200);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
let groupItemTwo = createGroupItemWithBlankTabs(window, 300, 300, 200, 1);
|
||||
groupItemTwoId = groupItemTwoId;
|
||||
hideTabView(function() {
|
||||
// start the test
|
||||
testGroupSwitch(contentWindow, groupItemOne, groupItemTwo);
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
// click on the + button
|
||||
let newTabButton = groupItemTwo.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
|
||||
};
|
||||
window.addEventListener("tabviewshown", onTabviewShown, false);
|
||||
TabView.toggle();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) {
|
||||
|
@ -46,8 +46,8 @@ function onTabViewWindowLoaded() {
|
||||
is(group.getChildren()[0].tab.linkedBrowser.contentWindow.location, secondTab.linkedBrowser.contentWindow.location, "The second tab was there first");
|
||||
is(group.getChildren()[1].tab.linkedBrowser.contentWindow.location, firstTab.linkedBrowser.contentWindow.location, "The first tab was just added and went to the end of the line");
|
||||
|
||||
group.addSubscriber(group, "close", function() {
|
||||
group.removeSubscriber(group, "close");
|
||||
group.addSubscriber("close", function onClose() {
|
||||
group.removeSubscriber("close", onClose);
|
||||
|
||||
ok(group.isEmpty(), "The group is empty again");
|
||||
|
||||
|
@ -29,14 +29,14 @@ function testCloseLastGroup() {
|
||||
{ type: "click" }, groupItem.$undoContainer[0], contentWindow);
|
||||
};
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
groupItem.addSubscriber("groupHidden", function onHidden() {
|
||||
groupItem.removeSubscriber("groupHidden", onHidden);
|
||||
// it should still stay after 3 ms.
|
||||
setTimeout(checkExistence, 3);
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupShown", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupShown");
|
||||
groupItem.addSubscriber("groupShown", function onShown() {
|
||||
groupItem.removeSubscriber("groupShown", onShown);
|
||||
|
||||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
|
@ -23,75 +23,49 @@ function test() {
|
||||
}
|
||||
|
||||
function testOne() {
|
||||
whenSearchEnabledAndDisabled(testTwo);
|
||||
hideSearchWhenSearchEnabled(testTwo);
|
||||
// press cmd/ctrl F
|
||||
EventUtils.synthesizeKey("f", {accelKey: true}, cw);
|
||||
}
|
||||
|
||||
function testTwo() {
|
||||
whenSearchEnabledAndDisabled(testThree);
|
||||
hideSearchWhenSearchEnabled(testThree);
|
||||
// press /
|
||||
EventUtils.synthesizeKey("VK_SLASH", {}, cw);
|
||||
}
|
||||
|
||||
function testThree() {
|
||||
let onTabViewShown = function () {
|
||||
is(cw.UI.getActiveTab(), groupItem.getChild(0),
|
||||
"The active tab is newly created tab item");
|
||||
ok(win.TabView.isVisible(), "Tab View is visible");
|
||||
// create another group with a tab.
|
||||
let groupItem = createGroupItemWithBlankTabs(win, 300, 300, 200, 1);
|
||||
is(cw.UI.getActiveTab(), groupItem.getChild(0),
|
||||
"The active tab is newly created tab item");
|
||||
|
||||
let onSearchEnabled = function () {
|
||||
let doc = cw.document;
|
||||
let searchBox = cw.iQ("#searchbox");
|
||||
let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0];
|
||||
ok(hasFocus, "The search box has focus");
|
||||
whenSearchIsEnabled(function () {
|
||||
let doc = cw.document;
|
||||
let searchBox = cw.iQ("#searchbox");
|
||||
let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0];
|
||||
ok(hasFocus, "The search box has focus");
|
||||
|
||||
let tab = win.gBrowser.tabs[1];
|
||||
searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML);
|
||||
let tab = win.gBrowser.tabs[1];
|
||||
searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML);
|
||||
|
||||
cw.performSearch();
|
||||
cw.performSearch();
|
||||
|
||||
whenTabViewIsHidden(function () {
|
||||
is(tab, win.gBrowser.selectedTab, "The search result tab is shown");
|
||||
waitForFocus(finish);
|
||||
}, win);
|
||||
whenTabViewIsHidden(function () {
|
||||
is(tab, win.gBrowser.selectedTab, "The search result tab is shown");
|
||||
finish()
|
||||
}, win);
|
||||
|
||||
// use the tabview menu (the same as pressing cmd/ctrl + e)
|
||||
win.document.getElementById("menu_tabview").doCommand();
|
||||
};
|
||||
|
||||
whenSearchEnabled(onSearchEnabled);
|
||||
EventUtils.synthesizeKey("VK_SLASH", {}, cw);
|
||||
};
|
||||
|
||||
whenTabViewIsHidden(function () {
|
||||
showTabView(onTabViewShown, win);
|
||||
// use the tabview menu (the same as pressing cmd/ctrl + e)
|
||||
win.document.getElementById("menu_tabview").doCommand();
|
||||
}, win);
|
||||
|
||||
// click on the + button
|
||||
let groupItem = createEmptyGroupItem(cw, 300, 300, 200);
|
||||
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
|
||||
EventUtils.sendMouseEvent({type: "click"}, newTabButton[0], cw);
|
||||
EventUtils.synthesizeKey("VK_SLASH", {}, cw);
|
||||
}
|
||||
|
||||
function whenSearchEnabledAndDisabled(callback) {
|
||||
whenSearchEnabled(function () {
|
||||
whenSearchDisabled(callback);
|
||||
cw.hideSearch();
|
||||
});
|
||||
function hideSearchWhenSearchEnabled(callback) {
|
||||
whenSearchIsEnabled(function() {
|
||||
hideSearch(callback, win);
|
||||
}, win);
|
||||
}
|
||||
|
||||
function whenSearchEnabled(callback) {
|
||||
cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
|
||||
cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
|
||||
callback();
|
||||
}, false);
|
||||
}
|
||||
|
||||
function whenSearchDisabled(callback) {
|
||||
cw.addEventListener("tabviewsearchdisabled", function onSearchDisabled() {
|
||||
cw.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false);
|
||||
callback();
|
||||
}, false);
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ function onTabViewWindowLoaded() {
|
||||
ok(group1.getChildren().some(function(child) child == tab1Item), "The tab was made in our new group");
|
||||
is(group1.getChildren().length, 1, "Only one tab in the first group");
|
||||
|
||||
group1.addSubscriber(group1, "close", function() {
|
||||
group1.removeSubscriber(group1, "close");
|
||||
group1.addSubscriber("close", function onClose() {
|
||||
group1.removeSubscriber("close", onClose);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
@ -45,16 +45,11 @@ function onTabViewWindowLoaded() {
|
||||
});
|
||||
});
|
||||
|
||||
group1.addSubscriber(group1, "groupHidden", function() {
|
||||
group1.removeSubscriber(group1, "groupHidden");
|
||||
|
||||
hideGroupItem(group1, function () {
|
||||
// close undo group
|
||||
let closeButton = group1.$undoContainer.find(".close");
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "click" }, closeButton[0], contentWindow);
|
||||
});
|
||||
|
||||
// Get rid of the group and its children
|
||||
group1.closeAll();
|
||||
}
|
||||
|
||||
|
@ -35,8 +35,8 @@ function setupTwo(win) {
|
||||
// force all canvases to update, and hook in imageData save detection
|
||||
tabItems.forEach(function(tabItem) {
|
||||
contentWindow.TabItems.update(tabItem.tab);
|
||||
tabItem.addSubscriber(tabItem, "savedCachedImageData", function(item) {
|
||||
item.removeSubscriber(item, "savedCachedImageData");
|
||||
tabItem.addSubscriber("savedCachedImageData", function onSaved(item) {
|
||||
item.removeSubscriber("savedCachedImageData", onSaved);
|
||||
--numTabsToSave;
|
||||
});
|
||||
});
|
||||
@ -87,8 +87,8 @@ function setupTwo(win) {
|
||||
let count = tabItems.length;
|
||||
|
||||
tabItems.forEach(function(tabItem) {
|
||||
tabItem.addSubscriber(tabItem, "loadedCachedImageData", function() {
|
||||
tabItem.removeSubscriber(tabItem, "loadedCachedImageData");
|
||||
tabItem.addSubscriber("loadedCachedImageData", function onLoaded() {
|
||||
tabItem.removeSubscriber("loadedCachedImageData", onLoaded);
|
||||
ok(tabItem.isShowingCachedData(),
|
||||
"Tab item is showing cached data and is just connected. " +
|
||||
tabItem.tab.linkedBrowser.currentURI.spec);
|
||||
|
@ -1,161 +1,87 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let handleDialog;
|
||||
let timer; // keep in outer scope so it's not GC'd before firing
|
||||
const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
|
||||
'function(e){e.returnValue="?"}</script>';
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(onTabViewShown);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
function onTabViewShown() {
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
let groupItemOne = contentWindow.GroupItems.getActiveGroupItem();
|
||||
let groupItemTwo = createGroupItemWithTabs(window, 300, 300, 10, [TEST_URL]);
|
||||
|
||||
// Create a group and make it active
|
||||
let box = new contentWindow.Rect(10, 10, 300, 300);
|
||||
let groupItemTwo = new contentWindow.GroupItem([], { bounds: box });
|
||||
contentWindow.UI.setActive(groupItemTwo);
|
||||
|
||||
let testTab =
|
||||
gBrowser.addTab(
|
||||
"http://mochi.test:8888/browser/browser/base/content/test/tabview/test_bug599626.html");
|
||||
let browser = gBrowser.getBrowserForTab(testTab);
|
||||
let onLoad = function() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
||||
afterAllTabsLoaded(function () {
|
||||
testStayOnPage(contentWindow, groupItemOne, groupItemTwo);
|
||||
}
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
});
|
||||
}
|
||||
|
||||
function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
|
||||
setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
|
||||
groupItemTwo.addSubscriber(groupItemTwo, "groupShown", function() {
|
||||
groupItemTwo.removeSubscriber(groupItemTwo, "groupShown");
|
||||
whenDialogOpened(function (dialog) {
|
||||
groupItemTwo.addSubscriber("groupShown", function onShown() {
|
||||
groupItemTwo.removeSubscriber("groupShown", onShown);
|
||||
|
||||
is(gBrowser.tabs.length, 2,
|
||||
"The total number of tab is 2 when staying on the page");
|
||||
is(contentWindow.TabItems.getItems().length, 2,
|
||||
"The total number of tab items is 2 when staying on the page");
|
||||
|
||||
let onTabViewShown = function() {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
|
||||
showTabView(function () {
|
||||
// start the next test
|
||||
testLeavePage(contentWindow, groupItemOne, groupItemTwo);
|
||||
};
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
TabView.toggle();
|
||||
});
|
||||
});
|
||||
|
||||
// stay on page
|
||||
doc.documentElement.getButton("cancel").click();
|
||||
dialog.cancelDialog();
|
||||
});
|
||||
|
||||
closeGroupItem(groupItemTwo);
|
||||
}
|
||||
|
||||
function testLeavePage(contentWindow, groupItemOne, groupItemTwo) {
|
||||
setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
|
||||
whenDialogOpened(function (dialog) {
|
||||
// clean up and finish the test
|
||||
groupItemTwo.addSubscriber(groupItemTwo, "close", function() {
|
||||
groupItemTwo.removeSubscriber(groupItemTwo, "close");
|
||||
groupItemTwo.addSubscriber("close", function onClose() {
|
||||
groupItemTwo.removeSubscriber("close", onClose);
|
||||
|
||||
is(gBrowser.tabs.length, 1,
|
||||
"The total number of tab is 1 after leaving the page");
|
||||
is(contentWindow.TabItems.getItems().length, 1,
|
||||
"The total number of tab items is 1 after leaving the page");
|
||||
|
||||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", endGame, false);
|
||||
hideTabView(finish);
|
||||
});
|
||||
|
||||
// Leave page
|
||||
doc.documentElement.getButton("accept").click();
|
||||
dialog.acceptDialog();
|
||||
});
|
||||
|
||||
closeGroupItem(groupItemTwo);
|
||||
}
|
||||
|
||||
function setupAndRun(contentWindow, groupItemOne, groupItemTwo, callback) {
|
||||
let closeButton = groupItemTwo.container.getElementsByClassName("close");
|
||||
ok(closeButton[0], "Group close button exists");
|
||||
// click the close button
|
||||
EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
|
||||
// ----------
|
||||
function whenDialogOpened(callback) {
|
||||
let listener = {
|
||||
onCloseWindow: function () {},
|
||||
onWindowTitleChange: function () {},
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
onOpenWindow: function (xulWin) {
|
||||
let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
|
||||
handleDialog = function(doc) {
|
||||
callback(doc);
|
||||
};
|
||||
startCallbackTimer();
|
||||
whenWindowLoaded(domWin, function () {
|
||||
let dialog = domWin.document.querySelector("dialog");
|
||||
if (dialog) {
|
||||
Services.wm.removeListener(listener);
|
||||
callback(dialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
let tabItem = groupItemOne.getChild(0);
|
||||
tabItem.zoomIn();
|
||||
}
|
||||
|
||||
// Copied from http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/tests/mochitest/prompt_common.js
|
||||
let observer = {
|
||||
QueryInterface : function (iid) {
|
||||
const interfaces = [Ci.nsIObserver, Ci.nsISupports, Ci.nsISupportsWeakReference];
|
||||
|
||||
if (!interfaces.some( function(v) { return iid.equals(v) } ))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
},
|
||||
|
||||
observe : function (subject, topic, data) {
|
||||
let doc = getDialogDoc();
|
||||
if (doc)
|
||||
handleDialog(doc);
|
||||
else
|
||||
startCallbackTimer(); // try again in a bit
|
||||
}
|
||||
};
|
||||
|
||||
function startCallbackTimer() {
|
||||
// Delay before the callback twiddles the prompt.
|
||||
const dialogDelay = 10;
|
||||
|
||||
// Use a timer to invoke a callback to twiddle the authentication dialog
|
||||
timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
function getDialogDoc() {
|
||||
// Find the <browser> which contains notifyWindow, by looking
|
||||
// through all the open windows and all the <browsers> in each.
|
||||
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
let enumerator = wm.getXULWindowEnumerator(null);
|
||||
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let win = enumerator.getNext();
|
||||
let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
|
||||
|
||||
let containedDocShells = windowDocShell.getDocShellEnumerator(
|
||||
Ci.nsIDocShellTreeItem.typeChrome,
|
||||
Ci.nsIDocShell.ENUMERATE_FORWARDS);
|
||||
while (containedDocShells.hasMoreElements()) {
|
||||
// Get the corresponding document for this docshell
|
||||
let childDocShell = containedDocShells.getNext();
|
||||
// We don't want it if it's not done loading.
|
||||
if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
|
||||
continue;
|
||||
let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell).
|
||||
contentViewer.DOMDocument;
|
||||
|
||||
if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
|
||||
return childDoc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
Services.wm.addListener(listener);
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ function test() {
|
||||
cw.TabItems.pausePainting();
|
||||
|
||||
groupItem.getChildren().forEach(function (tabItem) {
|
||||
tabItem.addSubscriber(tabItem, "updated", function () {
|
||||
tabItem.removeSubscriber(tabItem, "updated");
|
||||
tabItem.addSubscriber("updated", function onUpdated() {
|
||||
tabItem.removeSubscriber("updated", onUpdated);
|
||||
tabItem._testLastTabUpdateTime = tabItem._lastTabUpdateTime;
|
||||
|
||||
if (--numTabsToUpdate)
|
||||
|
@ -36,12 +36,7 @@ function test() {
|
||||
let groupItem = cw.GroupItems.groupItems[1];
|
||||
is(groupItem.getTitle(), "t", "new groupItem's title is correct");
|
||||
|
||||
groupItem.addSubscriber(groupItem, "close", function () {
|
||||
groupItem.removeSubscriber(groupItem, "close");
|
||||
executeSoon(callback);
|
||||
});
|
||||
|
||||
groupItem.closeAll();
|
||||
closeGroupItem(groupItem, callback);
|
||||
};
|
||||
|
||||
let testDragOutOfGroup = function (callback) {
|
||||
|
@ -28,8 +28,7 @@ function onTabViewWindowLoaded() {
|
||||
ok(TabView.isVisible(), "Tab View is still visible after removing a tab");
|
||||
is(groupItems[0].getChildren().length, 2, "The group has two tab items");
|
||||
|
||||
tabTwo = undoCloseTab(0);
|
||||
whenTabIsReconnected(tabTwo, function() {
|
||||
restoreTab(function (tabTwo) {
|
||||
ok(TabView.isVisible(), "Tab View is still visible after restoring a tab");
|
||||
is(groupItems[0].getChildren().length, 3, "The group still has three tab items");
|
||||
|
||||
@ -41,18 +40,3 @@ function onTabViewWindowLoaded() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenTabIsReconnected(tab, callback) {
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
|
||||
if (tabItem._reconnected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
tabItem.addSubscriber(tabItem, "reconnected", function () {
|
||||
tabItem.removeSubscriber(tabItem, "reconnected");
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
@ -18,9 +18,7 @@ function onTabViewWindowLoaded() {
|
||||
is(gBrowser.tabs.length, 1, "There is one tab on startup");
|
||||
let groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
@ -35,5 +33,4 @@ function onTabViewWindowLoaded() {
|
||||
|
||||
TabView.hide();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
@ -160,13 +160,13 @@ function test() {
|
||||
|
||||
ok(groupItem.isStacked(), 'testExpandedMode: group is stacked');
|
||||
|
||||
groupItem.addSubscriber(groupItem, 'expanded', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'expanded');
|
||||
groupItem.addSubscriber('expanded', function onGroupExpanded() {
|
||||
groupItem.removeSubscriber('expanded', onGroupExpanded);
|
||||
onExpanded();
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, 'collapsed', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'collapsed');
|
||||
groupItem.addSubscriber('collapsed', function onGroupCollapsed() {
|
||||
groupItem.removeSubscriber('collapsed', onGroupCollapsed);
|
||||
onCollapsed();
|
||||
});
|
||||
|
||||
|
@ -36,8 +36,8 @@ function onTabViewWindowLoaded(win) {
|
||||
ok(!group.shouldStack(group._children.length), "Group should not stack.");
|
||||
|
||||
// PREPARE FINISH:
|
||||
group.addSubscriber(group, "close", function() {
|
||||
group.removeSubscriber(group, "close");
|
||||
group.addSubscriber("close", function onClose() {
|
||||
group.removeSubscriber("close", onClose);
|
||||
|
||||
ok(group.isEmpty(), "The group is empty again");
|
||||
|
||||
@ -78,11 +78,7 @@ function onTabViewWindowLoaded(win) {
|
||||
|
||||
// Get rid of the group and its children
|
||||
// The group close will trigger a finish().
|
||||
group.addSubscriber(group, "groupHidden", function() {
|
||||
group.removeSubscriber(group, "groupHidden");
|
||||
group.closeHidden();
|
||||
});
|
||||
group.closeAll();
|
||||
closeGroupItem(group);
|
||||
}, win);
|
||||
}, win);
|
||||
}
|
||||
|
@ -20,23 +20,6 @@ function test() {
|
||||
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 () {
|
||||
|
@ -41,20 +41,6 @@ function test() {
|
||||
return createTab('about:blank');
|
||||
}
|
||||
|
||||
let restoreTab = function (callback) {
|
||||
let tab = undoCloseTab(0);
|
||||
|
||||
if (tab._tabViewTabItem._reconnected) {
|
||||
afterAllTabsLoaded(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
|
||||
afterAllTabsLoaded(callback);
|
||||
});
|
||||
}
|
||||
|
||||
let finishTest = function () {
|
||||
prefix = 'finish';
|
||||
assertValidPrerequisites();
|
||||
|
@ -39,10 +39,7 @@ function test1() {
|
||||
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
|
||||
"Should not save the thumbnail for tab");
|
||||
|
||||
tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
|
||||
tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
|
||||
test2();
|
||||
});
|
||||
whenDeniedToCacheImageData(tabItem, test2);
|
||||
tabItem.save(true);
|
||||
HttpRequestObserver.cacheControlValue = null;
|
||||
});
|
||||
@ -59,10 +56,7 @@ function test2() {
|
||||
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
|
||||
"Should save the thumbnail for tab");
|
||||
|
||||
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
|
||||
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
|
||||
test3();
|
||||
});
|
||||
whenSavedCachedImageData(tabItem, test3);
|
||||
tabItem.save(true);
|
||||
});
|
||||
}
|
||||
@ -82,11 +76,7 @@ function test3() {
|
||||
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
|
||||
"Should save the thumbnail for tab");
|
||||
|
||||
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
|
||||
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
|
||||
|
||||
test4();
|
||||
});
|
||||
whenSavedCachedImageData(tabItem, test4);
|
||||
tabItem.save(true);
|
||||
});
|
||||
}
|
||||
@ -104,11 +94,7 @@ function test4() {
|
||||
ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
|
||||
"Should save the thumbnail for tab");
|
||||
|
||||
tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
|
||||
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
|
||||
|
||||
test5();
|
||||
});
|
||||
whenSavedCachedImageData(tabItem, test5);
|
||||
tabItem.save(true);
|
||||
});
|
||||
}
|
||||
@ -124,9 +110,7 @@ function test5() {
|
||||
ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
|
||||
"Should not the thumbnail for tab");
|
||||
|
||||
tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
|
||||
tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
|
||||
|
||||
whenDeniedToCacheImageData(tabItem, function () {
|
||||
hideTabView(function () {
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
finish();
|
||||
@ -154,3 +138,17 @@ let HttpRequestObserver = {
|
||||
Services.obs.removeObserver(this, "http-on-examine-response");
|
||||
}
|
||||
};
|
||||
|
||||
function whenSavedCachedImageData(tabItem, callback) {
|
||||
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
|
||||
tabItem.removeSubscriber("savedCachedImageData", onSaved);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function whenDeniedToCacheImageData(tabItem, callback) {
|
||||
tabItem.addSubscriber("deniedToCacheImageData", function onDenied() {
|
||||
tabItem.removeSubscriber("deniedToCacheImageData", onDenied);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ function test() {
|
||||
afterAllTabsLoaded(function () {
|
||||
tabItem = tab._tabViewTabItem;
|
||||
|
||||
tabItem.addSubscriber(tabItem, "savedCachedImageData", function () {
|
||||
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
|
||||
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
|
||||
tabItem.removeSubscriber("savedCachedImageData", onSaved);
|
||||
|
||||
tabItem.addSubscriber(tabItem, "loadedCachedImageData", function () {
|
||||
tabItem.removeSubscriber(tabItem, "loadedCachedImageData");
|
||||
tabItem.addSubscriber("loadedCachedImageData", function onLoaded() {
|
||||
tabItem.removeSubscriber("loadedCachedImageData", onLoaded);
|
||||
|
||||
ok(tabItem.isShowingCachedData(), 'tabItem shows cached data');
|
||||
testChangeUrlAfterReconnect();
|
||||
|
@ -28,10 +28,10 @@ function onTabViewWindowLoaded(win) {
|
||||
|
||||
function check() {
|
||||
if (groupOrTab == 'group') {
|
||||
group.removeSubscriber(group, "groupHidden", check);
|
||||
group.removeSubscriber("groupHidden", check);
|
||||
group.closeHidden();
|
||||
} else
|
||||
tab.removeSubscriber(tab, "tabRemoved", check);
|
||||
tab.removeSubscriber("tabRemoved", check);
|
||||
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
|
||||
"The original group is active.");
|
||||
@ -42,10 +42,10 @@ function onTabViewWindowLoaded(win) {
|
||||
}
|
||||
|
||||
if (groupOrTab == 'group') {
|
||||
group.addSubscriber(group, "groupHidden", check);
|
||||
group.addSubscriber("groupHidden", check);
|
||||
group.closeAll();
|
||||
} else {
|
||||
tab.addSubscriber(tab, "tabRemoved", check);
|
||||
tab.addSubscriber("tabRemoved", check);
|
||||
tab.close();
|
||||
}
|
||||
}
|
||||
@ -58,4 +58,4 @@ function onTabViewWindowLoaded(win) {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -25,20 +25,6 @@ function test() {
|
||||
return cw.GroupItems.groupItems[index];
|
||||
}
|
||||
|
||||
let restoreTab = function (callback) {
|
||||
let tab = undoCloseTab(0);
|
||||
|
||||
if (tab._tabViewTabItem._reconnected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
|
||||
afterAllTabsLoaded(callback);
|
||||
});
|
||||
}
|
||||
|
||||
let activateFirstGroupItem = function () {
|
||||
let activeTabItem = getGroupItem(0).getChild(0);
|
||||
cw.GroupItems.updateActiveGroupItemAndTabBar(activeTabItem);
|
||||
|
@ -19,12 +19,7 @@ function test() {
|
||||
|
||||
// show the undo close group button
|
||||
let group = contentWindow.GroupItems.groupItems[0];
|
||||
group.closeAll();
|
||||
|
||||
group.addSubscriber(group, "groupHidden", function() {
|
||||
group.removeSubscriber(group, "groupHidden");
|
||||
restore(group.id);
|
||||
});
|
||||
hideGroupItem(group, function () restore(group.id));
|
||||
},
|
||||
function(newWin) {
|
||||
win = newWin;
|
||||
|
@ -65,11 +65,6 @@ function test() {
|
||||
simulateDoubleClick(container, 2);
|
||||
assertNumberOfTabs(1);
|
||||
|
||||
// simulate double click with left mouse button
|
||||
let container = groupItem.container;
|
||||
simulateDoubleClick(container);
|
||||
assertNumberOfTabs(1);
|
||||
|
||||
groupItem.close();
|
||||
hideTabView(finishTest);
|
||||
}
|
||||
|
@ -43,13 +43,13 @@ function test() {
|
||||
}
|
||||
|
||||
let testDragOutOfExpandedStackedGroup = function () {
|
||||
groupItem.addSubscriber(groupItem, "expanded", function () {
|
||||
groupItem.removeSubscriber(groupItem, "expanded");
|
||||
groupItem.addSubscriber("expanded", function onExpanded() {
|
||||
groupItem.removeSubscriber("expanded", onExpanded);
|
||||
dragTabItem();
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, "collapsed", function () {
|
||||
groupItem.removeSubscriber(groupItem, "collapsed");
|
||||
groupItem.addSubscriber("collapsed", function onCollapsed() {
|
||||
groupItem.removeSubscriber("collapsed", onCollapsed);
|
||||
|
||||
let secondGroup = cw.GroupItems.groupItems[1];
|
||||
closeGroupItem(secondGroup, function () hideTabView(finishTest));
|
||||
|
@ -71,8 +71,8 @@ function testCreateTabAndThen(callback) {
|
||||
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab))
|
||||
|
||||
tabItem.addSubscriber(tabItem, "zoomedIn", function() {
|
||||
tabItem.removeSubscriber(tabItem, "zoomedIn");
|
||||
tabItem.addSubscriber("zoomedIn", function onZoomedIn() {
|
||||
tabItem.removeSubscriber("zoomedIn", onZoomedIn);
|
||||
|
||||
is(gBrowser.selectedTab, tab,
|
||||
"The selected tab is the same as the newly opened tab");
|
||||
|
@ -21,8 +21,8 @@ function test() {
|
||||
|
||||
cw.TabItems.pausePainting();
|
||||
|
||||
tabItem.addSubscriber(tabItem, "updated", function () {
|
||||
tabItem.removeSubscriber(tabItem, "updated");
|
||||
tabItem.addSubscriber("updated", function onUpdated() {
|
||||
tabItem.removeSubscriber("updated", onUpdated);
|
||||
ok(isIdle, "tabItem is updated only when UI is idle");
|
||||
finish();
|
||||
});
|
||||
|
@ -8,8 +8,8 @@ function test() {
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let tabItem = win.gBrowser.tabs[0]._tabViewTabItem;
|
||||
|
||||
tabItem.addSubscriber(tabItem, "savedCachedImageData", function () {
|
||||
tabItem.removeSubscriber(tabItem, "savedCachedImageData");
|
||||
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
|
||||
tabItem.removeSubscriber("savedCachedImageData", onSaved);
|
||||
|
||||
ok(cw.UI.isDOMWindowClosing, "dom window is closing");
|
||||
waitForFocus(finish);
|
||||
|
@ -18,8 +18,8 @@ function test() {
|
||||
ok(groupItem.isStacked(), "groupItem is now stacked");
|
||||
is(win.gBrowser.tabs.length, 5, "we have five tabs");
|
||||
|
||||
groupItem.addSubscriber(groupItem, "expanded", function onExpanded() {
|
||||
groupItem.removeSubscriber(groupItem, "expanded");
|
||||
groupItem.addSubscriber("expanded", function onExpanded() {
|
||||
groupItem.removeSubscriber("expanded", onExpanded);
|
||||
|
||||
ok(groupItem.expanded, "groupItem is expanded");
|
||||
let bounds = children[1].getBounds();
|
||||
|
@ -0,0 +1,48 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
function onLoad(win) {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
let tab = win.gBrowser.addTab();
|
||||
win.gBrowser.pinTab(tab);
|
||||
}
|
||||
|
||||
function onShow(win) {
|
||||
let tabs = win.gBrowser.tabs;
|
||||
|
||||
// zoom into normal tab
|
||||
zoomIn(tabs[1], function () {
|
||||
is(win.gBrowser.selectedTab, tabs[1], "normal tab is selected");
|
||||
|
||||
// select app tab
|
||||
win.gBrowser.selectedTab = tabs[0];
|
||||
|
||||
toggleTabView(win, function () {
|
||||
is(win.gBrowser.selectedTab, tabs[0], "app tab is selected");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newWindowWithTabView(onShow, onLoad);
|
||||
}
|
||||
|
||||
// ----------
|
||||
function zoomIn(tab, callback) {
|
||||
whenTabViewIsHidden(function () {
|
||||
executeSoon(callback);
|
||||
}, tab.ownerDocument.defaultView);
|
||||
|
||||
tab._tabViewTabItem.zoomIn();
|
||||
}
|
||||
|
||||
// ----------
|
||||
function toggleTabView(win, callback) {
|
||||
showTabView(function () {
|
||||
hideTabView(callback, win);
|
||||
}, win);
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let contentWindow;
|
||||
let groupItem;
|
||||
let groupItemId;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
contentWindow.gPrefBranch.clearUserPref("animate_zoom");
|
||||
let createdGroupItem = contentWindow.GroupItems.groupItem(groupItemId)
|
||||
if (createdGroupItem)
|
||||
closeGroupItem(createdGroupItem, function() {});
|
||||
hideTabView(function() {});
|
||||
});
|
||||
|
||||
showTabView(function() {
|
||||
contentWindow = TabView.getContentWindow();
|
||||
groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
|
||||
groupItemId = groupItem.id;
|
||||
testMouseClickOnEmptyGroupItem();
|
||||
});
|
||||
}
|
||||
|
||||
function testMouseClickOnEmptyGroupItem() {
|
||||
whenTabViewIsHidden(function() {
|
||||
is(groupItem.getChildren().length, 1, "The group item contains one tab item now");
|
||||
showTabView(testDraggingWithinGroupItem);
|
||||
});
|
||||
is(groupItem.getChildren().length, 0, "The group item doesn't contain any tab items");
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, groupItem.container, contentWindow);
|
||||
EventUtils.sendMouseEvent({ type: "mouseup" }, groupItem.container, contentWindow);
|
||||
}
|
||||
|
||||
function testDraggingWithinGroupItem() {
|
||||
let target = groupItem.container;
|
||||
contentWindow.gPrefBranch.setBoolPref("animate_zoom", false);
|
||||
|
||||
// stimulate drag and drop
|
||||
EventUtils.sendMouseEvent( {type: "mousedown" }, target, contentWindow);
|
||||
EventUtils.synthesizeMouse(target, 10, 10, { type: "mousemove" }, contentWindow);
|
||||
ok(groupItem.isDragging, "The group item is being dragged")
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mouseup" }, target, contentWindow);
|
||||
ok(!groupItem.isDragging, "The dragging is competely");
|
||||
|
||||
executeSoon(function() {
|
||||
ok(TabView.isVisible(), "The tab view is still visible after dragging");
|
||||
contentWindow.gPrefBranch.clearUserPref("animate_zoom");
|
||||
|
||||
testMouseClickOnGroupItem();
|
||||
});
|
||||
}
|
||||
|
||||
function testMouseClickOnGroupItem() {
|
||||
whenTabViewIsHidden(function() {
|
||||
is(groupItem.getChildren().length, 1, "The group item still contains one tab item");
|
||||
|
||||
closeGroupItem(groupItem, function() {
|
||||
hideTabView(finish);
|
||||
});
|
||||
});
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, groupItem.container, contentWindow);
|
||||
EventUtils.sendMouseEvent({ type: "mouseup" }, groupItem.container, contentWindow);
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ function onTabViewWindowLoaded() {
|
||||
let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
|
||||
let groupTwo = new contentWindow.GroupItem([], { bounds: boxTwo });
|
||||
|
||||
groupOne.addSubscriber(groupOne, "childAdded", function() {
|
||||
groupOne.removeSubscriber(groupOne, "childAdded");
|
||||
groupOne.addSubscriber("childAdded", function onChildAdded() {
|
||||
groupOne.removeSubscriber("childAdded", onChildAdded);
|
||||
groupTwo.newTab();
|
||||
});
|
||||
|
||||
@ -68,7 +68,7 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
Math.round(groupTwoRectCenter.y - tabItemRectCenter.y);
|
||||
|
||||
function endGame() {
|
||||
groupTwo.removeSubscriber(groupTwo, "childAdded");
|
||||
groupTwo.removeSubscriber("childAdded", endGame);
|
||||
|
||||
is(groupOne.getChildren().length, --groupOneTabItemCount,
|
||||
"The number of children in group one is decreased by 1");
|
||||
@ -83,14 +83,14 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "click" }, closeButton[0], contentWindow);
|
||||
};
|
||||
groupTwo.addSubscriber(groupTwo, "close", function() {
|
||||
groupTwo.removeSubscriber(groupTwo, "close");
|
||||
finish();
|
||||
groupTwo.addSubscriber("close", function onClose() {
|
||||
groupTwo.removeSubscriber("close", onClose);
|
||||
finish();
|
||||
});
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
gBrowser.selectedTab = originalTab;
|
||||
}
|
||||
groupTwo.addSubscriber(groupTwo, "childAdded", endGame);
|
||||
groupTwo.addSubscriber("childAdded", endGame);
|
||||
|
||||
simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ function onTabViewWindowLoaded(win) {
|
||||
// Here, we just expand the group, click elsewhere, and make sure
|
||||
// it collapsed.
|
||||
let stage1expanded = function() {
|
||||
group.removeSubscriber("test stage 1", "expanded", stage1expanded);
|
||||
group.removeSubscriber("expanded", stage1expanded);
|
||||
|
||||
ok(group.expanded, "The group is now expanded.");
|
||||
is(expander[0].style.display, "none", "The expander is hidden!");
|
||||
@ -60,14 +60,14 @@ function onTabViewWindowLoaded(win) {
|
||||
ok(overlay, "The expanded tray exists.");
|
||||
let $overlay = contentWindow.iQ(overlay);
|
||||
|
||||
group.addSubscriber("test stage 1", "collapsed", stage1collapsed);
|
||||
group.addSubscriber("collapsed", stage1collapsed);
|
||||
// null type means "click", for some reason...
|
||||
EventUtils.synthesizeMouse(contentWindow.document.body, 10, $overlay.bounds().bottom + 5,
|
||||
{type: null}, contentWindow);
|
||||
};
|
||||
|
||||
let stage1collapsed = function() {
|
||||
group.removeSubscriber("test stage 1", "collapsed", stage1collapsed);
|
||||
group.removeSubscriber("collapsed", stage1collapsed);
|
||||
ok(!group.expanded, "The group is no longer expanded.");
|
||||
isnot(expander[0].style.display, "none", "The expander is visible!");
|
||||
let expanderBounds = expander.bounds();
|
||||
@ -76,7 +76,7 @@ function onTabViewWindowLoaded(win) {
|
||||
ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack.");
|
||||
|
||||
// now, try opening it up again.
|
||||
group.addSubscriber("test stage 2", "expanded", stage2expanded);
|
||||
group.addSubscriber("expanded", stage2expanded);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
|
||||
};
|
||||
|
||||
@ -84,7 +84,7 @@ function onTabViewWindowLoaded(win) {
|
||||
// Now make sure every child of the group shows up within this "tray", and
|
||||
// click on one of them and make sure we go into the tab and the tray collapses.
|
||||
let stage2expanded = function() {
|
||||
group.removeSubscriber("test stage 2", "expanded", stage2expanded);
|
||||
group.removeSubscriber("expanded", stage2expanded);
|
||||
|
||||
ok(group.expanded, "The group is now expanded.");
|
||||
is(expander[0].style.display, "none", "The expander is hidden!");
|
||||
@ -132,27 +132,27 @@ function onTabViewWindowLoaded(win) {
|
||||
}
|
||||
|
||||
// okay, expand this group one last time
|
||||
group.addSubscriber("test stage 3", "expanded", stage3expanded);
|
||||
group.addSubscriber("expanded", stage3expanded);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
|
||||
}
|
||||
|
||||
// STAGE 3:
|
||||
// Ensure that stack still shows the same top item after a expand and a collapse.
|
||||
let stage3expanded = function() {
|
||||
group.removeSubscriber("test stage 3", "expanded", stage3expanded);
|
||||
group.removeSubscriber("expanded", stage3expanded);
|
||||
|
||||
ok(group.expanded, "The group is now expanded.");
|
||||
let overlay = contentWindow.document.getElementById("expandedTray");
|
||||
let $overlay = contentWindow.iQ(overlay);
|
||||
|
||||
group.addSubscriber("test stage 3", "collapsed", stage3collapsed);
|
||||
group.addSubscriber("collapsed", stage3collapsed);
|
||||
// null type means "click", for some reason...
|
||||
EventUtils.synthesizeMouse(contentWindow.document.body, 10, $overlay.bounds().bottom + 5,
|
||||
{type: null}, contentWindow);
|
||||
};
|
||||
|
||||
let stage3collapsed = function() {
|
||||
group.removeSubscriber("test stage 3", "collapsed", stage3collapsed);
|
||||
group.removeSubscriber("collapsed", stage3collapsed);
|
||||
|
||||
ok(!group.expanded, "The group is no longer expanded.");
|
||||
isnot(expander[0].style.display, "none", "The expander is visible!");
|
||||
@ -176,7 +176,7 @@ function onTabViewWindowLoaded(win) {
|
||||
contentWindow.UI.setActive(originalTabItem);
|
||||
|
||||
// now, try opening it up again.
|
||||
group.addSubscriber("test stage 4", "expanded", stage4expanded);
|
||||
group.addSubscriber("expanded", stage4expanded);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
|
||||
};
|
||||
|
||||
@ -185,7 +185,7 @@ function onTabViewWindowLoaded(win) {
|
||||
// enter Panorama (i.e., zoom into this other group), and make sure we can go to
|
||||
// it and that the tray gets collapsed.
|
||||
let stage4expanded = function() {
|
||||
group.removeSubscriber("test stage 4", "expanded", stage4expanded);
|
||||
group.removeSubscriber("expanded", stage4expanded);
|
||||
|
||||
ok(group.expanded, "The group is now expanded.");
|
||||
is(expander[0].style.display, "none", "The expander is hidden!");
|
||||
@ -231,7 +231,7 @@ function onTabViewWindowLoaded(win) {
|
||||
}
|
||||
|
||||
// get the ball rolling
|
||||
group.addSubscriber("test stage 1", "expanded", stage1expanded);
|
||||
group.addSubscriber("expanded", stage1expanded);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
|
||||
}, win);
|
||||
}
|
||||
|
@ -4,18 +4,16 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
|
||||
let originalGroupItem = null;
|
||||
let originalTab = null;
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item on startup");
|
||||
originalGroupItem = contentWindow.GroupItems.groupItems[0];
|
||||
@ -37,8 +35,8 @@ function testEmptyGroupItem(contentWindow) {
|
||||
is(contentWindow.GroupItems.groupItems.length, ++groupItemCount,
|
||||
"The number of groups is increased by 1");
|
||||
|
||||
emptyGroupItem.addSubscriber(emptyGroupItem, "close", function() {
|
||||
emptyGroupItem.removeSubscriber(emptyGroupItem, "close");
|
||||
emptyGroupItem.addSubscriber("close", function onClose() {
|
||||
emptyGroupItem.removeSubscriber("close", onClose);
|
||||
|
||||
// check the number of groups.
|
||||
is(contentWindow.GroupItems.groupItems.length, --groupItemCount,
|
||||
@ -58,46 +56,27 @@ function testGroupItemWithTabItem(contentWindow) {
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
|
||||
let tabItemCount = 0;
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
is(groupItem.getChildren().length, ++tabItemCount,
|
||||
"The number of children in new tab group is increased by 1");
|
||||
|
||||
ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
|
||||
|
||||
TabView.toggle();
|
||||
};
|
||||
let onTabViewShown = function() {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
|
||||
let tabItem = groupItem.getChild(groupItem.getChildren().length - 1);
|
||||
ok(tabItem, "Tab item exists");
|
||||
|
||||
let tabItemClosed = false;
|
||||
tabItem.addSubscriber(tabItem, "close", function() {
|
||||
tabItem.removeSubscriber(tabItem, "close");
|
||||
tabItem.addSubscriber("close", function onClose() {
|
||||
tabItem.removeSubscriber("close", onClose);
|
||||
tabItemClosed = true;
|
||||
});
|
||||
tabItem.addSubscriber(tabItem, "tabRemoved", function() {
|
||||
tabItem.removeSubscriber(tabItem, "tabRemoved");
|
||||
tabItem.addSubscriber("tabRemoved", function onTabRemoved() {
|
||||
tabItem.removeSubscriber("tabRemoved", onTabRemoved);
|
||||
|
||||
ok(tabItemClosed, "The tab item is closed");
|
||||
is(groupItem.getChildren().length, --tabItemCount,
|
||||
"The number of children in new tab group is decreased by 1");
|
||||
|
||||
|
||||
ok(TabView.isVisible(), "Tab View is still shown");
|
||||
|
||||
// Now there should only be one tab left, so we need to hide TabView
|
||||
// and go into that tab.
|
||||
is(gBrowser.tabs.length, 1, "There is only one tab left");
|
||||
|
||||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", endGame, false);
|
||||
|
||||
// after the last selected tabitem is closed, there would be not active
|
||||
// tabitem on the UI so we set the active tabitem before toggling the
|
||||
@ -106,7 +85,11 @@ function testGroupItemWithTabItem(contentWindow) {
|
||||
ok(tabItems[0], "A tab item exists");
|
||||
contentWindow.UI.setActive(tabItems[0]);
|
||||
|
||||
TabView.toggle();
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
closeGroupItem(groupItem, finish);
|
||||
});
|
||||
});
|
||||
|
||||
// remove the tab item. The code detects mousedown and mouseup so we stimulate here
|
||||
@ -115,15 +98,14 @@ function testGroupItemWithTabItem(contentWindow) {
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, closeButton[0], contentWindow);
|
||||
EventUtils.sendMouseEvent({ type: "mouseup" }, closeButton[0], contentWindow);
|
||||
|
||||
TabView.toggle();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
|
||||
// click on the + button
|
||||
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
|
||||
EventUtils.synthesizeMouse(newTabButton[0], 1, 1, {}, contentWindow);
|
||||
whenTabViewIsHidden(function() {
|
||||
is(groupItem.getChildren().length, ++tabItemCount,
|
||||
"The number of children in new tab group is increased by 1");
|
||||
|
||||
ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
|
||||
showTabView(onTabViewShown);
|
||||
});
|
||||
groupItem.newTab();
|
||||
}
|
||||
|
@ -82,8 +82,8 @@ function testEmptyGroupItem(contentWindow) {
|
||||
}
|
||||
|
||||
// Shut down
|
||||
emptyGroupItem.addSubscriber(emptyGroupItem, "close", function() {
|
||||
emptyGroupItem.removeSubscriber(emptyGroupItem, "close");
|
||||
emptyGroupItem.addSubscriber("close", function onClose() {
|
||||
emptyGroupItem.removeSubscriber("close", onClose);
|
||||
|
||||
// check the number of groups.
|
||||
is(contentWindow.GroupItems.groupItems.length, --groupItemCount,
|
||||
|
@ -31,21 +31,26 @@ function test() {
|
||||
let transitioned = 0;
|
||||
|
||||
let initCallback = function() {
|
||||
tabViewWindow = win.TabView._window;
|
||||
tabViewWindow = win.TabView.getContentWindow();
|
||||
function onTransitionEnd(event) {
|
||||
transitioned++;
|
||||
info(transitioned);
|
||||
}
|
||||
tabViewWindow.document.addEventListener("transitionend", onTransitionEnd, false);
|
||||
|
||||
showTabView(function() {
|
||||
// don't use showTabView() here because we only want to check whether
|
||||
// zoom out animation happens. Other animations would happen before
|
||||
// the callback as waitForFocus() was added to showTabView() in head.js
|
||||
let onTabViewShown = function() {
|
||||
tabViewWindow.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
tabViewWindow.document.removeEventListener("transitionend", onTransitionEnd, false);
|
||||
|
||||
ok(!transitioned, "There should be no transitions");
|
||||
|
||||
tabViewWindow.document.removeEventListener(
|
||||
"transitionend", onTransitionEnd, false);
|
||||
|
||||
finish();
|
||||
}, win);
|
||||
};
|
||||
tabViewWindow.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
win.TabView.toggle();
|
||||
};
|
||||
|
||||
win.TabView._initFrame(initCallback);
|
||||
|
@ -4,50 +4,38 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
registerCleanupFunction(function() {
|
||||
while (gBrowser.tabs[1])
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
hideTabView(function() {});
|
||||
});
|
||||
showTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
let groupItem = contentWindow.GroupItems.groupItem(groupItemId);
|
||||
if (groupItem)
|
||||
closeGroupItem(groupItem, function() {});
|
||||
});
|
||||
|
||||
// create a group item
|
||||
let box = new contentWindow.Rect(20, 400, 300, 300);
|
||||
let groupItem = new contentWindow.GroupItem([], { bounds: box });
|
||||
|
||||
// create a tab item in the new group
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
|
||||
// show tab view
|
||||
TabView.toggle();
|
||||
};
|
||||
let onTabViewShown = function() {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
|
||||
is(groupItem.getChildren().length, 1, "The new group has a tab item");
|
||||
// start the tests
|
||||
waitForFocus(function() {
|
||||
testUndoGroup(contentWindow, groupItem);
|
||||
}, contentWindow);
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
|
||||
// click on the + button
|
||||
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
|
||||
let groupItem = createGroupItemWithBlankTabs(window, 300, 300, 400, 1);
|
||||
groupItemId = groupItem.id;
|
||||
is(groupItem.getChildren().length, 1, "The new group has a tab item");
|
||||
// start the tests
|
||||
waitForFocus(function() {
|
||||
testUndoGroup(contentWindow, groupItem);
|
||||
}, contentWindow);
|
||||
}
|
||||
|
||||
function testUndoGroup(contentWindow, groupItem) {
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
groupItem.addSubscriber("groupHidden", function onHidden() {
|
||||
groupItem.removeSubscriber("groupHidden", onHidden);
|
||||
|
||||
// check the data of the group
|
||||
let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
|
||||
@ -64,8 +52,8 @@ function testUndoGroup(contentWindow, groupItem) {
|
||||
{ type: "click" }, theGroupItem.$undoContainer[0], contentWindow);
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupShown", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupShown");
|
||||
groupItem.addSubscriber("groupShown", function onShown() {
|
||||
groupItem.removeSubscriber("groupShown", onShown);
|
||||
|
||||
// check the data of the group
|
||||
let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
|
||||
@ -87,8 +75,8 @@ function testUndoGroup(contentWindow, groupItem) {
|
||||
}
|
||||
|
||||
function testCloseUndoGroup(contentWindow, groupItem) {
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
groupItem.addSubscriber("groupHidden", function onHidden() {
|
||||
groupItem.removeSubscriber("groupHidden", onHidden);
|
||||
|
||||
// check the data of the group
|
||||
let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
|
||||
@ -107,19 +95,12 @@ function testCloseUndoGroup(contentWindow, groupItem) {
|
||||
{ type: "click" }, closeButton[0], contentWindow);
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, "close", function() {
|
||||
groupItem.removeSubscriber(groupItem, "close");
|
||||
groupItem.addSubscriber("close", function onClose() {
|
||||
groupItem.removeSubscriber("close", onClose);
|
||||
|
||||
let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
|
||||
ok(!theGroupItem, "The group item doesn't exists");
|
||||
|
||||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", endGame, false);
|
||||
|
||||
// after the last selected tabitem is closed, there would be not active
|
||||
// tabitem on the UI so we set the active tabitem before toggling the
|
||||
// visibility of tabview
|
||||
@ -127,7 +108,10 @@ function testCloseUndoGroup(contentWindow, groupItem) {
|
||||
ok(tabItems[0], "A tab item exists");
|
||||
contentWindow.UI.setActive(tabItems[0]);
|
||||
|
||||
TabView.toggle();
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
|
||||
let closeButton = groupItem.container.getElementsByClassName("close");
|
||||
|
@ -32,6 +32,9 @@ function createGroupItemWithTabs(win, width, height, padding, urls, animate) {
|
||||
ok(newItem.container, "Created element "+t+":"+newItem.container);
|
||||
++t;
|
||||
});
|
||||
// to set one of tabItem to be active since we load tabs into a group
|
||||
// in a non-standard flow.
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
@ -45,15 +48,15 @@ function createGroupItemWithBlankTabs(win, width, height, padding, numNewTabs, a
|
||||
|
||||
// ----------
|
||||
function closeGroupItem(groupItem, callback) {
|
||||
groupItem.addSubscriber(groupItem, "close", function () {
|
||||
groupItem.removeSubscriber(groupItem, "close");
|
||||
groupItem.addSubscriber("close", function onClose() {
|
||||
groupItem.removeSubscriber("close", onClose);
|
||||
if ("function" == typeof callback)
|
||||
executeSoon(callback);
|
||||
});
|
||||
|
||||
if (groupItem.getChildren().length) {
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function () {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
groupItem.addSubscriber("groupHidden", function onHide() {
|
||||
groupItem.removeSubscriber("groupHidden", onHide);
|
||||
groupItem.closeHidden();
|
||||
});
|
||||
}
|
||||
@ -133,11 +136,13 @@ function showTabView(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
if (win.TabView.isVisible()) {
|
||||
callback();
|
||||
waitForFocus(callback, win);
|
||||
return;
|
||||
}
|
||||
|
||||
whenTabViewIsShown(callback, win);
|
||||
whenTabViewIsShown(function() {
|
||||
waitForFocus(callback, win);
|
||||
}, win);
|
||||
win.TabView.show();
|
||||
}
|
||||
|
||||
@ -222,8 +227,8 @@ function whenSearchIsEnabled(callback, win) {
|
||||
return;
|
||||
}
|
||||
|
||||
contentWindow.addEventListener("tabviewsearchenabled", function () {
|
||||
contentWindow.removeEventListener("tabviewsearchenabled", arguments.callee, false);
|
||||
contentWindow.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
|
||||
contentWindow.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
|
||||
callback();
|
||||
}, false);
|
||||
}
|
||||
@ -238,8 +243,8 @@ function whenSearchIsDisabled(callback, win) {
|
||||
return;
|
||||
}
|
||||
|
||||
contentWindow.addEventListener("tabviewsearchdisabled", function () {
|
||||
contentWindow.removeEventListener("tabviewsearchdisabled", arguments.callee, false);
|
||||
contentWindow.addEventListener("tabviewsearchdisabled", function onSearchDisabled() {
|
||||
contentWindow.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false);
|
||||
callback();
|
||||
}, false);
|
||||
}
|
||||
@ -252,8 +257,8 @@ function hideGroupItem(groupItem, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function () {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
groupItem.addSubscriber("groupHidden", function onHide() {
|
||||
groupItem.removeSubscriber("groupHidden", onHide);
|
||||
callback();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
@ -266,8 +271,8 @@ function unhideGroupItem(groupItem, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
groupItem.addSubscriber(groupItem, "groupShown", function () {
|
||||
groupItem.removeSubscriber(groupItem, "groupShown");
|
||||
groupItem.addSubscriber("groupShown", function onShown() {
|
||||
groupItem.removeSubscriber("groupShown", onShown);
|
||||
callback();
|
||||
});
|
||||
groupItem._unhide();
|
||||
@ -342,8 +347,8 @@ function restoreTab(callback, index, win) {
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, "reconnected", function onReconnected() {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, "reconnected");
|
||||
tab._tabViewTabItem.addSubscriber("reconnected", function onReconnected() {
|
||||
tab._tabViewTabItem.removeSubscriber("reconnected", onReconnected);
|
||||
finalize();
|
||||
});
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
<html>
|
||||
<script>
|
||||
window.onbeforeunload = function(event){
|
||||
event.returnValue = 'Confirmation? ';
|
||||
}
|
||||
</script>
|
||||
<body>
|
||||
Test page
|
||||
</body>
|
||||
</html>
|
@ -327,6 +327,11 @@
|
||||
gBrowser.loadURIWithFlags(url, flags, null, null, postData);
|
||||
}
|
||||
|
||||
// Focus the content area before triggering loads, since if the load
|
||||
// occurs in a new tab, we want focus to be restored to the content
|
||||
// area when the current tab is re-selected.
|
||||
gBrowser.selectedBrowser.focus();
|
||||
|
||||
if (aTriggeringEvent instanceof MouseEvent) {
|
||||
// We have a mouse event (from the go button), so use the standard
|
||||
// UI link behaviors
|
||||
@ -335,18 +340,12 @@
|
||||
loadCurrent();
|
||||
} else {
|
||||
this.handleRevert();
|
||||
content.focus();
|
||||
openUILinkIn(url, where,
|
||||
{ allowThirdPartyFixup: true, postData: postData });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTriggeringEvent &&
|
||||
aTriggeringEvent.altKey &&
|
||||
!isTabEmpty(gBrowser.selectedTab)) {
|
||||
} else if (aTriggeringEvent && aTriggeringEvent.altKey &&
|
||||
!isTabEmpty(gBrowser.selectedTab)) {
|
||||
this.handleRevert();
|
||||
content.focus();
|
||||
gBrowser.loadOneTab(url, {
|
||||
postData: postData,
|
||||
inBackground: false,
|
||||
@ -356,8 +355,6 @@
|
||||
} else {
|
||||
loadCurrent();
|
||||
}
|
||||
|
||||
gBrowser.selectedBrowser.focus();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
@ -378,9 +378,11 @@ BrowserGlue.prototype = {
|
||||
// Show about:rights notification, if needed.
|
||||
if (this._shouldShowRights()) {
|
||||
this._showRightsNotification();
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
} else {
|
||||
// Only show telemetry notification when about:rights notification is not shown.
|
||||
this._showTelemetryNotification();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -740,6 +742,7 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
_showTelemetryNotification: function BG__showTelemetryNotification() {
|
||||
const PREF_TELEMETRY_PROMPTED = "toolkit.telemetry.prompted";
|
||||
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
|
||||
@ -805,6 +808,7 @@ BrowserGlue.prototype = {
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
},
|
||||
#endif
|
||||
|
||||
_showPluginUpdatePage: function BG__showPluginUpdatePage() {
|
||||
Services.prefs.setBoolPref(PREF_PLUGINS_NOTIFYUSER, false);
|
||||
|
@ -116,18 +116,7 @@ ifndef LIBXUL_SDK
|
||||
INSTALL_SDK = 1
|
||||
endif
|
||||
|
||||
ifneq (1_,$(if $(CROSS_COMPILE),1,0)_$(UNIVERSAL_BINARY))
|
||||
ifdef RUN_TEST_PROGRAM
|
||||
_ABS_RUN_TEST_PROGRAM = $(call core_abspath,$(RUN_TEST_PROGRAM))
|
||||
endif
|
||||
|
||||
GENERATE_CACHE = \
|
||||
$(_ABS_RUN_TEST_PROGRAM) $(LIBXUL_DIST)/bin/xpcshell$(BIN_SUFFIX) -g "$$PWD" -a "$$PWD" -f $(topsrcdir)/browser/installer/precompile_cache.js -e 'populate_startupcache("omni.jar", "startupCache.zip");' && \
|
||||
rm -rf jsloader && \
|
||||
$(UNZIP) startupCache.zip && \
|
||||
rm startupCache.zip && \
|
||||
$(ZIP) -r9m omni.jar jsloader
|
||||
endif
|
||||
GENERATE_CACHE = 1
|
||||
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
||||
|
||||
|
@ -992,7 +992,6 @@ xpicleanup@BIN_SUFFIX@
|
||||
modules/services-sync/type_records/prefs.js
|
||||
modules/services-sync/type_records/tabs.js
|
||||
modules/services-sync/util.js
|
||||
modules/SpatialNavigation.js
|
||||
modules/stylePanel.jsm
|
||||
modules/tabview/AllTabs.jsm
|
||||
modules/tabview/groups.jsm
|
||||
|
@ -18,7 +18,7 @@
|
||||
<!ENTITY useSmoothScrolling.label "Use smooth scrolling">
|
||||
<!ENTITY useSmoothScrolling.accesskey "m">
|
||||
<!ENTITY allowHWAccel.label "Use hardware acceleration when available">
|
||||
<!ENTITY allowHWAccel.accesskey "h">
|
||||
<!ENTITY allowHWAccel.accesskey "r">
|
||||
<!ENTITY checkSpelling.label "Check my spelling as I type">
|
||||
<!ENTITY checkSpelling.accesskey "t">
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
tabview.groupItem.newTabButton=New tab
|
||||
tabview.groupItem.defaultName=Name this tab group…
|
||||
tabview.groupItem.undoCloseGroup=Undo Close Group
|
||||
tabview.search.otherWindowTabs=Tabs from other windows
|
||||
|
@ -79,7 +79,6 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.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/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)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 466 B |
@ -190,7 +190,7 @@ html[dir=rtl] .stack-trayed .tab-title {
|
||||
----------------------------------*/
|
||||
|
||||
.groupItem {
|
||||
cursor: move;
|
||||
cursor: pointer;
|
||||
border: 1px solid rgba(230,230,230,1);
|
||||
background-color: window;
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.1));
|
||||
@ -385,25 +385,6 @@ html[dir=rtl] .guideTrench {
|
||||
/* Other
|
||||
----------------------------------*/
|
||||
|
||||
.newTabButton {
|
||||
width: 16px;
|
||||
height: 15px;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
cursor: pointer;
|
||||
opacity: .3;
|
||||
background-image: url(chrome://browser/skin/tabview/new-tab.png);
|
||||
}
|
||||
|
||||
html[dir=rtl] .newTabButton {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.newTabButton:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active {
|
||||
box-shadow: 5px 5px 3px rgba(0,0,0,.5);
|
||||
}
|
||||
@ -421,6 +402,7 @@ html[dir=rtl] .acceptsDrop {
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
cursor: move;
|
||||
font-size: 12px;
|
||||
height: 18px;
|
||||
}
|
||||
|
@ -117,7 +117,6 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/tabview/close.png (tabview/close.png)
|
||||
skin/classic/browser/tabview/edit-light.png (tabview/edit-light.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)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 466 B |
@ -191,7 +191,7 @@ html[dir=rtl] .stack-trayed .tab-title {
|
||||
----------------------------------*/
|
||||
|
||||
.groupItem {
|
||||
cursor: move;
|
||||
cursor: pointer;
|
||||
background-color: rgb(240,240,240);
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
|
||||
@ -376,25 +376,6 @@ html[dir=rtl] .guideTrench {
|
||||
/* Other
|
||||
----------------------------------*/
|
||||
|
||||
.newTabButton {
|
||||
width: 16px;
|
||||
height: 15px;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
cursor: pointer;
|
||||
opacity: .3;
|
||||
background-image: url(chrome://browser/skin/tabview/new-tab.png);
|
||||
}
|
||||
|
||||
html[dir=rtl] .newTabButton {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.newTabButton:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active {
|
||||
box-shadow: 5px 5px 3px rgba(0,0,0,.5);
|
||||
}
|
||||
@ -412,6 +393,7 @@ html[dir=rtl] .acceptsDrop {
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
cursor: move;
|
||||
font-size: 12px;
|
||||
height: 18px;
|
||||
}
|
||||
|
BIN
browser/themes/winstripe/browser/Toolbar-inverted.png
Normal file
BIN
browser/themes/winstripe/browser/Toolbar-inverted.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
@ -138,6 +138,13 @@
|
||||
border-right-style: none !important;
|
||||
}
|
||||
|
||||
#toolbar-menubar :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme),
|
||||
#TabsToolbar[tabsontop=true] :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme),
|
||||
#navigator-toolbox[tabsontop=false] > #nav-bar :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme),
|
||||
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme) {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
|
||||
}
|
||||
|
||||
/* Vertical toolbar border */
|
||||
#main-window[sizemode=normal] #navigator-toolbox::after,
|
||||
#main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > toolbar:not(#toolbar-menubar):not(#TabsToolbar),
|
||||
|
@ -57,6 +57,7 @@
|
||||
%define bgTabTexture -moz-linear-gradient(transparent, hsla(0,0%,45%,.1) 1px, hsla(0,0%,32%,.2) 80%, hsla(0,0%,0%,.2))
|
||||
%define bgTabTextureHover -moz-linear-gradient(hsla(0,0%,100%,.3) 1px, hsla(0,0%,75%,.2) 80%, hsla(0,0%,60%,.2))
|
||||
%define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32);
|
||||
%define navbarLargeIcons #navigator-toolbox[iconsize=large][mode=icons] > #nav-bar
|
||||
|
||||
#menubar-items {
|
||||
-moz-box-orient: vertical; /* for flex hack */
|
||||
@ -582,6 +583,10 @@ menuitem.bookmark-item {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
}
|
||||
|
||||
.toolbarbutton-1:-moz-lwtheme-brighttext {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
|
||||
}
|
||||
|
||||
.toolbarbutton-1:not([type="menu-button"]) {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
@ -596,19 +601,18 @@ menuitem.bookmark-item {
|
||||
counter-reset: smallicons;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize=small] > #nav-bar {
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize=large][mode=icons] > #nav-bar {
|
||||
@navbarLargeIcons@ {
|
||||
-moz-padding-start: 0;
|
||||
-moz-padding-end: 2px;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
|
||||
#nav-bar .toolbarbutton-1 {
|
||||
@navbarLargeIcons@ :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png") !important;
|
||||
}
|
||||
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button,
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
|
||||
@navbarLargeIcons@ .toolbarbutton-1 {
|
||||
-moz-appearance: none;
|
||||
padding: 1px 5px;
|
||||
background: rgba(151,152,153,.05)
|
||||
@ -624,14 +628,12 @@ menuitem.bookmark-item {
|
||||
text-shadow: 0 0 2px white;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
|
||||
#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
|
||||
#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1[type="menu-button"] {
|
||||
@navbarLargeIcons@ .toolbarbutton-1[type="menu-button"] {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
background: none !important;
|
||||
@ -639,44 +641,39 @@ menuitem.bookmark-item {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 {
|
||||
margin: 1px 3px;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||
-moz-border-start-style: none;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr),
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr),
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl),
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl),
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1[disabled="true"] {
|
||||
@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon {
|
||||
@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
|
||||
#nav-bar .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
|
||||
#nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover,
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
|
||||
@navbarLargeIcons@ .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
|
||||
@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover,
|
||||
@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon {
|
||||
background-color: hsla(190,60%,70%,.5);
|
||||
border-color: hsla(190,50%,65%,.8) hsla(190,50%,50%,.8) hsla(190,50%,40%,.8);
|
||||
box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
|
||||
@ -687,12 +684,12 @@ menuitem.bookmark-item {
|
||||
box-shadow .3s ease-in;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
|
||||
#nav-bar .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
|
||||
#nav-bar .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker,
|
||||
#nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active,
|
||||
#nav-bar .toolbarbutton-1:not([type="menu-button"])[checked="true"],
|
||||
#nav-bar .toolbarbutton-1[open="true"] {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
|
||||
@navbarLargeIcons@ .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
|
||||
@navbarLargeIcons@ .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker,
|
||||
@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active,
|
||||
@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"])[checked="true"],
|
||||
@navbarLargeIcons@ .toolbarbutton-1[open="true"] {
|
||||
background-color: transparent;
|
||||
border-color: rgba(0,0,0,.65) rgba(0,0,0,.55) rgba(0,0,0,.5);
|
||||
box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
|
||||
@ -701,7 +698,7 @@ menuitem.bookmark-item {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1[checked="true"]:not(:active):hover {
|
||||
@navbarLargeIcons@ .toolbarbutton-1[checked="true"]:not(:active):hover {
|
||||
background-color: rgba(90%,90%,90%,.4);
|
||||
-moz-transition: background-color .4s;
|
||||
}
|
||||
@ -711,8 +708,8 @@ menuitem.bookmark-item {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon {
|
||||
@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
@navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon {
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
@ -764,37 +761,31 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
-moz-image-region: rect(0, 36px, 18px, 18px);
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
|
||||
-moz-image-region: rect(18px, 20px, 38px, 0);
|
||||
}
|
||||
|
||||
#back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
|
||||
#forward-button:-moz-locale-dir(rtl),
|
||||
#forward-button:-moz-locale-dir(rtl) > .toolbarbutton-text {
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
#nav-bar #back-button {
|
||||
-moz-margin-end: 0 !important;
|
||||
}
|
||||
|
||||
#nav-bar #forward-button {
|
||||
@navbarLargeIcons@ #forward-button {
|
||||
border-left-style: none;
|
||||
-moz-margin-start: 0 !important;
|
||||
}
|
||||
|
||||
#nav-bar #back-button:-moz-locale-dir(ltr) {
|
||||
@navbarLargeIcons@ #back-button:-moz-locale-dir(ltr) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
#nav-bar #back-button:-moz-locale-dir(rtl),
|
||||
#nav-bar #forward-button {
|
||||
@navbarLargeIcons@ #back-button:-moz-locale-dir(rtl),
|
||||
@navbarLargeIcons@ #forward-button {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
|
||||
@navbarLargeIcons@ #back-button {
|
||||
-moz-image-region: rect(18px, 20px, 38px, 0);
|
||||
-moz-margin-end: 0 !important;
|
||||
margin: -5px 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
@ -808,11 +799,11 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-locale-dir(rtl) {
|
||||
@navbarLargeIcons@ #back-button:-moz-locale-dir(rtl) {
|
||||
border-radius: 10000px 0 0 10000px;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button > .toolbarbutton-icon {
|
||||
@navbarLargeIcons@ #back-button > .toolbarbutton-icon {
|
||||
border-radius: 10000px;
|
||||
padding: 5px;
|
||||
border: none;
|
||||
@ -825,7 +816,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
0 1px 1px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
|
||||
@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
|
||||
box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
|
||||
0 0 0 2px rgba(255,255,255,.1) inset,
|
||||
0 0 0 1px hsla(190,50%,40%,.3),
|
||||
@ -834,16 +825,16 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
0 0 5px 1px hsl(190,90%,80%);
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button[open="true"] > .toolbarbutton-icon {
|
||||
@navbarLargeIcons@ #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
|
||||
@navbarLargeIcons@ #back-button[open="true"] > .toolbarbutton-icon {
|
||||
box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
|
||||
0 0 2px rgba(0,0,0,.4) inset,
|
||||
0 0 0 1px rgba(0,0,0,.65),
|
||||
0 2px 0 rgba(255,255,255,.4);
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar[currentset*="unified-back-forward-button"],
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar:not([currentset]) {
|
||||
@navbarLargeIcons@[currentset*="unified-back-forward-button"],
|
||||
@navbarLargeIcons@:not([currentset]) {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
@ -853,7 +844,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button {
|
||||
@navbarLargeIcons@ #forward-button {
|
||||
/*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
|
||||
mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask);
|
||||
-moz-margin-start: -6px !important;
|
||||
@ -861,7 +852,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:not([disabled="true"]):not(:active):hover {
|
||||
@navbarLargeIcons@ #forward-button:not([disabled="true"]):not(:active):hover {
|
||||
/*mask: url(keyhole-forward-mask.svg#mask-hover);*/
|
||||
mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask-hover);
|
||||
/* Don't animate the box shadow, as the blur and spread radii affect the mask. */
|
||||
@ -895,6 +886,9 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
#home-button.bookmark-item {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
}
|
||||
#home-button.bookmark-item:-moz-lwtheme-brighttext {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
|
||||
}
|
||||
#home-button {
|
||||
-moz-image-region: rect(0, 90px, 18px, 72px);
|
||||
}
|
||||
@ -969,6 +963,10 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
}
|
||||
|
||||
#bookmarks-menu-button.bookmark-item:-moz-lwtheme-brighttext {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
|
||||
}
|
||||
|
||||
#bookmarks-menu-button.toolbarbutton-1 {
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ browser.jar:
|
||||
skin/classic/browser/reload-stop-go.png
|
||||
skin/classic/browser/Secure24.png (Secure24.png)
|
||||
skin/classic/browser/Toolbar.png (Toolbar.png)
|
||||
skin/classic/browser/Toolbar-inverted.png
|
||||
skin/classic/browser/Go-arrow.png (Go-arrow.png)
|
||||
* skin/classic/browser/searchbar.css (searchbar.css)
|
||||
skin/classic/browser/section_collapsed.png
|
||||
@ -96,7 +97,6 @@ browser.jar:
|
||||
skin/classic/browser/tabview/close.png (tabview/close.png)
|
||||
skin/classic/browser/tabview/edit-light.png (tabview/edit-light.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)
|
||||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
@ -149,6 +149,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/reload-stop-go.png
|
||||
skin/classic/aero/browser/Secure24.png (Secure24-aero.png)
|
||||
skin/classic/aero/browser/Toolbar.png
|
||||
skin/classic/aero/browser/Toolbar-inverted.png
|
||||
skin/classic/aero/browser/Go-arrow.png (Go-arrow-aero.png)
|
||||
* skin/classic/aero/browser/searchbar.css (searchbar.css)
|
||||
skin/classic/aero/browser/section_collapsed.png
|
||||
@ -211,7 +212,6 @@ browser.jar:
|
||||
skin/classic/aero/browser/tabview/close.png (tabview/close.png)
|
||||
skin/classic/aero/browser/tabview/edit-light.png (tabview/edit-light.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)
|
||||
skin/classic/aero/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/aero/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 466 B |
@ -204,7 +204,7 @@ html[dir=rtl] .tab.focus {
|
||||
----------------------------------*/
|
||||
|
||||
.groupItem {
|
||||
cursor: move;
|
||||
cursor: pointer;
|
||||
background-color: #E0EAF5;
|
||||
border-radius: 0.4em;
|
||||
box-shadow:
|
||||
@ -398,25 +398,6 @@ html[dir=rtl] .guideTrench {
|
||||
/* Other
|
||||
----------------------------------*/
|
||||
|
||||
.newTabButton {
|
||||
width: 16px;
|
||||
height: 15px;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
cursor: pointer;
|
||||
opacity: .3;
|
||||
background-image: url(chrome://browser/skin/tabview/new-tab.png);
|
||||
}
|
||||
|
||||
html[dir=rtl] .newTabButton {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.newTabButton:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active {
|
||||
box-shadow: 5px 5px 3px rgba(0,0,0,.5);
|
||||
}
|
||||
@ -434,6 +415,7 @@ html[dir=rtl] .acceptsDrop {
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
cursor: move;
|
||||
font-size: 12px;
|
||||
height: 18px;
|
||||
}
|
||||
|
2
build/autoconf/config.sub
vendored
2
build/autoconf/config.sub
vendored
@ -1433,7 +1433,7 @@ case $os in
|
||||
os=-dicos
|
||||
;;
|
||||
-android*)
|
||||
os=android
|
||||
os=-android
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
|
@ -1,16 +1,30 @@
|
||||
import subprocess
|
||||
from devicemanager import DeviceManager, DMError
|
||||
import re
|
||||
import os
|
||||
|
||||
class DeviceManagerADB(DeviceManager):
|
||||
|
||||
def __init__(self, host = None, port = 20701, retrylimit = 5):
|
||||
def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.retrylimit = retrylimit
|
||||
self.retries = 0
|
||||
self._sock = None
|
||||
self.getDeviceRoot()
|
||||
self.Init(packageName)
|
||||
|
||||
def Init(self, packageName):
|
||||
# Initialization code that may fail: Catch exceptions here to allow
|
||||
# successful initialization even if, for example, adb is not installed.
|
||||
try:
|
||||
root = self.getDeviceRoot()
|
||||
self.verifyPackage(packageName)
|
||||
self.tmpDir = root + "/tmp"
|
||||
if (not self.dirExists(self.tmpDir)):
|
||||
self.mkDir(self.tmpDir)
|
||||
except:
|
||||
self.packageName = None
|
||||
self.tmpDir = None
|
||||
try:
|
||||
# a test to see if we have root privs
|
||||
self.checkCmd(["shell", "ls", "/sbin"])
|
||||
@ -26,7 +40,17 @@ class DeviceManagerADB(DeviceManager):
|
||||
# failure: False
|
||||
def pushFile(self, localname, destname):
|
||||
try:
|
||||
self.checkCmd(["push", localname, destname])
|
||||
if (os.name == "nt"):
|
||||
destname = destname.replace('\\', '/')
|
||||
if (self.packageName):
|
||||
remoteTmpFile = self.tmpDir + "/" + os.path.basename(localname)
|
||||
self.checkCmd(["push", os.path.realpath(localname), remoteTmpFile])
|
||||
self.checkCmdAs(["shell", "cp", remoteTmpFile, destname])
|
||||
self.checkCmd(["shell", "rm", remoteTmpFile])
|
||||
else:
|
||||
self.checkCmd(["push", os.path.realpath(localname), destname])
|
||||
if (self.isDir(destname)):
|
||||
destname = destname + "/" + os.path.basename(localname)
|
||||
self.chmodDir(destname)
|
||||
return True
|
||||
except:
|
||||
@ -38,7 +62,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
# failure: None
|
||||
def mkDir(self, name):
|
||||
try:
|
||||
self.checkCmd(["shell", "mkdir", name])
|
||||
self.checkCmdAs(["shell", "mkdir", name])
|
||||
self.chmodDir(name)
|
||||
return name
|
||||
except:
|
||||
@ -50,8 +74,17 @@ class DeviceManagerADB(DeviceManager):
|
||||
# success: directory structure that we created
|
||||
# failure: None
|
||||
def mkDirs(self, filename):
|
||||
self.checkCmd(["shell", "mkdir", "-p ", name])
|
||||
return filename
|
||||
parts = filename.split('/')
|
||||
name = ""
|
||||
for part in parts:
|
||||
if (part == parts[-1]): break
|
||||
if (part != ""):
|
||||
name += '/' + part
|
||||
if (not self.dirExists(name)):
|
||||
if (self.mkDir(name) == None):
|
||||
print "failed making directory: " + str(name)
|
||||
return None
|
||||
return name
|
||||
|
||||
# push localDir from host to remoteDir on the device
|
||||
# external function
|
||||
@ -59,9 +92,29 @@ class DeviceManagerADB(DeviceManager):
|
||||
# success: remoteDir
|
||||
# failure: None
|
||||
def pushDir(self, localDir, remoteDir):
|
||||
# adb "push" accepts a directory as an argument, but if the directory
|
||||
# contains symbolic links, the links are pushed, rather than the linked
|
||||
# files; we push file-by-file to get around this limitation
|
||||
try:
|
||||
self.checkCmd(["push", localDir, remoteDir])
|
||||
self.chmodDir(remoteDir)
|
||||
if (not self.dirExists(remoteDir)):
|
||||
self.mkDirs(remoteDir+"/x")
|
||||
for root, dirs, files in os.walk(localDir):
|
||||
relRoot = os.path.relpath(root, localDir)
|
||||
for file in files:
|
||||
localFile = os.path.join(root, file)
|
||||
remoteFile = remoteDir + "/"
|
||||
if (relRoot!="."):
|
||||
remoteFile = remoteFile + relRoot + "/"
|
||||
remoteFile = remoteFile + file
|
||||
self.pushFile(localFile, remoteFile)
|
||||
for dir in dirs:
|
||||
targetDir = remoteDir + "/"
|
||||
if (relRoot!="."):
|
||||
targetDir = targetDir + relRoot + "/"
|
||||
targetDir = targetDir + dir
|
||||
if (not self.dirExists(targetDir)):
|
||||
self.mkDir(targetDir)
|
||||
self.checkCmdAs(["shell", "chmod", "777", remoteDir])
|
||||
return True
|
||||
except:
|
||||
print "pushing " + localDir + " to " + remoteDir + " failed"
|
||||
@ -72,11 +125,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
# success: True
|
||||
# failure: False
|
||||
def dirExists(self, dirname):
|
||||
try:
|
||||
self.checkCmd(["shell", "ls", dirname])
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
return self.isDir(dirname)
|
||||
|
||||
# Because we always have / style paths we make this a lot easier with some
|
||||
# assumptions
|
||||
@ -112,19 +161,19 @@ class DeviceManagerADB(DeviceManager):
|
||||
if (self.isDir(remoteDir.strip() + "/" + f.strip())):
|
||||
out += self.removeDir(remoteDir.strip() + "/" + f.strip())
|
||||
else:
|
||||
out += self.removeFile(remoteDir.strip())
|
||||
out += self.removeSingleDir(remoteDir)
|
||||
out += self.removeFile(remoteDir.strip() + "/" + f.strip())
|
||||
out += self.removeSingleDir(remoteDir.strip())
|
||||
else:
|
||||
out += self.removeFile(remoteDir.strip())
|
||||
return out
|
||||
|
||||
def isDir(self, remotePath):
|
||||
p = self.runCmd(["shell", "ls", remotePath])
|
||||
p = self.runCmd(["shell", "ls", "-a", remotePath])
|
||||
data = p.stdout.readlines()
|
||||
if (len(data) == 0):
|
||||
return True
|
||||
if (len(data) == 1):
|
||||
if (data[0] == remotePath):
|
||||
if (data[0].rstrip() == remotePath):
|
||||
return False
|
||||
if (data[0].find("No such file or directory") != -1):
|
||||
return False
|
||||
@ -133,7 +182,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
return True
|
||||
|
||||
def listFiles(self, rootdir):
|
||||
p = self.runCmd(["shell", "ls", rootdir])
|
||||
p = self.runCmd(["shell", "ls", "-a", rootdir])
|
||||
data = p.stdout.readlines()
|
||||
if (len(data) == 1):
|
||||
if (data[0] == rootdir):
|
||||
@ -165,7 +214,11 @@ class DeviceManagerADB(DeviceManager):
|
||||
# success: pid
|
||||
# failure: None
|
||||
def fireProcess(self, appname, failIfRunning=False):
|
||||
return self.runCmd(["shell", appname]).pid
|
||||
#strip out env vars
|
||||
parts = appname.split('"');
|
||||
if (len(parts) > 2):
|
||||
parts = parts[2:]
|
||||
return self.launchProcess(parts, failIfRunning)
|
||||
|
||||
# external function
|
||||
# returns:
|
||||
@ -173,7 +226,7 @@ class DeviceManagerADB(DeviceManager):
|
||||
# failure: None
|
||||
def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
|
||||
acmd = ["shell", "am","start"]
|
||||
cmd = ' '.join(cmd)
|
||||
cmd = ' '.join(cmd).strip()
|
||||
i = cmd.find(" ")
|
||||
acmd.append("-n")
|
||||
acmd.append(cmd[0:i] + "/.App")
|
||||
@ -299,9 +352,18 @@ class DeviceManagerADB(DeviceManager):
|
||||
# success: path for device root
|
||||
# failure: None
|
||||
def getDeviceRoot(self):
|
||||
if (not self.dirExists("/data/local/tests")):
|
||||
self.mkDir("/data/local/tests")
|
||||
return "/data/local/tests"
|
||||
# /mnt/sdcard/tests is preferred to /data/local/tests, but this can be
|
||||
# over-ridden by creating /data/local/tests
|
||||
testRoot = "/data/local/tests"
|
||||
if (self.dirExists(testRoot)):
|
||||
return testRoot
|
||||
root = "/mnt/sdcard"
|
||||
if (not self.dirExists(root)):
|
||||
root = "/data/local"
|
||||
testRoot = root + "/tests"
|
||||
if (not self.dirExists(testRoot)):
|
||||
self.mkDir(testRoot)
|
||||
return testRoot
|
||||
|
||||
# Either we will have /tests/fennec or /tests/firefox but we will never have
|
||||
# both. Return the one that exists
|
||||
@ -319,10 +381,16 @@ class DeviceManagerADB(DeviceManager):
|
||||
return devroot + '/fennec'
|
||||
elif (self.dirExists(devroot + '/firefox')):
|
||||
return devroot + '/firefox'
|
||||
elif (self.dirExsts('/data/data/org.mozilla.fennec')):
|
||||
return 'org.mozilla.fennec'
|
||||
elif (self.dirExists('/data/data/org.mozilla.fennec')):
|
||||
return '/data/data/org.mozilla.fennec'
|
||||
elif (self.dirExists('/data/data/org.mozilla.firefox')):
|
||||
return 'org.mozilla.firefox'
|
||||
return '/data/data/org.mozilla.firefox'
|
||||
elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
|
||||
return '/data/data/org.mozilla.fennec_unofficial'
|
||||
elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
|
||||
return '/data/data/org.mozilla.fennec_aurora'
|
||||
elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
|
||||
return '/data/data/org.mozilla.firefox_beta'
|
||||
|
||||
# Failure (either not installed or not a recognized platform)
|
||||
return None
|
||||
@ -423,18 +491,34 @@ class DeviceManagerADB(DeviceManager):
|
||||
args.insert(0, "adb")
|
||||
return subprocess.check_call(args)
|
||||
|
||||
def checkCmdAs(self, args):
|
||||
if (self.packageName):
|
||||
args.insert(1, "run-as")
|
||||
args.insert(2, self.packageName)
|
||||
return self.checkCmd(args)
|
||||
|
||||
def chmodDir(self, remoteDir):
|
||||
print "called chmodDir"
|
||||
if (self.isDir(remoteDir)):
|
||||
files = self.listFiles(remoteDir.strip())
|
||||
for f in files:
|
||||
if (self.isDir(remoteDir.strip() + "/" + f.strip())):
|
||||
self.chmodDir(remoteDir.strip() + "/" + f.strip())
|
||||
else:
|
||||
self.checkCmd(["shell", "chmod", "777", remoteDir.strip()])
|
||||
self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
|
||||
print "chmod " + remoteDir.strip()
|
||||
self.checkCmd(["shell", "chmod", "777", remoteDir])
|
||||
self.checkCmdAs(["shell", "chmod", "777", remoteDir])
|
||||
print "chmod " + remoteDir
|
||||
else:
|
||||
self.checkCmd(["shell", "chmod", "777", remoteDir.strip()])
|
||||
print "chmod " + remoteDir
|
||||
self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
|
||||
print "chmod " + remoteDir.strip()
|
||||
|
||||
def verifyPackage(self, packageName):
|
||||
# If a valid package name is specified, it will be used for certain
|
||||
# file operations, so that pushed files and directories are created
|
||||
# by the uid associated with the package.
|
||||
self.packageName = None
|
||||
if (packageName):
|
||||
data = self.runCmd(["shell", "run-as", packageName, "pwd"]).stdout.read()
|
||||
if (not re.search('is unknown', data)):
|
||||
self.packageName = packageName
|
||||
print "package set: " + self.packageName
|
||||
|
@ -64,24 +64,11 @@ if __name__ == '__main__':
|
||||
from optparse import OptionParser
|
||||
automation = Automation()
|
||||
|
||||
parser = OptionParser(usage='OBJDIR=path/to/objdir python %prog [NUM_RUNS]')
|
||||
parser = OptionParser()
|
||||
addCommonOptions(parser)
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if not os.getenv('OBJDIR'):
|
||||
parser.error('Please specify the OBJDIR environment variable.')
|
||||
|
||||
if not args:
|
||||
num_runs = 1
|
||||
else:
|
||||
try:
|
||||
num_runs = int(args[0])
|
||||
except:
|
||||
parser.error('NUM_RUNS argument must be an integer.')
|
||||
if num_runs < 1:
|
||||
parser.error('NUM_RUNS must be greater than zero.')
|
||||
|
||||
debuggerInfo = getDebuggerInfo(".", options.debugger, options.debuggerArgs,
|
||||
options.debuggerInteractive)
|
||||
|
||||
@ -91,21 +78,16 @@ if __name__ == '__main__':
|
||||
t.start()
|
||||
|
||||
automation.setServerInfo("localhost", PORT)
|
||||
automation.initializeProfile(PROFILE_DIRECTORY)
|
||||
browserEnv = automation.environment()
|
||||
browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
|
||||
browserEnv["MOZ_JAR_LOG_DIR"] = MOZ_JAR_LOG_DIR
|
||||
|
||||
url = "http://localhost:%d/index.html" % PORT
|
||||
appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
|
||||
|
||||
for i in range(0, num_runs):
|
||||
if num_runs != 1:
|
||||
print "Starting profiling run %d of %d" % (i + 1, num_runs)
|
||||
automation.initializeProfile(PROFILE_DIRECTORY)
|
||||
status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
|
||||
debuggerInfo=debuggerInfo,
|
||||
# the profiling HTML doesn't output anything,
|
||||
# so let's just run this without a timeout
|
||||
timeout = None)
|
||||
if status != 0:
|
||||
sys.exit(status)
|
||||
status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
|
||||
debuggerInfo=debuggerInfo,
|
||||
# the profiling HTML doesn't output anything,
|
||||
# so let's just run this without a timeout
|
||||
timeout = None)
|
||||
sys.exit(status)
|
||||
|
@ -91,7 +91,6 @@
|
||||
#include "nsIURIFixup.h"
|
||||
#include "nsCDefaultURIFixup.h"
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user