Merge mozilla-central to tracemonkey.

This commit is contained in:
Robert Sayre 2010-09-19 15:59:10 -04:00
Родитель 52e7bc13b8 aca937ac81
Коммит 69238bc33b
1479 изменённых файлов: 44388 добавлений и 38666 удалений

Просмотреть файл

@ -93,7 +93,7 @@ nsIAtom *nsDocAccessible::gLastFocusedFrameType = nsnull;
nsDocAccessible::
nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
nsIWeakReference *aShell) :
nsHyperTextAccessibleWrap(aRootContent, aShell), mWnd(nsnull),
nsHyperTextAccessibleWrap(aRootContent, aShell),
mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE)
{
// XXX aaronl should we use an algorithm for the initial cache size?
@ -103,17 +103,6 @@ nsDocAccessible::
if (!mDocument)
return;
// Initialize mWnd
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
nsIViewManager* vm = shell->GetViewManager();
if (vm) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget) {
mWnd = widget->GetNativeData(NS_NATIVE_WINDOW);
}
}
// nsAccDocManager creates document accessible when scrollable frame is
// available already, it should be safe time to add scroll listener.
AddScrollListener();
@ -473,7 +462,8 @@ NS_IMETHODIMP nsDocAccessible::GetNameSpaceURIForID(PRInt16 aNameSpaceID, nsAStr
NS_IMETHODIMP nsDocAccessible::GetWindowHandle(void **aWindow)
{
*aWindow = mWnd;
NS_ENSURE_ARG_POINTER(aWindow);
*aWindow = GetNativeWindow();
return NS_OK;
}
@ -1335,6 +1325,20 @@ nsDocAccessible::HandleAccEvent(AccEvent* aAccEvent)
////////////////////////////////////////////////////////////////////////////////
// Public members
void*
nsDocAccessible::GetNativeWindow() const
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
nsIViewManager* vm = shell->GetViewManager();
if (vm) {
nsCOMPtr<nsIWidget> widget;
vm->GetRootWidget(getter_AddRefs(widget));
if (widget)
return widget->GetNativeData(NS_NATIVE_WINDOW);
}
return nsnull;
}
nsAccessible*
nsDocAccessible::GetCachedAccessibleInSubtree(void* aUniqueID)
{

Просмотреть файл

@ -141,6 +141,11 @@ public:
*/
void MarkAsLoaded() { mIsLoaded = PR_TRUE; }
/**
* Return a native window handler or pointer depending on platform.
*/
virtual void* GetNativeWindow() const;
/**
* Return the parent document.
*/
@ -363,7 +368,6 @@ protected:
*/
nsAccessibleHashtable mAccessibleCache;
void *mWnd;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsITimer> mScrollWatchTimer;
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events

Просмотреть файл

@ -594,9 +594,13 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
nsAccessibleWrap *accWrap = static_cast<nsAccessibleWrap*>(mGeckoAccessible);
// Get a pointer to the native window (NSWindow) we reside in.
NSWindow *nativeWindow = nil;
accWrap->GetNativeWindow ((void**)&nativeWindow);
nsDocAccessible* docAcc = accWrap->GetDocAccessible();
if (docAcc)
nativeWindow = static_cast<NSWindow*>(docAcc->GetNativeWindow());
NSAssert1(nativeWindow, @"Could not get native window for %@", self);
return nativeWindow;

Просмотреть файл

@ -71,10 +71,7 @@ class nsAccessibleWrap : public nsAccessible
// should be instantied with. used on runtime to determine the
// right type for this accessible's associated native object.
virtual objc_class* GetNativeType ();
// returns a pointer to the native window for this accessible tree.
void GetNativeWindow (void **aOutNativeWindow);
virtual void Shutdown ();
virtual void InvalidateChildren();

Просмотреть файл

@ -86,17 +86,6 @@ nsAccessibleWrap::GetNativeInterface (void **aOutInterface)
return NS_ERROR_FAILURE;
}
// get the native NSWindow we reside in.
void
nsAccessibleWrap::GetNativeWindow (void **aOutNativeWindow)
{
*aOutNativeWindow = nsnull;
nsDocAccessible *docAcc = GetDocAccessible();
if (docAcc)
docAcc->GetWindowHandle (aOutNativeWindow);
}
// overridden in subclasses to create the right kind of object. by default we create a generic
// 'mozAccessible' node.
objc_class*

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsApplicationAccessibleWrap.h"
#include "nsCoreUtils.h"
#include "nsRootAccessible.h"
#include "nsWinUtils.h"
#include "nsAttrName.h"
#include "nsIDocument.h"
@ -63,6 +64,7 @@
HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
LPFNLRESULTFROMOBJECT nsAccessNodeWrap::gmLresultFromObject = NULL;
LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
@ -569,7 +571,14 @@ void nsAccessNodeWrap::InitAccessibility()
}
DoATSpecificProcessing();
// Register window class that'll be used for document accessibles associated
// with tabs.
if (nsWinUtils::IsWindowEmulationEnabled()) {
nsWinUtils::RegisterNativeWindow(kClassNameTabContent);
sHWNDCache.Init(4);
}
nsAccessNode::InitXPAccessibility();
}
@ -578,6 +587,11 @@ void nsAccessNodeWrap::ShutdownAccessibility()
NS_IF_RELEASE(gTextEvent);
::DestroyCaret();
// Unregister window call that's used for document accessibles associated
// with tabs.
if (nsWinUtils::IsWindowEmulationEnabled())
::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
nsAccessNode::ShutdownXPAccessibility();
}
@ -624,7 +638,7 @@ GetHRESULT(nsresult aResult)
PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
{
HMODULE jhookhandle = ::GetModuleHandleW(L"jhook");
HMODULE jhookhandle = ::GetModuleHandleW(kJAWSModuleHandle);
if (!jhookhandle)
return PR_FALSE; // No JAWS, or some other screen reader, use IA2
@ -655,10 +669,10 @@ PRBool nsAccessNodeWrap::IsOnlyMsaaCompatibleJawsPresent()
void nsAccessNodeWrap::TurnOffNewTabSwitchingForJawsAndWE()
{
HMODULE srHandle = ::GetModuleHandleW(L"jhook");
HMODULE srHandle = ::GetModuleHandleW(kJAWSModuleHandle);
if (!srHandle) {
// No JAWS, try Window-Eyes
srHandle = ::GetModuleHandleW(L"gwm32inc");
srHandle = ::GetModuleHandleW(kWEModuleHandle);
if (!srHandle) {
// no screen reader we're interested in. Bail out.
return;
@ -694,3 +708,49 @@ void nsAccessNodeWrap::DoATSpecificProcessing()
TurnOffNewTabSwitchingForJawsAndWE();
}
nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> nsAccessNodeWrap::sHWNDCache;
LRESULT CALLBACK
nsAccessNodeWrap::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_GETOBJECT:
{
if (lParam == OBJID_CLIENT) {
nsDocAccessible* document = sHWNDCache.GetWeak(static_cast<void*>(hWnd));
if (document) {
IAccessible* msaaAccessible = NULL;
document->GetNativeInterface((void**)&msaaAccessible); // does an addref
if (msaaAccessible) {
LRESULT result = LresultFromObject(IID_IAccessible, wParam,
msaaAccessible); // does an addref
msaaAccessible->Release(); // release extra addref
return result;
}
}
}
return 0;
}
}
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}
STDMETHODIMP_(LRESULT)
nsAccessNodeWrap::LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc)
{
// open the dll dynamically
if (!gmAccLib)
gmAccLib =::LoadLibraryW(L"OLEACC.DLL");
if (gmAccLib) {
if (!gmLresultFromObject)
gmLresultFromObject = (LPFNLRESULTFROMOBJECT)GetProcAddress(gmAccLib,"LresultFromObject");
if (gmLresultFromObject)
return gmLresultFromObject(riid, wParam, pAcc);
}
return 0;
}

Просмотреть файл

@ -68,6 +68,8 @@
#include "nsICrashReporter.h"
#endif
#include "nsRefPtrHashtable.h"
typedef LRESULT (STDAPICALLTYPE *LPFNNOTIFYWINEVENT)(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
typedef LRESULT (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD idThread, GUITHREADINFO* pgui);
@ -154,6 +156,7 @@ public: // construction, destruction
static HINSTANCE gmAccLib;
static HINSTANCE gmUserLib;
static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
static LPFNLRESULTFROMOBJECT gmLresultFromObject;
static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
@ -165,6 +168,13 @@ public: // construction, destruction
static void DoATSpecificProcessing();
static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,
WPARAM WParam, LPARAM lParam);
static nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> sHWNDCache;
protected:
/**

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "nsRelUtils.h"
#include "nsWinUtils.h"
#include "nsIAccessibleDocument.h"
#include "nsIAccessibleEvent.h"
@ -193,58 +194,23 @@ STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *pp
{
__try {
*ppdispParent = NULL;
if (!mWeakShell)
return E_FAIL; // We've been shut down
nsIFrame *frame = GetFrame();
HWND hwnd = 0;
if (frame) {
nsIView *view = frame->GetViewExternal();
if (view) {
// This code is essentially our implementation of WindowFromAccessibleObject,
// because MSAA iterates get_accParent() until it sees an object of ROLE_WINDOW
// to know where the window for a given accessible is. We must expose the native
// window accessible that MSAA creates for us. This must be done for the document
// object as well as any layout that creates its own window (e.g. via overflow: scroll)
nsIWidget *widget = view->GetWidget();
if (widget) {
hwnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "No window handle for window");
if (IsDefunct())
return E_FAIL;
nsIViewManager* viewManager = view->GetViewManager();
if (!viewManager)
return E_UNEXPECTED;
nsIView *rootView;
viewManager->GetRootView(rootView);
if (rootView == view) {
// If the client accessible (OBJID_CLIENT) has a window but its window
// was created by an outer window then we want the native accessible
// for that outer window. If the accessible was created for outer
// window (if the outer window has inner windows then they share the
// same client accessible with it) then return native accessible for
// the outer window.
HWND parenthwnd = ::GetParent(hwnd);
if (parenthwnd)
hwnd = parenthwnd;
NS_ASSERTION(hwnd, "No window handle for window");
}
nsRefPtr<nsDocAccessible> doc(do_QueryObject(this));
if (doc) {
// Return window system accessible object for root document and tab document
// accessibles.
if (!doc->ParentDocument() ||
nsWinUtils::IsWindowEmulationEnabled() &&
nsWinUtils::IsTabDocument(doc->GetDocumentNode())) {
HWND hwnd = static_cast<HWND>(doc->GetNativeWindow());
if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
IID_IAccessible,
(void**)ppdispParent))) {
return S_OK;
}
else {
// If a frame is a scrollable frame, then it has one window for the client area,
// not an extra parent window for just the scrollbars
nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
if (scrollFrame) {
hwnd = (HWND)scrollFrame->GetScrolledFrame()->GetNearestWidget()->GetNativeData(NS_NATIVE_WINDOW);
NS_ASSERTION(hwnd, "No window handle for window");
}
}
}
if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible,
(void**)ppdispParent))) {
return S_OK;
}
}
@ -387,6 +353,9 @@ STDMETHODIMP nsAccessibleWrap::get_accRole(
__try {
VariantInit(pvarRole);
if (IsDefunct())
return E_FAIL;
nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
if (!xpAccessible)
return E_FAIL;
@ -1187,6 +1156,9 @@ nsAccessibleWrap::role(long *aRole)
__try {
*aRole = 0;
if (IsDefunct())
return E_FAIL;
NS_ASSERTION(gWindowsRoleMap[nsIAccessibleRole::ROLE_LAST_ENTRY].ia2Role == ROLE_WINDOWS_LAST_ENTRY,
"MSAA role map skewed");
@ -1662,45 +1634,11 @@ PRInt32 nsAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
HWND
nsAccessibleWrap::GetHWNDFor(nsAccessible *aAccessible)
{
HWND hWnd = 0;
if (!aAccessible)
return hWnd;
return 0;
nsIFrame *frame = aAccessible->GetFrame();
if (frame) {
nsIWidget *window = frame->GetNearestWidget();
PRBool isVisible;
window->IsVisible(isVisible);
if (isVisible) {
// Short explanation:
// If HWND for frame is inside a hidden window, fire the event on the
// containing document's visible window.
//
// Long explanation:
// This is really just to fix combo boxes with JAWS. Window-Eyes already
// worked with combo boxes because they use the value change event in
// the closed combo box case. JAWS will only pay attention to the focus
// events on the list items. The JAWS developers haven't fixed that, so
// we'll use the focus events to make JAWS work. However, JAWS is
// ignoring events on a hidden window. So, in order to fix the bug where
// JAWS doesn't echo the current option as it changes in a closed
// combo box, we need to use an ensure that we never fire an event with
// an HWND for a hidden window.
hWnd = (HWND)frame->GetNearestWidget()->GetNativeData(NS_NATIVE_WINDOW);
}
}
if (!hWnd) {
void* handle = nsnull;
nsDocAccessible *accessibleDoc = aAccessible->GetDocAccessible();
if (!accessibleDoc)
return 0;
accessibleDoc->GetWindowHandle(&handle);
hWnd = (HWND)handle;
}
return hWnd;
nsDocAccessible* document = aAccessible->GetDocAccessible();
return document ? static_cast<HWND>(document->GetNativeWindow()) : 0;
}
HRESULT

Просмотреть файл

@ -39,6 +39,9 @@
#include "nsDocAccessibleWrap.h"
#include "ISimpleDOMDocument_i.c"
#include "nsIAccessibilityService.h"
#include "nsRootAccessible.h"
#include "nsWinUtils.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeNode.h"
#include "nsIFrame.h"
@ -60,7 +63,7 @@
nsDocAccessibleWrap::
nsDocAccessibleWrap(nsIDocument *aDocument, nsIContent *aRootContent,
nsIWeakReference *aShell) :
nsDocAccessible(aDocument, aRootContent, aShell)
nsDocAccessible(aDocument, aRootContent, aShell), mHWND(NULL)
{
}
@ -245,3 +248,53 @@ STDMETHODIMP nsDocAccessibleWrap::get_accValue(
return get_URL(pszValue);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccessNode
PRBool
nsDocAccessibleWrap::Init()
{
if (nsWinUtils::IsWindowEmulationEnabled()) {
// Create window for tab document.
if (nsWinUtils::IsTabDocument(mDocument)) {
nsRefPtr<nsRootAccessible> root = GetRootAccessible();
mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
static_cast<HWND>(root->GetNativeWindow()));
nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
} else {
nsDocAccessible* parentDocument = ParentDocument();
if (parentDocument)
mHWND = parentDocument->GetNativeWindow();
}
}
return nsDocAccessible::Init();
}
void
nsDocAccessibleWrap::Shutdown()
{
if (nsWinUtils::IsWindowEmulationEnabled()) {
// Destroy window created for root document.
if (nsWinUtils::IsTabDocument(mDocument)) {
nsAccessibleWrap::sHWNDCache.Remove(mHWND);
::DestroyWindow(static_cast<HWND>(mHWND));
}
mHWND = nsnull;
}
nsDocAccessible::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////
// nsDocAccessible
void*
nsDocAccessibleWrap::GetNativeWindow() const
{
return mHWND ? mHWND : nsDocAccessible::GetNativeWindow();
}

Просмотреть файл

@ -89,8 +89,18 @@ public:
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszValue);
// nsAccessNode
virtual PRBool Init();
virtual void Shutdown();
// nsAccessibleWrap
virtual nsAccessible *GetXPAccessibleFor(const VARIANT& varChild);
// nsDocAccessible
virtual void* GetNativeWindow() const;
protected:
void* mHWND;
};
#endif

Просмотреть файл

@ -43,6 +43,7 @@
#include "nsAccessibleWrap.h"
#include "nsIWinAccessNode.h"
#include "nsArrayUtils.h"
#include "nsIDocShellTreeItem.h"
HRESULT
nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
@ -96,3 +97,57 @@ nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
*aIA2ArrayLen = length;
return S_OK;
}
void
nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
{
WNDCLASSW wc;
wc.style = CS_GLOBALCLASS;
wc.lpfnWndProc = nsAccessNodeWrap::WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = aWindowClass;
::RegisterClassW(&wc);
}
HWND
nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd)
{
return ::CreateWindowW(aWindowClass,
L"NetscapeDispatchWnd",
WS_CHILD | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0,
aParentWnd,
NULL,
GetModuleHandle(NULL),
NULL);
}
bool
nsWinUtils::IsWindowEmulationEnabled()
{
return ::GetModuleHandleW(kJAWSModuleHandle) ||
::GetModuleHandleW(kWEModuleHandle) ||
::GetModuleHandleW(kDolphnModuleHandle);
}
bool
nsWinUtils::IsTabDocument(nsIDocument* aDocumentNode)
{
nsCOMPtr<nsISupports> container = aDocumentNode->GetContainer();
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
treeItem->GetParent(getter_AddRefs(parentTreeItem));
nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
return parentTreeItem == rootTreeItem;
}

Просмотреть файл

@ -44,6 +44,14 @@
#include "Accessible2.h"
#include "nsIArray.h"
#include "nsIDocument.h"
const LPCWSTR kClassNameRoot = L"MozillaUIWindowClass";
const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
const LPCWSTR kJAWSModuleHandle = L"jhook";
const LPCWSTR kWEModuleHandle = L"gwm32inc";
const LPCWSTR kDolphnModuleHandle = L"dolwinhk";
class nsWinUtils
{
@ -54,6 +62,26 @@ public:
*/
static HRESULT ConvertToIA2Array(nsIArray *aCollection,
IUnknown ***aAccessibles, long *aCount);
/**
* Helper to register window class.
*/
static void RegisterNativeWindow(LPCWSTR aWindowClass);
/**
* Helper to create a window.
*/
static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd);
/**
* Return true if window emulation is enabled.
*/
static bool IsWindowEmulationEnabled();
/**
* Return true if the given document node is for tab document accessible.
*/
static bool IsTabDocument(nsIDocument* aDocumentNode);
};
#endif

Просмотреть файл

@ -50,19 +50,7 @@
role: ROLE_ENTRY,
children: [
{
role: ROLE_TEXT_LEAF // hello1 text
},
{
role: ROLE_WHITESPACE
},
{
role: ROLE_TEXT_LEAF, // hello2 text
},
{
role: ROLE_WHITESPACE
},
{
role: ROLE_TEXT_LEAF, // whitepsace text
role: ROLE_TEXT_LEAF // hello1\nhello2 text
},
{
role: ROLE_WHITESPACE

Просмотреть файл

@ -73,6 +73,8 @@ pref("extensions.blocklist.level", 2);
pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
pref("extensions.update.autoUpdateDefault", true);
// Dictionary download preference
pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/%APP%/dictionaries/");
@ -89,6 +91,11 @@ pref("app.update.timer", 600000);
// Enables some extra Application Update Logging (can reduce performance)
pref("app.update.log", false);
// The number of general background check failures to allow before notifying the
// user of the failure. User initiated update checks always notify the user of
// the failure.
pref("app.update.backgroundMaxErrors", 10);
// When |app.update.cert.requireBuiltIn| is true or not specified the
// final certificate and all certificates the connection is redirected to before
// the final certificate for the url specified in the |app.update.url|
@ -793,6 +800,8 @@ pref("browser.sessionstore.max_windows_undo", 3);
// number of crashes that can occur before the about:sessionrestore page is displayed
// (this pref has no effect if more than 6 hours have passed since the last crash)
pref("browser.sessionstore.max_resumed_crashes", 1);
// number of tabs to restore concurrently
pref("browser.sessionstore.max_concurrent_tabs", 3);
// allow META refresh by default
pref("accessibility.blockautorefresh", false);

Просмотреть файл

@ -3,104 +3,82 @@
-moz-padding-end: 0;
padding-bottom: 10px;
-moz-padding-start: 0;
width: 299px;
}
#modes {
min-height: 400px;
width: 600px;
}
#clientBox {
/* Add a min-width equal to chrome://branding/content/about.png's
* width, to maintain the dialog layout on OS X where the dialog is
* align="end" to right-align the button.
*/
min-width: 300px;
background-image: url("chrome://branding/content/about.png");
background-color: #F7F7F7;
color: #222222;
}
#leftBox {
background-image: url("chrome://branding/content/about-logo.png");
background-repeat: no-repeat;
background-color: #FFFFFF;
padding-top: 203px;
color: #000000;
/* min-width and min-height create room for the logo */
min-width: 210px;
min-height: 210px;
margin-top:20px;
-moz-margin-start: 30px;
}
#brandName {
font-weight: bold; font-size: larger;
#rightBox {
background-image: url("chrome://branding/content/about-wordmark.png");
background-repeat: no-repeat;
/* padding-top creates room for the wordmark */
padding-top: 38px;
margin-top:20px;
-moz-margin-end: 30px;
-moz-margin-start: 30px;
}
#userAgent {
direction: ltr;
margin-top: 10px;
-moz-margin-end: 13px;
margin-bottom: 0;
-moz-margin-start: 13px;
background-color: #FFFFFF;
color: #000000;
padding-top: 1px;
-moz-padding-end: 1px;
padding-bottom: 1px;
-moz-padding-start: 3px;
-moz-appearance: none;
overflow: hidden;
border: 0;
#rightBox:-moz-locale-dir(rtl) {
background-position: 100% 0;
}
#groove {
margin-top: 0;
}
#creditsIframe {
cursor: default;
-moz-user-select: none;
border: 0;
#bottomBox {
padding: 15px 10px 0;
}
#version {
font-weight: bold;
color: #909090;
margin-top: 1em;
-moz-margin-end: 0;
margin-bottom: 10px;
-moz-margin-start: 17px;
margin-top: 5px;
}
#distribution {
font-weight: bold;
color: #909090;
display: none;
margin-top: 0;
-moz-margin-end: 0;
margin-bottom: 0;
-moz-margin-start: 17px;
#released {
color: #666666;
}
#distribution,
#distributionId {
font-weight: bold;
color: #909090;
display: none;
margin-top: 0;
-moz-margin-end: 0;
margin-bottom: 0;
}
#checkForUpdatesButton,
.text-blurb {
margin-bottom: 10px;
-moz-margin-start: 17px;
}
#copyright {
margin-top: 0;
-moz-margin-end: 16px;
margin-bottom: 3px;
-moz-margin-start: 16px;
}
button[dlgtype="extra2"] {
-moz-margin-start: 13px;
}
button[dlgtype="accept"] {
-moz-margin-end: 13px;
-moz-margin-start: 0;
-moz-padding-start: 0;
}
.version-label,
.trademark-label,
.text-link,
.text-link:focus {
margin: 0px;
padding: 0px;
border: 0px;
}
.bottom-link,
.bottom-link:focus {
text-align: center;
margin: 0 40px;
}
#trademark {
font-size: xx-small;
text-align: center;
color: #999999;
margin-top: 10px;
}

Просмотреть файл

@ -20,6 +20,7 @@
#
# Contributor(s):
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
# Margaret Leibovic <margaret.leibovic@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -35,27 +36,25 @@
#
# ***** END LICENSE BLOCK ***** -->
var gSelectedPage = 0;
// Services = object with smart getters for common XPCOM services
Components.utils.import("resource://gre/modules/Services.jsm");
function init(aEvent)
{
if (aEvent.target != document)
return;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
try {
var distroId = prefs.getCharPref("distribution.id");
var distroId = Services.prefs.getCharPref("distribution.id");
if (distroId) {
var distroVersion = prefs.getCharPref("distribution.version");
var distroAbout = prefs.getComplexValue("distribution.about",
var distroVersion = Services.prefs.getCharPref("distribution.version");
var distroAbout = Services.prefs.getComplexValue("distribution.about",
Components.interfaces.nsISupportsString);
var distroField = document.getElementById("distribution");
distroField.value = distroAbout;
distroField.style.display = "block";
var distroIdField = document.getElementById("distributionId");
distroIdField.value = distroId + " - " + distroVersion;
distroIdField.style.display = "block";
@ -65,19 +64,9 @@ function init(aEvent)
// Pref is unset
}
var userAgentField = document.getElementById("userAgent");
userAgentField.value = navigator.userAgent;
var button = document.documentElement.getButton("extra2");
button.setAttribute("label", document.documentElement.getAttribute("creditslabel"));
button.setAttribute("accesskey", document.documentElement.getAttribute("creditsaccesskey"));
button.addEventListener("command", switchPage, false);
var acceptButton = document.documentElement.getButton("accept");
#ifdef XP_UNIX
acceptButton.setAttribute("icon", "close");
#ifdef MOZ_UPDATER
initUpdates();
#endif
acceptButton.focus();
#ifdef XP_MACOSX
// it may not be sized at this point, and we need its width to calculate its position
@ -86,34 +75,27 @@ function init(aEvent)
#endif
}
function uninit(aEvent)
#ifdef MOZ_UPDATER
/**
* Creates "Last Updated" message and sets up "Check for Updates..." button.
*/
function initUpdates()
{
if (aEvent.target != document)
return;
var iframe = document.getElementById("creditsIframe");
iframe.setAttribute("src", "");
}
var um = Components.classes["@mozilla.org/updates/update-manager;1"].
getService(Components.interfaces.nsIUpdateManager);
var browserBundle = Services.strings.
createBundle("chrome://browser/locale/browser.properties");
function switchPage(aEvent)
{
var button = aEvent.target;
if (button.localName != "button")
return;
var iframe = document.getElementById("creditsIframe");
if (gSelectedPage == 0) {
iframe.setAttribute("src", "chrome://browser/content/credits.xhtml");
button.setAttribute("label", document.documentElement.getAttribute("aboutlabel"));
button.setAttribute("accesskey", document.documentElement.getAttribute("aboutaccesskey"));
gSelectedPage = 1;
if (um.updateCount) {
let buildID = um.getUpdateAt(0).buildID;
let released = browserBundle.formatStringFromName("aboutdialog.released",
[buildID.substring(0, 4),
buildID.substring(4, 6),
buildID.substring(6, 8)], 3);
document.getElementById("released").setAttribute("value", released);
}
else {
iframe.setAttribute("src", "");
button.setAttribute("label", document.documentElement.getAttribute("creditslabel"));
button.setAttribute("accesskey", document.documentElement.getAttribute("creditsaccesskey"));
gSelectedPage = 0;
}
var modes = document.getElementById("modes");
modes.setAttribute("selectedIndex", gSelectedPage);
}
var checkForUpdates = document.getElementById("checkForUpdatesButton");
setupCheckForUpdates(checkForUpdates, browserBundle);
}
#endif

Просмотреть файл

@ -22,6 +22,7 @@
#
# Contributor(s):
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
# Margaret Leibovic <margaret.leibovic@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -51,55 +52,62 @@
<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
#endif
<dialog xmlns:html="http://www.w3.org/1999/xhtml"
<window xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="aboutDialog"
windowtype="Browser:About"
onload="init(event);" onunload="uninit(event);"
onload="init(event);"
#ifdef XP_MACOSX
inwindowmenu="false"
buttons="extra2"
align="end"
#else
title="&aboutDialog.title;"
buttons="accept,extra2"
#ifdef XP_UNIX
buttonlabelaccept="&closeCmdGNOME.label;"
buttonaccesskeyaccept="&closeCmdGNOME.accesskey;"
#endif
#endif
creditslabel="&copyright;"
#ifdef XP_UNIX
creditsaccesskey="&copyrightGNOME.accesskey;"
#else
creditsaccesskey="&copyright.accesskey;"
#endif
aboutlabel="&aboutLink;"
aboutaccesskey="&aboutLink.accesskey;">
>
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/>
<deck id="modes" flex="1">
<vbox flex="1" id="clientBox">
#expand <label id="version" value="&aboutVersion; __MOZ_APP_VERSION__"/>
<label id="distribution"/>
<label id="distributionId"/>
<description id="copyright">
<label
class="text-link" href="about:license"
>&licenseLinkText;</label>&licenseLinkSuffix;&trademarkInfo;
<vbox>
<hbox id="clientBox">
<vbox id="leftBox" flex="1"/>
<vbox id="rightBox" flex="1">
<description id="version">
#expand <label class="version-label" value="__MOZ_APP_VERSION__"/> <label class="version-label" id="released"/>
</description>
<label id="distribution" class="text-blurb"/>
<label id="distributionId" class="text-blurb"/>
#ifdef MOZ_UPDATER
<hbox>
<button id="checkForUpdatesButton" oncommand="checkForUpdates();" align="start"/>
<spacer flex="1"/>
</hbox>
#endif
<description class="text-blurb">
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
</description>
<description class="text-blurb">
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
</description>
</vbox>
</hbox>
<vbox id="bottomBox">
<hbox pack="center">
<label class="text-link bottom-link" href="about:license">&bottomLinks.license;</label>
<label class="text-link bottom-link" href="about:rights">&bottomLinks.rights;</label>
<label class="text-link bottom-link" href="http://www.mozilla.com/legal/privacy/">&bottomLinks.privacy;</label>
</hbox>
<description id="trademark">
<label class="trademark-label">&trademarkInfo.part1;</label>
<label class="trademark-label">&trademarkInfo.part2;</label>
</description>
<textbox id="userAgent" multiline="true" readonly="true" flex="1"/>
</vbox>
<vbox flex="1" id="creditsBox">
<iframe id="creditsIframe" flex="1"/>
</vbox>
</deck>
<separator class="groove" id="groove"/>
</vbox>
<keyset>
<key keycode="VK_ESCAPE" oncommand="window.close();"/>
</keyset>
#ifdef XP_MACOSX
#include browserMountPoints.inc
#endif
</dialog>
</window>

Просмотреть файл

@ -55,7 +55,8 @@ html {
#brandStart {
background: -moz-linear-gradient(top, #42607C, #1E4262 30%, #1E4262 80%, #143552 98%, #244665);
border-radius: 5.6px;
padding-bottom: 0.2em;
padding-top: 0.1em;
padding-bottom: 0.1em;
-moz-padding-start: 0.5em;
font-size: 250%;
font-weight: bold;

Просмотреть файл

@ -141,7 +141,6 @@ function loadSnippets()
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
// Try to update from network.
let xhr = new XMLHttpRequest();
xhr.mozBackgroundRequest = true;
xhr.open('GET', updateURL, true);
xhr.onerror = function (event) {
showSnippets();

Просмотреть файл

@ -109,11 +109,13 @@
oncommand="openFeedbackPage()"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator id="updateSeparator"/>
#ifdef XP_MACOSX
#ifdef MOZ_UPDATER
<menuitem id="checkForUpdates"
label="&updateCmd.label;"
class="menuitem-iconic"
oncommand="checkForUpdates();"/>
#endif
#endif
<menuseparator id="aboutSeparator"/>
<menuitem id="aboutName"

Просмотреть файл

@ -19,5 +19,7 @@
<!ENTITY % safebrowsingDTD SYSTEM "chrome://browser/locale/safebrowsing/phishing-afterload-warning-message.dtd">
%safebrowsingDTD;
#endif
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%aboutHomeDTD;
]>

Просмотреть файл

@ -209,8 +209,8 @@
accesskey="&viewMenu.accesskey;">
<menupopup id="menu_viewPopup">
<menuitem id="menu_tabview"
label="&showTabView2.label;"
accesskey="&showTabView2.accesskey;"
label="&viewTabGroups.label;"
accesskey="&viewTabGroups.accesskey;"
command="Browser:ToggleTabView"/>
<menu id="viewToolbarsMenu"
label="&viewToolbarsMenu.label;"
@ -513,29 +513,13 @@
<menuitem id="sync-setup"
label="&syncSetup.label;"
accesskey="&syncSetup.accesskey;"
observes="sync-setup-state"
oncommand="gSyncUI.openSetup()"/>
<menu id="sync-menu"
label="&syncMenu.label;"
accesskey="&syncMenu.accesskey;">
<menupopup id="sync-menu-popup"
onpopupshowing="if (event.target == this) gSyncUI.doUpdateMenu(event);">
<menuitem id="sync-loginitem"
label="&syncLogInItem.label;"
accesskey="&syncLogInItem.accesskey;"
oncommand="gSyncUI.doLogin();"/>
<menuitem id="sync-logoutitem"
label="&syncLogOutItem.label;"
accesskey="&syncLogOutItem.accesskey;"
oncommand="gSyncUI.doLogout();"/>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
oncommand="gSyncUI.doSync(event);"/>
<menuseparator id="sync-lastsyncsep" hidden="true"/>
<menuitem id="sync-lastsyncitem"
disabled="true" hidden="true"/>
</menupopup>
</menu>
<menuitem id="sync-syncnowitem"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
observes="sync-syncnow-state"
oncommand="gSyncUI.doSync(event);"/>
#endif
<menuseparator id="devToolsSeparator"/>
<menuitem id="menu_pageinspect"

Просмотреть файл

@ -192,6 +192,10 @@
<broadcaster id="singleFeedMenuitemState" disabled="true"/>
<broadcaster id="multipleFeedsMenuState" hidden="true"/>
<broadcaster id="tabviewGroupsNumber" groups="0"/>
#ifdef MOZ_SERVICES_SYNC
<broadcaster id="sync-setup-state"/>
<broadcaster id="sync-syncnow-state"/>
#endif
</broadcasterset>
<keyset id="mainKeyset">

Просмотреть файл

@ -22,6 +22,7 @@
# Chris Beard <cbeard@mozilla.com>
# Dan Mosedale <dmose@mozilla.org>
# Paul OShannessy <paul@oshannessy.com>
# Philipp von Weitershausen <philipp@weitershausen.de>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -56,6 +57,7 @@ let gSyncUI = {
"weave:service:sync:finish",
"weave:service:sync:error",
"weave:service:sync:delayed",
"weave:service:quota:remaining",
"weave:service:setup-complete",
"weave:service:login:start",
"weave:service:login:finish",
@ -103,22 +105,20 @@ let gSyncUI = {
updateUI: function SUI_updateUI() {
let needsSetup = this._needsSetup();
document.getElementById("sync-setup").hidden = !needsSetup;
document.getElementById("sync-menu").hidden = needsSetup;
document.getElementById("sync-setup-state").hidden = !needsSetup;
document.getElementById("sync-syncnow-state").hidden = needsSetup;
if (gBrowser) {
let showLabel = !this._isLoggedIn() && !needsSetup;
let button = document.getElementById("sync-status-button");
button.setAttribute("class", showLabel ? "statusbarpanel-iconic-text"
: "statusbarpanel-iconic");
button.image = "chrome://browser/skin/sync-16.png";
if (!gBrowser)
return;
if (!this._isLoggedIn()) {
//XXXzpao When we move the string bundle, we can add more and make this
// say "needs setup" or something similar. (bug 583381)
button.removeAttribute("tooltiptext");
}
}
let button = document.getElementById("sync-button");
if (!button)
return;
button.removeAttribute("status");
this._updateLastSyncTime();
if (needsSetup)
button.removeAttribute("tooltiptext");
},
alltabsPopupShowing: function(event) {
@ -151,10 +151,14 @@ let gSyncUI = {
// Functions called by observers
onActivityStart: function SUI_onActivityStart() {
//XXXzpao Followup: Do this with a class. (bug 583384)
if (gBrowser)
document.getElementById("sync-status-button").image =
"chrome://browser/skin/sync-16-throbber.png";
if (!gBrowser)
return;
let button = document.getElementById("sync-button");
if (!button)
return;
button.setAttribute("status", "active");
},
onSyncFinish: function SUI_onSyncFinish() {
@ -180,7 +184,7 @@ let gSyncUI = {
Weave.Notifications.removeAll(title);
this.updateUI();
this._updateLastSyncItem();
this._updateLastSyncTime();
},
onLoginError: function SUI_onLoginError() {
@ -218,6 +222,21 @@ let gSyncUI = {
this.updateUI();
},
onQuotaNotice: function onQuotaNotice(subject, data) {
let title = this._stringBundle.GetStringFromName("warning.sync.quota.label");
let description = this._stringBundle.GetStringFromName("warning.sync.quota.description");
let buttons = [];
buttons.push(new Weave.NotificationButton(
this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.label"),
this._stringBundle.GetStringFromName("error.sync.viewQuotaButton.accesskey"),
function() { gSyncUI.openQuotaDialog(); return true; }
));
let notification = new Weave.Notification(
title, description, null, Weave.Notifications.PRIORITY_WARNING, buttons);
Weave.Notifications.replaceTitle(notification);
},
onNotificationAdded: function SUI_onNotificationAdded() {
if (!gBrowser)
return;
@ -249,32 +268,6 @@ let gSyncUI = {
},
// Commands
doUpdateMenu: function SUI_doUpdateMenu(event) {
this._updateLastSyncItem();
let loginItem = document.getElementById("sync-loginitem");
let logoutItem = document.getElementById("sync-logoutitem");
let syncItem = document.getElementById("sync-syncnowitem");
// Don't allow "login" to be selected in some cases
let offline = Services.io.offline;
let locked = Weave.Service.locked;
let noUser = Weave.Service.username == "";
let notReady = offline || locked || noUser;
loginItem.setAttribute("disabled", notReady);
logoutItem.setAttribute("disabled", notReady);
// Don't allow "sync now" to be selected in some cases
let loggedIn = Weave.Service.isLoggedIn;
let noNode = Weave.Status.sync == Weave.NO_SYNC_NODE_FOUND;
let disableSync = notReady || !loggedIn || noNode;
syncItem.setAttribute("disabled", disableSync);
// Only show one of login/logout
loginItem.setAttribute("hidden", loggedIn);
logoutItem.setAttribute("hidden", !loggedIn);
},
doLogin: function SUI_doLogin() {
Weave.Service.login();
},
@ -284,16 +277,15 @@ let gSyncUI = {
},
doSync: function SUI_doSync() {
Weave.Service.sync();
if (Weave.Service.isLoggedIn || Weave.Service.login())
Weave.Service.sync();
},
handleStatusbarButton: function SUI_handleStatusbarButton() {
if (Weave.Service.isLoggedIn)
Weave.Service.sync();
else if (this._needsSetup())
handleToolbarButton: function SUI_handleStatusbarButton() {
if (this._needsSetup())
this.openSetup();
else
Weave.Service.login();
this.doSync();
},
//XXXzpao should be part of syncCommon.js - which we might want to make a module...
@ -308,34 +300,46 @@ let gSyncUI = {
}
},
openQuotaDialog: function SUI_openQuotaDialog() {
let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
if (win)
win.focus();
else
Services.ww.activeWindow.openDialog(
"chrome://browser/content/syncQuota.xul", "",
"centerscreen,chrome,dialog,modal");
},
openPrefs: function SUI_openPrefs() {
openPreferences("paneSync");
},
// Helpers
_updateLastSyncItem: function SUI__updateLastSyncItem() {
_updateLastSyncTime: function SUI__updateLastSyncTime() {
if (!gBrowser)
return;
let syncButton = document.getElementById("sync-button");
if (!syncButton)
return;
let lastSync;
try {
lastSync = Services.prefs.getCharPref("services.sync.lastSync");
}
catch (e) { };
if (!lastSync)
if (!lastSync || this._needsSetup()) {
syncButton.removeAttribute("tooltiptext");
return;
let lastSyncItem = document.getElementById("sync-lastsyncitem");
}
// Show the day-of-week and time (HH:MM) of last sync
let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
let lastSyncLabel =
this._stringBundle.formatStringFromName("lastSync.label", [lastSyncDate], 1);
lastSyncItem.setAttribute("label", lastSyncLabel);
lastSyncItem.setAttribute("hidden", "false");
document.getElementById("sync-lastsyncsep").hidden = false;
if (gBrowser)
document.getElementById("sync-status-button").
setAttribute("tooltiptext", lastSyncLabel);
syncButton.setAttribute("tooltiptext", lastSyncLabel);
},
_onSyncEnd: function SUI__onSyncEnd(success) {
@ -352,7 +356,18 @@ let gSyncUI = {
let priority = Weave.Notifications.PRIORITY_WARNING;
let buttons = [];
if (!Weave.Status.enforceBackoff) {
if (Weave.Status.sync == Weave.OVER_QUOTA) {
description = this._stringBundle.GetStringFromName(
"error.sync.quota.description");
buttons.push(new Weave.NotificationButton(
this._stringBundle.GetStringFromName(
"error.sync.viewQuotaButton.label"),
this._stringBundle.GetStringFromName(
"error.sync.viewQuotaButton.accesskey"),
function() { gSyncUI.openQuotaDialog(); return true; } )
);
}
else if (!Weave.Status.enforceBackoff) {
priority = Weave.Notifications.PRIORITY_INFO;
buttons.push(new Weave.NotificationButton(
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
@ -377,7 +392,7 @@ let gSyncUI = {
}
this.updateUI();
this._updateLastSyncItem();
this._updateLastSyncTime();
},
observe: function SUI_observe(subject, topic, data) {
@ -394,6 +409,9 @@ let gSyncUI = {
case "weave:service:sync:delayed":
this.onSyncDelay();
break;
case "weave:service:quota:remaining":
this.onQuotaNotice();
break;
case "weave:service:setup-complete":
this.onLoginFinish();
break;

Просмотреть файл

@ -136,6 +136,20 @@ let TabView = {
else
this.show();
},
getActiveGroupName: function Tabview_getActiveGroupName() {
// We get the active group this way, instead of querying
// GroupItems.getActiveGroupItem() because the tabSelect event
// will not have happened by the time the browser tries to
// update the title.
let activeTab = window.gBrowser.selectedTab;
if (activeTab.tabItem && activeTab.tabItem.parent){
let groupName = activeTab.tabItem.parent.getTitle();
if (groupName)
return groupName;
}
return null;
},
// ----------
updateContextMenu: function(tab, popup) {

Просмотреть файл

@ -37,15 +37,17 @@ tabbrowser {
min-width: 1px;
}
.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-text,
.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-icon-image,
.tabbrowser-tab:not([fadein]):not([pinned]) > .tab-close-button {
.tab-progress:not([fadein]):not([pinned]),
.tab-label:not([fadein]):not([pinned]),
.tab-icon-image:not([fadein]):not([pinned]),
.tab-close-button:not([fadein]):not([pinned]) {
opacity: 0 !important;
}
.tabbrowser-tab > .tab-text,
.tabbrowser-tab > .tab-icon-image,
.tabbrowser-tab > .tab-close-button {
.tab-progress,
.tab-label,
.tab-icon-image,
.tab-close-button {
-moz-transition: opacity .25s;
}
@ -54,14 +56,6 @@ tabbrowser {
display: block; /* position:fixed already does this (bug 579776), but let's be explicit */
}
.tabbrowser-tab[pinned] > .tab-text {
display: none;
}
.tabbrowser-tab[pinned] > .tab-icon-image {
vertical-align: middle;
}
#alltabs-popup {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
}
@ -148,16 +142,69 @@ toolbar[mode="icons"] > #reload-button[displaystop] {
-moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
}
#urlbar-progress {
-moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter");
}
/* Some child nodes want to be ordered based on the locale's direction, while
everything else should be ltr. */
#urlbar:-moz-locale-dir(rtl) > .autocomplete-textbox-container > .textbox-input-box {
.urlbar-input-box:-moz-locale-dir(rtl) {
direction: rtl;
}
#urlbar html|*.autocomplete-textbox {
html|*.urlbar-input {
direction: ltr;
}
/* over-link in location bar */
.urlbar-over-link-layer[overlinkstate="fade-in"],
.urlbar-textbox-container:not([overlinkstate]) {
-moz-transition-property: color;
-moz-transition-duration: 150ms;
-moz-transition-delay: 50ms;
-moz-transition-timing-function: cubic-bezier(0.0, 0.6, 1.0, 1.0);
}
.urlbar-textbox-container[overlinkstate="fade-in"],
.urlbar-over-link-layer:not([overlinkstate]) {
-moz-transition-property: color;
-moz-transition-duration: 150ms;
-moz-transition-delay: 50ms;
-moz-transition-timing-function: linear;
color: transparent;
}
.urlbar-over-link-box[overlinkstate="fade-in"],
.urlbar-textbox-container-children:not([overlinkstate]) {
-moz-transition-property: opacity;
-moz-transition-duration: 150ms;
-moz-transition-delay: 50ms;
-moz-transition-timing-function: cubic-bezier(0.0, 0.6, 1.0, 1.0);
opacity: 1;
}
.urlbar-textbox-container-children[overlinkstate="fade-in"],
.urlbar-over-link-box:not([overlinkstate]) {
-moz-transition-property: opacity;
-moz-transition-duration: 150ms;
-moz-transition-delay: 50ms;
-moz-transition-timing-function: linear;
opacity: 0;
}
.urlbar-textbox-container[overlinkstate="showing"] {
color: transparent;
}
.urlbar-over-link-box[overlinkstate="showing"] {
opacity: 1;
}
.urlbar-textbox-container-children[overlinkstate="showing"] {
opacity: 0;
}
/* For results that are actions, their description text is shown instead of
the URL - this needs to follow the locale's direction, unlike URLs. */
richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
@ -186,15 +233,6 @@ richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
display: none;
}
#feed-button > .button-box > .box-inherit > .button-text,
#feed-button > .button-box > .button-menu-dropmarker {
display: none;
}
#feed-menu > .feed-menuitem:-moz-locale-dir(rtl) {
direction: rtl;
}
#urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button,
#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button,

Просмотреть файл

@ -2327,56 +2327,6 @@ function BrowserPageInfo(doc, initialTab, imageElement) {
"chrome,toolbar,dialog=no,resizable", args);
}
#ifdef DEBUG
// Initialize the LeakDetector class.
function LeakDetector(verbose)
{
this.verbose = verbose;
}
const NS_LEAKDETECTOR_CONTRACTID = "@mozilla.org/xpcom/leakdetector;1";
if (NS_LEAKDETECTOR_CONTRACTID in Components.classes) {
try {
LeakDetector.prototype = Components.classes[NS_LEAKDETECTOR_CONTRACTID]
.createInstance(Components.interfaces.nsILeakDetector);
} catch (err) {
LeakDetector.prototype = Object.prototype;
}
} else {
LeakDetector.prototype = Object.prototype;
}
var leakDetector = new LeakDetector(false);
// Dumps current set of memory leaks.
function dumpMemoryLeaks()
{
leakDetector.dumpLeaks();
}
// Traces all objects reachable from the chrome document.
function traceChrome()
{
leakDetector.traceObject(document, leakDetector.verbose);
}
// Traces all objects reachable from the content document.
function traceDocument()
{
// keep the chrome document out of the dump.
leakDetector.markObject(document, true);
leakDetector.traceObject(content, leakDetector.verbose);
leakDetector.markObject(document, false);
}
// Controls whether or not we do verbose tracing.
function traceVerbose(verbose)
{
leakDetector.verbose = (verbose == "true");
}
#endif
function URLBarSetURI(aURI) {
var value = gBrowser.userTypedValue;
var valid = false;
@ -2979,8 +2929,6 @@ function openHomeDialog(aURL)
str.data = aURL;
gPrefService.setComplexValue("browser.startup.homepage",
Components.interfaces.nsISupportsString, str);
var homeButton = document.getElementById("home-button");
homeButton.setAttribute("tooltiptext", aURL);
} catch (ex) {
dump("Failed to set the home page.\n"+ex+"\n");
}
@ -3233,32 +3181,8 @@ const BrowserSearch = {
if (hidden)
browser.hiddenEngines = engines;
else {
browser.engines = engines;
if (browser == gBrowser.selectedBrowser)
this.updateSearchButton();
}
},
/**
* Update the browser UI to show whether or not additional engines are
* available when a page is loaded or the user switches tabs to a page that
* has search engines.
*/
updateSearchButton: function() {
var searchBar = this.searchBar;
// The search bar binding might not be applied even though the element is
// in the document (e.g. when the navigation toolbar is hidden), so check
// for .searchButton specifically.
if (!searchBar || !searchBar.searchButton)
return;
var engines = gBrowser.selectedBrowser.engines;
if (engines && engines.length > 0)
searchBar.searchButton.setAttribute("addengines", "true");
else
searchBar.searchButton.removeAttribute("addengines");
browser.engines = engines;
},
/**
@ -4010,7 +3934,6 @@ var XULBrowserWindow = {
defaultStatus: "",
jsStatus: "",
jsDefaultStatus: "",
overLink: "",
startTime: 0,
statusText: "",
isBusy: false,
@ -4029,7 +3952,7 @@ var XULBrowserWindow = {
get statusMeter () {
delete this.statusMeter;
return this.statusMeter = document.getElementById("statusbar-icon");
return this.statusMeter = document.getElementById("urlbar-progress");
},
get stopCommand () {
delete this.stopCommand;
@ -4093,16 +4016,16 @@ var XULBrowserWindow = {
this.updateStatusField();
},
setOverLink: function (link, b) {
setOverLink: function (link) {
// Encode bidirectional formatting characters.
// (RFC 3987 sections 3.2 and 4.1 paragraph 6)
this.overLink = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
encodeURIComponent);
this.updateStatusField();
link = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
encodeURIComponent);
gURLBar.setOverLink(link);
},
updateStatusField: function () {
var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
var text = this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
// check the current value so we don't trigger an attribute change
// and cause needless (slow!) UI updates
@ -4165,7 +4088,7 @@ var XULBrowserWindow = {
this._progressCollapseTimer = 0;
}
else
this.statusMeter.parentNode.collapsed = false;
this.statusMeter.collapsed = false;
// XXX: This needs to be based on window activity...
this.stopCommand.removeAttribute("disabled");
@ -4229,7 +4152,7 @@ var XULBrowserWindow = {
// Turn the progress meter and throbber off.
this._progressCollapseTimer = setTimeout(function (self) {
self.statusMeter.parentNode.collapsed = true;
self.statusMeter.collapsed = true;
self._progressCollapseTimer = 0;
}, 100, this);
@ -4366,7 +4289,6 @@ var XULBrowserWindow = {
asyncUpdateUI: function () {
FeedHandler.updateFeeds();
BrowserSearch.updateSearchButton();
},
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
@ -5001,7 +4923,10 @@ var gHomeButton = {
if (homeButton) {
var homePage = this.getHomePage();
homePage = homePage.replace(/\|/g,', ');
homeButton.setAttribute("tooltiptext", homePage);
if (homePage.toLowerCase() == "about:home")
homeButton.setAttribute("tooltiptext", homeButton.getAttribute("aboutHomeOverrideTooltip"));
else
homeButton.setAttribute("tooltiptext", homePage);
}
},
@ -6705,23 +6630,7 @@ function convertFromUnicode(charset, str)
*/
var FeedHandler = {
/**
* The click handler for the Feed icon in the location bar. Opens the
* subscription page if user is not given a choice of feeds.
* (Otherwise the list of available feeds will be presented to the
* user in a popup menu.)
*/
onFeedButtonClick: function(event) {
event.stopPropagation();
if (event.target.hasAttribute("feed") &&
event.eventPhase == Event.AT_TARGET &&
(event.button == 0 || event.button == 1)) {
this.subscribeToFeed(null, event);
}
},
/**
* Called when the user clicks on the Feed icon in the location bar.
* Called when the user clicks on the Subscribe to This Page... menu item.
* Builds a menu of unique feeds associated with the page, and if there
* is only one, shows the feed inline in the browser window.
* @param menuPopup
@ -6746,13 +6655,6 @@ var FeedHandler = {
while (menuPopup.firstChild)
menuPopup.removeChild(menuPopup.firstChild);
if (feeds.length == 1) {
var feedButton = document.getElementById("feed-button");
if (feedButton)
feedButton.setAttribute("feed", feeds[0].href);
return false;
}
// Build the menu showing the available feed choices for viewing.
for (var i = 0; i < feeds.length; ++i) {
var feedInfo = feeds[i];
@ -6824,30 +6726,16 @@ var FeedHandler = {
* a page is loaded or the user switches tabs to a page that has feeds.
*/
updateFeeds: function() {
var feedButton = document.getElementById("feed-button");
var feeds = gBrowser.selectedBrowser.feeds;
if (!feeds || feeds.length == 0) {
if (feedButton) {
feedButton.collapsed = true;
feedButton.removeAttribute("feed");
}
this._feedMenuitem.setAttribute("disabled", "true");
this._feedMenupopup.setAttribute("hidden", "true");
this._feedMenuitem.removeAttribute("hidden");
} else {
if (feedButton)
feedButton.collapsed = false;
if (feeds.length > 1) {
this._feedMenuitem.setAttribute("hidden", "true");
this._feedMenupopup.removeAttribute("hidden");
if (feedButton)
feedButton.removeAttribute("feed");
} else {
if (feedButton)
feedButton.setAttribute("feed", feeds[0].href);
this._feedMenuitem.setAttribute("feed", feeds[0].href);
this._feedMenuitem.removeAttribute("disabled");
this._feedMenuitem.removeAttribute("hidden");
@ -6868,12 +6756,6 @@ var FeedHandler = {
browserForLink.feeds = [];
browserForLink.feeds.push({ href: link.href, title: link.title });
if (browserForLink == gBrowser.selectedBrowser) {
var feedButton = document.getElementById("feed-button");
if (feedButton)
feedButton.collapsed = false;
}
}
};

Просмотреть файл

@ -116,10 +116,6 @@
tbattr="tabbrowser-multiple"
oncommand="gBrowser.reloadAllTabs();"/>
<menuseparator/>
<menuitem id="context_openTabInWindow" label="&openTabInNewWindow.label;"
accesskey="&openTabInNewWindow.accesskey;"
tbattr="tabbrowser-multiple"
oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
<menuitem id="context_pinTab" label="&pinAppTab.label;"
accesskey="&pinAppTab.accesskey;"
oncommand="gBrowser.pinTab(TabContextMenu.contextTab);"/>
@ -135,6 +131,10 @@
oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/>
</menupopup>
</menu>
<menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;"
accesskey="&moveToNewWindow.accesskey;"
tbattr="tabbrowser-multiple"
oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
<menuseparator/>
<menuitem id="context_bookmarkAllTabs"
label="&bookmarkAllTabs.label;"
@ -415,7 +415,7 @@
<stack id="allTabs-stack">
<vbox id="allTabs-container"><hbox/></vbox>
<toolbarbutton id="allTabs-tab-close-button"
class="tab-close-button"
class="tabs-closebutton"
oncommand="allTabs.closeTab(event);"
tooltiptext="&closeCmd.label;"
style="visibility:hidden"/>
@ -441,10 +441,18 @@
<hbox id="appmenu-button-container" align="start">
<button id="appmenu-button"
type="menu"
#ifdef XP_WIN
label="&brandShortName;"
#else
label="&appMenuButton.label;"
#endif
style="-moz-user-focus: ignore;">
<menupopup id="appmenu-popup"
#ifdef MOZ_SERVICES_SYNC
onpopupshowing="updateEditUIVisibility();gSyncUI.updateUI();">
#else
onpopupshowing="updateEditUIVisibility();">
#endif
<hbox>
<vbox id="appmenuPrimaryPane">
<hbox flex="1"
@ -760,6 +768,18 @@
</menupopup>
</menu>
</hbox>
#ifdef MOZ_SERVICES_SYNC
<spacer flex="1"/>
<!-- only one of sync-setup or sync-syncnow will be showing at once -->
<menuitem id="sync-setup-appmenu"
label="&syncSetup.label;"
observes="sync-setup-state"
oncommand="gSyncUI.openSetup()"/>
<menuitem id="sync-syncnowitem-appmenu"
label="&syncSyncNowItem.label;"
observes="sync-syncnow-state"
oncommand="gSyncUI.doSync(event);"/>
#endif
</vbox>
</hbox>
</menupopup>
@ -856,7 +876,8 @@
ondragenter="homeButtonObserver.onDragOver(event)"
ondrop="homeButtonObserver.onDrop(event)"
ondragleave="homeButtonObserver.onDragLeave(event)"
onclick="BrowserGoHome(event);"/>
onclick="BrowserGoHome(event);"
aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
<toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true"
title="&locationItem.title;" class="chromeclass-location" removable="true">
@ -911,19 +932,6 @@
</box>
<label id="urlbar-display" value="&urlbar.switchToTab.label;"/>
<hbox id="urlbar-icons">
<button type="menu"
style="-moz-user-focus: none"
class="plain urlbar-icon"
id="feed-button"
collapsed="true"
tooltiptext="&feedButton.tooltip;"
onclick="return FeedHandler.onFeedButtonClick(event);">
<menupopup position="after_end"
id="feed-menu"
onpopupshowing="return FeedHandler.buildFeedList(this);"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"/>
</button>
<image id="star-button"
class="urlbar-icon"
onclick="PlacesStarButton.onClick(event);"/>
@ -932,6 +940,7 @@
tooltiptext="&goEndCap.tooltip;"
onclick="gURLBar.handleCommand(event);"/>
</hbox>
<progressmeter id="urlbar-progress" mode="normal"/>
<toolbarbutton id="urlbar-go-button"
onclick="gURLBar.handleCommand(event);"
tooltiptext="&goEndCap.tooltip;"/>
@ -985,6 +994,19 @@
if (!this.parentNode._placesView)
new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
tooltip="bhTooltip" popupsinherittooltip="true">
<menuitem id="BMB_subscribeToPageMenuitem"
label="&subscribeToPageMenuitem.label;"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"
observes="singleFeedMenuitemState"/>
<menu id="BMB_subscribeToPageMenupopup"
label="&subscribeToPageMenupopup.label;"
observes="multipleFeedsMenuState">
<menupopup id="BMB_subscribeToPageSubmenuMenupopup"
onpopupshowing="return FeedHandler.buildFeedList(event.target);"
oncommand="return FeedHandler.subscribeToFeed(null, event);"
onclick="checkForMiddleClick(this, event);"/>
</menu>
<menuitem id="BMB_bookmarkAllTabs"
label="&addCurPagesCmd.label;"
command="Browser:BookmarkAllTabs"
@ -1138,9 +1160,9 @@
</toolbarbutton>
<toolbarbutton id="tabview-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&tabViewButton2.label;"
label="&tabGroupsButton.label;"
command="Browser:ToggleTabView"
tooltiptext="&tabViewButton2.tooltip;"
tooltiptext="&tabGroupsButton.tooltip;"
removable="true"
observes="tabviewGroupsNumber"/>
@ -1228,7 +1250,12 @@
command="cmd_fullZoomEnlarge"
tooltiptext="&zoomInButton.tooltip;"/>
</toolbaritem>
#ifdef MOZ_SERVICES_SYNC
<toolbarbutton id="sync-button"
class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&syncToolbarButton.label;"
oncommand="gSyncUI.handleToolbarButton()"/>
#endif
</toolbarpalette>
</toolbox>
@ -1261,9 +1288,6 @@
#endif
>
<statusbarpanel id="statusbar-display" label="" flex="1"/>
<statusbarpanel class="statusbarpanel-progress" collapsed="true" id="statusbar-progresspanel">
<progressmeter class="progressmeter-statusbar" id="statusbar-icon" mode="normal" value="0"/>
</statusbarpanel>
<statusbarpanel id="download-monitor" class="statusbarpanel-iconic-text"
tooltiptext="&downloadMonitor2.tooltip;" hidden="true"
command="Tools:Downloads"/>
@ -1271,14 +1295,6 @@
hidden="true"
onclick="if (event.button == 0 &amp;&amp; event.detail == 1) displaySecurityInfo();"/>
#ifdef MOZ_SERVICES_SYNC
<statusbarpanel id="sync-status-button"
class="statusbarpanel-iconic"
image="chrome://browser/skin/sync-16.png"
label="&syncLogInItem.label;"
oncommand="gSyncUI.handleStatusbarButton();"
onmousedown="event.preventDefault();">
</statusbarpanel>
<separator class="thin"/>
<statusbarpanel id="sync-notifications-button"
class="statusbarpanel-iconic-text"
hidden="true"

Просмотреть файл

@ -1,648 +0,0 @@
<!-- -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Firefox Credits.
#
# The Initial Developer of the Original Code is Ben Goodger.
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <ben@mozilla.org>
# David Baron <dbaron@mozilla.org>
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
[
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
<!ENTITY % creditsDTD SYSTEM "chrome://browser/locale/credits.dtd">
%creditsDTD;
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
%globalDTD;
]
>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&brandFullName; Credits</title>
<style>
html {
background-color: white;
}
* {
cursor: default;
-moz-user-select: none;
}
#titleBox {
position: fixed;
left: 0px;
top: 0px;
right: 0px;
bottom: auto;
z-index: 999;
}
#footerBox {
position: fixed;
left: 0px;
top: auto;
right: 0px;
bottom: 0px;
z-index: 999;
}
#creditsBox {
position: absolute;
left: 0px;
top: 0px;
bottom: 8px;
overflow: hidden;
z-index: 1;
width: 280px;
margin-left: 10px;
margin-right: 10px;
font-family: Arial, sans-serif;
font-size: small;
}
h3 {
font-weight: bold;
font-size: small;
text-align: center;
margin: 15px 0px 5px 0px;
}
.creditsGroup {
margin-bottom: 1px;
text-align: center;
}
.footnote {
font-size: x-small;
text-align: justify;
line-height: 110%;
}
h2.title {
margin-top: 200px;
margin-bottom: 60px;
text-align: center;
}
.links {
font-weight: normal;
font-size: small;
font-style: italic;
text-align: center;
margin: 0px 0px 100px 0px;
}
.motto {
margin-top: 2px;
font-style: italic;
font-size: small;
font-weight: normal;
padding-left: 2em;
}
#gecko {
margin-top: 100px;
margin-bottom: 100px;
font-size: medium;
}
a {
color: blue;
text-decoration: underline;
}
ul {
margin-top: 0px;
margin-left: 0px;
padding-left: 0px;
}
li {
list-style-type: none;
}
.center {
text-align: center;
}
</style>
<script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
<script type="application/javascript">
<![CDATA[
var gCreditsInterval = -1;
function uninit()
{
if (gCreditsInterval > -1)
clearInterval(gCreditsInterval);
}
function init()
{
var cb = document.getElementById("creditsBox");
cb.scrollTop = 0;
setTimeout(runCredits, 3000);
}
function runCredits()
{
gCreditsInterval = setInterval("creditsCallback()", 25);
}
function creditsCallback()
{
var cb = document.getElementById("creditsBox");
var newtop = cb.scrollTop + 1;
cb.scrollTop = newtop;
if (cb.scrollTop != newtop) {
// we're at the bottom
clearInterval(gCreditsInterval);
setTimeout(function() { cb.scrollTop = 0 }, 10000);
}
}
]]>
</script>
</head>
<body onload="init();" onunload="uninit();">
<div id="titleBox">
<img src="chrome://branding/content/aboutCredits.png" />
</div>
<div id="creditsBox">
<h2 class="title" dir="&locale.dir;">&brandFullName;&trade;
<div class="motto">&brandMotto;</div>
</h2>
<div class="links" dir="&locale.dir;">
&credit.thanks2; <a href="" link="about:credits" onclick="visitLink(event);">&credit.contributors2;</a>
</div>
<div class="creditsGroup">
<ul>
<li>Josh Aas</li>
<li>Robert Accettura</li>
<li>Lucas Adamski</li>
<li>Raymond Etornam Agbeame</li>
<li>Ehsan Akhgari</li>
<li>Sean Alamares</li>
<li>Pedro Alves</li>
<li>David Anderson</li>
<li>Harvey Anderson</li>
<li>Smokey Ardisson</li>
<li>Rob Arnold</li>
<li>Tomoya Asai</li>
<li>Chris AtLee</li>
<li>Dietrich Ayala</li>
<li>Mitchell Baker</li>
<li>Rhian Baker</li>
<li>Jeff Balogh</li>
<li>Jan Bambas</li>
<li>Rey Bango</li>
<li>Mark Banner</li>
<li>Jason Barnabe</li>
<li>David Baron</li>
<li>Colin Barrett</li>
<li>Curtis Bartley</li>
<li>Bo Bayles</li>
<li>Christopher Beard</li>
<li>Glen Beasley</li>
<li>Juan Becerra</li>
<li>Brian Behlendorf</li>
<li>Mike Beltzner</li>
<li>Mic Berman</li>
<li>Uri Bernstein</li>
<li>Christian Biesinger</li>
<li>Al Billings</li>
<li>Seth Bindernagel</li>
<li>Lukas Blakk</li>
<li>Jim Blandy</li>
<li>Chris Blizzard</li>
<li>Jamey Boje</li>
<li>David Bolter</li>
<li>Nelson Bolyard</li>
<li>Marco Bonardo</li>
<li>Carsten Book</li>
<li>Paul Booker</li>
<li>Jennifer Boriss</li>
<li>Dan Born</li>
<li>Arpad Borsos</li>
<li>David Boswell</li>
<li>Ondřej Brablc</li>
<li>Catherine Brady</li>
<li>Dave Bragsalla</li>
<li>Alex Buchanan</li>
<li>Igor Bukanov</li>
<li>Simon Bünzli</li>
<li>Lapo Calamandrei</li>
<li>Dave Camp</li>
<li>Rob Campbell</li>
<li>Regis Caspar</li>
<li>Garrett Casto</li>
<li>Tony Chang</li>
<li>Wan-Teh Chang</li>
<li>Emily Chen</li>
<li>Ginn Chen</li>
<li>Pascal Chevrel</li>
<li>Adam Christian</li>
<li>Tony Chung</li>
<li>Bob Clary</li>
<li>Wil Clouser</li>
<li>Mary Colvig</li>
<li>Majken Connor</li>
<li>Mike Connor</li>
<li>Chris Cooper</li>
<li>Eric Cooper</li>
<li>Paul Craciunoiu</li>
<li>Brian Crowder</li>
<li>John Daggett</li>
<li>David Dahl</li>
<li>Michael Davis</li>
<li>Neil Deakin</li>
<li>Julie Deroche</li>
<li>Aakash Desai</li>
<li>Ryan Doherty</li>
<li>Justin Dolske</li>
<li>Stephen Donner</li>
<li>Asa Dotzler</li>
<li>Chris Double</li>
<li>Joe Drew</li>
<li>Jason Duell</li>
<li>Karsten Düsterloh</li>
<li>Brendan Eich</li>
<li>Daniel Einspanjer</li>
<li>Kai Engert</li>
<li>Steve England</li>
<li>Madhava Enros</li>
<li>Behdad Esfahbod</li>
<li>Elika Etemad</li>
<li>Anthony Evans</li>
<li>Jason Evans</li>
<li>Alex Faaborg</li>
<li>Jane Finette</li>
<li>Mark Finkle</li>
<li>Darin Fisher</li>
<li>Jayson Fittipaldi</li>
<li>Justin Fitzhugh</li>
<li>Ryan Flint</li>
<li>Alix Franquet</li>
<li>Eli Friedman</li>
<li>Andreas Gal</li>
<li>Steven Garrity</li>
<li>Armen Zambrano Gasparnian</li>
<li>Serge Gautherie</li>
<li>Kevin Gerich</li>
<li>Taras Glek</li>
<li>Aravind Gottipati</li>
<li>Dão Gottwald</li>
<li>Zak Greant</li>
<li>Matthew Gregan</li>
<li>Will Guaraldi</li>
<li>Adam Guthrie</li>
<li>Mohammad Reza Haghighat</li>
<li>Andrei Hajdukewycz</li>
<li>Trevor Hardcastle</li>
<li>Basil Hashem</li>
<li>Ian Hayward</li>
<li>Ben Hearsum</li>
<li>Axel Hecht</li>
<li>Frank Hecker</li>
<li>Robert Helmer</li>
<li>Stefan Hermes</li>
<li>Jon Hicks</li>
<li>Graydon Hoare</li>
<li>Chris Hofmann</li>
<li>Timothy Hogan</li>
<li>Daniel Holbert</li>
<li>Bobby Holley</li>
<li>Mike Hommey</li>
<li>Stephen Horlander</li>
<li>Barbara Hueppe</li>
<li>Anthony Hughes</li>
<li>David Humphrey</li>
<li>Takeshi Ichimaru</li>
<li>Chris Ilias</li>
<li>Eri Inoue</li>
<li>Joichi Ito</li>
<li>Steven Johnson</li>
<li>Laurent Jouanneau</li>
<li>Robert Kaiser</li>
<li>Gen Kanai</li>
<li>Masanori Kaneko</li>
<li>Blake Kaplan</li>
<li>Mike Kaplinskiy</li>
<li>Michael Kaply</li>
<li>Mitch Kapor</li>
<li>Kazuyoshi Kato</li>
<li>Tomomi Kato</li>
<li>Alfred Kayser</li>
<li>Jonathan Kew</li>
<li>Paul Kim</li>
<li>Masatoshi Kimura</li>
<li>Austin King</li>
<li>Ria Klaassen</li>
<li>Marcia Knous</li>
<li>Nelson Ko</li>
<li>Michael Kohler</li>
<li>Gary Kwong</li>
<li>David Lanham</li>
<li>Brad Lassey</li>
<li>Delphine Lebédel</li>
<li>Edward Lee</li>
<li>Neil Lee</li>
<li>Raymond Lee</li>
<li>Garrett LeSage</li>
<li>Aaron Leventhal</li>
<li>Anne-Julie Ligneau</li>
<li>John Lilly</li>
<li>Zach Lipton</li>
<li>Kai Liu</li>
<li>Reed Loden</li>
<li>Lars Lohn</li>
<li>Robert Longson</li>
<li>Bob Lord</li>
<li>Phil Machalski</li>
<li>Joel Maher</li>
<li>Ere Maijala</li>
<li>David Mandelin</li>
<li>Gervase Markham</li>
<li>Sean Martell</li>
<li>Jim Mathies</li>
<li>Blair McBride</li>
<li>Erica McClure</li>
<li>Graeme McCutcheon</li>
<li>Patrick McManus</li>
<li>Heather Meeker</li>
<li>Walter Meinl</li>
<li>Myk Melez</li>
<li>Federico Mena-Quintero</li>
<li>Mark Mentovai</li>
<li>Laura Mesa</li>
<li>Steven Michaud</li>
<li>Matthew Middleton</li>
<li>Ted Mielczarek</li>
<li>Bernd Mielke</li>
<li>Dave Miller</li>
<li>Dan Mills</li>
<li>Michael Monreal</li>
<li>Simon Montagu</li>
<li>Derek Moore</li>
<li>Mike Morgan</li>
<li>Tiffney Mortensen</li>
<li>Dan Mosedale</li>
<li>Michael Moy</li>
<li>Jeff Muizelaar</li>
<li>Masayuki Nakano</li>
<li>Murali Nandigama</li>
<li>Marria Nazif</li>
<li>Kev Needham</li>
<li>Kaori Negoro</li>
<li>Nicholas Nethercote</li>
<li>Ben Newman</li>
<li>Nick Nguyen</li>
<li>Johnathan Nightingale</li>
<li>Timothy Nikkel</li>
<li>Andreas Nilsson</li>
<li>Tristan Nitot</li>
<li>Alice Nodelman</li>
<li>Matthew Noorenberghe</li>
<li>Michal Novotny</li>
<li>Robert O'Callahan</li>
<li>John O'Duinn</li>
<li>Paul O'Shannessy</li>
<li>Jan Odvárko</li>
<li>Tomoyuki Okazaki</li>
<li>Les Orchard</li>
<li>Jeremy Orem</li>
<li>Jason Orendorff</li>
<li>Hideo Oshima</li>
<li>Mats Palmgren</li>
<li>Stuart Parmenter</li>
<li>Jay Patel</li>
<li>Chris Pearce</li>
<li>Javier Pedemonte</li>
<li>Alfred Peng</li>
<li>Christian Persch</li>
<li>Kalle Persson</li>
<li>Ulisse Perusin</li>
<li>Olli Pettay</li>
<li>Julien Pierre</li>
<li>Anthony Piraino</li>
<li>Alex Polvi</li>
<li>Nickolay Ponomarev</li>
<li>Dan Portillo</li>
<li>Karen Prescott</li>
<li>Florian Quèze</li>
<li>Krupa Raj</li>
<li>Arun Ranganathan</li>
<li>Neil Rashbrook</li>
<li>Bret Reckard</li>
<li>J. Paul Reed</li>
<li>Rick Reitmaier</li>
<li>Robert Relyea</li>
<li>John Resig</li>
<li>Deb Richardson</li>
<li>Tim Riley</li>
<li>Phil Ringnalda</li>
<li>Julien Rivaud</li>
<li>Mikeal Rogers</li>
<li>David Rolnitzky</li>
<li>Asaf Romano</li>
<li>Oleg Romashin</li>
<li>Paul Rouget</li>
<li>Tim Rowley</li>
<li>Jesse Ruderman</li>
<li>Brian Ryner</li>
<li>Alexander Sack</li>
<li>Hideo Saito</li>
<li>Atsushi Sakai</li>
<li>Eiko Sakuma</li>
<li>Andrei Saprykin</li>
<li>Aki Sasaki</li>
<li>Ken Saunders</li>
<li>Robert Sayre</li>
<li>Mike Schroepfer</li>
<li>Kurt Schultz</li>
<li>Keith Schwarz</li>
<li>Justin Scott</li>
<li>Hiroshi Sekiya</li>
<li>Tara Shahian</li>
<li>Melissa Shapiro</li>
<li>Gavin Sharp</li>
<li>Mike Shaver</li>
<li>Eric Shepherd</li>
<li>Hiroshi Shimoda</li>
<li>Atsushi Shimono</li>
<li>Jungshik Shin</li>
<li>Jonas Sicking</li>
<li>Damon Sicore</li>
<li>Roger B. Sidje</li>
<li>Samuel Sidler</li>
<li>Henrik Skupin</li>
<li>John Slater</li>
<li>Benjamin Smedberg</li>
<li>Andrew Smith</li>
<li>Edwin Smith</li>
<li>Mark Smith</li>
<li>Window Snyder</li>
<li>Josh Soref</li>
<li>Nochum Sossonko</li>
<li>Ian Spence</li>
<li>Seth Spitzer</li>
<li>Markus Stange</li>
<li>Jakub Steiner</li>
<li>Johnny Stenback</li>
<li>Brandon Sterne</li>
<li>Rob Stradling</li>
<li>Robert Strong</li>
<li>Jay Sullivan</li>
<li>Vicky Sun</li>
<li>Alexander Surkov</li>
<li>Mark Surman</li>
<li>Andrew Sutherland</li>
<li>Clint Talbert</li>
<li>Margaret Tallman</li>
<li>David Tenser</li>
<li>Chris Thomas</li>
<li>Nick Thomas</li>
<li>Laura Thomson</li>
<li>Karl Tomlinson</li>
<li>Dave Townsend</li>
<li>Aaron Train</li>
<li>Phong Tran</li>
<li>Ben Turner</li>
<li>Doug Turner</li>
<li>Amié Tyrrel</li>
<li>Peter Van der Beken</li>
<li>Peter van der Woude</li>
<li>Teune van Steeg</li>
<li>Ryan VanderMeulen</li>
<li>Daniel Veditz</li>
<li>Michael Ventnor</li>
<li>Alexei Volkov</li>
<li>Vladimir Vukićević</li>
<li>Håkan Waara</li>
<li>Jeff Walden</li>
<li>Tracy Walker</li>
<li>Cheng Wang</li>
<li>Martijn Wargers</li>
<li>Jonathan Watt</li>
<li>Peter Weilbacher</li>
<li>Zack Weinberg</li>
<li>Frédéric Wenzel</li>
<li>Steffen Wilberg</li>
<li>Drew Willcoxon</li>
<li>Shawn Wilsher</li>
<li>Kathleen Wilson</li>
<li>Dan Witte</li>
<li>John Wolfe</li>
<li>Steve Won</li>
<li>Justin Wood</li>
<li>Michael Wu</li>
<li>Masahiro Yamada</li>
<li>Satoko Takita Yamaguchi (Chibi)</li>
<li>Christine Yen</li>
<li>Kohei Yoshino</li>
<li>Shigeru Yoshitake</li>
<li>Tanner M. Young</li>
<li>Boris Zbarsky</li>
<li>Marco Zehe</li>
<li>Matthew Zeier</li>
</ul>
<div dir="&locale.dir;">
&credit.translation;
</div>
</div>
<!-- organizational supporters -->
<div class="creditsGroup">
<h3 dir="&locale.dir;">&credit.thanks;</h3>
<ul>
<li>Google</li>
<li>Yahoo!</li>
<li>IBM</li>
<li>Sun Microsystems</li>
<li>Red Hat</li>
<li></li>
<li>Oregon State University - Open Source Lab</li>
<li></li>
<li>Global Netoptex, Inc</li>
<li>Internet Software Consortium</li>
<li></li>
<li>Cooley Godward, LLP</li>
<li>Greenburg Traurig, LLP</li>
<li></li>
<li>OutCast Communications</li>
<li></li>
<li>The Royal Order of Experience Design</li>
<li>Nobox</li>
<li>silverorange</li>
<li>Glaxstar</li>
<li></li>
<li>MozillaZine Community</li>
</ul>
</div>
<p id="gecko" class="center" dir="&locale.dir;">&credit.poweredByGeckoReg;</p>
<p class="footnote">
Mozilla Firefox&reg; and the Firefox logo are registered trademarks of the
Mozilla Foundation. You are not granted rights or licenses to the trademarks
of the Mozilla Foundation or any party, including without limitation the
Firefox name or logo. Gecko&reg; is a registered trademark of Netscape
Communications Corporation.</p>
<p class="footnote">
U.S. GOVERNMENT END USERS. The Software is a &ldquo;commercial item,&rdquo;
as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of
&ldquo;commercial computer software&rdquo; and &ldquo;commercial computer software
documentation,&rdquo; as such terms are used in 48 C.F.R. 12.212 (Sept. 1995).
Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through
227.7202-4 (June 1995), all U.S. Government End Users acquire the
Software with only those rights set forth herein.</p>
</div>
<div id="footerBox">
<img src="chrome://branding/content/aboutFooter.png" />
</div>
</body>
</html>

Просмотреть файл

@ -105,7 +105,7 @@ let Change = {
document.title = this._str("change.synckey.title");
introText.innerHTML = this._str("change.synckey.introText");
introText2.innerHTML = this._str("change.synckey.introText2");
warningText.innerHTML = this._str("change.synckey.warningText");
warningText.innerHTML = this._str("change.synckey2.warningText");
this._dialog.getButton("accept")
.setAttribute("label", this._str("change.synckey.acceptButton"));
}
@ -127,7 +127,7 @@ let Change = {
else {
document.title = this._str("change.password.title");
box2label.value = this._str("new.password.confirm");
introText.textContent = this._str("change.password.introText");
introText.textContent = this._str("change.password2.introText");
warningText.textContent = this._str("change.password.warningText");
this._dialog.getButton("accept")
.setAttribute("label", this._str("change.password.acceptButton"));
@ -181,7 +181,7 @@ let Change = {
if (this._updatingPassphrase) {
Weave.Service.passphrase = pp;
if (Weave.Service.login()) {
this._updateStatus("change.synckey.success", "success");
this._updateStatus("change.synckey2.success", "success");
Weave.Service.persistLogin();
}
else {
@ -192,9 +192,9 @@ let Change = {
this._updateStatus("change.synckey.label", "active");
if (Weave.Service.changePassphrase(pp))
this._updateStatus("change.synckey.success", "success");
this._updateStatus("change.synckey2.success", "success");
else
this._updateStatus("change.synckey.error", "error");
this._updateStatus("change.synckey2.error", "error");
}
return false;

Просмотреть файл

@ -40,23 +40,44 @@
<!DOCTYPE html [
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
%htmlDTD;
<!ENTITY % syncSetupDTD SYSTEM "chrome://browser/locale/syncSetup.dtd">
%syncSetupDTD;
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
%syncBrandDTD;
<!ENTITY % syncKeyDTD SYSTEM "chrome://browser/locale/syncKey.dtd">
%syncKeyDTD;
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&page.syncKeyBackup.title;</title>
<title>&syncKey.page.title;</title>
<style type="text/css">
#synckey { font-size: 150% }
footer { font-size: 70% }
# Bug 575675: Need to have an a:visited rule in a chrome document.
a:visited { color: purple; }
</style>
</head>
<body>
<h1>&page.syncKeyBackup.title;</h1>
<h1>&syncKey.page.title;</h1>
<p id="synckey">SYNCKEY</p>
<p>&page.syncKeyBackup.descr;</p>
<p>&syncKey.page.description;</p>
<div id="column1">
<h2>&syncKey.keepItSecret.heading;</h2>
<p>&syncKey.keepItSecret.description;</p>
</div>
<div id="column2">
<h2>&syncKey.keepItSafe.heading;</h2>
<p><em>&syncKey.keepItSafe1.description;</em>&syncKey.keepItSafe2.description;<em>&syncKey.keepItSafe3.description;</em>&syncKey.keepItSafe4.description;</p>
</div>
<p>&syncKey.findOutMore1.label;<a href="https://services.mozilla.com">https://services.mozilla.com</a>&syncKey.findOutMore2.label;</p>
<footer>
&syncKey.footer1.label;<a id="tosLink" href="termsURL">termsURL</a>&syncKey.footer2.label;<a id="ppLink" href="privacyURL">privacyURL</a>&syncKey.footer3.label;
</footer>
</body>
</html>

Просмотреть файл

@ -0,0 +1,282 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Firefox Sync.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Philipp von Weitershausen <philipp@weitershausen.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const Ci = Components.interfaces;
const Cc = Components.classes;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://services-sync/main.js");
Cu.import("resource://gre/modules/DownloadUtils.jsm");
let gSyncQuota = {
init: function init() {
this.bundle = document.getElementById("quotaStrings");
let caption = document.getElementById("treeCaption");
caption.firstChild.nodeValue = this.bundle.getString("quota.treeCaption.label");
gUsageTreeView.init();
this.tree = document.getElementById("usageTree");
this.tree.view = gUsageTreeView;
this.loadData();
},
loadData: function loadData() {
window.setTimeout(function() {
let usage = Weave.Service.getCollectionUsage();
gUsageTreeView.displayUsageData(usage);
}, 0);
let usageLabel = document.getElementById("usageLabel");
let bundle = this.bundle;
window.setTimeout(function() {
let quota = Weave.Service.getQuota();
if (!quota) {
usageLabel.value = bundle.getString("quota.usageError.label");
return;
}
let used = gSyncQuota.convertKB(quota[0]);
if (!quota[1]) {
// No quota on the server.
usageLabel.value = bundle.getFormattedString(
"quota.usageNoQuota.label", used);
return;
}
let percent = Math.round(100 * quota[0] / quota[1]);
let total = gSyncQuota.convertKB(quota[1]);
usageLabel.value = bundle.getFormattedString(
"quota.usagePercentage.label", [percent].concat(used).concat(total));
}, 0);
},
onAccept: function onAccept() {
let engines = gUsageTreeView.getEnginesToDisable();
for each (let engine in engines) {
Weave.Engines.get(engine).enabled = false;
}
if (engines.length) {
// The 'Weave' object will disappear once the window closes.
let Service = Weave.Service;
Weave.Utils.delay(function() Service.sync(), 0);
}
return true;
},
convertKB: function convertKB(value) {
return DownloadUtils.convertByteUnits(value * 1024);
}
};
let gUsageTreeView = {
_ignored: {keys: true,
meta: true,
clients: true},
/*
* Internal data structures underlaying the tree.
*/
_collections: [],
_byname: {},
init: function init() {
let retrievingLabel = gSyncQuota.bundle.getString("quota.retrieving.label");
for each (let engine in Weave.Engines.getEnabled()) {
if (this._ignored[engine.name])
continue;
// Some engines use the same pref, which means they can only be turned on
// and off together. We need to combine them here as well.
let existing = this._byname[engine.prefName];
if (existing) {
existing.engines.push(engine.name);
continue;
}
let obj = {name: engine.prefName,
title: this._collectionTitle(engine),
engines: [engine.name],
enabled: true,
sizeLabel: retrievingLabel};
this._collections.push(obj);
this._byname[engine.prefName] = obj;
}
},
_collectionTitle: function _collectionTitle(engine) {
try {
return gSyncQuota.bundle.getString(
"collection." + engine.prefName + ".label");
} catch (ex) {
return engine.Name;
}
},
/*
* Process the quota information as returned by info/collection_usage.
*/
displayUsageData: function displayUsageData(data) {
data = data || {};
for each (let coll in this._collections) {
coll.size = 0;
for each (let engineName in coll.engines)
coll.size += data[engineName] || 0;
let sizeLabel = "";
if (coll.size)
sizeLabel = gSyncQuota.bundle.getFormattedString(
"quota.sizeValueUnit.label", gSyncQuota.convertKB(coll.size));
coll.sizeLabel = sizeLabel;
}
let sizeColumn = this.treeBox.columns.getNamedColumn("size");
this.treeBox.invalidateColumn(sizeColumn);
},
/*
* Handle click events on the tree.
*/
onTreeClick: function onTreeClick(event) {
if (event.button == 2)
return;
let row = {}, col = {};
this.treeBox.getCellAt(event.clientX, event.clientY, row, col, {});
if (col.value && col.value.id == "enabled")
this.toggle(row.value);
},
/*
* Toggle enabled state of an engine.
*/
toggle: function toggle(row) {
// Update the tree
let collection = this._collections[row];
collection.enabled = !collection.enabled;
this.treeBox.invalidateRow(row);
// Display which ones will be removed
let freeup = 0;
let toremove = [];
for each (collection in this._collections) {
if (collection.enabled)
continue;
toremove.push(collection.name);
freeup += collection.size;
}
let caption = document.getElementById("treeCaption");
if (!toremove.length) {
caption.className = "";
caption.firstChild.nodeValue = gSyncQuota.bundle.getString(
"quota.treeCaption.label");
return;
}
toremove = [this._byname[coll].title for each (coll in toremove)];
toremove = toremove.join(gSyncQuota.bundle.getString("quota.list.separator"));
caption.firstChild.nodeValue = gSyncQuota.bundle.getFormattedString(
"quota.removal.label", [toremove]);
if (freeup)
caption.firstChild.nodeValue += gSyncQuota.bundle.getFormattedString(
"quota.freeup.label", gSyncQuota.convertKB(freeup));
caption.className = "captionWarning";
},
/*
* Return a list of engines (or rather their pref names) that should be
* disabled.
*/
getEnginesToDisable: function getEnginesToDisable() {
return [coll.name for each (coll in this._collections) if (!coll.enabled)];
},
// nsITreeView
get rowCount() {
return this._collections.length;
},
getRowProperties: function(index, properties) {},
getCellProperties: function(row, col, properties) {},
getColumnProperties: function(col, properties) {},
isContainer: function(index) { return false; },
isContainerOpen: function(index) { return false; },
isContainerEmpty: function(index) { return false; },
isSeparator: function(index) { return false; },
isSorted: function() { return false; },
canDrop: function(index, orientation, dataTransfer) { return false; },
drop: function(row, orientation, dataTransfer) {},
getParentIndex: function(rowIndex) {},
hasNextSibling: function(rowIndex, afterIndex) { return false; },
getLevel: function(index) { return 0; },
getImageSrc: function(row, col) {},
getCellValue: function(row, col) {
return this._collections[row].enabled;
},
getCellText: function getCellText(row, col) {
let collection = this._collections[row];
switch (col.id) {
case "collection":
return collection.title;
case "size":
return collection.sizeLabel;
default:
return "";
}
},
setTree: function setTree(tree) {
this.treeBox = tree;
},
toggleOpenState: function(index) {},
cycleHeader: function(col) {},
selectionChanged: function() {},
cycleCell: function(row, col) {},
isEditable: function(row, col) { return false; },
isSelectable: function (row, col) { return false; },
setCellValue: function(row, col, value) {},
setCellText: function(row, col, value) {},
performAction: function(action) {},
performActionOnRow: function(action, row) {},
performActionOnCell: function(action, row, col) {}
};

Просмотреть файл

@ -0,0 +1,97 @@
<?xml version="1.0"?>
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Firefox Sync.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2010
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Philipp von Weitershausen <philipp@weitershausen.de>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/syncQuota.css"?>
<!DOCTYPE dialog [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
<!ENTITY % syncQuotaDTD SYSTEM "chrome://browser/locale/syncQuota.dtd">
%brandDTD;
%syncBrandDTD;
%syncQuotaDTD;
]>
<dialog id="quotaDialog"
windowtype="Sync:ViewQuota"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
onload="gSyncQuota.init()"
buttons="accept,cancel"
title="&quota.dialogTitle.label;"
ondialogcancel="return true;"
ondialogaccept="return gSyncQuota.onAccept();">
<script type="application/javascript"
src="chrome://browser/content/syncQuota.js"/>
<stringbundleset id="stringbundleset">
<stringbundle id="quotaStrings"
src="chrome://browser/locale/syncQuota.properties"/>
</stringbundleset>
<vbox flex="1">
<label id="usageLabel"
value="&quota.retrievingInfo.label;"/>
<separator/>
<tree id="usageTree"
seltype="single"
hidecolumnpicker="true"
onclick="gUsageTreeView.onTreeClick(event);"
flex="1">
<treecols>
<treecol id="enabled"
type="checkbox"
fixed="true"/>
<splitter class="tree-splitter"/>
<treecol id="collection"
label="Type"
flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="size"
label="Size"
flex="1"/>
</treecols>
<treechildren flex="1"/>
</tree>
<separator/>
<description id="treeCaption"> </description>
</vbox>
</dialog>

Просмотреть файл

@ -71,7 +71,6 @@ var gSyncSetup = {
_remoteSites: [Weave.Service.serverURL, "https://api-secure.recaptcha.net"],
status: {
username: false,
password: false,
email: false,
server: false
@ -221,7 +220,7 @@ var gSyncSetup = {
case NEW_ACCOUNT_PP_PAGE:
return this._haveSyncKeyBackup && this.checkPassphrase();
case EXISTING_ACCOUNT_LOGIN_PAGE:
let hasUser = document.getElementById("existingUsername").value != "";
let hasUser = document.getElementById("existingAccountName").value != "";
let hasPass = document.getElementById("existingPassword").value != "";
if (hasUser && hasPass) {
if (this._usingMainServers)
@ -238,29 +237,42 @@ var gSyncSetup = {
return true;
},
onUsernameChange: function () {
let feedback = document.getElementById("usernameFeedbackRow");
let val = document.getElementById("weaveUsername").value;
let availCheck = "", str = "";
let available = true;
if (val) {
availCheck = Weave.Service.checkUsername(val);
available = availCheck == "available";
onEmailChange: function () {
let value = document.getElementById("weaveEmail").value;
if (!value) {
this.status.email = false;
this.checkFields();
return;
}
// Do this async to avoid blocking the widget while we go to the server.
window.setTimeout(function() {
gSyncSetup.checkAccount(value);
}, 0);
},
checkAccount: function(value) {
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
let feedback = document.getElementById("emailFeedbackRow");
let valid = re.test(value);
let str = "";
if (!valid) {
str = "invalidEmail.label";
} else {
let availCheck = Weave.Service.checkAccount(value);
valid = availCheck == "available";
if (!valid) {
if (availCheck == "notAvailable")
str = "usernameNotAvailable.label";
else
str = availCheck;
}
}
if (!available) {
if (availCheck == "notAvailable")
str = "usernameNotAvailable.label";
else
str = availCheck;
}
this._setFeedbackMessage(feedback, available, str);
this.status.username = val && available;
if (available)
Weave.Service.username = val;
this._setFeedbackMessage(feedback, valid, str);
this.status.email = valid;
if (valid)
Weave.Service.account = value;
this.checkFields();
},
@ -284,22 +296,19 @@ var gSyncSetup = {
this.checkFields();
},
onEmailChange: function () {
//XXXzpao Not sure about this regex. Look into it in followup (bug 583650)
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
this.status.email = re.test(document.getElementById("weaveEmail").value);
this._setFeedbackMessage(document.getElementById("emailFeedbackRow"),
this.status.email,
"invalidEmail.label");
this.checkFields();
},
onPassphraseChange: function () {
// Ignore if there's no actual change from the generated one.
let el = document.getElementById("weavePassphrase");
if (gSyncUtils.normalizePassphrase(el.value) == Weave.Service.passphrase) {
el = document.getElementById("generatePassphraseButton");
el.hidden = true;
this._haveCustomSyncKey = false;
return;
}
this._haveSyncKeyBackup = true;
this._haveCustomSyncKey = true;
let el = document.getElementById("generatePassphraseButton");
el = document.getElementById("generatePassphraseButton");
el.hidden = false;
this.checkFields();
},
@ -420,17 +429,16 @@ var gSyncSetup = {
label.value = this._stringBundle.GetStringFromName("verifying.label");
feedback.hidden = false;
let username = document.getElementById("weaveUsername").value;
let password = document.getElementById("weavePassword").value;
let email = document.getElementById("weaveEmail").value;
let challenge = getField("challenge");
let response = getField("response");
let error = Weave.Service.createAccount(username, password, email,
let error = Weave.Service.createAccount(email, password,
challenge, response);
if (error == null) {
Weave.Service.username = username;
Weave.Service.account = email;
Weave.Service.password = password;
this._handleNoScript(false);
this.wizard.pageIndex = SETUP_SUCCESS_PAGE;
@ -449,7 +457,7 @@ var gSyncSetup = {
this.captchaBrowser.loadURI(Weave.Service.miscAPI + "captcha_html");
break;
case EXISTING_ACCOUNT_LOGIN_PAGE:
Weave.Service.username = document.getElementById("existingUsername").value;
Weave.Service.account = document.getElementById("existingAccountName").value;
Weave.Service.password = document.getElementById("existingPassword").value;
Weave.Service.passphrase = document.getElementById("existingPassphrase").value;
// verifyLogin() will likely return false because we probably don't
@ -622,9 +630,9 @@ var gSyncSetup = {
this._setFeedbackMessage(feedback, true);
}
// recheck username against the new server
// Recheck account against the new server.
if (valid)
this.onUsernameChange();
this.onEmailChange();
this.status.server = valid;
this.checkFields();
@ -646,7 +654,7 @@ var gSyncSetup = {
if (uri && checkRemote) {
function isValid(uri) {
Weave.Service.serverURL = uri.spec;
let check = Weave.Service.checkUsername("a");
let check = Weave.Service.checkAccount("a");
return (check == "available" || check == "notAvailable");
}
@ -721,7 +729,7 @@ var gSyncSetup = {
document.getElementById("historyCount").value =
PluralForm.get(daysOfHistory,
this._stringBundle.GetStringFromName("historyDaysCount.label"))
.replace("#1", daysOfHistory);
.replace("%S", daysOfHistory);
// bookmarks
let bookmarks = 0;
@ -736,14 +744,14 @@ var gSyncSetup = {
document.getElementById("bookmarkCount").value =
PluralForm.get(bookmarks,
this._stringBundle.GetStringFromName("bookmarksCount.label"))
.replace("#1", bookmarks);
.replace("%S", bookmarks);
// passwords
let logins = Weave.Svc.Login.getAllLogins({});
document.getElementById("passwordCount").value =
PluralForm.get(logins.length,
this._stringBundle.GetStringFromName("passwordsCount.label"))
.replace("#1", logins.length);
.replace("%S", logins.length);
this._case1Setup = true;
break;
case 2:
@ -771,7 +779,7 @@ var gSyncSetup = {
let label =
PluralForm.get(count - 5,
this._stringBundle.GetStringFromName("additionalClientCount.label"))
.replace("#1", count - 5);
.replace("%S", count - 5);
appendNode(label);
}
this._case2Setup = true;

Просмотреть файл

@ -107,16 +107,14 @@
<column class="inputColumn" flex="1"/>
</columns>
<rows>
<row id="usernameRow" align="center">
<label value="&signIn.username.label;"
accesskey="&signIn.username.accesskey;"
control="weaveUsername"/>
<textbox id="weaveUsername"
onchange="gSyncSetup.onUsernameChange()"/>
<row id="emailRow" align="center">
<label value="&setup.emailAddress.label;"
accesskey="&setup.emailAddress.accesskey;"
control="weaveEmail"/>
<textbox id="weaveEmail"
onchange="gSyncSetup.onEmailChange()"/>
</row>
<row id="usernameFeedbackRow"
align="center"
hidden="true">
<row id="emailFeedbackRow" align="center" hidden="true">
<spacer/>
<hbox>
<image class="statusIcon"/>
@ -146,20 +144,6 @@
<label class="status" value=" "/>
</hbox>
</row>
<row id="emailRow" align="center">
<label value="&setup.emailAddress.label;"
accesskey="&setup.emailAddress.accesskey;"
control="weaveEmail"/>
<textbox id="weaveEmail"
onchange="gSyncSetup.onEmailChange()"/>
</row>
<row id="emailFeedbackRow" align="center" hidden="true">
<spacer/>
<hbox>
<image class="statusIcon"/>
<label class="status" value=" "/>
</hbox>
</row>
<row align="center">
<label control="serverType"
value="&server.label;"/>
@ -308,16 +292,16 @@
<textbox id="existingServerURL"
onchange="gSyncSetup.checkFields(event)"/>
</row>
<row id="existingUsernameRow" align="center">
<label id="existingUsernameLabel"
value="&signIn.username.label;"
accesskey="&signIn.username.accesskey;"
control="existingUsername"/>
<textbox id="existingUsername"
<row id="existingAccountRow" align="center">
<label id="existingAccountLabel"
value="&signIn.account.label;"
accesskey="&signIn.account.accesskey;"
control="existingAccount"/>
<textbox id="existingAccountName"
oninput="gSyncSetup.checkFields(event)"
onchange="gSyncSetup.checkFields(event)"/>
</row>
<row id="existingUsernameFeedbackRow" align="center" hidden="true">
<row id="existingAccountFeedbackRow" align="center" hidden="true">
<spacer/>
<hbox>
<image class="statusIcon"/>

Просмотреть файл

@ -153,9 +153,19 @@ let gSyncUtils = {
*/
passphraseEmail: function(elid) {
let pp = document.getElementById(elid).value;
let subject = this.bundle.GetStringFromName("email.synckey.subject");
let body = this.bundle.formatStringFromName("email.synckey.body", [pp], 1);
let uri = Weave.Utils.makeURI("mailto:?subject=" + subject + "&body=" + body);
let subject = this.bundle.GetStringFromName("email.syncKey.subject");
let label = this.bundle.formatStringFromName("email.syncKey.label", [pp], 1);
let body = "&body=" + label + "%0A%0A" +
this.bundle.GetStringFromName("email.syncKey.description")
+ "%0A%0A" +
this.bundle.GetStringFromName("email.keepItSecret.label") +
this.bundle.GetStringFromName("email.keepItSecret.description")
+ "%0A%0A" +
this.bundle.GetStringFromName("email.keepItSafe.label") +
this.bundle.GetStringFromName("email.keepItSafe.description")
+ "%0A%0A" +
this.bundle.GetStringFromName("email.findOutMore.label");
let uri = Weave.Utils.makeURI("mailto:?subject=" + subject + body);
let protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Ci.nsIExternalProtocolService);
protoSvc.loadURI(uri);
@ -183,6 +193,17 @@ let gSyncUtils = {
let el = iframe.contentDocument.getElementById("synckey");
el.firstChild.nodeValue = pp;
// Insert the TOS and Privacy Policy URLs into the page.
let termsURL = Weave.Svc.Prefs.get("termsURL");
el = iframe.contentDocument.getElementById("tosLink");
el.setAttribute("href", termsURL);
el.firstChild.nodeValue = termsURL;
let privacyURL = Weave.Svc.Prefs.get("privacyURL");
el = iframe.contentDocument.getElementById("ppLink");
el.setAttribute("href", privacyURL);
el.firstChild.nodeValue = privacyURL;
callback(iframe);
}, false);
},
@ -237,6 +258,9 @@ let gSyncUtils = {
let serializer = new XMLSerializer();
let output = serializer.serializeToString(iframe.contentDocument);
output = output.replace(/<!DOCTYPE (.|\n)*?]>/,
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' +
'"DTD/xhtml1-strict.dtd">');
output = Weave.Utils.encodeUTF8(output);
stream.write(output, output.length);
}
@ -262,6 +286,8 @@ let gSyncUtils = {
valid = val1.length >= Weave.MIN_PASS_LENGTH;
else if (val1 && val1 == Weave.Service.username)
error = "change.password.pwSameAsUsername";
else if (val1 && val1 == Weave.Service.account)
error = "change.password.pwSameAsEmail";
else if (val1 && val1 == Weave.Service.password)
error = "change.password.pwSameAsPassword";
else if (val1 && val1 == Weave.Service.passphrase)
@ -293,6 +319,8 @@ let gSyncUtils = {
if (val == Weave.Service.username)
error = "change.synckey.sameAsUsername";
else if (val == Weave.Service.account)
error = "change.synckey.sameAsEmail";
else if (val == Weave.Service.password)
error = "change.synckey.sameAsPassword";
else if (change && val == Weave.Service.passphrase)

Просмотреть файл

@ -11,11 +11,25 @@
display: none;
}
.tabbrowser-tabs:not([closebuttons="noclose"]):not([closebuttons="closeatend"]) > .tabbrowser-tab[selected="true"]:not([pinned]) > .tab-close-button,
.tabbrowser-tabs[closebuttons="alltabs"] > .tabbrowser-tab:not([pinned]) > .tab-close-button {
.tabbrowser-tabs:not([closebuttons="noclose"]):not([closebuttons="closeatend"]) > * > * > * .tab-close-button:not([pinned])[selected="true"],
.tabbrowser-tabs[closebuttons="alltabs"] > * > * > * > .tab-close-button:not([pinned]) {
display: -moz-box;
}
.tab-close-button[selected="true"] {
/* Make this button focusable so clicking on it will not focus the tab while
it's getting closed */
-moz-user-focus: normal;
}
.tab-label[pinned] {
display: none;
}
.tab-stack {
vertical-align: middle; /* for pinned tabs */
}
tabpanels {
background-color: white;
}
@ -24,3 +38,20 @@ tabpanels {
position: relative;
z-index: 1;
}
/* tab progress */
.tab-progress {
-moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter") !important;
margin: 0;
min-width: 0;
}
.tab-progress[selected],
.tab-progress:not([busy]) {
display: none;
}
.tab-progress-container {
-moz-box-pack: start;
}

Просмотреть файл

@ -372,13 +372,8 @@
return;
if (this.mTotalProgress) {
const STATES = 8;
let state = Math.ceil(STATES * this.mTotalProgress);
if (state != this.mTab.getAttribute("progress")) {
this.mTab.setAttribute("progress", state);
this.mTab.removeAttribute("stalled");
this._startStalledTimer();
}
let value = Math.ceil(this.mTotalProgress * 100);
this.mTab.setAttribute("progresspercent", value);
}
this._callProgressListeners("onProgressChange",
@ -435,6 +430,7 @@
if (!this.mBlank) {
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
this.mTab.setAttribute("busy", "true");
this.mTab.setAttribute("progresspercent", "0");
this._startStalledTimer();
this.mTabBrowser.updateIcon(this.mTab);
this.mTabBrowser.setTabTitleLoading(this.mTab);
@ -462,7 +458,7 @@
this.mBlank = false;
this.mTab.removeAttribute("busy");
this.mTab.removeAttribute("progress");
this.mTab.removeAttribute("progresspercent");
this.mTab.removeAttribute("stalled");
this._cancelStalledTimer();
this.mTabBrowser.updateIcon(this.mTab);
@ -733,6 +729,12 @@
}
} catch (e) {}
if (window.TabView) {
let groupName = TabView.getActiveGroupName();
if (groupName)
newTitle = groupName + sep + newTitle;
}
return newTitle;
]]>
</body>
@ -745,7 +747,8 @@
// ToDo: this will be removed when we gain ability to draw to the menu bar.
// Bug 586175
this.ownerDocument.title = TabView.windowTitle;
} else {
}
else {
this.ownerDocument.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
}
]]>
@ -3322,17 +3325,26 @@
</resources>
<content context="tabContextMenu" closetabtext="&closeTab.label;">
<xul:image xbl:inherits="validate,src=image"
class="tab-icon-image"
role="presentation"/>
<xul:label flex="1"
xbl:inherits="value=label,crop,accesskey"
class="tab-text"
role="presentation"/>
<xul:toolbarbutton anonid="close-button"
tabindex="-1"
clickthrough="never"
class="tab-close-button"/>
<xul:stack class="tab-stack" flex="1">
<xul:vbox class="tab-progress-container">
<xul:progressmeter class="tab-progress" mode="normal"
xbl:inherits="value=progresspercent,busy,stalled,fadein,selected"/>
</xul:vbox>
<xul:hbox class="tab-content" align="center">
<xul:image xbl:inherits="validate,src=image,fadein,pinned,busy,stalled,selected"
class="tab-icon-image"
role="presentation"/>
<xul:label flex="1"
xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected"
class="tab-text tab-label"
role="presentation"/>
<xul:toolbarbutton anonid="close-button"
xbl:inherits="fadein,pinned,selected"
tabindex="-1"
clickthrough="never"
class="tab-close-button"/>
</xul:hbox>
</xul:stack>
</content>
<implementation>

Просмотреть файл

@ -790,7 +790,14 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
if (typeof item.setResizable == 'function')
item.setResizable(false);
if (item.tab == gBrowser.selectedTab)
// if it is visually active, set it as the active tab.
if (iQ(item.container).hasClass("focus"))
this.setActiveTab(item);
// if it matches the selected tab or no active tab and the browser
// tab is hidden, the active group item would be set.
if (item.tab == gBrowser.selectedTab ||
(!GroupItems.getActiveGroupItem() && !item.tab.hidden))
GroupItems.setActiveGroupItem(this);
}
@ -835,7 +842,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
this._children.splice(index, 1);
if (item == this._activeTab) {
if (this._children.length)
if (this._children.length > 0)
this._activeTab = this._children[0];
else
this._activeTab = null;
@ -882,6 +889,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
addAppTab: function GroupItem_addAppTab(xulTab) {
let self = this;
// add the icon
let icon = xulTab.image || Utils.defaultFaviconURL;
let $appTab = iQ("<img>")
.addClass("appTabIcon")
@ -897,6 +905,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
UI.goToTab(iQ(this).data("xulTab"));
});
// adjust the tray
let columnWidth = $appTab.width();
if (parseInt(this.$appTabTray.css("width")) != columnWidth) {
this.$appTabTray.css({width: columnWidth});
@ -904,6 +913,25 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
},
// ----------
// Removes the given xul:tab as an app tab in this group's apptab tray
removeAppTab: function GroupItem_removeAppTab(xulTab) {
// remove the icon
iQ(".appTabIcon", this.$appTabTray).each(function(icon) {
let $icon = iQ(icon);
if ($icon.data("xulTab") != xulTab)
return;
$icon.remove();
});
// adjust the tray
if (!iQ(".appTabIcon", this.$appTabTray).length) {
this.$appTabTray.css({width: 0});
this.arrange();
}
},
// ----------
// Function: hideExpandControl
// Hide the control which expands a stacked groupItem into a quick-look view.
@ -1502,12 +1530,14 @@ let GroupItems = {
// ----------
// Function: uninit
uninit : function GroupItems_uninit () {
// call our cleanup functions
this._cleanupFunctions.forEach(function(func) {
func();
});
this._cleanupFunctions = [];
// additional clean up
this.groupItems = null;
},
@ -1530,6 +1560,22 @@ let GroupItems = {
});
},
// ----------
// when a tab becomes pinned, add it to the app tab tray in all groups
handleTabPin: function GroupItems_handleTabPin(xulTab) {
this.groupItems.forEach(function(groupItem) {
groupItem.addAppTab(xulTab);
});
},
// ----------
// when a tab becomes unpinned, remove it from the app tab tray in all groups
handleTabUnpin: function GroupItems_handleTabUnpin(xulTab) {
this.groupItems.forEach(function(groupItem) {
groupItem.removeAppTab(xulTab);
});
},
// ----------
// Function: getNextID
// Returns the next unused groupItem ID.

Просмотреть файл

@ -334,7 +334,7 @@ function hideSearch(event){
iQ("#searchbox").val("");
iQ("#search").hide();
iQ("#searchbutton").css({top: 0, left: 0, opacity:.8});
iQ("#searchbutton").css({ opacity:.8 });
var mainWindow = gWindow.document.getElementById("main-window");
mainWindow.setAttribute("activetitlebarcolor", "#C4C4C4");
@ -350,6 +350,10 @@ function hideSearch(event){
let newEvent = document.createEvent("Events");
newEvent.initEvent("tabviewsearchdisabled", false, false);
dispatchEvent(newEvent);
// Return focus to the tab window
UI.blurAll();
gTabViewFrame.contentWindow.focus();
}
function performSearch() {
@ -360,7 +364,7 @@ function performSearch() {
function ensureSearchShown(event){
var $search = iQ("#search");
var $searchbox = iQ("#searchbox");
iQ("#searchbutton").css({top: -78, left: -300, opacity: 1});
iQ("#searchbutton").css({ opacity: 1 });
if ($search.css("display") == "none") {

Просмотреть файл

@ -489,6 +489,9 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
// Updates this item to visually indicate that it's active.
makeActive: function TabItem_makeActive() {
iQ(this.container).addClass("focus");
if (this.parent)
this.parent.setActiveTab(this);
},
// ----------
@ -831,8 +834,8 @@ let TabItems = {
unlink: function TabItems_unlink(tab) {
try {
Utils.assertThrow(tab, "tab");
Utils.assertThrow(!tab.pinned, "shouldn't be an app tab");
Utils.assertThrow(tab.tabItem, "should already be linked");
// note that it's ok to unlink an app tab; see .handleTabUnpin
this.unregister(tab.tabItem);
tab.tabItem._sendToSubscribers("close");
@ -851,6 +854,19 @@ let TabItems = {
}
},
// ----------
// when a tab becomes pinned, destroy its TabItem
handleTabPin: function TabItems_handleTabPin(xulTab) {
this.unlink(xulTab);
},
// ----------
// when a tab becomes unpinned, create a TabItem for it
handleTabUnpin: function TabItems_handleTabUnpin(xulTab) {
this.link(xulTab);
this.update(xulTab);
},
// ----------
// Function: heartbeat
// Allows us to spreadout update calls over a period of time.
@ -993,7 +1009,10 @@ let TabItems = {
if (groupItem) {
groupItem.add(item);
if (item.tab == gBrowser.selectedTab)
// if it matches the selected tab or no active tab and the browser
// tab is hidden, the active group item would be set.
if (item.tab == gBrowser.selectedTab ||
(!GroupItems.getActiveGroupItem() && !item.tab.hidden))
GroupItems.setActiveGroupItem(item.parent);
}
}

Просмотреть файл

@ -24,6 +24,7 @@
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
* Ehsan Akhgari <ehsan@mozilla.com>
* Raymond Lee <raymond@appcoast.com>
* Sean Dunn <seanedunn@yahoo.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
@ -48,9 +49,9 @@ let Keys = { meta: false };
// Class: UI
// Singleton top-level UI manager.
let UI = {
// Variable: _frameInitalized
// Variable: _frameInitialized
// True if the Tab View UI frame has been initialized.
_frameInitalized: false,
_frameInitialized: false,
// Variable: _pageBounds
// Stores the page bounds.
@ -83,6 +84,10 @@ let UI = {
// Keeps track of event listeners added to the AllTabs object.
_eventListeners: {},
// Variable: _cleanupFunctions
// An array of functions to be called at uninit time
_cleanupFunctions: [],
// ----------
// Function: init
// Must be called after the object is created.
@ -225,14 +230,28 @@ let UI = {
Services.obs.addObserver(observer, "quit-application-requested", false);
// ___ Done
this._frameInitalized = true;
this._frameInitialized = true;
this._save();
// fire an iframe initialized event so everyone knows tab view is
// initialized.
let event = document.createEvent("Events");
event.initEvent("tabviewframeinitialized", true, false);
dispatchEvent(event);
} catch(e) {
Utils.log(e);
}
},
uninit: function UI_uninit() {
// call our cleanup functions
this._cleanupFunctions.forEach(function(func) {
func();
});
this._cleanupFunctions = [];
// additional clean up
TabItems.uninit();
GroupItems.uninit();
Storage.uninit();
@ -242,6 +261,16 @@ let UI = {
this._pageBounds = null;
this._reorderTabItemsOnShow = null;
this._reorderTabsOnHide = null;
this._frameInitialized = false;
},
// Function: blurAll
// Blurs any currently focused element
//
blurAll: function UI_blurAll() {
iQ(":focus").each(function(element) {
element.blur();
});
},
// ----------
@ -419,6 +448,13 @@ let UI = {
} else {
// if not closing the last tab
if (gBrowser.tabs.length > 1) {
// Don't return to TabView if there are any app tabs
for (let a = 0; a < gBrowser.tabs.length; a++) {
let theTab = gBrowser.tabs[a];
if (theTab.pinned && gBrowser._removingTabs.indexOf(theTab) == -1)
return;
}
var groupItem = GroupItems.getActiveGroupItem();
// 1) Only go back to the TabView tab when there you close the last
@ -429,7 +465,7 @@ let UI = {
// Can't use timeout here because user would see a flicker of
// switching to another tab before the TabView interface shows up.
if ((groupItem && groupItem._children.length == 1) ||
(groupItem == null && gBrowser.visibleTabs.length == 1)) {
(groupItem == null && gBrowser.visibleTabs.length <= 1)) {
// for the tab focus event to pick up.
self._closedLastVisibleTab = true;
// remove the zoom prep.
@ -459,6 +495,28 @@ let UI = {
for (let name in this._eventListeners)
AllTabs.register(name, this._eventListeners[name]);
// Start watching for tab pin events, and set up our uninit for same.
function handleTabPin(event) {
TabItems.handleTabPin(event.originalTarget);
GroupItems.handleTabPin(event.originalTarget);
}
gBrowser.tabContainer.addEventListener("TabPinned", handleTabPin, false);
this._cleanupFunctions.push(function() {
gBrowser.tabContainer.removeEventListener("TabPinned", handleTabPin, false);
});
// Start watching for tab unpin events, and set up our uninit for same.
function handleTabUnpin(event) {
TabItems.handleTabUnpin(event.originalTarget);
GroupItems.handleTabUnpin(event.originalTarget);
}
gBrowser.tabContainer.addEventListener("TabUnpinned", handleTabUnpin, false);
this._cleanupFunctions.push(function() {
gBrowser.tabContainer.removeEventListener("TabUnpinned", handleTabUnpin, false);
});
},
// ----------
@ -582,7 +640,7 @@ let UI = {
function getClosestTabBy(norm) {
var centers =
[[item.bounds.center(), item]
[[item.bounds.center(), item]
for each(item in TabItems.getItems()) if (!item.parent || !item.parent.hidden)];
var myCenter = self.getActiveTab().bounds.center();
var matches = centers
@ -900,6 +958,8 @@ let UI = {
activeTab = gBrowser.selectedTab.tabItem;
if (activeTab)
activeTab.zoomIn();
this.blurAll();
},
// ----------
@ -997,7 +1057,7 @@ let UI = {
// Function: _save
// Saves the data for this object to persistent storage
_save: function UI__save() {
if (!this._frameInitalized)
if (!this._frameInitialized)
return;
var data = {

Просмотреть файл

@ -94,6 +94,7 @@ endif
_BROWSER_FILES = \
browser_typeAheadFind.js \
browser_keywordSearch.js \
browser_NetworkPrioritizer.js \
browser_allTabsPanel.js \
browser_alltabslistener.js \
@ -183,6 +184,9 @@ _BROWSER_FILES = \
browser_sanitizeDialog.js \
browser_scope.js \
browser_selectTabAtIndex.js \
browser_tab_dragdrop.js \
browser_tab_dragdrop2.js \
browser_tab_dragdrop2_frame1.xul \
browser_tabfocus.js \
browser_tabs_owner.js \
browser_visibleTabs.js \
@ -208,6 +212,8 @@ _BROWSER_FILES = \
browser_tabMatchesInAwesomebar.js \
file_bug550565_popup.html \
file_bug550565_favicon.ico \
browser_overLinkInLocationBar.js \
browser_overLinkInLocationBar.html \
$(NULL)
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))

Просмотреть файл

@ -72,13 +72,14 @@ function imageZoomSwitch() {
finishTest();
});
gBrowser.selectedTab = gTab2;
finishTest();
});
});
}
var finishTestStarted = false;
function finishTest() {
ok(!finishTestStarted, "finishTest called more than once");
finishTestStarted = true;
gBrowser.selectedTab = gTab1;
FullZoom.reset();
gBrowser.removeTab(gTab1);
@ -94,7 +95,8 @@ function zoomTest(tab, val, msg) {
}
function load(tab, url, cb) {
let didLoad = didZoom = false;
let didLoad = false;
let didZoom = false;
tab.linkedBrowser.addEventListener("load", function (event) {
event.currentTarget.removeEventListener("load", arguments.callee, true);
didLoad = true;
@ -112,7 +114,8 @@ function load(tab, url, cb) {
}
function navigate(direction, cb) {
let didPs = didZoom = false;
let didPs = false;
let didZoom = false;
gBrowser.addEventListener("pageshow", function (event) {
gBrowser.removeEventListener("pageshow", arguments.callee, true);
didPs = true;

Просмотреть файл

@ -0,0 +1,60 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
**/
function test() {
waitForExplicitFinish();
let tab = gBrowser.selectedTab = gBrowser.addTab();
let searchText = "test search";
let listener = {
onStateChange: function onLocationChange(webProgress, req, flags, status) {
ok(flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT, "only notified for document");
// Only care about starts
if (!(flags & Ci.nsIWebProgressListener.STATE_START))
return;
ok(req instanceof Ci.nsIChannel, "req is a channel");
let searchURL = Services.search.originalDefaultEngine.getSubmission(searchText).uri.spec;
is(req.originalURI.spec, searchURL, "search URL was loaded");
info("Actual URI: " + req.URI.spec);
Services.ww.unregisterNotification(observer);
gBrowser.removeProgressListener(this);
executeSoon(function () {
gBrowser.removeTab(tab);
finish();
});
}
}
gBrowser.addProgressListener(listener, Ci.nsIWebProgressListener.NOTIFY_STATE_DOCUMENT);
let observer = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
ok(false, "Alert window opened");
let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
win.addEventListener("load", function() {
win.removeEventListener("load", arguments.callee, false);
win.close();
}, false);
gBrowser.removeProgressListener(listener);
executeSoon(function () {
gBrowser.removeTab(tab);
finish();
});
}
Services.ww.unregisterNotification(this);
}
};
Services.ww.registerNotification(observer);
// Simulate a user entering search terms
gURLBar.value = searchText;
gURLBar.focus();
EventUtils.synthesizeKey("VK_RETURN", {});
}

Просмотреть файл

@ -0,0 +1,7 @@
<html>
<body>
<p>
<a href="http://example.com/" id="link">LINK</a>
</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,177 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is browser test code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Drew Willcoxon <adw@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* This tests the "over-link" that appears in the location bar when the user
* mouses over a link. See bug 587908.
*/
const TEST_URL = "http://mochi.test:8888/browser/browser/base/content/test/browser_overLinkInLocationBar.html";
var gTestIter;
// TESTS //////////////////////////////////////////////////////////////////////
function smokeTestGenerator() {
let tab = openTestPage();
yield;
let contentDoc = gBrowser.contentDocument;
let link = contentDoc.getElementById("link");
mouseover(link);
yield;
checkURLBar(true);
mouseout(link);
yield;
checkURLBar(false);
gBrowser.removeTab(tab);
}
function test() {
waitForExplicitFinish();
gTestIter = smokeTestGenerator();
cont();
}
// HELPERS ////////////////////////////////////////////////////////////////////
/**
* Advances the test iterator. When all iterations have completed, the entire
* suite is finish()ed.
*/
function cont() {
try {
gTestIter.next();
}
catch (err if err instanceof StopIteration) {
finish();
}
}
/**
* Asserts that the location bar looks like it should.
*
* @param shouldShowOverLink
* True if you expect the over-link to be showing and false otherwise.
*/
function checkURLBar(shouldShowOverLink) {
let overLink = window.getComputedStyle(gURLBar._overLinkBox, null);
let origin = window.getComputedStyle(gURLBar._originLabel, null);
let editLayer = window.getComputedStyle(gURLBar._textboxContainer, null);
if (shouldShowOverLink) {
isnot(origin.color, "transparent",
"Origin color in over-link layer should not be transparent");
is(overLink.opacity, 1, "Over-link should be opaque");
is(editLayer.color, "transparent",
"Edit layer color should be transparent");
}
else {
is(origin.color, "transparent",
"Origin color in over-link layer should be transparent");
is(overLink.opacity, 0, "Over-link should be transparent");
isnot(editLayer.color, "transparent",
"Edit layer color should not be transparent");
}
}
/**
* Opens the test URL in a new foreground tab. When the page has finished
* loading, the test iterator is advanced, so you should yield after calling.
*
* @return The opened <tab>.
*/
function openTestPage() {
gBrowser.addEventListener("load", function onLoad(event) {
if (event.target.URL == TEST_URL) {
gBrowser.removeEventListener("load", onLoad, true);
cont();
}
}, true);
return gBrowser.loadOneTab(TEST_URL, { inBackground: false });
}
/**
* Sends a mouseover event to a given anchor node. When the over-link fade-in
* transition has completed, the test iterator is advanced, so you should yield
* after calling.
*
* @param anchorNode
* An anchor node.
*/
function mouseover(anchorNode) {
mouseAnchorNode(anchorNode, true);
}
/**
* Sends a mouseout event to a given anchor node. When the over-link fade-out
* transition has completed, the test iterator is advanced, so you should yield
* after calling.
*
* @param anchorNode
* An anchor node.
*/
function mouseout(anchorNode) {
mouseAnchorNode(anchorNode, false);
}
/**
* Helper for mouseover and mouseout. Sends a mouse event to a given node.
* When the over-link fade-in or -out transition has completed, the test
* iterator is advanced, so you should yield after calling.
*
* @param node
* An anchor node in a content document.
* @param over
* True for "mouseover" and false for "mouseout".
*/
function mouseAnchorNode(node, over) {
let overLink = gURLBar._overLinkBox;
overLink.addEventListener("transitionend", function onTrans(event) {
if (event.target == overLink) {
overLink.removeEventListener("transitionend", onTrans, false);
cont();
}
}, false);
let offset = over ? 0 : -1;
let eventType = over ? "mouseover" : "mouseout";
EventUtils.synthesizeMouse(node, offset, offset,
{ type: eventType, clickCount: 0 },
node.ownerDocument.defaultView);
}

Просмотреть файл

@ -20,6 +20,7 @@
*
* Contributor(s):
* Gavin Sharp <gavin@gavinsharp.com>
* Sylvain Pasche <sylvain.pasche@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
@ -142,6 +143,25 @@ function basicNotification() {
}
}
];
this.options = {
eventCallback: function (eventName) {
switch (eventName) {
case "dismissed":
self.dismissalCallbackTriggered = true;
break;
case "shown":
self.shownCallbackTriggered = true;
break;
case "removed":
self.removedCallbackTriggered = true;
break;
}
}
};
this.addOptions = function(options) {
for (let [name, value] in Iterator(options))
self.options[name] = value;
}
}
var wrongBrowserNotificationObject = new basicNotification();
@ -184,7 +204,9 @@ var tests = [
dismissNotification(popup);
},
onHidden: function (popup) {
ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
this.notification.remove();
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
}
},
// test opening a notification for a background browser
@ -199,6 +221,7 @@ var tests = [
is(PopupNotifications.isPanelOpen, false, "panel isn't open");
ok(!wrongBrowserNotificationObject.mainActionClicked, "main action wasn't clicked");
ok(!wrongBrowserNotificationObject.secondaryActionClicked, "secondary action wasn't clicked");
ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called");
}
},
// now select that browser and test to see that the notification appeared
@ -217,7 +240,10 @@ var tests = [
},
onHidden: function (popup) {
// actually remove the notification to prevent it from reappearing
ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called");
wrongBrowserNotification.remove();
ok(!wrongBrowserNotificationObject.dismissalCallbackTriggered, "dismissal callback wasn't called after remove()");
ok(wrongBrowserNotificationObject.removedCallbackTriggered, "removed callback triggered");
wrongBrowserNotification = null;
}
},
@ -270,9 +296,11 @@ var tests = [
onHidden: function (popup) {
ok(this.testNotif1.mainActionClicked, "main action #1 was clicked");
ok(!this.testNotif1.secondaryActionClicked, "secondary action #1 wasn't clicked");
ok(!this.testNotif1.dismissalCallbackTriggered, "dismissal callback #1 wasn't called");
ok(!this.testNotif2.mainActionClicked, "main action #2 wasn't clicked");
ok(this.testNotif2.secondaryActionClicked, "secondary action #2 was clicked");
ok(!this.testNotif2.dismissalCallbackTriggered, "dismissal callback #2 wasn't called");
}
},
// Test notification without mainAction
@ -310,6 +338,7 @@ var tests = [
onHidden: function (popup) {
// Remove the first notification
this.firstNotification.remove();
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
}
},
// Test optional params
@ -324,7 +353,9 @@ var tests = [
dismissNotification(popup);
},
onHidden: function (popup) {
ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
this.notification.remove();
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
}
},
// Test that icons appear
@ -354,9 +385,9 @@ var tests = [
let self = this;
loadURI("http://example.com/", function() {
self.notifyObj = new basicNotification();
self.notifyObj.options = {
self.notifyObj.addOptions({
persistence: 2
};
});
self.notification = showNotification(self.notifyObj);
});
},
@ -391,9 +422,9 @@ var tests = [
loadURI("http://example.com/", function() {
self.notifyObj = new basicNotification();
// Set a timeout of 10 minutes that should never be hit
self.notifyObj.options = {
self.notifyObj.addOptions({
timeout: Date.now() + 600000
};
});
self.notification = showNotification(self.notifyObj);
});
},
@ -433,7 +464,7 @@ var tests = [
// The notification should open up on the box
this.notifyObj = new basicNotification();
this.notifyObj.anchorID = this.box.id = "nested-box";
this.notifyObj.options = {dismissed: true};
this.notifyObj.addOptions({dismissed: true});
this.notification = showNotification(this.notifyObj);
EventUtils.synthesizeMouse(button, 1, 1, {});
@ -452,7 +483,7 @@ var tests = [
run: function() {
let notifyObj = new basicNotification();
notifyObj.anchorID = "geo-notification-icon";
notifyObj.options = {neverShow: true};
notifyObj.addOptions({neverShow: true});
showNotification(notifyObj);
},
updateNotShowing: function() {
@ -474,8 +505,10 @@ function showNotification(notifyObj) {
function checkPopup(popup, notificationObj) {
info("[Test #" + gTestIndex + "] checking popup");
let notifications = popup.childNodes;
ok(notificationObj.shownCallbackTriggered, "shown callback was triggered");
let notifications = popup.childNodes;
is(notifications.length, 1, "only one notification displayed");
let notification = notifications[0];
let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");

Просмотреть файл

@ -0,0 +1,114 @@
function test()
{
var embed = '<embed type="application/x-test" allowscriptaccess="always" allowfullscreen="true" wmode="window" width="640" height="480"></embed>'
waitForExplicitFinish();
// create a few tabs
var tabs = [
gBrowser.tabs[0],
gBrowser.addTab("about:blank", {skipAnimation: true}),
gBrowser.addTab("about:blank", {skipAnimation: true}),
gBrowser.addTab("about:blank", {skipAnimation: true}),
gBrowser.addTab("about:blank", {skipAnimation: true})
];
function setLocation(i, url) {
gBrowser.getBrowserForTab(tabs[i]).contentWindow.location = url;
}
function moveTabTo(a, b) {
gBrowser.swapBrowsersAndCloseOther(gBrowser.tabs[b], gBrowser.tabs[a]);
}
function clickTest(doc, win) {
var clicks = doc.defaultView.clicks;
EventUtils.synthesizeMouse(doc.body, 100, 600, {}, win);
is(doc.defaultView.clicks, clicks+1, "adding 1 more click on BODY");
}
function test1() {
moveTabTo(2, 3); // now: 0 1 2 4
is(gBrowser.tabs[1], tabs[1], "tab1");
is(gBrowser.tabs[2], tabs[3], "tab3");
var plugin = gBrowser.getBrowserForTab(tabs[4]).docShell.contentViewer.DOMDocument.wrappedJSObject.body.firstChild;
var tab4_plugin_object = plugin.getObjectValue();
gBrowser.selectedTab = gBrowser.tabs[2];
moveTabTo(3, 2); // now: 0 1 4
gBrowser.selectedTab = tabs[4];
var doc = gBrowser.getBrowserForTab(gBrowser.tabs[2]).docShell.contentViewer.DOMDocument.wrappedJSObject;
plugin = doc.body.firstChild;
ok(plugin && plugin.checkObjectValue(tab4_plugin_object), "same plugin instance");
is(gBrowser.tabs[1], tabs[1], "tab1");
is(gBrowser.tabs[2], tabs[3], "tab4");
is(doc.defaultView.clicks, 0, "no click on BODY so far");
clickTest(doc, window);
moveTabTo(2, 1); // now: 0 4
is(gBrowser.tabs[1], tabs[1], "tab1");
doc = gBrowser.getBrowserForTab(gBrowser.tabs[1]).docShell.contentViewer.DOMDocument.wrappedJSObject;
plugin = doc.body.firstChild;
ok(plugin && plugin.checkObjectValue(tab4_plugin_object), "same plugin instance");
clickTest(doc, window);
// Load a new document (about:blank) in tab4, then detach that tab into a new window.
// In the new window, navigate back to the original document and click on its <body>,
// verify that its onclick was called.
var t = tabs[1];
var b = gBrowser.getBrowserForTab(t);
gBrowser.selectedTab = t;
b.addEventListener("load", function() {
b.removeEventListener("load", arguments.callee, true);
executeSoon(function () {
var win = gBrowser.replaceTabWithWindow(t);
win.addEventListener("load", function () {
win.removeEventListener("load", arguments.callee, true);
// Verify that the original window now only has the initial tab left in it.
is(gBrowser.tabs[0], tabs[0], "tab0");
is(gBrowser.getBrowserForTab(gBrowser.tabs[0]).contentWindow.location, "about:blank", "tab0 uri");
executeSoon(function () {
win.gBrowser.addEventListener("pageshow", function () {
win.gBrowser.removeEventListener("pageshow", arguments.callee, false);
executeSoon(function () {
t = win.gBrowser.tabs[0];
b = win.gBrowser.getBrowserForTab(t);
var doc = b.docShell.contentViewer.DOMDocument.wrappedJSObject;
clickTest(doc, win);
win.close();
finish();
});
}, false);
win.gBrowser.goBack();
});
}, true);
});
}, true);
b.loadURI("about:blank");
}
var loads = 0;
function waitForLoad(tab) {
gBrowser.getBrowserForTab(gBrowser.tabs[tab]).removeEventListener("load", arguments.callee, true);
++loads;
if (loads == tabs.length - 1) {
executeSoon(test1);
}
}
function fn(f, arg) {
return function () { return f(arg); };
}
for (var i = 1; i < tabs.length; ++i) {
gBrowser.getBrowserForTab(tabs[i]).addEventListener("load", fn(waitForLoad,i), true);
}
setLocation(1, "data:text/html,<title>tab1</title><body>tab1<iframe>");
setLocation(2, "data:text/plain,tab2");
setLocation(3, "data:text/html,<title>tab3</title><body>tab3<iframe>");
setLocation(4, "data:text/html,<body onload='clicks=0' onclick='++clicks'>"+embed);
gBrowser.selectedTab = tabs[3];
}

Просмотреть файл

@ -0,0 +1,53 @@
function test()
{
waitForExplicitFinish();
var level1 = false;
var level2 = false;
function test1() {
// Load the following URI (which runs some child popup tests) in a new window (B),
// then add a blank tab to B and call replaceTabWithWindow to detach the URI tab
// into yet a new window (C), then close B.
// Now run the tests again and then close C.
// The test results does not matter, all this is just to exercise some code to
// catch assertions or crashes.
var uri = "chrome://mochikit/content/browser/" +
"browser/base/content/test/browser_tab_dragdrop2_frame1.xul";
let window_B = openDialog(location, "_blank", "chrome,all,dialog=no,left=200,top=200,width=200,height=200", uri);
window_B.addEventListener("load", function(aEvent) {
window_B.removeEventListener("load", arguments.callee, false);
if (level1) return; level1=true;
executeSoon(function () {
window_B.gBrowser.addEventListener("load", function(aEvent) {
window_B.removeEventListener("load", arguments.callee, true);
if (level2) return; level2=true;
is(window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location, uri, "sanity check");
//alert("1:"+window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location);
var windowB_tab2 = window_B.gBrowser.addTab("about:blank", {skipAnimation: true});
setTimeout(function () {
//alert("2:"+window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location);
window_B.gBrowser.addEventListener("pagehide", function(aEvent) {
window_B.gBrowser.removeEventListener("pagehide", arguments.callee, true);
executeSoon(function () {
// alert("closing window_B which has "+ window_B.gBrowser.tabs.length+" tabs\n"+
// window_B.gBrowser.getBrowserForTab(window_B.gBrowser.tabs[0]).contentWindow.location);
window_B.close();
var doc = window_C.gBrowser.getBrowserForTab(window_C.gBrowser.tabs[0])
.docShell.contentViewer.DOMDocument.wrappedJSObject;
var elems = document.documentElement.childNodes;
var calls = doc.defaultView.test_panels();
window_C.close();
finish();
});
}, true);
window_B.gBrowser.selectedTab = window_B.gBrowser.tabs[0];
var window_C = window_B.gBrowser.replaceTabWithWindow(window_B.gBrowser.tabs[0]);
}, 1000); // 1 second to allow the tests to create the popups
}, true);
});
}, false);
}
test1();
}

Просмотреть файл

@ -0,0 +1,170 @@
<?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"?>
<!--
XUL Widget Test for panels
-->
<window title="Titlebar" width="200" height="200"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<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="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<tree id="tree" seltype="single" width="100" height="100">
<treecols>
<treecol flex="1"/>
<treecol flex="1"/>
</treecols>
<treechildren id="treechildren">
<treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
<treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
<treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
<treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
<treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
<treeitem><treerow><treecell label="One"/><treecell label="Two"/></treerow></treeitem>
</treechildren>
</tree>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
SimpleTest.waitForExplicitFinish();
var currentTest = null;
var i = 0;
var my_debug = false;
function test_panels()
{
checkTreeCoords();
addEventListener("popupshown", popupShown, false);
addEventListener("popuphidden", nextTest, false);
return nextTest();
}
function nextTest()
{
ok(true,"popuphidden " + i)
if (i == tests.length) {
SimpleTest.finish();
return i;
}
currentTest = tests[i];
var panel = createPanel(currentTest.attrs);
currentTest.test(panel);
return i;
}
var waitSteps = 0;
function popupShown(event)
{
var panel = event.target;
if (waitSteps > 0 && navigator.platform.indexOf("Linux") >= 0 &&
panel.boxObject.screenY == 210) {
waitSteps--;
setTimeout(popupShown, 10, event);
return;
}
++i;
currentTest.result(currentTest.testname + " ", panel);
panel.hidePopup();
}
function createPanel(attrs)
{
var panel = document.createElement("panel");
for (var a in attrs) {
panel.setAttribute(a, attrs[a]);
}
var button = document.createElement("button");
panel.appendChild(button);
button.label = "OK";
button.width = 120;
button.height = 40;
button.setAttribute("style", "-moz-appearance: none; border: 0; margin: 0;");
panel.setAttribute("style", "-moz-appearance: none; border: 0; margin: 0;");
return document.documentElement.appendChild(panel);
}
function checkTreeCoords()
{
var tree = $("tree");
var treechildren = $("treechildren");
tree.currentIndex = 0;
tree.treeBoxObject.scrollToRow(0);
synthesizeMouse(treechildren, 10, tree.treeBoxObject.rowHeight + 2, { });
tree.treeBoxObject.scrollToRow(2);
synthesizeMouse(treechildren, 10, tree.treeBoxObject.rowHeight + 2, { });
}
var tests = [
{
testname: "normal panel",
attrs: { },
test: function(panel) {
panel.openPopupAtScreen(200, 210);
},
result: function(testname, panel) {
if (my_debug) alert(testname);
var panelrect = panel.getBoundingClientRect();
}
},
{
// only noautohide panels support titlebars, so one shouldn't be shown here
testname: "autohide panel with titlebar",
attrs: { titlebar: "normal" },
test: function(panel) {
panel.openPopupAtScreen(200, 210);
},
result: function(testname, panel) {
if (my_debug) alert(testname);
var panelrect = panel.getBoundingClientRect();
}
},
{
testname: "noautohide panel with titlebar",
attrs: { noautohide: true, titlebar: "normal" },
test: function(panel) {
waitSteps = 25;
panel.openPopupAtScreen(200, 210);
},
result: function(testname, panel) {
if (my_debug) alert(testname);
var panelrect = panel.getBoundingClientRect();
var gotMouseEvent = false;
function mouseMoved(event)
{
gotMouseEvent = true;
}
panel.addEventListener("mousemove", mouseMoved, true);
synthesizeMouse(panel, 10, 10, { type: "mousemove" });
panel.removeEventListener("mousemove", mouseMoved, true);
var tree = $("tree");
tree.currentIndex = 0;
panel.appendChild(tree);
checkTreeCoords();
}
}
];
SimpleTest.waitForFocus(test_panels);
]]>
</script>
</window>

Просмотреть файл

@ -44,15 +44,20 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_tabview_launch.js \
browser_tabview_apptabs.js \
browser_tabview_bug587040.js \
browser_tabview_bug587990.js \
browser_tabview_bug591706.js \
browser_tabview_bug595191.js \
browser_tabview_bug595518.js \
browser_tabview_bug595943.js \
browser_tabview_dragdrop.js \
browser_tabview_exit_button.js \
browser_tabview_group.js \
browser_tabview_launch.js \
browser_tabview_search.js \
browser_tabview_snapping.js \
browser_tabview_bug591706.js \
browser_tabview_apptabs.js \
browser_tabview_undo_group.js \
browser_tabview_exit_button.js \
$(NULL)
libs:: $(_BROWSER_FILES)

Просмотреть файл

@ -52,38 +52,77 @@ function onTabViewWindowLoaded() {
// establish initial state
is(contentWindow.GroupItems.groupItems.length, 1, "we start with one group (the default)");
is(gBrowser.tabs.length, 1, "we start with one tab");
let originalTab = gBrowser.tabs[0];
// create an app tab
let appXulTab = gBrowser.loadOneTab("about:blank");
gBrowser.pinTab(appXulTab);
is(gBrowser.tabs.length, 2, "we now have two tabs");
// Create a group
// create a group
let box = new contentWindow.Rect(20, 20, 180, 180);
let groupItem = new contentWindow.GroupItem([], { bounds: box });
let groupItemOne = new contentWindow.GroupItem([], { bounds: box, title: "test1" });
is(contentWindow.GroupItems.groupItems.length, 2, "we now have two groups");
contentWindow.GroupItems.setActiveGroupItem(groupItemOne);
// create a tab
let xulTab = gBrowser.loadOneTab("about:blank");
is(gBrowser.tabs.length, 2, "we now have two tabs");
is(groupItemOne._children.length, 1, "the new tab was added to the group");
// make sure the group has no app tabs
let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 0, "there are no app tab icons");
// pin the tab, make sure the TabItem goes away and the icon comes on
gBrowser.pinTab(xulTab);
is(groupItemOne._children.length, 0, "the app tab's TabItem was removed from the group");
appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 1, "there's now one app tab icon");
// create a second group and make sure it gets the icon too
box.offset(box.width + 20, 0);
let groupItemTwo = new contentWindow.GroupItem([], { bounds: box, title: "test2" });
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
appTabIcons = groupItemTwo.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 1, "there's an app tab icon in the second group");
// unpin the tab, make sure the icon goes away and the TabItem comes on
gBrowser.unpinTab(xulTab);
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 0, "the icon is gone from group one");
appTabIcons = groupItemTwo.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 0, "the icon is gone from group 2");
// pin the tab again
gBrowser.pinTab(xulTab);
// close the second group
groupItemTwo.close();
// find app tab in group and hit it
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
ok(!TabView.isVisible(), "Tab View is hidden because we clicked on the app tab");
// clean up
gBrowser.unpinTab(appXulTab);
gBrowser.removeTab(appXulTab);
gBrowser.selectedTab = originalTab;
gBrowser.unpinTab(xulTab);
gBrowser.removeTab(xulTab);
is(gBrowser.tabs.length, 1, "we finish with one tab");
groupItem.close();
groupItemOne.close();
is(contentWindow.GroupItems.groupItems.length, 1, "we finish with one group");
ok(!TabView.isVisible(), "Tab View is not visible");
ok(!TabView.isVisible(), "we finish with Tab View not visible");
finish();
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
let appTabButtons = groupItem.$appTabTray[0].getElementsByTagName("img");
ok(appTabButtons.length == 1, "there is one app tab button");
EventUtils.sendMouseEvent({ type: "click" }, appTabButtons[0], contentWindow);
appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
}

Просмотреть файл

@ -0,0 +1,150 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tabview test for bug 587040.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
waitForExplicitFinish();
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(TabView.isVisible(), "Tab View is visible");
let [originalTab] = gBrowser.visibleTabs;
let contentWindow = document.getElementById("tab-view").contentWindow;
// create a group
let box = new contentWindow.Rect(20, 20, 300, 300);
let groupItem = new contentWindow.GroupItem([], { bounds: box });
let onTabViewShown = function() {
window.removeEventListener("tabviewshown", onTabViewShown, false);
is(groupItem.getChildren().length, 2, "The new group has two tab items");
// start the test
testSameTabItemAndClickGroup(contentWindow, groupItem);
};
// 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");
let anotherTab = gBrowser.addTab("http://mochi.test:8888/");
let browser = gBrowser.getBrowserForTab(anotherTab);
let onLoad = function() {
browser.removeEventListener("load", onLoad, true);
window.addEventListener("tabviewshown", onTabViewShown, false);
TabView.toggle();
}
browser.addEventListener("load", onLoad, true);
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
// click on the + button to create a blank tab
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
ok(newTabButton[0], "New tab button exists");
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
}
function testSameTabItemAndClickGroup(contentWindow, groupItem, originalTab) {
let activeTabItem = groupItem.getActiveTab();
ok(activeTabItem, "Has active item");
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
is(activeTabItem.tab, gBrowser.selectedTab, "The correct tab is selected");
TabView.toggle();
};
let onTabViewShown = function() {
window.removeEventListener("tabviewshown", onTabViewShown, false);
testDifferentTabItemAndClickGroup(contentWindow, groupItem, originalTab);
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
window.addEventListener("tabviewshown", onTabViewShown, false);
let groupElement = groupItem.container;
EventUtils.sendMouseEvent({ type: "mousedown" }, groupElement, contentWindow);
EventUtils.sendMouseEvent({ type: "mouseup" }, groupElement, contentWindow);
}
function testDifferentTabItemAndClickGroup(contentWindow, groupItem, originalTab) {
let activeTabItem = groupItem.getActiveTab();
ok(activeTabItem, "Has old active item");
// press tab
EventUtils.synthesizeKey("VK_TAB", {}, contentWindow);
let newActiveTabItem = groupItem.getActiveTab();
ok(newActiveTabItem, "Has new active item");
isnot(newActiveTabItem, activeTabItem, "The old and new active items are different");
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
is(newActiveTabItem.tab, gBrowser.selectedTab, "The correct tab is selected");
// clean up and finish the test
groupItem.addSubscriber(groupItem, "close", function() {
groupItem.removeSubscriber(groupItem, "close");
finish();
});
gBrowser.selectedTab = originalTab;
groupItem.closeAll();
// close undo group
let closeButton = groupItem.$undoContainer.find(".close");
EventUtils.sendMouseEvent(
{ type: "click" }, closeButton[0], contentWindow);
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
// press the group Item
let groupElement = groupItem.container;
EventUtils.sendMouseEvent({ type: "mousedown" }, groupElement, contentWindow);
EventUtils.sendMouseEvent({ type: "mouseup" }, groupElement, contentWindow);
}

Просмотреть файл

@ -0,0 +1,103 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is bug 587990 test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
let newTab;
let win;
function test() {
waitForExplicitFinish();
win = window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", "about:blank");
let onLoad = function() {
win.removeEventListener("load", onLoad, false);
newTab = win.gBrowser.addTab();
let onTabViewFrameInitialized = function() {
win.removeEventListener(
"tabviewframeinitialized", onTabViewFrameInitialized, false);
win.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
win.TabView.toggle();
}
win.addEventListener(
"tabviewframeinitialized", onTabViewFrameInitialized, false);
win.TabView.updateContextMenu(
newTab, win.document.getElementById("context_tabViewMenuPopup"));
}
win.addEventListener("load", onLoad, false);
}
function onTabViewWindowLoaded() {
win.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(win.TabView.isVisible(), "Tab View is visible");
let contentWindow = win.document.getElementById("tab-view").contentWindow;
is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
let groupItem = contentWindow.GroupItems.groupItems[0];
let tabItems = groupItem.getChildren();
is(tabItems[tabItems.length - 1].tab, newTab, "The new tab exists in the group");
win.gBrowser.removeTab(newTab);
whenWindowObservesOnce(win, "domwindowclosed", function() {
finish();
});
win.close();
}
function whenWindowObservesOnce(win, topic, func) {
let windowWatcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
let origWin = win;
let origTopic = topic;
let origFunc = func;
function windowObserver(aSubject, aTopic, aData) {
let theWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
if (origWin && theWin != origWin)
return;
if(aTopic == origTopic) {
windowWatcher.unregisterNotification(windowObserver);
origFunc.apply(this, []);
}
}
windowWatcher.registerNotification(windowObserver);
}

Просмотреть файл

@ -0,0 +1,109 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tabview search test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Sean Dunn <seanedunn@yahoo.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
waitForExplicitFinish();
// show the tab view
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(!TabView.isVisible(), "Tab View is hidden");
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(TabView.isVisible(), "Tab View is visible");
let contentWindow = document.getElementById("tab-view").contentWindow;
let searchButton = contentWindow.document.getElementById("searchbutton");
ok(searchButton, "Search button exists");
let onSearchEnabled = function() {
let search = contentWindow.document.getElementById("search");
ok(search.style.display != "none", "Search is enabled");
contentWindow.removeEventListener(
"tabviewsearchenabled", onSearchEnabled, false);
escapeTest(contentWindow);
}
contentWindow.addEventListener("tabviewsearchenabled", onSearchEnabled,
false);
// enter search mode
EventUtils.sendMouseEvent({ type: "mousedown" }, searchButton,
contentWindow);
}
function escapeTest(contentWindow) {
let onSearchDisabled = function() {
let search = contentWindow.document.getElementById("search");
ok(search.style.display == "none", "Search is disabled");
contentWindow.removeEventListener(
"tabviewsearchdisabled", onSearchDisabled, false);
toggleTabViewTest(contentWindow);
}
contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled,
false);
// the search box focus()es in a function on the timeout queue, so we just
// want to queue behind it.
setTimeout( function() {
EventUtils.synthesizeKey("VK_ESCAPE", {});
}, 0);
}
function toggleTabViewTest(contentWindow) {
let onTabViewHidden = function() {
contentWindow.removeEventListener("tabviewhidden", onTabViewHidden, false);
ok(!TabView.isVisible(), "Tab View is hidden");
finish();
}
contentWindow.addEventListener("tabviewhidden", onTabViewHidden, false);
// When search is hidden, it focus()es on the background, so avert the
// race condition by delaying ourselves on the timeout queue
setTimeout( function() {
// Use keyboard shortcut to toggle back to browser view
if(navigator.platform.indexOf("Mac") >= 0) {
EventUtils.synthesizeKey("VK_SPACE", {altKey : true}, contentWindow);
} else {
EventUtils.synthesizeKey("VK_SPACE", {ctrlKey : true}, contentWindow);
}
}, 0);
}

Просмотреть файл

@ -0,0 +1,114 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is bug 595518 test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
* Ian Gilman <ian@iangilman.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
waitForExplicitFinish();
// show tab view
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(TabView.isVisible(), "Tab View is visible");
let contentWindow = document.getElementById("tab-view").contentWindow;
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
// verify exit button worked
ok(!TabView.isVisible(), "Tab View is hidden");
// verify that the exit button no longer has focus
is(contentWindow.iQ("#exit-button:focus").length, 0,
"The exit button doesn't have the focus");
// verify that the keyboard combo works (this is the crux of bug 595518)
// Prepare the key combo
window.addEventListener("tabviewshown", onTabViewShown, false);
let utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
let keyCode = 0;
let charCode;
let eventObject;
if (navigator.platform.indexOf("Mac") != -1) {
charCode = 160; // character code for option (alt) + space
eventObject = { altKey: true };
} else {
charCode = KeyEvent.DOM_VK_SPACE;
eventObject = { ctrlKey: true };
}
// Fire off the key combo
let modifiers = EventUtils._parseModifiers(eventObject);
let keyDownDefaultHappened =
utils.sendKeyEvent("keydown", keyCode, charCode, modifiers);
utils.sendKeyEvent("keypress", keyCode, charCode, modifiers,
!keyDownDefaultHappened);
utils.sendKeyEvent("keyup", keyCode, charCode, modifiers);
}
let onTabViewShown = function() {
window.removeEventListener("tabviewshown", onTabViewShown, false);
// test if the key combo worked
ok(TabView.isVisible(), "Tab View is visible");
// clean up
let endGame = function() {
window.removeEventListener("tabviewhidden", endGame, false);
ok(!TabView.isVisible(), "Tab View is hidden");
finish();
}
window.addEventListener("tabviewhidden", endGame, false);
TabView.toggle();
}
window.addEventListener("tabviewhidden", onTabViewHidden, false);
// locate exit button
let button = contentWindow.document.getElementById("exit-button");
ok(button, "Exit button exists");
// click exit button
button.focus();
EventUtils.sendMouseEvent({ type: "click" }, button, contentWindow);
}

Просмотреть файл

@ -0,0 +1,107 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tabview bug 959943 test.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Raymond Lee <raymond@appcoast.com>
* Ian Gilman <ian@iangilman.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
waitForExplicitFinish();
// Show TabView
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
TabView.toggle();
}
function onTabViewWindowLoaded() {
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
ok(TabView.isVisible(), "Tab View is visible");
let contentWindow = document.getElementById("tab-view").contentWindow;
// establish initial state
is(contentWindow.GroupItems.groupItems.length, 1, "we start with one group (the default)");
is(gBrowser.tabs.length, 1, "we start with one tab");
let originalTab = gBrowser.tabs[0];
ok(contentWindow.GroupItems.groupItems[0]._children[0].tab == originalTab,
"the original tab is in the original group");
// create a second group
let box = new contentWindow.Rect(20, 20, 180, 180);
let groupItem = new contentWindow.GroupItem([], { bounds: box });
is(contentWindow.GroupItems.groupItems.length, 2, "we now have two groups");
contentWindow.GroupItems.setActiveGroupItem(groupItem);
// create a second tab
let normalXulTab = gBrowser.loadOneTab("about:blank");
is(gBrowser.tabs.length, 2, "we now have two tabs");
is(groupItem._children.length, 1, "the new tab was added to the group");
// create a third tab
let appXulTab = gBrowser.loadOneTab("about:blank");
is(gBrowser.tabs.length, 3, "we now have three tabs");
gBrowser.pinTab(appXulTab);
is(groupItem._children.length, 1, "the app tab is not in the group");
// We now have two groups with one tab each, plus an app tab.
// Click into one of the tabs, close it and make sure we don't go back to Tab View.
function onTabViewHidden() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
ok(!TabView.isVisible(), "Tab View is hidden because we clicked on the app tab");
// Remove the tab we're looking at. Note: this will also close groupItem (verified below)
gBrowser.removeTab(normalXulTab);
// Make sure we haven't returned to TabView; this is the crux of this test
ok(!TabView.isVisible(), "Tab View remains hidden");
// clean up
gBrowser.selectedTab = originalTab;
gBrowser.unpinTab(appXulTab);
gBrowser.removeTab(appXulTab);
// Verify ending state
is(gBrowser.tabs.length, 1, "we finish with one tab");
is(contentWindow.GroupItems.groupItems.length, 1, "we finish with one group");
ok(!TabView.isVisible(), "we finish with Tab View hidden");
finish();
}
window.addEventListener("tabviewhidden", onTabViewHidden, false);
EventUtils.sendMouseEvent({ type: "mousedown" }, normalXulTab.tabItem.container, contentWindow);
EventUtils.sendMouseEvent({ type: "mouseup" }, normalXulTab.tabItem.container, contentWindow);
}

Просмотреть файл

@ -83,5 +83,5 @@ function test() {
let button = document.getElementById("tabview-button");
ok(button, "Tab View button exists");
EventUtils.synthesizeMouse(button, 1, 1, {});
button.doCommand();
}

Просмотреть файл

@ -22,7 +22,8 @@
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Dão Gottwald <dao@design-noir.de>
# Dão Gottwald <dao@design-noir.de>
# Drew Willcoxon <adw@mozilla.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
@ -39,10 +40,68 @@
# ***** END LICENSE BLOCK *****
<bindings id="urlbarBindings" xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="urlbar" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
<content sizetopopup="pref">
<xul:vbox class="urlbar-contents" flex="1">
<xul:hbox class="urlbar-frontcap-and-textbox" flex="1">
<xul:hbox class="urlbar-frontcap">
<children includes="image|deck|stack|box">
<xul:image class="autocomplete-icon" allowevents="true"/>
</children>
</xul:hbox>
<xul:stack anonid="stack" class="urlbar-stack" flex="1">
<xul:scrollbox class="urlbar-over-link-layer" flex="1"
xbl:inherits="overlinkstate" align="center">
<xul:label anonid="origin-label" class="urlbar-origin-label" flex="1"
crop="end"/>
<xul:hbox anonid="over-link-box" class="urlbar-over-link-box"
xbl:inherits="overlinkstate" align="center">
<xul:label anonid="over-link-host-label"
class="urlbar-over-link-host-label"/>
<xul:label anonid="over-link-path-label"
class="urlbar-over-link-path-label" flex="1"/>
</xul:hbox>
</xul:scrollbox>
<xul:hbox anonid="textbox-container"
class="autocomplete-textbox-container urlbar-textbox-container"
flex="1" xbl:inherits="focused,overlinkstate">
<xul:hbox anonid="textbox-input-box"
class="textbox-input-box urlbar-input-box"
flex="1" xbl:inherits="tooltiptext=inputtooltiptext">
<xul:hbox class="urlbar-textbox-container-children"
xbl:inherits="overlinkstate">
<children/>
</xul:hbox>
<html:input anonid="input"
class="autocomplete-textbox urlbar-input textbox-input"
flex="1" allowevents="true"
xbl:inherits="tooltiptext=inputtooltiptext,onfocus,onblur,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
</xul:hbox>
<xul:hbox class="urlbar-textbox-container-children"
xbl:inherits="overlinkstate">
<children includes="hbox"/>
</xul:hbox>
</xul:hbox>
</xul:stack>
<xul:dropmarker anonid="historydropmarker"
class="autocomplete-history-dropmarker urlbar-history-dropmarker"
allowevents="true"
xbl:inherits="open,enablehistory,parentfocused=focused"/>
<xul:popupset anonid="popupset"
class="autocomplete-result-popupset"/>
</xul:hbox>
<xul:vbox class="urlbar-progress-container" flex="1" pack="end">
<children includes="progressmeter"/>
</xul:vbox>
</xul:vbox>
<children includes="toolbarbutton"/>
</content>
<implementation implements="nsIObserver, nsIDOMEventListener">
<constructor><![CDATA[
this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
@ -64,6 +123,26 @@
this.inputField.addEventListener("mouseout", this, false);
this.inputField.addEventListener("overflow", this, false);
this.inputField.addEventListener("underflow", this, false);
this._overLinkBox.addEventListener("transitionend", this, false);
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var textBox = document.getAnonymousElementByAttribute(this,
"anonid", "textbox-input-box");
var cxmenu = document.getAnonymousElementByAttribute(textBox,
"anonid", "input-box-contextmenu");
var insertLocation = cxmenu.firstChild;
while (insertLocation.nextSibling &&
insertLocation.getAttribute("cmd") != "cmd_paste")
insertLocation = insertLocation.nextSibling;
if (insertLocation) {
let element = document.createElement("menuitem");
let label = Services.strings.createBundle("chrome://browser/locale/browser.properties").
GetStringFromName("pasteAndGo.label");
element.setAttribute("label", label);
element.setAttribute("cmd", "cmd_paste");
element.setAttribute("oncommand", "goDoCommand('cmd_paste'); gURLBar.handleCommand();");
cxmenu.insertBefore(element, insertLocation.nextSibling);
}
]]></constructor>
<destructor><![CDATA[
@ -75,6 +154,7 @@
this.inputField.removeEventListener("mouseout", this, false);
this.inputField.removeEventListener("overflow", this, false);
this.inputField.removeEventListener("underflow", this, false);
this._overLinkBox.removeEventListener("transitionend", this, false);
]]></destructor>
<field name="_value"></field>
@ -238,7 +318,7 @@
// Tack www. and suffix on. If user has appended directories, insert
// suffix before them (bug 279035). Be careful not to get two slashes.
// Also, don't add the suffix if it's in the original url (bug 233853).
let firstSlash = url.indexOf("/");
let existingSuffix = url.indexOf(suffix.substring(0, suffix.length - 1));
@ -248,7 +328,7 @@
// Yes slash, no suffix: Insert suffix (mozilla/stuff)
// Yes slash, suffix before slash: Do nothing (mozilla.com/stuff)
// Yes slash, suffix after slash: Insert suffix (mozilla/?stuff=.com)
if (firstSlash >= 0) {
if (existingSuffix == -1 || existingSuffix > firstSlash)
url = url.substring(0, firstSlash) + suffix +
@ -444,6 +524,12 @@
this._contentIsCropped = false;
this._hideURLTooltip();
break;
case "transitionend":
if (aEvent.target == this._overLinkBox &&
aEvent.propertyName == "opacity") {
this._overLinkTransitioning = false;
}
break;
}
]]></body>
</method>
@ -481,6 +567,100 @@
return {type: action, param: param};
]]></body>
</method>
<field name="_stack" readonly="true"><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid", "stack");
]]></field>
<field name="_originLabel" readonly="true"><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid", "origin-label");
]]></field>
<field name="_overLinkBox" readonly="true"><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid",
"over-link-box");
]]></field>
<field name="_overLinkHostLabel" readonly="true"><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid",
"over-link-host-label");
]]></field>
<field name="_overLinkPathLabel" readonly="true"><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid",
"over-link-path-label");
]]></field>
<field name="_textboxContainer" readonly="true"><![CDATA[
document.getAnonymousElementByAttribute(this, "anonid",
"textbox-container");
]]></field>
<method name="setOverLink">
<parameter name="aURL"/>
<body><![CDATA[
// Hide the over-link if aURL is falsey or if the URL bar is focused.
if (!aURL || this.focused) {
if (this.hasAttribute("overlinkstate")) {
this.removeAttribute("overlinkstate");
this._overLinkTransitioning = true;
}
return;
}
// Get the width of the bar before we go modifying it.
var barWidth = this._stack.boxObject.width;
// Determine the pre-path and path of the over-link. Include the
// path's leading slash in the pre-path so that if the path is
// truncated its leading slash is visible.
var re = new RegExp("([a-z0-9+.-]+://[^/]+/)(.*)");
var match = re.exec(aURL);
var host = match ? match[1] : "";
var path = match ? match[2] : aURL;
var overLink = this._overLinkBox;
var overLinkHost = this._overLinkHostLabel;
var overLinkPath = this._overLinkPathLabel;
overLinkHost.value = host;
overLinkPath.value = path;
// Remove restrictions on the over-link's width.
overLinkHost.flex = 0;
overLinkHost.crop = "none";
overLinkPath.crop = "none";
overLink.style.minWidth = "";
overLink.style.maxWidth = "";
// Cap the width of the over-link to 2/3 of the location bar's.
var maxWidth = barWidth * 0.67;
var overLinkWidth = overLinkHost.boxObject.width +
overLinkPath.boxObject.width;
if (overLinkWidth > maxWidth) {
// If the host is wider than the cap and therefore the path is not
// visible at all, crop the host at the end.
if (overLinkHost.boxObject.width > maxWidth) {
overLinkHost.flex = 1;
overLinkHost.crop = "end";
}
overLinkPath.crop = host ? "start" : "end";
overLink.style.minWidth = maxWidth + "px";
overLink.style.maxWidth = maxWidth + "px";
}
this._originLabel.value = this.value;
// Finally, show the over-link. If its animation is currently in
// transition, show it immediately rather than animating it again.
if (this._overLinkTransitioning)
this.setAttribute("overlinkstate", "showing");
else {
this.setAttribute("overlinkstate", "fade-in");
this._overLinkTransitioning = true;
}
]]></body>
</method>
</implementation>
<handlers>
@ -513,7 +693,12 @@
dt.effectAllowed = "copyLink";
event.stopPropagation();
]]></handler>
<handler event="focus" phase="capturing" action="this._hideURLTooltip();"/>
<handler event="focus" phase="capturing"><![CDATA[
this._hideURLTooltip();
this.setOverLink(null);
]]></handler>
<handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/>
<handler event="drop" phase="capturing" action="this.onDrop(event, this);"/>
<handler event="select"><![CDATA[
@ -572,7 +757,7 @@
if (searchBar && searchBar.textbox == this.mInput) {
// Handle search bar popup clicks
var search = controller.getValueAt(this.selectedIndex);
// close the autocomplete popup and revert the entered search term
this.closePopup();
controller.handleEscape();

Просмотреть файл

@ -496,14 +496,12 @@ function checkForUpdates()
}
#endif
function buildHelpMenu()
{
// Enable/disable the "Report Web Forgery" menu item. safebrowsing object
// may not exist in OSX
if (typeof safebrowsing != "undefined")
safebrowsing.setReportPhishingMenu();
#ifdef MOZ_UPDATER
/**
* Updates an element to reflect the state of available update services.
*/
function setupCheckForUpdates(checkForUpdates, aStringBundle)
{
var updates =
Components.classes["@mozilla.org/updates/update-service;1"].
getService(Components.interfaces.nsIApplicationUpdateService);
@ -513,23 +511,21 @@ function buildHelpMenu()
// Disable the UI if the update enabled pref has been locked by the
// administrator or if we cannot update for some other reason
var checkForUpdates = document.getElementById("checkForUpdates");
var canCheckForUpdates = updates.canCheckForUpdates;
checkForUpdates.setAttribute("disabled", !canCheckForUpdates);
if (!canCheckForUpdates)
return;
var strings = document.getElementById("bundle_browser");
var activeUpdate = um.activeUpdate;
// If there's an active update, substitute its name into the label
// we show for this item, otherwise display a generic label.
function getStringWithUpdateName(key) {
if (activeUpdate && activeUpdate.name)
return strings.getFormattedString(key, [activeUpdate.name]);
return strings.getString(key + "Fallback");
return aStringBundle.formatStringFromName(key, [activeUpdate.name], 1);
return aStringBundle.GetStringFromName(key + "Fallback");
}
// By default, show "Check for Updates..."
var key = "default";
if (activeUpdate) {
@ -548,11 +544,31 @@ function buildHelpMenu()
}
}
checkForUpdates.label = getStringWithUpdateName("updatesItem_" + key);
checkForUpdates.accessKey = strings.getString("updatesItem_" + key + ".accesskey");
checkForUpdates.accessKey = aStringBundle.
GetStringFromName("updatesItem_" + key + ".accesskey");
if (um.activeUpdate && updates.isDownloading)
checkForUpdates.setAttribute("loading", "true");
else
checkForUpdates.removeAttribute("loading");
}
#endif
function buildHelpMenu()
{
// Enable/disable the "Report Web Forgery" menu item. safebrowsing object
// may not exist in OSX
if (typeof safebrowsing != "undefined")
safebrowsing.setReportPhishingMenu();
#ifdef XP_MACOSX
#ifdef MOZ_UPDATER
var checkForUpdates = document.getElementById("checkForUpdates");
var browserBundle = document.getElementById("bundle_browser").stringBundle;
setupCheckForUpdates(checkForUpdates, browserBundle);
#else
// Needed by safebrowsing for inserting its menuitem so just hide it
document.getElementById("updateSeparator").hidden = true;
#endif
#else
// Needed by safebrowsing for inserting its menuitem so just hide it
document.getElementById("updateSeparator").hidden = true;

Просмотреть файл

@ -26,7 +26,6 @@ browser.jar:
* content/browser/browser.js (content/browser.js)
* content/browser/browser.xul (content/browser.xul)
* content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml)
* content/browser/credits.xhtml (content/credits.xhtml)
* content/browser/fullscreen-video.xhtml (content/fullscreen-video.xhtml)
* content/browser/inspector.html (content/inspector.html)
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
@ -68,6 +67,8 @@ browser.jar:
content/browser/syncGenericChange.js (content/syncGenericChange.js)
* content/browser/syncKey.xhtml (content/syncKey.xhtml)
* content/browser/syncNotification.xml (content/syncNotification.xml)
* content/browser/syncQuota.xul (content/syncQuota.xul)
content/browser/syncQuota.js (content/syncQuota.js)
content/browser/syncUtils.js (content/syncUtils.js)
#endif
# XXX: We should exclude this one as well (bug 71895)

Двоичные данные
browser/branding/nightly/content/about-logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
browser/branding/nightly/content/about-wordmark.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичные данные
browser/branding/nightly/content/aboutFooter.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 227 B

Просмотреть файл

@ -1,8 +1,8 @@
browser.jar:
% content branding %content/branding/ contentaccessible=yes
content/branding/about.png (about.png)
content/branding/aboutCredits.png (aboutCredits.png)
content/branding/aboutFooter.png (aboutFooter.png)
content/branding/about-logo.png (about-logo.png)
content/branding/about-wordmark.png (about-wordmark.png)
content/branding/icon48.png (icon48.png)
content/branding/icon64.png (icon64.png)
content/branding/icon128.png (../mozicon128.png)

Просмотреть файл

@ -1,4 +1,5 @@
<!ENTITY brandShortName "Minefield">
<!ENTITY brandFullName "Minefield">
<!ENTITY vendorShortName "Mozilla">
<!ENTITY trademarkInfo " ">
<!ENTITY trademarkInfo.part1 " ">
<!ENTITY trademarkInfo.part2 " ">

Двоичные данные
browser/branding/unofficial/content/about-logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 29 KiB

Двоичные данные
browser/branding/unofficial/content/about-wordmark.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 764 B

Просмотреть файл

@ -1,8 +1,8 @@
browser.jar:
% content branding %content/branding/ contentaccessible=yes
content/branding/about.png (about.png)
content/branding/aboutCredits.png (aboutCredits.png)
content/branding/aboutFooter.png (aboutFooter.png)
content/branding/about-logo.png (about-logo.png)
content/branding/about-wordmark.png (about-wordmark.png)
content/branding/icon48.png (icon48.png)
content/branding/icon64.png (icon64.png)
content/branding/icon128.png (../mozicon128.png)

Просмотреть файл

@ -1,7 +1,5 @@
<!ENTITY brandShortName "Mozilla Developer Preview">
<!ENTITY brandFullName "Mozilla Developer Preview">
<!ENTITY vendorShortName "mozilla.org">
<!ENTITY trademarkInfo " ">
<!-- LOCALIZATION NOTE (releaseBaseURL): The about: page appends __MOZ_APP_VERSION__.html, e.g. 2.0.html -->
<!ENTITY releaseBaseURL "http://www.mozilla.org/projects/devpreview/releases/">
<!ENTITY trademarkInfo.part1 " ">
<!ENTITY trademarkInfo.part2 " ">

Просмотреть файл

@ -70,6 +70,7 @@ var gAdvancedPane = {
#ifdef MOZ_CRASHREPORTER
this.initSubmitCrashes();
#endif
this.updateActualCacheSize();
},
/**
@ -190,6 +191,8 @@ var gAdvancedPane = {
*
* browser.cache.disk.capacity
* - the size of the browser cache in KB
* browser.cache.disk.smart_size.enabled
* - If disabled, disk.capacity is used
*/
/**
@ -200,7 +203,50 @@ var gAdvancedPane = {
document.documentElement.openSubDialog("chrome://browser/content/preferences/connection.xul",
"", null);
},
// Retrieves the amount of space currently used by disk cache
updateActualCacheSize: function ()
{
var visitor = {
visitDevice: function (deviceID, deviceInfo)
{
if (deviceID == "disk") {
var actualSizeLabel = document.getElementById("actualCacheSize");
var sizeStrings = DownloadUtils.convertByteUnits(deviceInfo.totalSize);
var prefStrBundle = document.getElementById("bundlePreferences");
var sizeStr = prefStrBundle.getFormattedString("actualCacheSize",
sizeStrings);
actualSizeLabel.value = sizeStr;
}
// Do not enumerate entries
return false;
},
visitEntry: function (deviceID, entryInfo)
{
// Do not enumerate entries.
return false;
}
};
var cacheService =
Components.classes["@mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
cacheService.visitEntries(visitor);
},
updateCacheSizeUI: function (smartSizeEnabled)
{
document.getElementById("useCacheBefore").disabled = smartSizeEnabled;
document.getElementById("cacheSize").disabled = smartSizeEnabled;
document.getElementById("useCacheAfter").disabled = smartSizeEnabled;
},
readSmartSizeEnabled: function ()
{
var enabled = document.getElementById("browser.cache.disk.smart_size.enabled").value;
this.updateCacheSizeUI(enabled);
},
/**
* Converts the cache size from units of KB to units of MB and returns that
* value.
@ -232,6 +278,7 @@ var gAdvancedPane = {
try {
cacheService.evictEntries(Components.interfaces.nsICache.STORE_ANYWHERE);
} catch(ex) {}
this.updateActualCacheSize();
},
readOfflineNotify: function()

Просмотреть файл

@ -85,8 +85,12 @@
<!-- Network tab -->
<preference id="browser.cache.disk.capacity" name="browser.cache.disk.capacity" type="int"/>
<preference id="browser.offline-apps.notify" name="browser.offline-apps.notify" type="bool"/>
<!-- Update tab -->
<preference id="browser.cache.disk.smart_size.enabled"
name="browser.cache.disk.smart_size.enabled"
type="bool"/>
<!-- Update tab -->
#ifdef MOZ_UPDATER
<preference id="app.update.enabled" name="app.update.enabled" type="bool"
onchange="gAdvancedPane.updateAppUpdateItems();
@ -214,65 +218,71 @@
<!-- Network -->
<tabpanel id="networkPanel" orient="vertical">
<!-- Connection -->
<groupbox id="connectionGroup">
<caption label="&connection.label;"/>
<!-- Connection -->
<groupbox id="connectionGroup">
<caption label="&connection.label;"/>
<hbox align="center">
<description flex="1" control="connectionSettings">&connectionDesc.label;</description>
<button id="connectionSettings" icon="network" label="&connectionSettings.label;"
accesskey="&connectionSettings.accesskey;"
oncommand="gAdvancedPane.showConnections();"/>
</hbox>
</groupbox>
<hbox align="center">
<description flex="1" control="connectionSettings">&connectionDesc.label;</description>
<button id="connectionSettings" icon="network" label="&connectionSettings.label;"
accesskey="&connectionSettings.accesskey;"
oncommand="gAdvancedPane.showConnections();"/>
</hbox>
</groupbox>
<!-- Cache/Offline apps -->
<groupbox id="offlineGroup">
<caption label="&offlineStorage.label;"/>
<hbox align="center">
<label id="useCacheBefore" control="cacheSize"
accesskey="&useCacheBefore.accesskey;" value="&useCacheBefore.label;"/>
<textbox id="cacheSize" type="number" size="2"
preference="browser.cache.disk.capacity"
onsyncfrompreference="return gAdvancedPane.readCacheSize();"
onsynctopreference="return gAdvancedPane.writeCacheSize();"
aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
<label id="useCacheAfter" flex="1">&useCacheAfter.label;</label>
<button id="clearCacheButton" icon="clear"
label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"
oncommand="gAdvancedPane.clearCache();"/>
</hbox>
<hbox align="center">
<checkbox id="offlineNotify" flex="1"
label="&offlineNotify.label;" accesskey="&offlineNotify.accesskey;"
preference="browser.offline-apps.notify"
onsyncfrompreference="return gAdvancedPane.readOfflineNotify();"/>
<button id="offlineNotifyExceptions"
label="&offlineNotifyExceptions.label;"
accesskey="&offlineNotifyExceptions.accesskey;"
oncommand="gAdvancedPane.showOfflineExceptions();"/>
</hbox>
<hbox>
<vbox flex="1">
<label id="offlineAppsListLabel">&offlineAppsList.label;</label>
<listbox id="offlineAppsList"
style="height: &offlineAppsList.height;;"
flex="1"
aria-labelledby="offlineAppsListLabel"
onselect="gAdvancedPane.offlineAppSelected(event);">
</listbox>
</vbox>
<vbox pack="end">
<button id="offlineAppsListRemove"
disabled="true"
label="&offlineAppsListRemove.label;"
accesskey="&offlineAppsListRemove.accesskey;"
oncommand="gAdvancedPane.removeOfflineApp();"/>
</vbox>
</hbox>
</groupbox>
<!-- Cache/Offline apps -->
<groupbox id="offlineGroup">
<caption label="&offlineStorage.label;"/>
<hbox align="center">
<label id="actualCacheSize" flex="1"/>
<button id="clearCacheButton" icon="clear"
label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"
oncommand="gAdvancedPane.clearCache();"/>
</hbox>
<checkbox preference="browser.cache.disk.smart_size.enabled"
id="allowSmartSize" flex="1"
onsyncfrompreference="return gAdvancedPane.readSmartSizeEnabled();"
label="&smartSizeCache.label;" accesskey="&smartSizeCache.accesskey;"/>
<hbox align="center" class="indent">
<label id="useCacheBefore" control="cacheSize"
accesskey="&useCacheBefore.accesskey;" value="&useCacheBefore.label;"/>
<textbox id="cacheSize" type="number" size="4" max="1024"
preference="browser.cache.disk.capacity"
onsyncfrompreference="return gAdvancedPane.readCacheSize();"
onsynctopreference="return gAdvancedPane.writeCacheSize();"
aria-labelledby="useCacheBefore cacheSize useCacheAfter"/>
<label id="useCacheAfter" flex="1">&useCacheAfter.label;</label>
</hbox>
<hbox align="center">
<checkbox id="offlineNotify" flex="1"
label="&offlineNotify.label;" accesskey="&offlineNotify.accesskey;"
preference="browser.offline-apps.notify"
onsyncfrompreference="return gAdvancedPane.readOfflineNotify();"/>
<button id="offlineNotifyExceptions"
label="&offlineNotifyExceptions.label;"
accesskey="&offlineNotifyExceptions.accesskey;"
oncommand="gAdvancedPane.showOfflineExceptions();"/>
</hbox>
<hbox>
<vbox flex="1">
<label id="offlineAppsListLabel">&offlineAppsList.label;</label>
<listbox id="offlineAppsList"
style="height: &offlineAppsList.height;;"
flex="1"
aria-labelledby="offlineAppsListLabel"
onselect="gAdvancedPane.offlineAppSelected(event);">
</listbox>
</vbox>
<vbox pack="end">
<button id="offlineAppsListRemove"
disabled="true"
label="&offlineAppsListRemove.label;"
accesskey="&offlineAppsListRemove.accesskey;"
oncommand="gAdvancedPane.removeOfflineApp();"/>
</vbox>
</hbox>
</groupbox>
</tabpanel>
<!-- Update -->

Просмотреть файл

@ -51,6 +51,13 @@ var gMainPane = {
// set up the "use current page" label-changing listener
this._updateUseCurrentButton();
window.addEventListener("focus", this._updateUseCurrentButton, false);
this.updateBrowserStartupLastSession();
// Notify observers that the UI is now ready
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(window, "main-pane-loaded", null);
},
// HOME PAGE
@ -74,6 +81,35 @@ var gMainPane = {
* option is preserved.
*/
syncFromHomePref: function ()
{
let homePref = document.getElementById("browser.startup.homepage");
// If the pref is set to about:home, set the value to "" to show the
// placeholder text (about:home title).
if (homePref.value.toLowerCase() == "about:home")
return "";
// If the pref is actually "", show about:blank. The actual home page
// loading code treats them the same, and we don't want the placeholder text
// to be shown.
if (homePref.value == "")
return "about:blank";
// Otherwise, show the actual pref value.
return undefined;
},
syncToHomePref: function (value)
{
// If the value is "", use about:home.
if (value == "")
return "about:home";
// Otherwise, use the actual textbox value.
return undefined;
},
/**
* Sets the home page to the current displayed page (or frontmost tab, if the
* most recent browser window contains multiple tabs), updating preference
@ -462,5 +498,26 @@ var gMainPane = {
showAddonsMgr: function ()
{
openUILinkIn("about:addons", "window");
},
/**
* Hide/show the "Show my windows and tabs from last time" option based
* on the value of the browser.privatebrowsing.autostart pref.
*/
updateBrowserStartupLastSession: function()
{
let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart");
let startupPref = document.getElementById("browser.startup.page");
let menu = document.getElementById("browserStartupPage");
let option = document.getElementById("browserStartupLastSession");
if (pbAutoStartPref.value) {
option.setAttribute("disabled", "true");
if (option.selected) {
menu.selectedItem = document.getElementById("browserStartupHomePage");
}
} else {
option.removeAttribute("disabled");
startupPref.updateElements(); // select the correct index in the startup menulist
}
}
};

Просмотреть файл

@ -43,8 +43,10 @@
<!DOCTYPE overlay [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
<!ENTITY % mainDTD SYSTEM "chrome://browser/locale/preferences/main.dtd">
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
%brandDTD;
%mainDTD;
%aboutHomeDTD;
]>
<overlay id="MainPaneOverlay"
@ -77,6 +79,11 @@
name="pref.browser.homepage.disable_button.restore_default"
type="bool"/>
<preference id="browser.privatebrowsing.autostart"
name="browser.privatebrowsing.autostart"
type="bool"
onchange="gMainPane.updateBrowserStartupLastSession();"/>
<!-- Downloads -->
<preference id="browser.download.manager.showWhenStarting"
name="browser.download.manager.showWhenStarting"
@ -107,17 +114,20 @@
control="browserStartupPage"/>
<menulist id="browserStartupPage" preference="browser.startup.page">
<menupopup>
<menuitem label="&startupHomePage.label;" value="1"/>
<menuitem label="&startupBlankPage.label;" value="0"/>
<menuitem label="&startupLastSession.label;" value="3"/>
<menuitem label="&startupHomePage.label;" value="1" id="browserStartupHomePage"/>
<menuitem label="&startupBlankPage.label;" value="0" id="browserStartupBlank"/>
<menuitem label="&startupLastSession.label;" value="3" id="browserStartupLastSession"/>
</menupopup>
</menulist>
</hbox>
<separator class="thin"/>
<hbox align="center">
<label value="&location.label;" accesskey="&location.accesskey;" control="browserHomePage"/>
<label value="&homepage.label;" accesskey="&homepage.accesskey;" control="browserHomePage"/>
<textbox id="browserHomePage" class="padded uri-element" flex="1"
type="autocomplete" autocompletesearch="history"
onsyncfrompreference="return gMainPane.syncFromHomePref();"
onsynctopreference="return gMainPane.syncToHomePref(this.value);"
placeholder="&abouthome.pageTitle;"
preference="browser.startup.homepage"/>
</hbox>
<hbox align="center" pack="end">

Просмотреть файл

@ -119,7 +119,7 @@ let gSyncPane = {
this.page = PAGE_NO_ACCOUNT;
else {
this.page = PAGE_HAS_ACCOUNT;
document.getElementById("currentUser").value = Weave.Service.username;
document.getElementById("currentAccount").value = Weave.Service.account;
document.getElementById("syncComputerName").value = Weave.Clients.localName;
if (Weave.Status.service == Weave.LOGIN_FAILED)
this.onLoginError();
@ -144,7 +144,7 @@ let gSyncPane = {
Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL;
let buttonChoice =
Services.prompt.confirmEx(window,
this._stringBundle.GetStringFromName("differentAccount.title"),
this._stringBundle.GetStringFromName("stopUsingAccount.title"),
this._stringBundle.GetStringFromName("differentAccount.label"),
flags,
this._stringBundle.GetStringFromName("differentAccountConfirm.label"),
@ -206,6 +206,15 @@ let gSyncPane = {
}
},
openQuotaDialog: function () {
let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
if (win)
win.focus();
else
window.openDialog("chrome://browser/content/syncQuota.xul", "",
"centerscreen,chrome,dialog,modal");
},
resetSync: function () {
this.openSetup(true);
}

Просмотреть файл

@ -90,8 +90,8 @@
<grid>
<rows>
<row align="center">
<label value="&currentUser.label;" control="currentUser"/>
<textbox id="currentUser" readonly="true">
<label value="&currentAccount.label;" control="currentAccount"/>
<textbox id="currentAccount" readonly="true">
<image/>
</textbox>
<hbox align="center">
@ -117,6 +117,9 @@
<row id="manageAccountControls" hidden="true">
<spacer/>
<vbox class="indent">
<label class="text-link"
onclick="gSyncPane.openQuotaDialog(); return false;"
value="&viewQuota.label;"/>
<label class="text-link"
onclick="gSyncUtils.changePassword(); return false;"
value="&changePassword.label;"/>
@ -128,7 +131,7 @@
value="&resetSync.label;"/>
<label class="text-link"
onclick="gSyncPane.startOver(true); return false;"
value="&differentAccount.label;"/>
value="&stopUsingAccount.label;"/>
</vbox>
<spacer/>
</row>
@ -189,7 +192,7 @@
onclick="event.stopPropagation();gSyncUtils.openToS();"
value="&prefs.tosLink.label;"/>
<label class="text-link"
onclick="event.stopPropagation();gSyncUtils.openPP();"
onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"
value="&prefs.ppLink.label;"/>
</hbox>
</vbox>

Просмотреть файл

@ -45,6 +45,7 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_bug410900.js \
browser_bug567487.js \
privacypane_tests.js \
browser_privacypane_1.js \
browser_privacypane_2.js \

Просмотреть файл

@ -0,0 +1,67 @@
function test() {
waitForExplicitFinish();
function observer(win, topic, data) {
if (topic != "main-pane-loaded")
return;
Services.obs.removeObserver(observer, "main-pane-loaded");
runTest(win);
}
Services.obs.addObserver(observer, "main-pane-loaded", false);
openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences",
"chrome,titlebar,toolbar,centerscreen,dialog=no", "paneMain");
}
function runTest(win) {
let doc = win.document;
let pbAutoStartPref = doc.getElementById("browser.privatebrowsing.autostart");
let startupPref = doc.getElementById("browser.startup.page");
let menu = doc.getElementById("browserStartupPage");
let option = doc.getElementById("browserStartupLastSession");
let defOption = doc.getElementById("browserStartupHomePage");
let otherOption = doc.getElementById("browserStartupBlank");
ok(!pbAutoStartPref.value, "Sanity check");
is(startupPref.value, startupPref.defaultValue, "Sanity check");
// First, check to make sure that setting pbAutoStartPref disables the menu item
pbAutoStartPref.value = true;
is(option.getAttribute("disabled"), "true", "Setting private browsing to autostart " +
"should disable the 'Show my tabs and windows from last time' option");
pbAutoStartPref.value = false;
// Now ensure the correct behavior when pbAutoStartPref is set with option enabled
startupPref.value = option.getAttribute("value");
is(menu.selectedItem, option, "Sanity check");
pbAutoStartPref.value = true;
is(option.getAttribute("disabled"), "true", "Setting private browsing to autostart " +
"should disable the 'Show my tabs and windows from last time' option");
is(menu.selectedItem, defOption, "The 'Show home page' option should be selected");
is(startupPref.value, option.getAttribute("value"), "But the value of the startup " +
"pref itself shouldn't change");
menu.selectedItem = otherOption;
menu.doCommand();
is(startupPref.value, otherOption.getAttribute("value"), "And we should be able to " +
"chnage it!");
pbAutoStartPref.value = false;
// Now, ensure that with 'Show my windows and tabs from last time' enabled, toggling
// pbAutoStartPref would restore that value in the menulist.
startupPref.value = option.getAttribute("value");
is(menu.selectedItem, option, "Sanity check");
pbAutoStartPref.value = true;
is(menu.selectedItem, defOption, "The 'Show home page' option should be selected");
pbAutoStartPref.value = false;
is(menu.selectedItem, option, "The correct value should be restored");
// cleanup
[pbAutoStartPref, startupPref].forEach(function (pref) {
if (pref.hasUserValue)
pref.reset();
});
win.close();
finish();
}

Просмотреть файл

@ -45,6 +45,13 @@
%globalDTD;
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
%browserDTD;
#ifdef XP_WIN
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&brandShortName;</span><span class='toolsMenu'>&toolsMenu.label;</span>">
#elifdef XP_MACOSX
<!ENTITY basePBMenu.label "&toolsMenu.label;">
#else
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&appMenuButton.label;</span><span class='toolsMenu'>&toolsMenu.label;</span>">
#endif
<!ENTITY % privatebrowsingpageDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
%privatebrowsingpageDTD;
]>
@ -58,6 +65,12 @@
body.private .showNormal {
display: none;
}
body.appMenuButtonVisible .toolsMenu {
display: none;
}
body.appMenuButtonInvisible .appMenuButton {
display: none;
}
]]></style>
<script type="application/javascript;version=1.7"><![CDATA[
const Cc = Components.classes;
@ -113,6 +126,13 @@
let moreInfoLink = document.getElementById("moreInfoLink");
if (moreInfoLink)
moreInfoLink.setAttribute("href", moreInfoURL + "private-browsing");
// Show the correct menu structure based on whether the App Menu button is
// shown or not.
var menuBar = mainWindow.document.getElementById("toolbar-menubar");
var appMenuButtonIsVisible = menuBar.getAttribute("autohide") == "true";
document.body.classList.add(appMenuButtonIsVisible ? "appMenuButtonVisible" :
"appMenuButtonInvisible");
}, false);
function togglePrivateBrowsing() {
@ -157,8 +177,8 @@
<!-- Footer -->
<div id="footerDesc">
<p id="footerText" class="showPrivate">&privatebrowsingpage.howToStop;</p>
<p id="footerTextNormal" class="showNormal">&privatebrowsingpage.howToStart;</p>
<p id="footerText" class="showPrivate">&privatebrowsingpage.howToStop2;</p>
<p id="footerTextNormal" class="showNormal">&privatebrowsingpage.howToStart2;</p>
</div>
<!-- More Info -->

Просмотреть файл

@ -45,6 +45,12 @@ function test() {
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
// clear the history of closed windows (that other tests have created)
// to avoid the issue in bug 596592
// XXX remove this when bug 597071 is fixed
while (ss.getClosedWindowCount())
ss.forgetClosedWindow(0);
// backup our state
let stateBackup = ss.getWindowState(window);

Просмотреть файл

@ -121,7 +121,7 @@
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "browser-search-engine-modified", false);
this._addedObserver = true;
]]></body>
</method>
@ -275,7 +275,6 @@
}
}
}
BrowserSearch.updateSearchButton();
]]></body>
</method>
@ -303,7 +302,6 @@
}
}
}
BrowserSearch.updateSearchButton();
]]></body>
</method>
@ -581,15 +579,30 @@
var cxmenu = document.getAnonymousElementByAttribute(textBox,
"anonid", "input-box-contextmenu");
var element = document.createElementNS(kXULNS, "menuseparator");
var element, label, akey;
element = document.createElementNS(kXULNS, "menuseparator");
cxmenu.appendChild(element);
var insertLocation = cxmenu.firstChild;
while (insertLocation.nextSibling &&
insertLocation.getAttribute("cmd") != "cmd_paste")
insertLocation = insertLocation.nextSibling;
if (insertLocation) {
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("cmd", "cmd_paste");
element.setAttribute("oncommand", "goDoCommand('cmd_paste'); document.getElementById('searchbar').handleSearchCommand();");
cxmenu.insertBefore(element, insertLocation.nextSibling);
}
element = document.createElementNS(kXULNS, "menuitem");
var label = this._stringBundle.getString("cmd_clearHistory");
var akey = this._stringBundle.getString("cmd_clearHistory_accesskey");
label = this._stringBundle.getString("cmd_clearHistory");
akey = this._stringBundle.getString("cmd_clearHistory_accesskey");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_clearhistory");
cxmenu.appendChild(element);
element = document.createElementNS(kXULNS, "menuitem");
@ -602,7 +615,6 @@
element.setAttribute("type", "checkbox");
element.setAttribute("checked", this._suggestEnabled);
element.setAttribute("autocheck", "false");
this._suggestMenuItem = element;
cxmenu.appendChild(element);
@ -631,7 +643,7 @@
popup.mInput = this;
popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
popup.invalidate();
popup.showCommentColumn = this.showCommentColumn;
popup.showImageColumn = this.showImageColumn;

Просмотреть файл

@ -114,6 +114,9 @@ const CAPABILITIES = [
// that gets saved to disk nor part of the strings returned by the API.
const INTERNAL_KEYS = ["_tabStillLoading", "_hosts", "_formDataSaved"];
// These are tab events that we listen to.
const TAB_EVENTS = ["TabOpen", "TabClose", "TabSelect", "TabShow", "TabHide"];
#ifndef XP_WIN
#define BROKEN_WM_Z_ORDER
#endif
@ -201,6 +204,13 @@ SessionStoreService.prototype = {
// whether the last window was closed and should be restored
_restoreLastWindow: false,
// tabs to restore in order
_tabsToRestore: { visible: [], hidden: [] },
_tabsRestoringCount: 0,
// number of tabs to restore concurrently, pref controlled.
_maxConcurrentTabRestores: null,
// The state from the previous session (after restoring pinned tabs)
_lastSessionState: null,
@ -259,6 +269,14 @@ SessionStoreService.prototype = {
this._sessionhistory_max_entries =
this._prefBranch.getIntPref("sessionhistory.max_entries");
this._maxConcurrentTabRestores =
this._prefBranch.getIntPref("sessionstore.max_concurrent_tabs");
this._prefBranch.addObserver("sessionstore.max_concurrent_tabs", this, true);
// Make sure gRestoreTabsProgressListener has a reference to sessionstore
// so that it can make calls back in
gRestoreTabsProgressListener.ss = this;
// get file references
this._sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
this._sessionFileBackup = this._sessionFile.clone();
@ -348,6 +366,13 @@ SessionStoreService.prototype = {
// save all data for session resuming
this.saveState(true);
// clear out _tabsToRestore in case it's still holding refs
this._tabsToRestore.visible = null;
this._tabsToRestore.hidden = null;
// remove the ref to us from the progress listener
gRestoreTabsProgressListener.ss = null;
// Make sure to break our cycle with the save timer
if (this._saveTimer) {
this._saveTimer.cancel();
@ -403,6 +428,7 @@ SessionStoreService.prototype = {
this._forEachBrowserWindow(function(aWindow) {
Array.forEach(aWindow.gBrowser.browsers, function(aBrowser) {
delete aBrowser.__SS_data;
delete aBrowser.__SS_needsRestore;
});
openWindows[aWindow.__SSi] = true;
});
@ -507,6 +533,10 @@ SessionStoreService.prototype = {
this._clearDisk();
this.saveState(true);
break;
case "sessionstore.max_concurrent_tabs":
this._maxConcurrentTabRestores =
this._prefBranch.getIntPref("sessionstore.max_concurrent_tabs");
break;
}
break;
case "timer-callback": // timer call back for delayed saving
@ -547,6 +577,9 @@ SessionStoreService.prototype = {
// to objects that can change (specifically this._windows[x]).
this._stateBackup = JSON.parse(this._toJSONString(this._getCurrentState(true)));
}
// Make sure _tabsToRestore is cleared. It will be repopulated when
// entering/exiting private browsing (by calls to setBrowserState).
this._resetRestoringState();
break;
}
},
@ -575,21 +608,23 @@ SessionStoreService.prototype = {
this.onTabInput(win, aEvent.currentTarget);
break;
case "TabOpen":
this.onTabAdd(win, aEvent.originalTarget);
break;
case "TabClose":
let browser = aEvent.originalTarget.linkedBrowser;
if (aEvent.type == "TabOpen") {
this.onTabAdd(win, browser);
}
else {
// aEvent.detail determines if the tab was closed by moving to a different window
if (!aEvent.detail)
this.onTabClose(win, aEvent.originalTarget);
this.onTabRemove(win, browser);
}
// aEvent.detail determines if the tab was closed by moving to a different window
if (!aEvent.detail)
this.onTabClose(win, aEvent.originalTarget);
this.onTabRemove(win, aEvent.originalTarget);
break;
case "TabSelect":
this.onTabSelect(win);
break;
case "TabShow":
this.onTabShow(aEvent.originalTarget);
break;
case "TabHide":
this.onTabHide(aEvent.originalTarget);
break;
}
},
@ -692,13 +727,13 @@ SessionStoreService.prototype = {
var tabbrowser = aWindow.gBrowser;
// add tab change listeners to all already existing tabs
for (let i = 0; i < tabbrowser.browsers.length; i++) {
this.onTabAdd(aWindow, tabbrowser.browsers[i], true);
for (let i = 0; i < tabbrowser.tabs.length; i++) {
this.onTabAdd(aWindow, tabbrowser.tabs[i], true);
}
// notification of tab add/remove/selection
tabbrowser.tabContainer.addEventListener("TabOpen", this, true);
tabbrowser.tabContainer.addEventListener("TabClose", this, true);
tabbrowser.tabContainer.addEventListener("TabSelect", this, true);
// notification of tab add/remove/selection/show/hide
TAB_EVENTS.forEach(function(aEvent) {
tabbrowser.tabContainer.addEventListener(aEvent, this, true);
}, this);
},
/**
@ -730,10 +765,13 @@ SessionStoreService.prototype = {
var tabbrowser = aWindow.gBrowser;
tabbrowser.tabContainer.removeEventListener("TabOpen", this, true);
tabbrowser.tabContainer.removeEventListener("TabClose", this, true);
tabbrowser.tabContainer.removeEventListener("TabSelect", this, true);
TAB_EVENTS.forEach(function(aEvent) {
tabbrowser.tabContainer.removeEventListener(aEvent, this, true);
}, this);
// remove the progress listener for this window
tabbrowser.removeTabsProgressListener(gRestoreTabsProgressListener);
let winData = this._windows[aWindow.__SSi];
if (this._loadState == STATE_RUNNING) { // window not closed during a regular shut-down
// update all window data for a last time
@ -760,8 +798,8 @@ SessionStoreService.prototype = {
this.saveStateDelayed();
}
for (let i = 0; i < tabbrowser.browsers.length; i++) {
this.onTabRemove(aWindow, tabbrowser.browsers[i], true);
for (let i = 0; i < tabbrowser.tabs.length; i++) {
this.onTabRemove(aWindow, tabbrowser.tabs[i], true);
}
// cache the window state until the window is completely gone
@ -774,18 +812,19 @@ SessionStoreService.prototype = {
* set up listeners for a new tab
* @param aWindow
* Window reference
* @param aBrowser
* Browser reference
* @param aTab
* Tab reference
* @param aNoNotification
* bool Do not save state if we're updating an existing tab
*/
onTabAdd: function sss_onTabAdd(aWindow, aBrowser, aNoNotification) {
aBrowser.addEventListener("load", this, true);
aBrowser.addEventListener("pageshow", this, true);
aBrowser.addEventListener("change", this, true);
aBrowser.addEventListener("input", this, true);
aBrowser.addEventListener("DOMAutoComplete", this, true);
onTabAdd: function sss_onTabAdd(aWindow, aTab, aNoNotification) {
let browser = aTab.linkedBrowser;
browser.addEventListener("load", this, true);
browser.addEventListener("pageshow", this, true);
browser.addEventListener("change", this, true);
browser.addEventListener("input", this, true);
browser.addEventListener("DOMAutoComplete", this, true);
if (!aNoNotification) {
this.saveStateDelayed(aWindow);
}
@ -797,20 +836,33 @@ SessionStoreService.prototype = {
* remove listeners for a tab
* @param aWindow
* Window reference
* @param aBrowser
* Browser reference
* @param aTab
* Tab reference
* @param aNoNotification
* bool Do not save state if we're updating an existing tab
*/
onTabRemove: function sss_onTabRemove(aWindow, aBrowser, aNoNotification) {
aBrowser.removeEventListener("load", this, true);
aBrowser.removeEventListener("pageshow", this, true);
aBrowser.removeEventListener("change", this, true);
aBrowser.removeEventListener("input", this, true);
aBrowser.removeEventListener("DOMAutoComplete", this, true);
delete aBrowser.__SS_data;
onTabRemove: function sss_onTabRemove(aWindow, aTab, aNoNotification) {
let browser = aTab.linkedBrowser;
browser.removeEventListener("load", this, true);
browser.removeEventListener("pageshow", this, true);
browser.removeEventListener("change", this, true);
browser.removeEventListener("input", this, true);
browser.removeEventListener("DOMAutoComplete", this, true);
delete browser.__SS_data;
// If this tab was in the middle of restoring, we want to restore the next
// tab. If the tab hasn't been restored, we want to remove it from the array.
if (browser.__SS_restoring) {
this.restoreNextTab(true);
}
else if (browser.__SS_needsRestore) {
if (aTab.hidden)
this._tabsToRestore.hidden.splice(this._tabsToRestore.hidden.indexOf(aTab));
else
this._tabsToRestore.visible.splice(this._tabsToRestore.visible.indexOf(aTab));
}
if (!aNoNotification) {
this.saveStateDelayed(aWindow);
}
@ -904,11 +956,37 @@ SessionStoreService.prototype = {
if (this._loadState == STATE_RUNNING) {
this._windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex;
let tab = aWindow.gBrowser.selectedTab;
// If __SS_needsRestore is still on the browser, then we haven't restored
// this tab yet. Explicitly call restoreTab to kick off the restore.
if (tab.linkedBrowser.__SS_needsRestore) {
this._tabsToRestore.visible.splice(this._tabsToRestore.visible.indexOf(tab));
this.restoreTab(tab);
}
// attempt to update the current URL we send in a crash report
this._updateCrashReportURL(aWindow);
}
},
onTabShow: function sss_onTabShow(aTab) {
// If the tab hasn't been restored yet, move it into the right _tabsToRestore bucket
if (aTab.linkedBrowser.__SS_needsRestore) {
this._tabsToRestore.hidden.splice(this._tabsToRestore.hidden.indexOf(aTab));
// Just put it at the end of the list of visible tabs;
this._tabsToRestore.visible.push(aTab);
}
},
onTabHide: function sss_onTabHide(aTab) {
// If the tab hasn't been restored yet, move it into the right _tabsToRestore bucket
if (aTab.linkedBrowser.__SS_needsRestore) {
this._tabsToRestore.visible.splice(this._tabsToRestore.visible.indexOf(aTab));
// Just put it at the end of the list of hidden tabs;
this._tabsToRestore.hidden.push(aTab);
}
},
/* ........ nsISessionStore API .............. */
getBrowserState: function sss_getBrowserState() {
@ -927,6 +1005,9 @@ SessionStoreService.prototype = {
this._browserSetState = true;
// Make sure _tabsToRestore is emptied out
this._resetRestoringState();
var window = this._getMostRecentBrowserWindow();
if (!window) {
this._restoreCount = 1;
@ -2175,7 +2256,14 @@ SessionStoreService.prototype = {
restoreHistoryPrecursor:
function sss_restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab, aIx, aCount) {
var tabbrowser = aWindow.gBrowser;
// In order for setTabState to add gTabsProgressListener, we want to add it
// here. We'll only attempt to do it when aCount == 0 though so we don't add
// it multiple times.
if (aCount == 0 &&
tabbrowser.mTabsProgressListeners.indexOf(gRestoreTabsProgressListener) == -1)
tabbrowser.addTabsProgressListener(gRestoreTabsProgressListener);
// make sure that all browsers and their histories are available
// - if one's not, resume this check in 100ms (repeat at most 10 times)
for (var t = aIx; t < aTabs.length; t++) {
@ -2208,6 +2296,12 @@ SessionStoreService.prototype = {
tab.hidden = tabData.hidden;
tabData._tabStillLoading = true;
// keep the data around to prevent dataloss in case
// a tab gets closed before it's been properly restored
browser.__SS_data = tabData;
browser.__SS_needsRestore = true;
if (!tabData.entries || tabData.entries.length == 0) {
// make sure to blank out this tab's content
// (just purging the tab's history won't be enough)
@ -2219,17 +2313,16 @@ SessionStoreService.prototype = {
tab.setAttribute("busy", "true");
tabbrowser.updateIcon(tab);
tabbrowser.setTabTitleLoading(tab);
// wall-paper fix for bug 439675: make sure that the URL to be loaded
// is always visible in the address bar
let activeIndex = (tabData.index || tabData.entries.length) - 1;
let activePageData = tabData.entries[activeIndex] || null;
browser.userTypedValue = activePageData ? activePageData.url || null : null;
// keep the data around to prevent dataloss in case
// a tab gets closed before it's been properly restored
browser.__SS_data = tabData;
// If the page has a title, set it.
if (activePageData && activePageData.title)
tab.label = activePageData.title;
}
if (aTabs.length > 0) {
@ -2358,39 +2451,124 @@ SessionStoreService.prototype = {
var event = aWindow.document.createEvent("Events");
event.initEvent("SSTabRestoring", true, false);
tab.dispatchEvent(event);
let activeIndex = (tabData.index || tabData.entries.length) - 1;
if (activeIndex >= tabData.entries.length)
activeIndex = tabData.entries.length - 1;
try {
if (activeIndex >= 0)
browser.webNavigation.gotoIndex(activeIndex);
}
catch (ex) {
// ignore page load errors
tab.removeAttribute("busy");
}
if (tabData.entries.length > 0) {
// restore those aspects of the currently active documents
// which are not preserved in the plain history entries
// (mainly scroll state and text data)
browser.__SS_restore_data = tabData.entries[activeIndex] || {};
browser.__SS_restore_pageStyle = tabData.pageStyle || "";
browser.__SS_restore_tab = tab;
}
// Handle userTypedValue. Setting userTypedValue seems to update gURLbar
// as needed. Calling loadURI will cancel form filling in restoreDocument_proxy
if (tabData.userTypedValue) {
browser.userTypedValue = tabData.userTypedValue;
if (tabData.userTypedClear)
browser.loadURI(tabData.userTypedValue, null, null, true);
}
// Restore the history in the next tab
aWindow.setTimeout(function(){
_this.restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap);
}, 0);
// This could cause us to ignore the max_concurrent_tabs pref a bit, but
// it ensures each window will have its selected tab loaded.
if (aWindow.gBrowser.selectedBrowser == browser) {
this.restoreTab(tab);
}
else {
// Put the tab into the right bucket
if (tabData.hidden)
this._tabsToRestore.hidden.push(tab);
else
this._tabsToRestore.visible.push(tab);
this.restoreNextTab();
}
},
restoreTab: function(aTab) {
let browser = aTab.linkedBrowser;
let tabData = browser.__SS_data;
// There are cases within where we haven't actually started a load and so we
// should call restoreNextTab. We don't want to do it immediately though
// since we might not set userTypedValue in a timely fashion.
let shouldRestoreNextTab = false;
// Increase our internal count.
this._tabsRestoringCount++;
delete browser.__SS_needsRestore;
let activeIndex = (tabData.index || tabData.entries.length) - 1;
if (activeIndex >= tabData.entries.length)
activeIndex = tabData.entries.length - 1;
// Attach data that will be restored on "load" event, after tab is restored.
if (activeIndex > -1) {
// restore those aspects of the currently active documents which are not
// preserved in the plain history entries (mainly scroll state and text data)
browser.__SS_restore_data = tabData.entries[activeIndex] || {};
browser.__SS_restore_pageStyle = tabData.pageStyle || "";
browser.__SS_restore_tab = aTab;
try {
// Get the tab title (set in restoreHistoryPrecursor) for later
let label = aTab.label;
browser.__SS_restoring = true;
browser.webNavigation.gotoIndex(activeIndex);
// gotoIndex will force the "loading" string, so set the title
aTab.label = label;
}
catch (ex) {
// ignore page load errors
aTab.removeAttribute("busy");
shouldRestoreNextTab = true;
}
}
else {
// If there is no active index, then we'll never set __SS_restore_data
// and even if there is a load event, we won't kick of the next tab
// (restoreDocument won't get called), so do it ourselves.
shouldRestoreNextTab = true;
}
// Handle userTypedValue. Setting userTypedValue seems to update gURLbar
// as needed. Calling loadURI will cancel form filling in restoreDocument
if (tabData.userTypedValue) {
browser.userTypedValue = tabData.userTypedValue;
if (tabData.userTypedClear) {
browser.__SS_restoring = true;
browser.loadURI(tabData.userTypedValue, null, null, true);
}
else {
shouldRestoreNextTab = true;
}
}
if (shouldRestoreNextTab)
this.restoreNextTab(true);
},
restoreNextTab: function sss_restoreNextTab(aFromTabFinished) {
// If we call in here while quitting, we don't actually want to do anything
if (this._loadState == STATE_QUITTING)
return;
if (aFromTabFinished)
this._tabsRestoringCount--;
// If it's not possible to restore anything, then just bail out.
if (this._maxConcurrentTabRestores >= 0 &&
this._tabsRestoringCount >= this._maxConcurrentTabRestores)
return;
// Look in visible, then hidden
let nextTabArray;
if (this._tabsToRestore.visible.length) {
nextTabArray = this._tabsToRestore.visible;
}
else if (this._tabsToRestore.hidden.length) {
nextTabArray = this._tabsToRestore.hidden;
}
if (nextTabArray) {
let tab = nextTabArray.shift();
this.restoreTab(tab);
}
else {
// Remove the progress listener from windows. It will get re-added as needed.
this._forEachBrowserWindow(function(aWindow) {
// This won't fail since removeTabsProgressListener just filters. It
// doesn't attempt to splice.
aWindow.gBrowser.removeTabsProgressListener(gRestoreTabsProgressListener)
});
}
},
/**
@ -3304,6 +3482,15 @@ SessionStoreService.prototype = {
this._closedWindows.splice(spliceTo);
},
/**
* Reset state to prepare for a new session state to be restored.
*/
_resetRestoringState: function sss__initRestoringState() {
//
this._tasToRestore = { visible: [], hidden: [] };
this._tabsRestoringCount = 0;
},
/* ........ Storage API .............. */
/**
@ -3429,6 +3616,25 @@ let XPathHelper = {
}
};
// This is used to help meter the number of restoring tabs. This is the control
// point for telling the next tab to restore. It gets attached to each gBrowser
// via gBrowser.addTabsProgressListener
let gRestoreTabsProgressListener = {
ss: null,
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
// Ignore state changes on browsers that we've already restored
if (!aBrowser.__SS_restoring)
return;
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
delete aBrowser.__SS_restoring;
this.ss.restoreNextTab(true);
}
}
}
// see nsPrivateBrowsingService.js
String.prototype.hasRootDomain = function hasRootDomain(aDomain)
{

Просмотреть файл

@ -117,6 +117,7 @@ _BROWSER_TEST_FILES = \
browser_579879.js \
browser_580512.js \
browser_586147.js \
browser_586068-cascaded_restore.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -0,0 +1,245 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul OShannessy <paul@oshannessy.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
Cu.import("resource://gre/modules/Services.jsm");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let stateBackup = ss.getBrowserState();
function test() {
/** Test for Bug 586068 - Cascade page loads when restoring **/
waitForExplicitFinish();
runNextTest();
}
let tests = [test_cascade, test_select];
function runNextTest() {
if (tests.length) {
ss.setWindowState(window,
JSON.stringify({ windows: [{ tabs: [{ url: 'about:blank' }], }] }),
true);
executeSoon(tests.shift());
}
else {
ss.setBrowserState(stateBackup);
executeSoon(finish);
}
}
function test_cascade() {
// Set the pref to 1 so we know exactly how many tabs should be restoring at any given time
Services.prefs.setIntPref("browser.sessionstore.max_concurrent_tabs", 1);
// We have our own progress listener for this test, which we'll attach before our state is set
let progressListener = {
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
test_cascade_progressCallback();
}
}
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.com" }], extData: { "uniq": r() } }
] }] };
let loadCount = 0;
// Since our progress listener is fired before the one in sessionstore, our
// expected counts look a little weird. This is because we inspect the state
// before sessionstore has marked the tab as finished restoring and before it
// starts restoring the next tab
let expectedCounts = [
[5, 1, 0],
[4, 1, 1],
[3, 1, 2],
[2, 1, 3],
[1, 1, 4],
[0, 1, 5]
];
function test_cascade_progressCallback() {
loadCount++;
// We'll get the first <length of windows[0].tabs> load events here, even
// though they are ignored by sessionstore. Those are due to explicit
// "stop" events before any restoring action takes place. We can safely
// ignore these events.
if (loadCount <= state.windows[0].tabs.length)
return;
let counts = countTabs();
let expected = expectedCounts[loadCount - state.windows[0].tabs.length - 1];
is(counts[0], expected[0], "test_cascade: load " + loadCount + " - # tabs that need to be restored");
is(counts[1], expected[1], "test_cascade: load " + loadCount + " - # tabs that are restoring");
is(counts[2], expected[2], "test_cascade: load " + loadCount + " - # tabs that has been restored");
if (loadCount == state.windows[0].tabs.length * 2) {
window.gBrowser.removeTabsProgressListener(progressListener);
// Reset the pref
try {
Services.prefs.clearUserPref("browser.sessionstore.max_concurrent_tabs");
} catch (e) {}
runNextTest();
}
}
// This progress listener will get attached before the listener in session store.
window.gBrowser.addTabsProgressListener(progressListener);
ss.setBrowserState(JSON.stringify(state));
}
function test_select() {
// Set the pref to 0 so we know exactly how many tabs should be restoring at
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setIntPref("browser.sessionstore.max_concurrent_tabs", 0);
// We have our own progress listener for this test, which we'll attach before our state is set
let progressListener = {
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
test_select_progressCallback(aBrowser);
}
}
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org" }], extData: { "uniq": r() } }
], selectedIndex: 1 }] };
let loadCount = 0;
// expectedCounts looks a little wierd for the test case, but it works. See
// comment in test_cascade for an explanation
let expectedCounts = [
[5, 1, 0],
[4, 1, 1],
[3, 1, 2],
[2, 1, 3],
[1, 1, 4],
[0, 1, 5]
];
let tabOrder = [0, 5, 1, 4, 3, 2];
function test_select_progressCallback(aBrowser) {
loadCount++;
// We'll get the first <length of windows[0].tabs> load events here, even
// though they are ignored by sessionstore. Those are due to explicit
// "stop" events before any restoring action takes place. We can safely
// ignore these events.
if (loadCount <= state.windows[0].tabs.length)
return;
let loadIndex = loadCount - state.windows[0].tabs.length - 1;
let counts = countTabs();
let expected = expectedCounts[loadIndex];
is(counts[0], expected[0], "test_select: load " + loadCount + " - # tabs that need to be restored");
is(counts[1], expected[1], "test_select: load " + loadCount + " - # tabs that are restoring");
is(counts[2], expected[2], "test_select: load " + loadCount + " - # tabs that has been restored");
if (loadCount == state.windows[0].tabs.length * 2) {
window.gBrowser.removeTabsProgressListener(progressListener);
// Reset the pref
try {
Services.prefs.clearUserPref("browser.sessionstore.max_concurrent_tabs");
} catch (e) {}
runNextTest();
}
else {
// double check that this tab was the right one
let expectedData = state.windows[0].tabs[tabOrder[loadIndex]].extData.uniq;
let tab;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
if (!tab && window.gBrowser.tabs[i].linkedBrowser == aBrowser)
tab = window.gBrowser.tabs[i];
}
is(ss.getTabValue(tab, "uniq"), expectedData, "test_select: load " + loadCount + " - correct tab was restored");
// select the next tab
window.gBrowser.selectTabAtIndex(tabOrder[loadIndex + 1]);
}
}
window.gBrowser.addTabsProgressListener(progressListener);
ss.setBrowserState(JSON.stringify(state));
}
function countTabs() {
let needsRestore = 0,
isRestoring = 0,
wasRestored = 0;
let windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let window = windowsEnum.getNext();
if (window.closed)
continue;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
let browser = window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoring)
isRestoring++;
else if (browser.__SS_needsRestore)
needsRestore++;
else
wasRestored++;
}
}
return [needsRestore, isRestoring, wasRestored];
}
function r() {
return "" + Date.now() + Math.random();
}

Просмотреть файл

@ -1 +1 @@
4.0b6pre
4.0b7pre

Просмотреть файл

@ -458,7 +458,7 @@ Section "-InstallEndCleanup"
${EndUnless}
; Win7 taskbar and start menu link maintenance
${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}"
${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}" $0
; Refresh desktop icons
System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"

Просмотреть файл

@ -85,7 +85,7 @@
${SetUninstallKeys}
; Win7 taskbar and start menu link maintenance
${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}"
${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}" $0
; Remove files that may be left behind by the application in the
; VirtualStore directory.

Просмотреть файл

@ -1,11 +1,23 @@
<!ENTITY aboutDialog.title "About &brandFullName;">
<!ENTITY copyright "Credits">
<!ENTITY copyright.accesskey "C">
<!ENTITY copyrightGNOME.accesskey "r">
<!ENTITY aboutLink "&lt; About &brandFullName;">
<!ENTITY aboutLink.accesskey "A">
<!ENTITY aboutVersion "version">
<!ENTITY closeCmdGNOME.label "Close">
<!ENTITY closeCmdGNOME.accesskey "C">
<!ENTITY licenseLinkText "Licensing information">
<!ENTITY licenseLinkSuffix ".">
<!ENTITY community.start2 "&brandShortName; is designed by ">
<!-- LOCALIZATION NOTE (community.mozillaLink): This is a link title that links to http://www.mozilla.org/. -->
<!ENTITY community.mozillaLink "&vendorShortName;">
<!ENTITY community.middle2 ", a ">
<!-- LOCALIZATION NOTE (community.creditsLink): This is a link title that links to about:credits. -->
<!ENTITY community.creditsLink "global community">
<!ENTITY community.end2 " working together to make the Internet better. We believe that the Internet should be open, public, and accessible to everyone without any restrictions.">
<!ENTITY contribute.start "Sound interesting? ">
<!-- LOCALIZATION NOTE (contribute.getInvolvedLink): This is a link title that links to http://www.mozilla.org/contribute/. -->
<!ENTITY contribute.getInvolvedLink "Get involved!">
<!ENTITY contribute.end "">
<!-- LOCALIZATION NOTE (bottomLinks.license): This is a link title that links to about:license. -->
<!ENTITY bottomLinks.license "Licensing Information">
<!-- LOCALIZATION NOTE (bottomLinks.rights): This is a link title that links to about:rights. -->
<!ENTITY bottomLinks.rights "End User Rights">
<!-- LOCALIZATION NOTE (bottomLinks.privacy): This is a link title that links to http://www.mozilla.com/legal/privacy/. -->
<!ENTITY bottomLinks.privacy "Privacy Policy">

Просмотреть файл

@ -15,8 +15,10 @@
<!ENTITY privatebrowsingpage.startPrivateBrowsing.label "Start Private Browsing">
<!ENTITY privatebrowsingpage.startPrivateBrowsing.accesskey "P">
<!ENTITY privatebrowsingpage.howToStop "To stop Private Browsing, select &toolsMenu.label; &gt; &privateBrowsingCmd.stop.label;, or close &brandShortName;.">
<!ENTITY privatebrowsingpage.howToStart "To start Private Browsing, you can also select &toolsMenu.label; &gt; &privateBrowsingCmd.start.label;.">
<!-- LOCALIZATION NOTE (privatebrowsingpage.howToStop2): please leave &basePBMenu.label; intact in the translation -->
<!-- LOCALIZATION NOTE (privatebrowsingpage.howToStart2): please leave &basePBMenu.label; intact in the translation -->
<!ENTITY privatebrowsingpage.howToStop2 "To stop Private Browsing, select &basePBMenu.label; &gt; &privateBrowsingCmd.stop.label;, or close &brandShortName;.">
<!ENTITY privatebrowsingpage.howToStart2 "To start Private Browsing, you can also select &basePBMenu.label; &gt; &privateBrowsingCmd.start.label;.">
<!ENTITY privatebrowsingpage.moreInfo "While this computer won't have a record of your browsing history, your internet service provider or employer can still track the pages you visit.">
<!ENTITY privatebrowsingpage.learnMore "Learn More">

Просмотреть файл

@ -18,8 +18,6 @@
<!ENTITY reloadAllTabs.accesskey "A">
<!ENTITY closeOtherTabs.label "Close Other Tabs">
<!ENTITY closeOtherTabs.accesskey "o">
<!ENTITY openTabInNewWindow.label "Open in a New Window">
<!ENTITY openTabInNewWindow.accesskey "W">
<!-- LOCALIZATION NOTE (pinAppTab.label, unpinAppTab.label): "Pin" is being
used as a metaphor for expressing the fact that these tabs are "pinned" to the
@ -33,6 +31,8 @@ can reach it easily. -->
<!ENTITY moveToGroup.label "Move to Group">
<!ENTITY moveToGroup.accesskey "M">
<!ENTITY moveToNewGroup.label "New Group">
<!ENTITY moveToNewWindow.label "Move to New Window">
<!ENTITY moveToNewWindow.accesskey "W">
<!ENTITY bookmarkAllTabs.label "Bookmark All Tabs…">
<!ENTITY bookmarkAllTabs.accesskey "T">
<!ENTITY undoCloseTab.label "Undo Close Tab">
@ -133,9 +133,11 @@ can reach it easily. -->
<!ENTITY bookmarksItem.title "Bookmarks">
<!-- Toolbar items -->
<!ENTITY homeButton.label "Home">
<!ENTITY tabViewButton2.label "Tab Groups">
<!ENTITY tabViewButton2.tooltip "Group Your Tabs">
<!ENTITY appMenuButton.label "Menu">
<!ENTITY homeButton.label "Home">
<!ENTITY tabGroupsButton.label "Tab Groups">
<!ENTITY tabGroupsButton.tooltip "Group your tabs">
<!ENTITY bookmarksButton.label "Bookmarks">
<!ENTITY bookmarksButton.tooltip "Display your bookmarks">
@ -249,8 +251,8 @@ can reach it easily. -->
<!ENTITY viewMenu.label "View">
<!ENTITY viewMenu.accesskey "V">
<!ENTITY showTabView2.label "Group Your Tabs…">
<!ENTITY showTabView2.accesskey "G">
<!ENTITY viewTabGroups.label "Tab Groups">
<!ENTITY viewTabGroups.accesskey "G">
<!ENTITY viewToolbarsMenu.label "Toolbars">
<!ENTITY viewToolbarsMenu.accesskey "T">
<!ENTITY viewSidebarMenu.label "Sidebar">
@ -489,7 +491,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY dontShowMessage.accesskey "D">
<!ENTITY bidiSwitchPageDirectionItem.label "Switch Page Direction">
<!ENTITY bidiSwitchPageDirectionItem.accesskey "g">
<!ENTITY bidiSwitchPageDirectionItem.accesskey "D">
<!ENTITY bidiSwitchTextDirectionItem.label "Switch Text Direction">
<!ENTITY bidiSwitchTextDirectionItem.accesskey "w">
<!ENTITY bidiSwitchTextDirectionItem.commandkey "X">
@ -540,17 +542,10 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!-- LOCALIZATION NOTE (syncTabsMenu.label): This appears in the history menu -->
<!ENTITY syncTabsMenu.label "Tabs From Other Computers">
<!ENTITY syncBrand.shortName.label "Sync">
<!ENTITY syncBrand.shortName.label "Sync">
<!ENTITY syncMenu.label "&syncBrand.shortName.label;">
<!-- LOCALIZATION NOTE (sync.menu.accesskey): This is part of the tools menu, so
don't use a conflicting access key -->
<!ENTITY syncMenu.accesskey "Y">
<!ENTITY syncSetup.label "Set Up &syncBrand.shortName.label;…">
<!ENTITY syncSetup.accesskey "Y">
<!ENTITY syncLogInItem.label "Connect">
<!ENTITY syncLogInItem.accesskey "C">
<!ENTITY syncLogOutItem.label "Disconnect">
<!ENTITY syncLogOutItem.accesskey "D">
<!ENTITY syncSyncNowItem.label "Sync Now">
<!ENTITY syncSyncNowItem.accesskey "S">
<!ENTITY syncToolbarButton.label "Sync">

Просмотреть файл

@ -141,6 +141,33 @@ updatesItem_pending=Apply Downloaded Update Now…
updatesItem_pendingFallback=Apply Downloaded Update Now…
updatesItem_pending.accesskey=D
# Check for Updates in the About Dialog - button labels and accesskeys
# LOCALIZATION NOTE - all of the following update buttons and labels will only
# be displayed one at a time. So, if a button is displayed no other buttons or
# labels will be displayed and if a label is displayed no other buttons or
# labels will be displayed. They will be placed directly under the Firefox
# version in the about dialog.
update.checkButton.label=Check for Updates…
update.checkButton.accesskey=C
update.resumeButton.label=Resume Downloading %S…
update.resumeButton.accesskey=D
update.openUpdateUI.applyButton.label=Apply Update…
update.openUpdateUI.applyButton.accesskey=A
update.restart.applyButton.label=Apply Update
update.restart.applyButton.accesskey=A
update.openUpdateUI.upgradeButton.label=Upgrade Now…
update.openUpdateUI.upgradeButton.accesskey=U
update.restart.upgradeButton.label=Upgrade Now
update.restart.upgradeButton.accesskey=U
# Check for Updates in the About Dialog - status labels
update.checkingForUpdate.label=Checking for updates…
update.checkingAddonCompat.label=Checking add-on compatibility…
update.noUpdateFound.label=This is the latest available version
# LOCALIZATION NOTE (update.downloading) — is the "em dash" (long dash)
# %S is the amount download
# examples: Downloading update — 111 KB of 13 MB
update.downloading=Downloading update — %S
# RSS Pretty Print
feedShowFeedNew=Subscribe to '%S'…
@ -162,6 +189,9 @@ tabHistory.current=Stay on this page
tabHistory.goBack=Go back to this page
tabHistory.goForward=Go forward to this page
# URL Bar
pasteAndGo.label=Paste & Go
# Block autorefresh
refreshBlocked.goButton=Allow
refreshBlocked.goButton.accesskey=A
@ -288,3 +318,8 @@ tabView2.title=%S - Group Your Tabs
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name=Default
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description=The default theme.
# About Firefox Dialog
# LOCALIZATION NOTE (aboutdialog.released): %1$S = year, %2$S = month,
# %3$S = day. These are just numbers, and the month/day values are zero-padded.
aboutdialog.released=(released %2$S-%3$S-%1$S)

Просмотреть файл

@ -1,15 +0,0 @@
<!ENTITY brandMotto "Rediscover the Web">
<!ENTITY credit.thanks "Special Thanks To">
<!ENTITY credit.thanks2 "Many thanks to our">
<!ENTITY credit.contributors2 "contributors">
<!-- localization credits look like this: -->
<!--
<!ENTITY credit.translation
"<h3>Translators</h3><ul><li>Name Here</li></ul>">
-->
<!ENTITY credit.translation "">
<!ENTITY credit.memory "In Fond Memory Of">
<!ENTITY credit.poweredByGeckoReg "Powered by Gecko&reg;">

Просмотреть файл

@ -51,6 +51,8 @@
<!ENTITY useCacheAfter.label "MB of space for the cache">
<!ENTITY clearCacheNow.label "Clear Now">
<!ENTITY clearCacheNow.accesskey "C">
<!ENTITY smartSizeCache.label "Let &brandShortName; manage the size of my cache">
<!ENTITY smartSizeCache.accesskey "L">
<!ENTITY updateTab.label "Update">

Просмотреть файл

@ -5,8 +5,8 @@
<!ENTITY startupHomePage.label "Show my home page">
<!ENTITY startupBlankPage.label "Show a blank page">
<!ENTITY startupLastSession.label "Show my windows and tabs from last time">
<!ENTITY location.label "Home Page:">
<!ENTITY location.accesskey "H">
<!ENTITY homepage.label "Home Page:">
<!ENTITY homepage.accesskey "P">
<!ENTITY useCurrentPage.label "Use Current Page">
<!ENTITY useCurrentPage.accesskey "C">
<!ENTITY useMultiple.label "Use Current Pages">

Просмотреть файл

@ -104,11 +104,17 @@ offlineAppUsage=%1$S %2$S
offlinepermissionstext=The following websites are not allowed to store data for offline use:
offlinepermissionstitle=Offline Data
####Preferences::Advanced::Network
#LOCALIZATION NOTE: The next string is for the disk usage of the http cache.
# e.g., "Your cache is currently using 200 MB"
# %1$S = size
# %2$S = unit (MB, KB, etc.)
actualCacheSize=Your cache is currently using %1$S %2$S of disk space
#### Syncing
connect.label=Connect
disconnect.label=Disconnect
differentAccount.title=Use a Different Account?
stopUsingAccount.title=Do you want to stop using this account?
differentAccount.label=This will reset all of your Sync account information and preferences.
differentAccountConfirm.label=Reset All Information

Просмотреть файл

@ -5,7 +5,7 @@
<!-- The page shown when logged in... -->
<!ENTITY accountGroupboxCaption.label "&syncBrand.fullName.label; Account">
<!ENTITY currentUser.label "Current User:">
<!ENTITY currentAccount.label "Current Account:">
<!-- Login error feedback -->
<!ENTITY updatePass.label "Update">
@ -14,10 +14,11 @@
<!-- Manage Account -->
<!ENTITY manageAccount.label "Manage Account">
<!ENTITY manageAccount.accesskey "A">
<!ENTITY viewQuota.label "View Quota">
<!ENTITY changePassword.label "Change Password">
<!ENTITY mySyncKey.label "My Sync Key">
<!ENTITY resetSync.label "Reset Sync">
<!ENTITY differentAccount.label "Use a Different Account">
<!ENTITY stopUsingAccount.label "Stop Using This Account">
<!-- Sync Settings -->
<!ENTITY syncPrefsCaption.label "Browser Sync">

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше