Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
580084e9e1 | ||
|
|
fc61780b35 | ||
|
|
69f7f9e5f1 | ||
|
|
2d4ff8df91 | ||
|
|
f4b8be889c | ||
|
|
e9dd029f5d | ||
|
|
9d6a7ae25d | ||
|
|
42f8488a5f | ||
|
|
681c39a0ec | ||
|
|
55eb2832f5 | ||
|
|
003273327d | ||
|
|
650371311d | ||
|
|
1fccd9d8ee | ||
|
|
f2f6f7e8b0 | ||
|
|
e73929a782 |
No files matched your search
@@ -22,5 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for NSS Update
|
||||
|
||||
Clobber required for updating NSS to 3.38 (poly1305 symbol changes)
|
||||
@@ -6,10 +6,11 @@ with an ESR-52 fork point.
|
||||
|
||||
In addition to further development based on the Mozilla upstream code, and
|
||||
selective cherry-picking of directly-applicable patches, this repository has its
|
||||
own development and holds the base for a maintained platform to be used by XUL
|
||||
own development and holds the base for a future platform to be used by XUL
|
||||
applications.
|
||||
|
||||
For a list of active projects making use of the Unified XUL Platform, checkout http://thereisonlyxul.org/.
|
||||
This repository will contain at least one application to demonstrate and make use
|
||||
of the platform: The Basilisk web browser, a close twin to Mozilla's Firefox.
|
||||
|
||||
## Additional documentation
|
||||
|
||||
@@ -19,7 +20,6 @@ using and distributing this code and its binaries.
|
||||
|
||||
If you are interested in the development and building side of things, some
|
||||
information will be available on the [Pale Moon developer wiki](http://developer.palemoon.org).
|
||||
You are also always welcome to get in touch with our community on the [Pale Moon forum](https://forum.palemoon.org/).
|
||||
|
||||
### A note about trademarks and branding
|
||||
|
||||
@@ -29,8 +29,7 @@ owners. For more details, please see the notifications in the respective directo
|
||||
|
||||
### Foundation and maintainership
|
||||
|
||||
This repository has been founded by Moonchild (M.C. Straver) and is maintained by him
|
||||
and other community members.
|
||||
If you fork this repository to perform your own work on it, please consider offering
|
||||
improvement patches upstream to its origin to mutually improve the platform and build
|
||||
a future for XUL.
|
||||
This repository has been founded and is maintained by Moonchild (M.C. Straver).
|
||||
If you fork this repository to perform your own work on it, please consider
|
||||
offering improvement patches upstream to its origin to mutually improve the
|
||||
platform and build a future for XUL.
|
||||
@@ -8,7 +8,7 @@ EXPORTS.mozilla.dom += [
|
||||
'AccessibleNode.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AccessibleNode.cpp',
|
||||
]
|
||||
|
||||
|
||||
@@ -60,7 +60,11 @@ struct GnomeAccessibilityModule
|
||||
};
|
||||
|
||||
static GnomeAccessibilityModule sAtkBridge = {
|
||||
#ifdef AIX
|
||||
"libatk-bridge.a(libatk-bridge.so.0)", nullptr,
|
||||
#else
|
||||
"libatk-bridge.so", nullptr,
|
||||
#endif
|
||||
"gnome_accessibility_module_init", nullptr,
|
||||
"gnome_accessibility_module_shutdown", nullptr
|
||||
};
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AccessibleOrProxy.h"
|
||||
#include "DocAccessible.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
AccessibleOrProxy
|
||||
AccessibleOrProxy::Parent() const
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
#include "Accessible-inl.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "EmbeddedObjCollector.h"
|
||||
#include "NotificationController.h"
|
||||
#ifdef A11Y_LOG
|
||||
#include "Logging.h"
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "AccEvent.h"
|
||||
#include "Accessible.h"
|
||||
#include "DocAccessible.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#ifndef mozilla_a11y_FocusManager_h_
|
||||
#define mozilla_a11y_FocusManager_h_
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
class nsINode;
|
||||
class nsIDocument;
|
||||
class nsISupports;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "Accessible-inl.h"
|
||||
#include "AccEvent.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "OuterDocAccessible.h"
|
||||
@@ -24,7 +23,6 @@
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIURI.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLBodyElement.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "DocAccessibleChild.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "TextLeafAccessible.h"
|
||||
#include "TextUpdater.h"
|
||||
|
||||
@@ -17,7 +16,6 @@
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NotificationCollector
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef A11Y_STATISTICS_H_
|
||||
#define A11Y_STATISTICS_H_
|
||||
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
namespace statistics {
|
||||
|
||||
inline void A11yInitialized()
|
||||
{ /* STUB */ }
|
||||
|
||||
inline void A11yConsumers(uint32_t aConsumer)
|
||||
{ /* STUB */ }
|
||||
|
||||
/**
|
||||
* Report that ISimpleDOM* has been used.
|
||||
*/
|
||||
inline void ISimpleDOMUsed()
|
||||
{ /* STUB */ }
|
||||
|
||||
/**
|
||||
* Report that IAccessibleTable has been used.
|
||||
*/
|
||||
inline void IAccessibleTableUsed()
|
||||
{ /* STUB */ }
|
||||
|
||||
} // namespace statistics
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "TreeWalker.h"
|
||||
|
||||
#include "Accessible.h"
|
||||
#include "Accessible-inl.h"
|
||||
#include "AccIterator.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "DocAccessible.h"
|
||||
|
||||
@@ -25,7 +25,7 @@ if CONFIG['MOZ_DEBUG']:
|
||||
'Logging.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AccessibleOrProxy.cpp',
|
||||
'AccEvent.cpp',
|
||||
'AccGroupInfo.cpp',
|
||||
@@ -55,7 +55,7 @@ SOURCES += [
|
||||
]
|
||||
|
||||
if CONFIG['A11Y_LOG']:
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'Logging.cpp',
|
||||
]
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "RootAccessibleWrap.h"
|
||||
#endif
|
||||
#include "States.h"
|
||||
#include "Statistics.h"
|
||||
#include "TextLeafAccessibleWrap.h"
|
||||
#include "TreeWalker.h"
|
||||
#include "xpcAccessibleApplication.h"
|
||||
@@ -1287,6 +1288,8 @@ nsAccessibilityService::Init()
|
||||
if (XRE_IsParentProcess())
|
||||
PlatformInit();
|
||||
|
||||
statistics::A11yInitialized();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
@@ -24,7 +23,6 @@
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
#include "Logging.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
|
||||
@@ -10,11 +10,9 @@
|
||||
#include "Accessible-inl.h"
|
||||
#include "AccIterator.h"
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIDOMXULLabeledControlEl.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
using namespace mozilla;
|
||||
|
||||
/**
|
||||
* The accessible for which we are computing a text equivalent. It is useful
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsPresContext.h"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "HTMLListAccessible.h"
|
||||
#include "Relation.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
#include "TextAttrs.h"
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "mozilla/a11y/DocAccessibleParent.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "nsIDOMCustomEvent.h"
|
||||
#include "nsIDOMXULMultSelectCntrlEl.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
@@ -10,7 +10,7 @@ EXPORTS.mozilla.a11y += [
|
||||
'HyperTextAccessible.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'Accessible.cpp',
|
||||
'ApplicationAccessible.cpp',
|
||||
'ARIAGridAccessible.cpp',
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "nsAccUtils.h"
|
||||
#include "Role.h"
|
||||
#include "States.h"
|
||||
#include "EventTree.h"
|
||||
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsBulletFrame.h"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'HTMLCanvasAccessible.cpp',
|
||||
'HTMLElementAccessibles.cpp',
|
||||
'HTMLFormControlAccessible.cpp',
|
||||
|
||||
@@ -44,7 +44,7 @@ if CONFIG['ACCESSIBILITY']:
|
||||
'ProxyAccessibleShared.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'DocAccessibleChildBase.cpp',
|
||||
'DocAccessibleParent.cpp',
|
||||
'ProxyAccessibleBase.cpp',
|
||||
|
||||
@@ -13,7 +13,7 @@ EXPORTS.mozilla.a11y += [
|
||||
'HyperTextAccessibleWrap.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AccessibleWrap.mm',
|
||||
'DocAccessibleWrap.mm',
|
||||
'MacUtils.mm',
|
||||
|
||||
@@ -49,6 +49,42 @@ using namespace mozilla::a11y;
|
||||
// - NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
|
||||
// - NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
|
||||
|
||||
// convert an array of Gecko accessibles to an NSArray of native accessibles
|
||||
static inline NSMutableArray*
|
||||
ConvertToNSArray(nsTArray<Accessible*>& aArray)
|
||||
{
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// iterate through the list, and get each native accessible.
|
||||
size_t totalCount = aArray.Length();
|
||||
for (size_t i = 0; i < totalCount; i++) {
|
||||
Accessible* curAccessible = aArray.ElementAt(i);
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(curAccessible);
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
// convert an array of Gecko proxy accessibles to an NSArray of native accessibles
|
||||
static inline NSMutableArray*
|
||||
ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
||||
{
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// iterate through the list, and get each native accessible.
|
||||
size_t totalCount = aArray.Length();
|
||||
for (size_t i = 0; i < totalCount; i++) {
|
||||
ProxyAccessible* curAccessible = aArray.ElementAt(i);
|
||||
mozAccessible* curNative = GetNativeFromProxy(curAccessible);
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation mozAccessible
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
|
||||
#import "nsCocoaUtils.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
@implementation mozHeadingAccessible
|
||||
|
||||
- (NSString*)title
|
||||
|
||||
@@ -5,50 +5,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import "Accessible-inl.h"
|
||||
#import "mozTableAccessible.h"
|
||||
#import "TableAccessible.h"
|
||||
#import "TableCellAccessible.h"
|
||||
#import "nsCocoaUtils.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
// convert an array of Gecko accessibles to an NSArray of native accessibles
|
||||
static inline NSMutableArray*
|
||||
ConvertToNSArray(nsTArray<Accessible*>& aArray)
|
||||
{
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// iterate through the list, and get each native accessible.
|
||||
size_t totalCount = aArray.Length();
|
||||
for (size_t i = 0; i < totalCount; i++) {
|
||||
Accessible* curAccessible = aArray.ElementAt(i);
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(curAccessible);
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
// convert an array of Gecko proxy accessibles to an NSArray of native accessibles
|
||||
static inline NSMutableArray*
|
||||
ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
|
||||
{
|
||||
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// iterate through the list, and get each native accessible.
|
||||
size_t totalCount = aArray.Length();
|
||||
for (size_t i = 0; i < totalCount; i++) {
|
||||
ProxyAccessible* curAccessible = aArray.ElementAt(i);
|
||||
mozAccessible* curNative = GetNativeFromProxy(curAccessible);
|
||||
if (curNative)
|
||||
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
|
||||
}
|
||||
|
||||
return nativeArray;
|
||||
}
|
||||
|
||||
@implementation mozTablePartAccessible
|
||||
- (BOOL)isLayoutTablePart;
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#import "mozTextAccessible.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
|
||||
#include "Accessible.h"
|
||||
#include "Accessible-inl.h"
|
||||
|
||||
#include "Accessible2_i.c"
|
||||
#include "Accessible2_2_i.c"
|
||||
#include "Accessible2_3_i.c"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
#include "IUnknownImpl.h"
|
||||
#include "Statistics.h"
|
||||
#include "TableAccessible.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
@@ -31,6 +32,7 @@ ia2AccessibleTable::QueryInterface(REFIID iid, void** ppv)
|
||||
*ppv = nullptr;
|
||||
|
||||
if (IID_IAccessibleTable == iid) {
|
||||
statistics::IAccessibleTableUsed();
|
||||
*ppv = static_cast<IAccessibleTable*>(this);
|
||||
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
|
||||
return S_OK;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "ProxyWrappers.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
StaticRefPtr<HyperTextAccessibleWrap> ia2AccessibleText::sLastTextChangeAcc;
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "nsIAccessibleText.h"
|
||||
|
||||
#include "AccessibleText.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
@@ -15,7 +15,7 @@ EXPORTS += [
|
||||
'ia2AccessibleValue.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'ia2Accessible.cpp',
|
||||
'ia2AccessibleAction.cpp',
|
||||
'ia2AccessibleComponent.cpp',
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Compatibility.h"
|
||||
|
||||
#include "nsWinUtils.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
@@ -51,6 +52,8 @@ uint32_t Compatibility::sConsumers = Compatibility::UNKNOWN;
|
||||
void
|
||||
Compatibility::Init()
|
||||
{
|
||||
// Note we collect some AT statistics/telemetry here for convenience.
|
||||
|
||||
HMODULE jawsHandle = ::GetModuleHandleW(L"jhook");
|
||||
if (jawsHandle)
|
||||
sConsumers |= (IsModuleVersionLessThan(jawsHandle, 8, 2173)) ?
|
||||
@@ -89,6 +92,15 @@ Compatibility::Init()
|
||||
if (sConsumers != Compatibility::UNKNOWN)
|
||||
sConsumers ^= Compatibility::UNKNOWN;
|
||||
|
||||
// Gather telemetry
|
||||
uint32_t temp = sConsumers;
|
||||
for (int i = 0; temp; i++) {
|
||||
if (temp & 0x1)
|
||||
statistics::A11yConsumers(i);
|
||||
|
||||
temp >>= 1;
|
||||
}
|
||||
|
||||
// Turn off new tab switching for Jaws and WE.
|
||||
if (sConsumers & (JAWS | OLDJAWS | WE)) {
|
||||
// Check to see if the pref for disallowing CtrlTab is already set. If so,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Role.h"
|
||||
#include "RootAccessible.h"
|
||||
#include "sdnDocAccessible.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
@@ -35,6 +36,7 @@ DocAccessibleWrap::~DocAccessibleWrap()
|
||||
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(DocAccessibleWrap)
|
||||
if (aIID == IID_ISimpleDOMDocument) {
|
||||
statistics::ISimpleDOMUsed();
|
||||
*aInstancePtr = static_cast<ISimpleDOMDocument*>(new sdnDocAccessible(this));
|
||||
static_cast<IUnknown*>(*aInstancePtr)->AddRef();
|
||||
return S_OK;
|
||||
|
||||
@@ -83,7 +83,7 @@ private:
|
||||
|
||||
} // namespace detail
|
||||
|
||||
MsaaIdGenerator::MsaaIdGenerator()
|
||||
constexpr MsaaIdGenerator::MsaaIdGenerator()
|
||||
: mIDSet(kNumUniqueIDBits)
|
||||
{}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class AccessibleWrap;
|
||||
class MsaaIdGenerator
|
||||
{
|
||||
public:
|
||||
MsaaIdGenerator();
|
||||
constexpr MsaaIdGenerator();
|
||||
|
||||
uint32_t GetID();
|
||||
void ReleaseID(AccessibleWrap* aAccWrap);
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Accessible.h"
|
||||
#include "Accessible-inl.h"
|
||||
|
||||
#include "AccEvent.h"
|
||||
#include "Compatibility.h"
|
||||
#include "HyperTextAccessibleWrap.h"
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
#include "TextLeafAccessibleWrap.h"
|
||||
|
||||
#include "sdnTextAccessible.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
IMPL_IUNKNOWN_QUERY_HEAD(TextLeafAccessibleWrap)
|
||||
if (aIID == IID_ISimpleDOMText) {
|
||||
statistics::ISimpleDOMUsed();
|
||||
*aInstancePtr = static_cast<ISimpleDOMText*>(new sdnTextAccessible(this));
|
||||
static_cast<IUnknown*>(*aInstancePtr)->AddRef();
|
||||
return S_OK;
|
||||
|
||||
@@ -16,7 +16,7 @@ EXPORTS.mozilla.a11y += [
|
||||
'MsaaIdGenerator.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AccessibleWrap.cpp',
|
||||
'ApplicationAccessibleWrap.cpp',
|
||||
'ARIAGridAccessibleWrap.cpp',
|
||||
@@ -32,12 +32,16 @@ SOURCES += [
|
||||
'nsWinUtils.cpp',
|
||||
'Platform.cpp',
|
||||
'RootAccessibleWrap.cpp',
|
||||
'ServiceProvider.cpp',
|
||||
'TextLeafAccessibleWrap.cpp',
|
||||
]
|
||||
|
||||
# This file cannot be built in unified mode because it includes ISimpleDOMNode_i.c.
|
||||
SOURCES += [
|
||||
'ServiceProvider.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_XUL']:
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'XULListboxAccessibleWrap.cpp',
|
||||
'XULMenuAccessibleWrap.cpp',
|
||||
'XULTreeGridAccessibleWrap.cpp',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'sdnAccessible.cpp',
|
||||
'sdnDocAccessible.cpp',
|
||||
'sdnTextAccessible.cpp',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'nsAccessibleRelation.cpp',
|
||||
'xpcAccessibilityService.cpp',
|
||||
'xpcAccessible.cpp',
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "xpcAccessibilityService.h"
|
||||
#include "xpcAccessibleDocument.h"
|
||||
|
||||
#include "nsAccessiblePivot.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
#include "nsIAccessibilityService.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
class xpcAccessibilityService : public nsIAccessibleRetrieval
|
||||
{
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "xpcAccessibleHyperText.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "mozilla/a11y/DocAccessibleParent.h"
|
||||
#include "HyperTextAccessible-inl.h"
|
||||
#include "TextRange.h"
|
||||
#include "xpcAccessibleDocument.h"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'XULAlertAccessible.cpp',
|
||||
'XULColorPickerAccessible.cpp',
|
||||
'XULComboboxAccessible.cpp',
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../toolkit/.eslintrc.js"
|
||||
],
|
||||
|
||||
"rules": {
|
||||
"no-unused-vars": ["error", {
|
||||
"vars": "local",
|
||||
"varsIgnorePattern": "^Cc|Ci|Cu|Cr|EXPORTED_SYMBOLS",
|
||||
"args": "none",
|
||||
}]
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
Please see the file ../toolkit/content/license.html for the copyright
|
||||
licensing conditions attached to this codebase, including copies of the
|
||||
licenses concerned.
|
||||
|
||||
You are not granted rights or licenses to the trademarks of Moonchild
|
||||
Productions or any other party, including without limitation the
|
||||
Basilisk name or logo.
|
||||
|
||||
The Serpent logo in branding/unofficial is derived from "Sea Serpent"
|
||||
by Lorc, licensed under the Creative Commons license CC-BY 3.0
|
||||
|
||||
For individual licensing restrictions on branding, see the LICENSE
|
||||
files in the appropriate branding directories.
|
||||
@@ -0,0 +1,16 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifdef MAKENSISU
|
||||
|
||||
# For Windows build the uninstaller during the application build since the
|
||||
# uninstaller is included with the application for mar file generation.
|
||||
libs::
|
||||
$(MAKE) -C installer/windows uninstaller
|
||||
ifdef MOZ_MAINTENANCE_SERVICE
|
||||
$(MAKE) -C installer/windows maintenanceservice_installer
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1 @@
|
||||
PURGECACHES_DIRS = $(DIST)/bin/browser
|
||||
@@ -0,0 +1,15 @@
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include('/toolkit/toolkit.mozbuild')
|
||||
|
||||
if CONFIG['MOZ_EXTENSIONS']:
|
||||
DIRS += ['/extensions']
|
||||
|
||||
DIRS += ['/%s' % CONFIG['MOZ_BRANDING_DIRECTORY']]
|
||||
|
||||
# Never add dirs after the browser root because they apparently won't
|
||||
# get packaged properly on Mac.
|
||||
DIRS += ['/application/basilisk']
|
||||
@@ -0,0 +1,94 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
dist_dest = $(DIST)/$(MOZ_MACBUNDLE_NAME)
|
||||
|
||||
# hardcode en-US for the moment
|
||||
AB_CD = en-US
|
||||
|
||||
# Build a binary bootstrapping with XRE_main
|
||||
|
||||
ifndef MOZ_WINCONSOLE
|
||||
ifneq (,$(MOZ_DEBUG)$(MOZ_ASAN))
|
||||
MOZ_WINCONSOLE = 1
|
||||
else
|
||||
MOZ_WINCONSOLE = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
# This switches $(INSTALL) to copy mode, like $(SYSINSTALL), so things that
|
||||
# shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall.
|
||||
NSDISTMODE = copy
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
# Rebuild firefox.exe if the manifest changes - it's included by splash.rc.
|
||||
# (this dependency should really be just for firefox.exe, not other targets)
|
||||
# Note the manifest file exists in the tree, so we use the explicit filename
|
||||
# here.
|
||||
EXTRA_DEPS += basilisk.exe.manifest
|
||||
endif
|
||||
|
||||
PROGRAMS_DEST = $(DIST)/bin
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifneq (,$(filter-out WINNT,$(OS_ARCH)))
|
||||
|
||||
ifdef COMPILE_ENVIRONMENT
|
||||
libs::
|
||||
cp -p $(MOZ_APP_NAME)$(BIN_SUFFIX) $(DIST)/bin/$(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
|
||||
endif
|
||||
|
||||
GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, basilisk.js)
|
||||
|
||||
endif
|
||||
|
||||
# channel-prefs.js is handled separate from other prefs due to bug 756325
|
||||
libs:: $(srcdir)/profile/channel-prefs.js
|
||||
$(NSINSTALL) -D $(DIST)/bin/defaults/pref
|
||||
$(call py_action,preprocessor,-Fsubstitution $(PREF_PPFLAGS) $(ACDEFINES) $^ -o $(DIST)/bin/defaults/pref/channel-prefs.js)
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
||||
MAC_APP_NAME = $(MOZ_APP_DISPLAYNAME)
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
MAC_APP_NAME := $(MAC_APP_NAME)Debug
|
||||
endif
|
||||
|
||||
AB_CD = $(MOZ_UI_LOCALE)
|
||||
|
||||
ifeq (zh-TW,$(AB_CD))
|
||||
LPROJ_ROOT := $(subst -,_,$(AB_CD))
|
||||
else
|
||||
LPROJ_ROOT := $(firstword $(subst -, ,$(AB_CD)))
|
||||
endif
|
||||
LPROJ := Contents/Resources/$(LPROJ_ROOT).lproj
|
||||
|
||||
clean clobber repackage::
|
||||
$(RM) -r $(dist_dest)
|
||||
|
||||
MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/buildid.h)
|
||||
|
||||
.PHONY: repackage
|
||||
tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME)
|
||||
$(MKDIR) -p $(dist_dest)/Contents/MacOS
|
||||
$(MKDIR) -p $(dist_dest)/$(LPROJ)
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/$(LPROJ)
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/$(LPROJ)/InfoPlist.strings
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
|
||||
$(RM) $(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)
|
||||
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) $(dist_dest)/Contents/MacOS
|
||||
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
|
||||
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
|
||||
$(MKDIR) -p $(dist_dest)/Contents/Library/LaunchServices
|
||||
mv -f $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(dist_dest)/Contents/Library/LaunchServices
|
||||
ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
|
||||
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
|
||||
endif
|
||||
@@ -0,0 +1,50 @@
|
||||
#if MOZ_APP_STATIC_INI
|
||||
#ifdef MOZ_BUILD_APP_IS_BROWSER
|
||||
; This file is not used. If you modify it and want the application to use
|
||||
; your modifications, move it under the browser/ subdirectory and start with
|
||||
; the "-app /path/to/browser/application.ini" argument.
|
||||
#else
|
||||
; This file is not used. If you modify it and want the application to use
|
||||
; your modifications, start with the "-app /path/to/application.ini"
|
||||
; argument.
|
||||
#endif
|
||||
#endif
|
||||
#if 0
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#endif
|
||||
#filter substitution
|
||||
#include @TOPOBJDIR@/buildid.h
|
||||
#include @TOPOBJDIR@/source-repo.h
|
||||
|
||||
[App]
|
||||
# Vendor=@MOZ_APP_VENDOR@
|
||||
Vendor=Moonchild Productions
|
||||
# Name=@MOZ_APP_BASENAME@
|
||||
Name=Basilisk
|
||||
RemotingName=@MOZ_APP_REMOTINGNAME@
|
||||
#ifdef MOZ_APP_DISPLAYNAME
|
||||
CodeName=@MOZ_APP_DISPLAYNAME@
|
||||
#endif
|
||||
Version=@MOZ_APP_VERSION@
|
||||
#ifdef MOZ_APP_PROFILE
|
||||
Profile=@MOZ_APP_PROFILE@
|
||||
#endif
|
||||
BuildID=@MOZ_BUILDID@
|
||||
#ifdef MOZ_SOURCE_REPO
|
||||
SourceRepository=@MOZ_SOURCE_REPO@
|
||||
#endif
|
||||
#ifdef MOZ_SOURCE_STAMP
|
||||
SourceStamp=@MOZ_SOURCE_STAMP@
|
||||
#endif
|
||||
ID=@MOZ_APP_ID@
|
||||
|
||||
[Gecko]
|
||||
MinVersion=@GRE_MILESTONE@
|
||||
MaxVersion=@GRE_MILESTONE@
|
||||
|
||||
[XRE]
|
||||
#ifdef MOZ_PROFILE_MIGRATOR
|
||||
EnableProfileMigrator=1
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="*"
|
||||
name="Basilisk"
|
||||
type="win32"
|
||||
/>
|
||||
<description>Firefox</description>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<ms_asmv3:security>
|
||||
<ms_asmv3:requestedPrivileges>
|
||||
<ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</ms_asmv3:requestedPrivileges>
|
||||
</ms_asmv3:security>
|
||||
</ms_asmv3:trustInfo>
|
||||
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>True/PM</dpiAware>
|
||||
</ms_asmv3:windowsSettings>
|
||||
</ms_asmv3:application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
@@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>html</string>
|
||||
<string>htm</string>
|
||||
<string>shtml</string>
|
||||
<string>xht</string>
|
||||
<string>xhtml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>HTML Document</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>HTML</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>svg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>image/svg+xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>SVG document</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>TEXT</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>NSDocumentClass</key>
|
||||
<string>BrowserDocument</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>text</string>
|
||||
<string>txt</string>
|
||||
<string>js</string>
|
||||
<string>log</string>
|
||||
<string>css</string>
|
||||
<string>xul</string>
|
||||
<string>rdf</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Text Document</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>TEXT</string>
|
||||
<string>utxt</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>jpeg</string>
|
||||
<string>jpg</string>
|
||||
<string>png</string>
|
||||
<string>gif</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>fileBookmark.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>GIFf</string>
|
||||
<string>JPEG</string>
|
||||
<string>PNGf</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>oga</string>
|
||||
<string>ogg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>audio/ogg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>HTML5 Audio (Ogg)</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>ogv</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>video/ogg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>HTML5 Video (Ogg)</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>webm</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>video/webm</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>HTML5 Video (WebM)</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>basilisk</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>%MAC_APP_NAME% %APP_VERSION%</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>firefox.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>%MOZ_MACBUNDLE_ID%</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>%MAC_APP_NAME%</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>%APP_VERSION%</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>MOZB</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>http URL</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>http</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLIconFile</key>
|
||||
<string>document.icns</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>https URL</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>https</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>ftp URL</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>ftp</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>file URL</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>file</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>%MAC_BUNDLE_VERSION%</string>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<true/>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.productivity</string>
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>MallocNanoZone</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>LSFileQuarantineEnabled</key>
|
||||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.7.0</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>GeckoNSApplication</string>
|
||||
<key>SMPrivilegedExecutables</key>
|
||||
<dict>
|
||||
<key>org.mozilla.updater</key>
|
||||
<string>identifier "org.mozilla.updater" and ((anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]) or (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "43AQ936H96"))</string>
|
||||
</dict>
|
||||
<key>NSDisablePersistence</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,9 @@
|
||||
/*.app/***
|
||||
/*.dylib
|
||||
/certutil
|
||||
/firefox-bin
|
||||
/gtest/***
|
||||
/pk12util
|
||||
/ssltunnel
|
||||
/xpcshell
|
||||
/XUL
|
||||
@@ -0,0 +1,5 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
CFBundleName = "%MAC_APP_NAME%";
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/python
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
from optparse import OptionParser
|
||||
import sys
|
||||
import re
|
||||
|
||||
o = OptionParser()
|
||||
o.add_option("--buildid", dest="buildid")
|
||||
o.add_option("--version", dest="version")
|
||||
|
||||
(options, args) = o.parse_args()
|
||||
|
||||
if not options.buildid:
|
||||
print >>sys.stderr, "--buildid is required"
|
||||
sys.exit(1)
|
||||
|
||||
if not options.version:
|
||||
print >>sys.stderr, "--version is required"
|
||||
sys.exit(1)
|
||||
|
||||
# We want to build a version number that matches the format allowed for
|
||||
# CFBundleVersion (nnnnn[.nn[.nn]]). We'll incorporate both the version
|
||||
# number as well as the date, so that it changes at least daily (for nightly
|
||||
# builds), but also so that newly-built older versions (e.g. beta build) aren't
|
||||
# considered "newer" than previously-built newer versions (e.g. a trunk nightly)
|
||||
|
||||
define, MOZ_BUILDID, buildid = open(options.buildid, 'r').read().split()
|
||||
|
||||
# extract only the major version (i.e. "14" from "14.0b1")
|
||||
majorVersion = re.match(r'^(\d+)[^\d].*', options.version).group(1)
|
||||
# last two digits of the year
|
||||
twodigityear = buildid[2:4]
|
||||
month = buildid[4:6]
|
||||
if month[0] == '0':
|
||||
month = month[1]
|
||||
day = buildid[6:8]
|
||||
if day[0] == '0':
|
||||
day = day[1]
|
||||
|
||||
print '%s.%s.%s' % (majorVersion + twodigityear, month, day)
|
||||
@@ -0,0 +1,8 @@
|
||||
WIN32_MODULE_COMPANYNAME=Moonchild Productions
|
||||
WIN32_MODULE_COPYRIGHT=©Basilisk and Mozilla Developers; available under the MPL 2 license.
|
||||
WIN32_MODULE_PRODUCTVERSION=@MOZ_APP_WINVERSION@
|
||||
WIN32_MODULE_PRODUCTVERSION_STRING=@MOZ_APP_VERSION@
|
||||
WIN32_MODULE_TRADEMARKS=Basilisk is a Trademark of Moonchild Productions.
|
||||
WIN32_MODULE_DESCRIPTION=@MOZ_APP_DISPLAYNAME@
|
||||
WIN32_MODULE_PRODUCTNAME=@MOZ_APP_DISPLAYNAME@
|
||||
WIN32_MODULE_NAME=@MOZ_APP_DISPLAYNAME@
|
||||
@@ -0,0 +1,75 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['profile/extensions']
|
||||
|
||||
GeckoProgram(CONFIG['MOZ_APP_NAME'])
|
||||
|
||||
JS_PREFERENCE_PP_FILES += [
|
||||
'profile/basilisk.js',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsBrowserApp.cpp',
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES += ['blocklist.xml']
|
||||
FINAL_TARGET_FILES.defaults.profile += ['profile/prefs.js']
|
||||
FINAL_TARGET_FILES.defaults += ['permissions']
|
||||
|
||||
DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'!/build',
|
||||
'/toolkit/xre',
|
||||
'/xpcom/base',
|
||||
'/xpcom/build',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'mozglue',
|
||||
]
|
||||
|
||||
if CONFIG['LIBFUZZER']:
|
||||
USE_LIBS += [ 'fuzzer' ]
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
# Always enter a Windows program through wmain, whether or not we're
|
||||
# a console application.
|
||||
WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
RCINCLUDE = 'splash.rc'
|
||||
DEFINES['MOZ_PHOENIX'] = True
|
||||
|
||||
for cdm in CONFIG['MOZ_EME_MODULES']:
|
||||
DEFINES['MOZ_%s_EME' % cdm.upper()] = True
|
||||
|
||||
# Control the default heap size.
|
||||
# This is the heap returned by GetProcessHeap().
|
||||
# As we use the CRT heap, the default size is too large and wastes VM.
|
||||
#
|
||||
# The default heap size is 1MB on Win32.
|
||||
# The heap will grow if need be.
|
||||
#
|
||||
# Set it to 256k. See bug 127069.
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']:
|
||||
LDFLAGS += ['/HEAP:0x40000']
|
||||
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
if CONFIG['MOZ_LINKER']:
|
||||
OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
|
||||
|
||||
if CONFIG['HAVE_CLOCK_MONOTONIC']:
|
||||
OS_LIBS += CONFIG['REALTIME_LIBS']
|
||||
|
||||
if CONFIG['MOZ_GPSD']:
|
||||
DEFINES['MOZ_GPSD'] = True
|
||||
|
||||
for icon in ('firefox', 'document', 'newwindow', 'newtab', 'pbmode'):
|
||||
DEFINES[icon.upper() + '_ICO'] = '"%s/dist/branding/%s.ico"' % (
|
||||
TOPOBJDIR, icon)
|
||||
@@ -0,0 +1,393 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/AppData.h"
|
||||
#include "application.ini.h"
|
||||
#include "nsXPCOMGlue.h"
|
||||
#if defined(XP_WIN)
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#elif defined(XP_UNIX)
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#define XRE_WANT_ENVIRON
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
#include "BinaryPath.h"
|
||||
|
||||
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
|
||||
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/WindowsDllBlocklist.h"
|
||||
|
||||
#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID)
|
||||
#define MOZ_BROWSER_CAN_BE_CONTENTPROC
|
||||
#include "../../ipc/contentproc/plugin-container.cpp"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#define kOSXResourcesFolder "Resources"
|
||||
#endif
|
||||
#define kDesktopFolder "browser"
|
||||
|
||||
static void Output(const char *fmt, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
#ifndef XP_WIN
|
||||
vfprintf(stderr, fmt, ap);
|
||||
#else
|
||||
char msg[2048];
|
||||
vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap);
|
||||
|
||||
wchar_t wide_msg[2048];
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
msg,
|
||||
-1,
|
||||
wide_msg,
|
||||
_countof(wide_msg));
|
||||
#if MOZ_WINCONSOLE
|
||||
fwprintf_s(stderr, wide_msg);
|
||||
#else
|
||||
// Linking user32 at load-time interferes with the DLL blocklist (bug 932100).
|
||||
// This is a rare codepath, so we can load user32 at run-time instead.
|
||||
HMODULE user32 = LoadLibraryW(L"user32.dll");
|
||||
if (user32) {
|
||||
decltype(MessageBoxW)* messageBoxW =
|
||||
(decltype(MessageBoxW)*) GetProcAddress(user32, "MessageBoxW");
|
||||
if (messageBoxW) {
|
||||
messageBoxW(nullptr, wide_msg, L"Basilisk", MB_OK
|
||||
| MB_ICONERROR
|
||||
| MB_SETFOREGROUND);
|
||||
}
|
||||
FreeLibrary(user32);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if |arg| matches the given argument name.
|
||||
*/
|
||||
static bool IsArg(const char* arg, const char* s)
|
||||
{
|
||||
if (*arg == '-')
|
||||
{
|
||||
if (*++arg == '-')
|
||||
++arg;
|
||||
return !strcasecmp(arg, s);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
if (*arg == '/')
|
||||
return !strcasecmp(++arg, s);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
XRE_GetFileFromPathType XRE_GetFileFromPath;
|
||||
XRE_CreateAppDataType XRE_CreateAppData;
|
||||
XRE_FreeAppDataType XRE_FreeAppData;
|
||||
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
|
||||
XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
|
||||
XRE_mainType XRE_main;
|
||||
XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
|
||||
XRE_XPCShellMainType XRE_XPCShellMain;
|
||||
XRE_GetProcessTypeType XRE_GetProcessType;
|
||||
XRE_SetProcessTypeType XRE_SetProcessType;
|
||||
XRE_InitChildProcessType XRE_InitChildProcess;
|
||||
XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc;
|
||||
#ifdef LIBFUZZER
|
||||
XRE_LibFuzzerSetMainType XRE_LibFuzzerSetMain;
|
||||
XRE_LibFuzzerGetFuncsType XRE_LibFuzzerGetFuncs;
|
||||
#endif
|
||||
|
||||
static const nsDynamicFunctionLoad kXULFuncs[] = {
|
||||
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
|
||||
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
|
||||
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
|
||||
{ "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
|
||||
{ "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
|
||||
{ "XRE_main", (NSFuncPtr*) &XRE_main },
|
||||
{ "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
|
||||
{ "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain },
|
||||
{ "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType },
|
||||
{ "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType },
|
||||
{ "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess },
|
||||
{ "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc },
|
||||
#ifdef LIBFUZZER
|
||||
{ "XRE_LibFuzzerSetMain", (NSFuncPtr*) &XRE_LibFuzzerSetMain },
|
||||
{ "XRE_LibFuzzerGetFuncs", (NSFuncPtr*) &XRE_LibFuzzerGetFuncs },
|
||||
#endif
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
#ifdef LIBFUZZER
|
||||
int libfuzzer_main(int argc, char **argv);
|
||||
|
||||
/* This wrapper is used by the libFuzzer main to call into libxul */
|
||||
|
||||
void libFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc,
|
||||
LibFuzzerTestingFunc* testingFunc) {
|
||||
return XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory)
|
||||
{
|
||||
nsCOMPtr<nsIFile> appini;
|
||||
nsresult rv;
|
||||
uint32_t mainFlags = 0;
|
||||
|
||||
// Allow basilisk.exe to launch XULRunner apps via -app <application.ini>
|
||||
// Note that -app must be the *first* argument.
|
||||
const char *appDataFile = getenv("XUL_APP_FILE");
|
||||
if (appDataFile && *appDataFile) {
|
||||
rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Invalid path found: '%s'", appDataFile);
|
||||
return 255;
|
||||
}
|
||||
}
|
||||
else if (argc > 1 && IsArg(argv[1], "app")) {
|
||||
if (argc == 2) {
|
||||
Output("Incorrect number of arguments passed to -app");
|
||||
return 255;
|
||||
}
|
||||
|
||||
rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("application.ini path not recognized: '%s'", argv[2]);
|
||||
return 255;
|
||||
}
|
||||
|
||||
char appEnv[MAXPATHLEN];
|
||||
SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
|
||||
if (putenv(strdup(appEnv))) {
|
||||
Output("Couldn't set %s.\n", appEnv);
|
||||
return 255;
|
||||
}
|
||||
argv[2] = argv[0];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
} else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
argv[i] = argv[i + 1];
|
||||
}
|
||||
|
||||
return XRE_XPCShellMain(--argc, argv, envp);
|
||||
}
|
||||
|
||||
if (appini) {
|
||||
nsXREAppData *appData;
|
||||
rv = XRE_CreateAppData(appini, &appData);
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Couldn't read application.ini");
|
||||
return 255;
|
||||
}
|
||||
#if defined(HAS_DLL_BLOCKLIST)
|
||||
// The dll blocklist operates in the exe vs. xullib. Pass a flag to
|
||||
// xullib so automated tests can check the result once the browser
|
||||
// is up and running.
|
||||
appData->flags |=
|
||||
DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
|
||||
#endif
|
||||
// xreDirectory already has a refcount from NS_NewLocalFile
|
||||
appData->xreDirectory = xreDirectory;
|
||||
int result = XRE_main(argc, argv, appData, mainFlags);
|
||||
XRE_FreeAppData(appData);
|
||||
return result;
|
||||
}
|
||||
|
||||
ScopedAppData appData(&sAppData);
|
||||
nsCOMPtr<nsIFile> exeFile;
|
||||
rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Couldn't find the application directory.\n");
|
||||
return 255;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
exeFile->GetParent(getter_AddRefs(greDir));
|
||||
#ifdef XP_MACOSX
|
||||
greDir->SetNativeLeafName(NS_LITERAL_CSTRING(kOSXResourcesFolder));
|
||||
#endif
|
||||
nsCOMPtr<nsIFile> appSubdir;
|
||||
greDir->Clone(getter_AddRefs(appSubdir));
|
||||
appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
|
||||
|
||||
SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
|
||||
// xreDirectory already has a refcount from NS_NewLocalFile
|
||||
appData.xreDirectory = xreDirectory;
|
||||
|
||||
#if defined(HAS_DLL_BLOCKLIST)
|
||||
appData.flags |=
|
||||
DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
|
||||
#endif
|
||||
|
||||
#ifdef LIBFUZZER
|
||||
if (getenv("LIBFUZZER"))
|
||||
XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
|
||||
#endif
|
||||
|
||||
return XRE_main(argc, argv, &appData, mainFlags);
|
||||
}
|
||||
|
||||
static bool
|
||||
FileExists(const char *path)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
wchar_t wideDir[MAX_PATH];
|
||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH);
|
||||
DWORD fileAttrs = GetFileAttributesW(wideDir);
|
||||
return fileAttrs != INVALID_FILE_ATTRIBUTES;
|
||||
#else
|
||||
return access(path, R_OK) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static nsresult
|
||||
InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
|
||||
{
|
||||
char exePath[MAXPATHLEN];
|
||||
|
||||
nsresult rv = mozilla::BinaryPath::Get(argv0, exePath);
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Couldn't find the application directory.\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
|
||||
if (!lastSlash ||
|
||||
(size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
strcpy(lastSlash + 1, XPCOM_DLL);
|
||||
|
||||
if (!FileExists(exePath)) {
|
||||
Output("Could not find the Mozilla runtime.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We do this because of data in bug 771745
|
||||
XPCOMGlueEnablePreload();
|
||||
|
||||
rv = XPCOMGlueStartup(exePath);
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Couldn't load XPCOM.\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
|
||||
if (NS_FAILED(rv)) {
|
||||
Output("Couldn't load XRE functions.\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// This will set this thread as the main thread.
|
||||
NS_LogInit();
|
||||
|
||||
if (xreDirectory) {
|
||||
// chop XPCOM_DLL off exePath
|
||||
*lastSlash = '\0';
|
||||
#ifdef XP_MACOSX
|
||||
lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
|
||||
strcpy(lastSlash + 1, kOSXResourcesFolder);
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
|
||||
xreDirectory);
|
||||
#else
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
|
||||
xreDirectory);
|
||||
#endif
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[], char* envp[])
|
||||
{
|
||||
mozilla::TimeStamp start = mozilla::TimeStamp::Now();
|
||||
|
||||
#ifdef HAS_DLL_BLOCKLIST
|
||||
DllBlocklist_Initialize();
|
||||
|
||||
#ifdef DEBUG
|
||||
// In order to be effective against AppInit DLLs, the blocklist must be
|
||||
// initialized before user32.dll is loaded into the process (bug 932100).
|
||||
if (GetModuleHandleA("user32.dll")) {
|
||||
fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
|
||||
// We are launching as a content process, delegate to the appropriate
|
||||
// main
|
||||
if (argc > 1 && IsArg(argv[1], "contentproc")) {
|
||||
nsresult rv = InitXPCOMGlue(argv[0], nullptr);
|
||||
if (NS_FAILED(rv)) {
|
||||
return 255;
|
||||
}
|
||||
|
||||
int result = content_process_main(argc, argv);
|
||||
|
||||
// InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
|
||||
NS_LogTerm();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
nsIFile *xreDirectory;
|
||||
|
||||
nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
|
||||
if (NS_FAILED(rv)) {
|
||||
return 255;
|
||||
}
|
||||
|
||||
XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
|
||||
|
||||
#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
|
||||
XRE_EnableSameExecutableForContentProc();
|
||||
#endif
|
||||
|
||||
int result = do_main(argc, argv, envp, xreDirectory);
|
||||
|
||||
NS_LogTerm();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Allow writes again. While we would like to catch writes from static
|
||||
// destructors to allow early exits to use _exit, we know that there is
|
||||
// at least one such write that we don't control (see bug 826029). For
|
||||
// now we enable writes again and early exits will have to use exit instead
|
||||
// of _exit.
|
||||
XRE_StopLateWriteChecks();
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# This file has default permissions for the permission manager.
|
||||
# The file-format is strict:
|
||||
# * matchtype \t type \t permission \t host
|
||||
# * "origin" should be used for matchtype, "host" is supported for legacy reasons
|
||||
# * type is a string that identifies the type of permission (e.g. "cookie")
|
||||
# * permission is an integer between 1 and 15
|
||||
# See nsPermissionManager.cpp for more...
|
||||
|
||||
# XPInstall
|
||||
origin install 1 https://addons.mozilla.org
|
||||
origin install 1 https://testpilot.firefox.com
|
||||
|
||||
# Remote troubleshooting
|
||||
origin remote-troubleshooting 1 https://input.mozilla.org
|
||||
origin remote-troubleshooting 1 https://support.mozilla.org
|
||||
@@ -0,0 +1,5 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
pref("app.update.channel", "@MOZ_UPDATE_CHANNEL@");
|
||||
@@ -0,0 +1,7 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['{972ce4c6-7e08-4474-a285-3208198ce6fd}']
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
|
||||
#filter substitution
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>{972ce4c6-7e08-4474-a285-3208198ce6fd}</em:id>
|
||||
<em:version>@MOZ_APP_VERSION@</em:version>
|
||||
|
||||
<!-- Target Application this theme can install into,
|
||||
with minimum and maximum supported versions. -->
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>@MOZ_APP_ID@</em:id>
|
||||
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
|
||||
<em:maxVersion>@MOZ_APP_VERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
<!-- Front End MetaData -->
|
||||
<em:name>Default</em:name>
|
||||
<em:description>The default theme.</em:description>
|
||||
|
||||
<!-- Front End Integration Hooks (used by Theme Manager)-->
|
||||
<em:creator>Mozilla</em:creator>
|
||||
<em:contributor>Mozilla Contributors</em:contributor>
|
||||
|
||||
<!-- Allow lightweight themes to apply to this theme -->
|
||||
<em:skinnable>true</em:skinnable>
|
||||
|
||||
<em:internalName>classic/1.0</em:internalName>
|
||||
</Description>
|
||||
|
||||
</RDF>
|
||||
@@ -0,0 +1,14 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
|
||||
DEFINES['MOZ_APP_ID'] = CONFIG['MOZ_APP_ID']
|
||||
|
||||
FINAL_TARGET = 'dist/bin/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}'
|
||||
|
||||
FINAL_TARGET_PP_FILES += [
|
||||
'install.rdf.in',
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0"?> <!-- -*- Mode: SGML -*- -->
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
# Mozilla User Preferences
|
||||
|
||||
/* Do not edit this file.
|
||||
*
|
||||
* If you make changes to this file while the browser is running,
|
||||
* the changes will be overwritten when the browser exits.
|
||||
*
|
||||
* To make a manual change to preferences, you can visit the URL about:config
|
||||
*/
|
||||
@@ -0,0 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <windows.h>
|
||||
#include "nsNativeAppSupportWin.h"
|
||||
|
||||
1 24 "basilisk.exe.manifest"
|
||||
|
||||
IDI_APPICON ICON FIREFOX_ICO
|
||||
IDI_DOCUMENT ICON DOCUMENT_ICO
|
||||
IDI_APPLICATION ICON FIREFOX_ICO
|
||||
IDI_NEWWINDOW ICON NEWWINDOW_ICO
|
||||
IDI_NEWTAB ICON NEWTAB_ICO
|
||||
IDI_PBMODE ICON PBMODE_ICO
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_STARTMENU_APPNAME, "@MOZ_APP_DISPLAYNAME@"
|
||||
END
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"rules": {
|
||||
"no-unused-vars": ["error", {
|
||||
"vars": "local",
|
||||
"varsIgnorePattern": "^Cc|Ci|Cu|Cr|EXPORTED_SYMBOLS",
|
||||
"args": "none",
|
||||
}]
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,428 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Note: this file is included in aboutDialog.xul if MOZ_UPDATER is defined.
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
|
||||
"resource://gre/modules/UpdateUtils.jsm");
|
||||
|
||||
const PREF_APP_UPDATE_CANCELATIONS_OSX = "app.update.cancelations.osx";
|
||||
const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never";
|
||||
|
||||
var gAppUpdater;
|
||||
|
||||
function onUnload(aEvent) {
|
||||
if (gAppUpdater.isChecking)
|
||||
gAppUpdater.checker.stopChecking(Components.interfaces.nsIUpdateChecker.CURRENT_CHECK);
|
||||
// Safe to call even when there isn't a download in progress.
|
||||
gAppUpdater.removeDownloadListener();
|
||||
gAppUpdater = null;
|
||||
}
|
||||
|
||||
|
||||
function appUpdater()
|
||||
{
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "aus",
|
||||
"@mozilla.org/updates/update-service;1",
|
||||
"nsIApplicationUpdateService");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "checker",
|
||||
"@mozilla.org/updates/update-checker;1",
|
||||
"nsIUpdateChecker");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "um",
|
||||
"@mozilla.org/updates/update-manager;1",
|
||||
"nsIUpdateManager");
|
||||
|
||||
this.updateDeck = document.getElementById("updateDeck");
|
||||
|
||||
// Hide the update deck when the update window is already open and it's not
|
||||
// already applied, to avoid syncing issues between them. Applied updates
|
||||
// don't have any information to sync between the windows as they both just
|
||||
// show the "Restart to continue"-type button.
|
||||
if (Services.wm.getMostRecentWindow("Update:Wizard") &&
|
||||
!this.isApplied) {
|
||||
this.updateDeck.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.bundle = Services.strings.
|
||||
createBundle("chrome://browser/locale/browser.properties");
|
||||
|
||||
let manualURL = Services.urlFormatter.formatURLPref("app.update.url.manual");
|
||||
let manualLink = document.getElementById("manualLink");
|
||||
manualLink.value = manualURL;
|
||||
manualLink.href = manualURL;
|
||||
document.getElementById("failedLink").href = manualURL;
|
||||
|
||||
if (this.updateDisabledAndLocked) {
|
||||
this.selectPanel("adminDisabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isPending || this.isApplied) {
|
||||
this.selectPanel("apply");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.aus.isOtherInstanceHandlingUpdates) {
|
||||
this.selectPanel("otherInstanceHandlingUpdates");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isDownloading) {
|
||||
this.startDownload();
|
||||
// selectPanel("downloading") is called from setupDownloadingUI().
|
||||
return;
|
||||
}
|
||||
|
||||
// Honor the "Never check for updates" option by not only disabling background
|
||||
// update checks, but also in the About dialog, by presenting a
|
||||
// "Check for updates" button.
|
||||
// If updates are found, the user is then asked if he wants to "Update to <version>".
|
||||
if (!this.updateEnabled ||
|
||||
Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
|
||||
this.selectPanel("checkForUpdates");
|
||||
return;
|
||||
}
|
||||
|
||||
// That leaves the options
|
||||
// "Check for updates, but let me choose whether to install them", and
|
||||
// "Automatically install updates".
|
||||
// In both cases, we check for updates without asking.
|
||||
// In the "let me choose" case, we ask before downloading though, in onCheckComplete.
|
||||
this.checkForUpdates();
|
||||
}
|
||||
|
||||
appUpdater.prototype =
|
||||
{
|
||||
// true when there is an update check in progress.
|
||||
isChecking: false,
|
||||
|
||||
// true when there is an update already staged / ready to be applied.
|
||||
get isPending() {
|
||||
if (this.update) {
|
||||
return this.update.state == "pending" ||
|
||||
this.update.state == "pending-service" ||
|
||||
this.update.state == "pending-elevate";
|
||||
}
|
||||
return this.um.activeUpdate &&
|
||||
(this.um.activeUpdate.state == "pending" ||
|
||||
this.um.activeUpdate.state == "pending-service" ||
|
||||
this.um.activeUpdate.state == "pending-elevate");
|
||||
},
|
||||
|
||||
// true when there is an update already installed in the background.
|
||||
get isApplied() {
|
||||
if (this.update)
|
||||
return this.update.state == "applied" ||
|
||||
this.update.state == "applied-service";
|
||||
return this.um.activeUpdate &&
|
||||
(this.um.activeUpdate.state == "applied" ||
|
||||
this.um.activeUpdate.state == "applied-service");
|
||||
},
|
||||
|
||||
// true when there is an update download in progress.
|
||||
get isDownloading() {
|
||||
if (this.update)
|
||||
return this.update.state == "downloading";
|
||||
return this.um.activeUpdate &&
|
||||
this.um.activeUpdate.state == "downloading";
|
||||
},
|
||||
|
||||
// true when updating is disabled by an administrator.
|
||||
get updateDisabledAndLocked() {
|
||||
return !this.updateEnabled &&
|
||||
Services.prefs.prefIsLocked("app.update.enabled");
|
||||
},
|
||||
|
||||
// true when updating is enabled.
|
||||
get updateEnabled() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref("app.update.enabled");
|
||||
}
|
||||
catch (e) { }
|
||||
return true; // Firefox default is true
|
||||
},
|
||||
|
||||
// true when updating in background is enabled.
|
||||
get backgroundUpdateEnabled() {
|
||||
return this.updateEnabled &&
|
||||
gAppUpdater.aus.canStageUpdates;
|
||||
},
|
||||
|
||||
// true when updating is automatic.
|
||||
get updateAuto() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref("app.update.auto");
|
||||
}
|
||||
catch (e) { }
|
||||
return true; // Firefox default is true
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the panel of the updateDeck.
|
||||
*
|
||||
* @param aChildID
|
||||
* The id of the deck's child to select, e.g. "apply".
|
||||
*/
|
||||
selectPanel: function(aChildID) {
|
||||
let panel = document.getElementById(aChildID);
|
||||
|
||||
let button = panel.querySelector("button");
|
||||
if (button) {
|
||||
if (aChildID == "downloadAndInstall") {
|
||||
let updateVersion = gAppUpdater.update.displayVersion;
|
||||
button.label = this.bundle.formatStringFromName("update.downloadAndInstallButton.label", [updateVersion], 1);
|
||||
button.accessKey = this.bundle.GetStringFromName("update.downloadAndInstallButton.accesskey");
|
||||
}
|
||||
this.updateDeck.selectedPanel = panel;
|
||||
if (!document.commandDispatcher.focusedElement || // don't steal the focus
|
||||
document.commandDispatcher.focusedElement.localName == "button") // except from the other buttons
|
||||
button.focus();
|
||||
|
||||
} else {
|
||||
this.updateDeck.selectedPanel = panel;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check for updates
|
||||
*/
|
||||
checkForUpdates: function() {
|
||||
// Clear prefs that could prevent a user from discovering available updates.
|
||||
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS_OSX)) {
|
||||
Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
|
||||
}
|
||||
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
|
||||
Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_NEVER);
|
||||
}
|
||||
this.selectPanel("checkingForUpdates");
|
||||
this.isChecking = true;
|
||||
this.checker.checkForUpdates(this.updateCheckListener, true);
|
||||
// after checking, onCheckComplete() is called
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles oncommand for the "Restart to Update" button
|
||||
* which is presented after the download has been downloaded.
|
||||
*/
|
||||
buttonRestartAfterDownload: function() {
|
||||
if (!this.isPending && !this.isApplied) {
|
||||
return;
|
||||
}
|
||||
|
||||
gAppUpdater.selectPanel("restarting");
|
||||
|
||||
// Notify all windows that an application quit has been requested.
|
||||
let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"].
|
||||
createInstance(Components.interfaces.nsISupportsPRBool);
|
||||
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
|
||||
|
||||
// Something aborted the quit process.
|
||||
if (cancelQuit.data) {
|
||||
gAppUpdater.selectPanel("apply");
|
||||
return;
|
||||
}
|
||||
|
||||
let appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"].
|
||||
getService(Components.interfaces.nsIAppStartup);
|
||||
|
||||
// If already in safe mode restart in safe mode (bug 327119)
|
||||
if (Services.appinfo.inSafeMode) {
|
||||
appStartup.restartInSafeMode(Components.interfaces.nsIAppStartup.eAttemptQuit);
|
||||
return;
|
||||
}
|
||||
|
||||
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit |
|
||||
Components.interfaces.nsIAppStartup.eRestart);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements nsIUpdateCheckListener. The methods implemented by
|
||||
* nsIUpdateCheckListener are in a different scope from nsIIncrementalDownload
|
||||
* to make it clear which are used by each interface.
|
||||
*/
|
||||
updateCheckListener: {
|
||||
/**
|
||||
* See nsIUpdateService.idl
|
||||
*/
|
||||
onCheckComplete: function(aRequest, aUpdates, aUpdateCount) {
|
||||
gAppUpdater.isChecking = false;
|
||||
gAppUpdater.update = gAppUpdater.aus.
|
||||
selectUpdate(aUpdates, aUpdates.length);
|
||||
if (!gAppUpdater.update) {
|
||||
gAppUpdater.selectPanel("noUpdatesFound");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAppUpdater.update.unsupported) {
|
||||
if (gAppUpdater.update.detailsURL) {
|
||||
let unsupportedLink = document.getElementById("unsupportedLink");
|
||||
unsupportedLink.href = gAppUpdater.update.detailsURL;
|
||||
}
|
||||
gAppUpdater.selectPanel("unsupportedSystem");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gAppUpdater.aus.canApplyUpdates) {
|
||||
gAppUpdater.selectPanel("manualUpdate");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAppUpdater.updateAuto) // automatically download and install
|
||||
gAppUpdater.startDownload();
|
||||
else // ask
|
||||
gAppUpdater.selectPanel("downloadAndInstall");
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIUpdateService.idl
|
||||
*/
|
||||
onError: function(aRequest, aUpdate) {
|
||||
// Errors in the update check are treated as no updates found. If the
|
||||
// update check fails repeatedly without a success the user will be
|
||||
// notified with the normal app update user interface so this is safe.
|
||||
gAppUpdater.isChecking = false;
|
||||
gAppUpdater.selectPanel("noUpdatesFound");
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsISupports.idl
|
||||
*/
|
||||
QueryInterface: function(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsIUpdateCheckListener) &&
|
||||
!aIID.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the download of an update mar.
|
||||
*/
|
||||
startDownload: function() {
|
||||
if (!this.update)
|
||||
this.update = this.um.activeUpdate;
|
||||
this.update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
|
||||
this.update.setProperty("foregroundDownload", "true");
|
||||
|
||||
this.aus.pauseDownload();
|
||||
let state = this.aus.downloadUpdate(this.update, false);
|
||||
if (state == "failed") {
|
||||
this.selectPanel("downloadFailed");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setupDownloadingUI();
|
||||
},
|
||||
|
||||
/**
|
||||
* Switches to the UI responsible for tracking the download.
|
||||
*/
|
||||
setupDownloadingUI: function() {
|
||||
this.downloadStatus = document.getElementById("downloadStatus");
|
||||
this.downloadStatus.value =
|
||||
DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size);
|
||||
this.selectPanel("downloading");
|
||||
this.aus.addDownloadListener(this);
|
||||
},
|
||||
|
||||
removeDownloadListener: function() {
|
||||
if (this.aus) {
|
||||
this.aus.removeDownloadListener(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIRequestObserver.idl
|
||||
*/
|
||||
onStartRequest: function(aRequest, aContext) {
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIRequestObserver.idl
|
||||
*/
|
||||
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
||||
switch (aStatusCode) {
|
||||
case Components.results.NS_ERROR_UNEXPECTED:
|
||||
if (this.update.selectedPatch.state == "download-failed" &&
|
||||
(this.update.isCompleteUpdate || this.update.patchCount != 2)) {
|
||||
// Verification error of complete patch, informational text is held in
|
||||
// the update object.
|
||||
this.removeDownloadListener();
|
||||
this.selectPanel("downloadFailed");
|
||||
break;
|
||||
}
|
||||
// Verification failed for a partial patch, complete patch is now
|
||||
// downloading so return early and do NOT remove the download listener!
|
||||
break;
|
||||
case Components.results.NS_BINDING_ABORTED:
|
||||
// Do not remove UI listener since the user may resume downloading again.
|
||||
break;
|
||||
case Components.results.NS_OK:
|
||||
this.removeDownloadListener();
|
||||
if (this.backgroundUpdateEnabled) {
|
||||
this.selectPanel("applying");
|
||||
let self = this;
|
||||
Services.obs.addObserver(function (aSubject, aTopic, aData) {
|
||||
// Update the UI when the background updater is finished
|
||||
let status = aData;
|
||||
if (status == "applied" || status == "applied-service" ||
|
||||
status == "pending" || status == "pending-service" ||
|
||||
status == "pending-elevate") {
|
||||
// If the update is successfully applied, or if the updater has
|
||||
// fallen back to non-staged updates, show the "Restart to Update"
|
||||
// button.
|
||||
self.selectPanel("apply");
|
||||
} else if (status == "failed") {
|
||||
// Background update has failed, let's show the UI responsible for
|
||||
// prompting the user to update manually.
|
||||
self.selectPanel("downloadFailed");
|
||||
} else if (status == "downloading") {
|
||||
// We've fallen back to downloading the full update because the
|
||||
// partial update failed to get staged in the background.
|
||||
// Therefore we need to keep our observer.
|
||||
self.setupDownloadingUI();
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(arguments.callee, "update-staged");
|
||||
}, "update-staged", false);
|
||||
} else {
|
||||
this.selectPanel("apply");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.removeDownloadListener();
|
||||
this.selectPanel("downloadFailed");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIProgressEventSink.idl
|
||||
*/
|
||||
onStatus: function(aRequest, aContext, aStatus, aStatusArg) {
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsIProgressEventSink.idl
|
||||
*/
|
||||
onProgress: function(aRequest, aContext, aProgress, aProgressMax) {
|
||||
this.downloadStatus.value =
|
||||
DownloadUtils.getTransferTotal(aProgress, aProgressMax);
|
||||
},
|
||||
|
||||
/**
|
||||
* See nsISupports.idl
|
||||
*/
|
||||
QueryInterface: function(aIID) {
|
||||
if (!aIID.equals(Components.interfaces.nsIProgressEventSink) &&
|
||||
!aIID.equals(Components.interfaces.nsIRequestObserver) &&
|
||||
!aIID.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#aboutDialog {
|
||||
width: 620px;
|
||||
/* Set an explicit line-height to avoid discrepancies in 'auto' spacing
|
||||
across screens with different device DPI, which may cause font metrics
|
||||
to round differently. */
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#rightBox:-moz-locale-dir(rtl) {
|
||||
background-position: 100% 0;
|
||||
}
|
||||
|
||||
#bottomBox {
|
||||
padding: 15px 10px 0;
|
||||
}
|
||||
|
||||
#version {
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
margin-left: 0;
|
||||
-moz-user-select: text;
|
||||
-moz-user-focus: normal;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
#version:-moz-locale-dir(rtl) {
|
||||
direction: ltr;
|
||||
text-align: right;
|
||||
margin-left: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#releasenotes {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#distribution,
|
||||
#distributionId {
|
||||
display: none;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.text-blurb {
|
||||
margin-bottom: 10px;
|
||||
margin-inline-start: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
#updateButton,
|
||||
#updateDeck > hbox > label {
|
||||
margin-inline-start: 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.update-throbber {
|
||||
width: 16px;
|
||||
min-height: 16px;
|
||||
margin-inline-end: 3px;
|
||||
list-style-image: url("chrome://global/skin/icons/loading.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.update-throbber {
|
||||
list-style-image: url("chrome://global/skin/icons/loading@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
description > .text-link,
|
||||
description > .text-link:focus {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.bottom-link,
|
||||
.bottom-link:focus {
|
||||
text-align: center;
|
||||
margin: 0 40px;
|
||||
}
|
||||
|
||||
#currentChannel {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Services = object with smart getters for common XPCOM services
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
function init(aEvent)
|
||||
{
|
||||
if (aEvent.target != document)
|
||||
return;
|
||||
|
||||
try {
|
||||
var distroId = Services.prefs.getCharPref("distribution.id");
|
||||
if (distroId) {
|
||||
var distroVersion = Services.prefs.getCharPref("distribution.version");
|
||||
|
||||
var distroIdField = document.getElementById("distributionId");
|
||||
distroIdField.value = distroId + " - " + distroVersion;
|
||||
distroIdField.style.display = "block";
|
||||
|
||||
try {
|
||||
// This is in its own try catch due to bug 895473 and bug 900925.
|
||||
var distroAbout = Services.prefs.getComplexValue("distribution.about",
|
||||
Components.interfaces.nsISupportsString);
|
||||
var distroField = document.getElementById("distribution");
|
||||
distroField.value = distroAbout;
|
||||
distroField.style.display = "block";
|
||||
}
|
||||
catch (ex) {
|
||||
// Pref is unset
|
||||
Components.utils.reportError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Pref is unset
|
||||
}
|
||||
|
||||
// Include the build ID
|
||||
let versionField = document.getElementById("version");
|
||||
let version = Services.appinfo.version;
|
||||
let buildID = Services.appinfo.appBuildID;
|
||||
let year = buildID.slice(0, 4);
|
||||
let month = buildID.slice(4, 6);
|
||||
let day = buildID.slice(6, 8);
|
||||
let hour = buildID.slice(8, 10);
|
||||
let minute = buildID.slice(10, 12);
|
||||
if (Services.prefs.getBoolPref("general.useragent.appVersionIsBuildID")) {
|
||||
versionField.textContent = `${year}.${month}.${day}`;
|
||||
} else {
|
||||
versionField.textContent = `v` + version + ` (${year}-${month}-${day})`;
|
||||
}
|
||||
|
||||
// Display warning if this is an "a#" (nightly or aurora) build
|
||||
if (/a\d+$/.test(version)) {
|
||||
document.getElementById("experimental").hidden = false;
|
||||
document.getElementById("communityDesc").hidden = true;
|
||||
}
|
||||
|
||||
// Append "(32-bit)" or "(64-bit)" build architecture to the version number:
|
||||
let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
let archResource = Services.appinfo.is64Bit
|
||||
? "aboutDialog.architecture.sixtyFourBit"
|
||||
: "aboutDialog.architecture.thirtyTwoBit";
|
||||
let arch = bundle.GetStringFromName(archResource);
|
||||
versionField.textContent += ` (${arch})`;
|
||||
|
||||
// Get Release Notes URL from Preferences
|
||||
let releaseNotesURL = Services.prefs.getCharPref("app.releaseNotesURL");
|
||||
document.getElementById("releasenotes").setAttribute("href", releaseNotesURL);
|
||||
|
||||
if (AppConstants.MOZ_UPDATER) {
|
||||
gAppUpdater = new appUpdater();
|
||||
|
||||
let channelLabel = document.getElementById("currentChannel");
|
||||
let currentChannelText = document.getElementById("currentChannelText");
|
||||
channelLabel.value = UpdateUtils.UpdateChannel;
|
||||
if (/^release($|\-)/.test(channelLabel.value))
|
||||
currentChannelText.hidden = true;
|
||||
}
|
||||
|
||||
if (AppConstants.platform == "macosx") {
|
||||
// it may not be sized at this point, and we need its width to calculate its position
|
||||
window.sizeToContent();
|
||||
window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0"?> <!-- -*- Mode: HTML -*- -->
|
||||
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/aboutDialog.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://branding/content/aboutDialog.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % aboutDialogDTD SYSTEM "chrome://browser/locale/aboutDialog.dtd" >
|
||||
%aboutDialogDTD;
|
||||
]>
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
<?xul-overlay href="chrome://browser/content/macBrowserOverlay.xul"?>
|
||||
#endif
|
||||
|
||||
<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);"
|
||||
#ifdef MOZ_UPDATER
|
||||
onunload="onUnload(event);"
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
inwindowmenu="false"
|
||||
#else
|
||||
title="&aboutDialog.title;"
|
||||
#endif
|
||||
role="dialog"
|
||||
aria-describedby="version distribution distributionId communityDesc contributeDesc trademark"
|
||||
>
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/aboutDialog.js"/>
|
||||
#ifdef MOZ_UPDATER
|
||||
<script type="application/javascript" src="chrome://browser/content/aboutDialog-appUpdater.js"/>
|
||||
#endif
|
||||
<vbox id="aboutDialogContainer">
|
||||
<hbox id="clientBox">
|
||||
<vbox id="leftBox" flex="1"/>
|
||||
<vbox id="rightBox" flex="1">
|
||||
<hbox align="baseline">
|
||||
#expand <label id="version"></label>
|
||||
#ifndef NIGHTLY_BUILD
|
||||
<label id="releasenotes" class="text-link">&releaseNotes.link;</label>
|
||||
#endif
|
||||
</hbox>
|
||||
|
||||
<label id="distribution" class="text-blurb"/>
|
||||
<label id="distributionId" class="text-blurb"/>
|
||||
|
||||
<vbox id="detailsBox">
|
||||
<vbox id="updateBox">
|
||||
#ifdef MOZ_UPDATER
|
||||
<deck id="updateDeck" orient="vertical">
|
||||
<hbox id="checkForUpdates" align="center">
|
||||
<button id="checkForUpdatesButton" align="start"
|
||||
label="&update.checkForUpdatesButton.label;"
|
||||
accesskey="&update.checkForUpdatesButton.accesskey;"
|
||||
oncommand="gAppUpdater.checkForUpdates();"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="downloadAndInstall" align="center">
|
||||
<button id="downloadAndInstallButton" align="start"
|
||||
oncommand="gAppUpdater.startDownload();"/>
|
||||
<!-- label and accesskey will be filled by JS -->
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="apply" align="center">
|
||||
<button id="updateButton" align="start"
|
||||
label="&update.updateButton.label2;"
|
||||
accesskey="&update.updateButton.accesskey;"
|
||||
oncommand="gAppUpdater.buttonRestartAfterDownload();"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="checkingForUpdates" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
|
||||
</hbox>
|
||||
<hbox id="downloading" align="center">
|
||||
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
|
||||
</hbox>
|
||||
<hbox id="applying" align="center">
|
||||
<image class="update-throbber"/><label>&update.applying;</label>
|
||||
</hbox>
|
||||
<hbox id="downloadFailed" align="center">
|
||||
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
|
||||
</hbox>
|
||||
<hbox id="adminDisabled" align="center">
|
||||
<label>&update.adminDisabled;</label>
|
||||
</hbox>
|
||||
<hbox id="noUpdatesFound" align="center">
|
||||
<label>&update.noUpdatesFound;</label>
|
||||
</hbox>
|
||||
<hbox id="otherInstanceHandlingUpdates" align="center">
|
||||
<label>&update.otherInstanceHandlingUpdates;</label>
|
||||
</hbox>
|
||||
<hbox id="manualUpdate" align="center">
|
||||
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
|
||||
</hbox>
|
||||
<hbox id="unsupportedSystem" align="center">
|
||||
<label>&update.unsupported.start;</label><label id="unsupportedLink" class="text-link">&update.unsupported.linkText;</label><label>&update.unsupported.end;</label>
|
||||
</hbox>
|
||||
<hbox id="restarting" align="center">
|
||||
<label>&update.restarting;</label>
|
||||
</hbox>
|
||||
</deck>
|
||||
#endif
|
||||
</vbox>
|
||||
|
||||
#ifdef MOZ_UPDATER
|
||||
<description class="text-blurb" id="currentChannelText">
|
||||
&channel.description.start;<label id="currentChannel"/>&channel.description.end;
|
||||
</description>
|
||||
#endif
|
||||
<vbox id="experimental" hidden="true">
|
||||
<description class="text-blurb" id="warningDesc">
|
||||
&warningDesc.version;
|
||||
</description>
|
||||
</vbox>
|
||||
#ifdef MC_PRIVATE_BUILD
|
||||
<description class="text-blurb" id="communityDesc">
|
||||
This is a private build of Basilisk. If you did not manually build this copy from source yourself, then please download an official version from the <label class="text-link" href="http://www.basilisk-browser.org/">Basilisk website</label>.
|
||||
</description>
|
||||
#else
|
||||
<description class="text-blurb" id="communityDesc">
|
||||
Basilisk is community software released by <label class="text-link" href="http://www.palemoon.org/">the Pale Moon team</label> and Mozilla developers. Learn <label class="text-link" useoriginprincipal="true" href="about:credits">who contributed</label> to this software.
|
||||
</description>
|
||||
<description class="text-blurb" id="contributeDesc">
|
||||
Want to help? Please consider <label class="text-link" href="https://www.palemoon.org/donations.shtml">donating</label> or get involved with our <label class="text-link" href="https://github.com/MoonchildProductions/UXP">development</label> of the Unified XUL Platform.
|
||||
</description>
|
||||
#endif
|
||||
</vbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<vbox id="bottomBox">
|
||||
<hbox pack="center">
|
||||
<label class="text-link bottom-link" useoriginprincipal="true" href="about:license">&bottomLinks.license;</label>
|
||||
<label class="text-link bottom-link" useoriginprincipal="true" href="about:rights">&bottomLinks.rights;</label>
|
||||
<label class="text-link bottom-link" href="https://www.palemoon.org/privacy.shtml">&bottomLinks.privacy;</label>
|
||||
</hbox>
|
||||
<description id="trademark">&trademarkInfo.part1;</description>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<keyset>
|
||||
<key keycode="VK_ESCAPE" oncommand="window.close();"/>
|
||||
</keyset>
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include browserMountPoints.inc
|
||||
#endif
|
||||
</window>
|
||||
@@ -0,0 +1,573 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % netErrorDTD
|
||||
SYSTEM "chrome://global/locale/netError.dtd">
|
||||
%netErrorDTD;
|
||||
<!ENTITY % globalDTD
|
||||
SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
]>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&loadError.label;</title>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
|
||||
<!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in
|
||||
toolkit/components/places/src/nsFaviconService.h should be updated. -->
|
||||
<link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
|
||||
|
||||
<script type="application/javascript"><![CDATA[
|
||||
// The following parameters are parsed from the error URL:
|
||||
// e - the error code
|
||||
// s - custom CSS class to allow alternate styling/favicons
|
||||
// d - error description
|
||||
// captive - "true" to indicate we're behind a captive portal.
|
||||
// Any other value is ignored.
|
||||
|
||||
// Note that this file uses document.documentURI to get
|
||||
// the URL (with the format from above). This is because
|
||||
// document.location.href gets the current URI off the docshell,
|
||||
// which is the URL displayed in the location bar, i.e.
|
||||
// the URI that the user attempted to load.
|
||||
|
||||
let searchParams = new URLSearchParams(document.documentURI.split("?")[1]);
|
||||
|
||||
// Set to true on init if the error code is nssBadCert.
|
||||
let gIsCertError;
|
||||
|
||||
function getErrorCode()
|
||||
{
|
||||
return searchParams.get("e");
|
||||
}
|
||||
|
||||
function getCSSClass()
|
||||
{
|
||||
return searchParams.get("s");
|
||||
}
|
||||
|
||||
function getDescription()
|
||||
{
|
||||
return searchParams.get("d");
|
||||
}
|
||||
|
||||
function isCaptive() {
|
||||
return searchParams.get("captive") == "true";
|
||||
}
|
||||
|
||||
function retryThis(buttonEl)
|
||||
{
|
||||
// Note: The application may wish to handle switching off "offline mode"
|
||||
// before this event handler runs, but using a capturing event handler.
|
||||
|
||||
// Session history has the URL of the page that failed
|
||||
// to load, not the one of the error page. So, just call
|
||||
// reload(), which will also repost POST data correctly.
|
||||
try {
|
||||
location.reload();
|
||||
} catch (e) {
|
||||
// We probably tried to reload a URI that caused an exception to
|
||||
// occur; e.g. a nonexistent file.
|
||||
}
|
||||
|
||||
buttonEl.disabled = true;
|
||||
}
|
||||
|
||||
function doOverride(buttonEl) {
|
||||
var event = new CustomEvent("AboutNetErrorOverride", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
retryThis(buttonEl);
|
||||
}
|
||||
|
||||
function toggleDisplay(node) {
|
||||
const toggle = {
|
||||
"": "block",
|
||||
"none": "block",
|
||||
"block": "none"
|
||||
};
|
||||
return (node.style.display = toggle[node.style.display]);
|
||||
}
|
||||
|
||||
function showPrefChangeContainer() {
|
||||
const panel = document.getElementById("prefChangeContainer");
|
||||
panel.style.display = "block";
|
||||
document.getElementById("netErrorButtonContainer").style.display = "none";
|
||||
document.getElementById("prefResetButton").addEventListener("click", function resetPreferences(e) {
|
||||
const event = new CustomEvent("AboutNetErrorResetPreferences", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
addAutofocus("prefResetButton", "beforeend");
|
||||
}
|
||||
|
||||
function setupAdvancedButton(allowOverride) {
|
||||
// Get the hostname and add it to the panel
|
||||
var panelId = gIsCertError ? "badCertAdvancedPanel" : "weakCryptoAdvancedPanel";
|
||||
var panel = document.getElementById(panelId);
|
||||
for (var span of panel.querySelectorAll("span.hostname")) {
|
||||
span.textContent = document.location.hostname;
|
||||
}
|
||||
if (!gIsCertError) {
|
||||
panel.replaceChild(document.getElementById("errorLongDesc"),
|
||||
document.getElementById("advancedLongDesc"));
|
||||
}
|
||||
|
||||
// Register click handler for the weakCryptoAdvancedPanel
|
||||
document.getElementById("advancedButton")
|
||||
.addEventListener("click", function togglePanelVisibility() {
|
||||
toggleDisplay(panel);
|
||||
|
||||
if (panel.style.display == "block") {
|
||||
// send event to trigger telemetry ping
|
||||
var event = new CustomEvent("AboutNetErrorUIExpanded", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
});
|
||||
|
||||
if (allowOverride) {
|
||||
document.getElementById("overrideWeakCryptoPanel").style.display = "flex";
|
||||
var overrideLink = document.getElementById("overrideWeakCrypto");
|
||||
overrideLink.addEventListener("click", () => doOverride(overrideLink), false);
|
||||
}
|
||||
if (!gIsCertError) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getCSSClass() == "expertBadCert") {
|
||||
toggleDisplay(document.getElementById("badCertAdvancedPanel"));
|
||||
}
|
||||
|
||||
disallowCertOverridesIfNeeded();
|
||||
|
||||
document.getElementById("badCertTechnicalInfo").textContent = getDescription();
|
||||
}
|
||||
|
||||
function disallowCertOverridesIfNeeded() {
|
||||
var cssClass = getCSSClass();
|
||||
// Disallow overrides if this is a Strict-Transport-Security
|
||||
// host and the cert is bad (STS Spec section 7.3) or if the
|
||||
// certerror is in a frame (bug 633691).
|
||||
if (cssClass == "badStsCert" || window != top) {
|
||||
document.getElementById("exceptionDialogButton").setAttribute("hidden", "true");
|
||||
}
|
||||
if (cssClass == "badStsCert") {
|
||||
document.getElementById("badStsCertExplanation").removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function initPage()
|
||||
{
|
||||
var err = getErrorCode();
|
||||
gIsCertError = (err == "nssBadCert");
|
||||
// Only worry about captive portals if this is a cert error.
|
||||
let showCaptivePortalUI = isCaptive() && gIsCertError;
|
||||
if (showCaptivePortalUI) {
|
||||
err = "captivePortal";
|
||||
}
|
||||
|
||||
// if it's an unknown error or there's no title or description
|
||||
// defined, get the generic message
|
||||
var errTitle = document.getElementById("et_" + err);
|
||||
var errDesc = document.getElementById("ed_" + err);
|
||||
if (!errTitle || !errDesc)
|
||||
{
|
||||
errTitle = document.getElementById("et_generic");
|
||||
errDesc = document.getElementById("ed_generic");
|
||||
}
|
||||
|
||||
document.querySelector(".title-text").innerHTML = errTitle.innerHTML;
|
||||
|
||||
var sd = document.getElementById("errorShortDescText");
|
||||
if (sd) {
|
||||
if (gIsCertError) {
|
||||
sd.innerHTML = errDesc.innerHTML;
|
||||
}
|
||||
else {
|
||||
sd.textContent = getDescription();
|
||||
}
|
||||
}
|
||||
if (showCaptivePortalUI) {
|
||||
initPageCaptivePortal();
|
||||
return;
|
||||
}
|
||||
if (gIsCertError) {
|
||||
initPageCertError();
|
||||
return;
|
||||
}
|
||||
addAutofocus("errorTryAgain");
|
||||
|
||||
document.body.className = "neterror";
|
||||
|
||||
var ld = document.getElementById("errorLongDesc");
|
||||
if (ld)
|
||||
{
|
||||
ld.innerHTML = errDesc.innerHTML;
|
||||
}
|
||||
|
||||
if (err == "sslv3Used") {
|
||||
document.body.className = "certerror";
|
||||
}
|
||||
|
||||
if (err == "weakCryptoUsed") {
|
||||
document.body.className = "certerror";
|
||||
}
|
||||
|
||||
// remove undisplayed errors to avoid bug 39098
|
||||
var errContainer = document.getElementById("errorContainer");
|
||||
errContainer.parentNode.removeChild(errContainer);
|
||||
|
||||
var className = getCSSClass();
|
||||
if (className && className != "expertBadCert") {
|
||||
// Associate a CSS class with the root of the page, if one was passed in,
|
||||
// to allow custom styling.
|
||||
// Not "expertBadCert" though, don't want to deal with the favicon
|
||||
document.documentElement.className = className;
|
||||
|
||||
// Also, if they specified a CSS class, they must supply their own
|
||||
// favicon. In order to trigger the browser to repaint though, we
|
||||
// need to remove/add the link element.
|
||||
var favicon = document.getElementById("favicon");
|
||||
var faviconParent = favicon.parentNode;
|
||||
faviconParent.removeChild(favicon);
|
||||
favicon.setAttribute("href", "chrome://global/skin/icons/" + className + "_favicon.png");
|
||||
faviconParent.appendChild(favicon);
|
||||
}
|
||||
|
||||
if (err == "remoteXUL") {
|
||||
// Remove the "Try again" button for remote XUL errors given that
|
||||
// it is useless.
|
||||
document.getElementById("netErrorButtonContainer").style.display = "none";
|
||||
}
|
||||
|
||||
if (err == "cspBlocked") {
|
||||
// Remove the "Try again" button for CSP violations, since it's
|
||||
// almost certainly useless. (Bug 553180)
|
||||
document.getElementById("netErrorButtonContainer").style.display = "none";
|
||||
}
|
||||
|
||||
window.addEventListener("AboutNetErrorOptions", function(evt) {
|
||||
// Pinning errors are of type nssFailure2
|
||||
if (getErrorCode() == "nssFailure2" || getErrorCode() == "weakCryptoUsed") {
|
||||
const hasPrefStyleError = [
|
||||
"interrupted", // This happens with subresources that are above the max tls
|
||||
"SSL_ERROR_PROTOCOL_VERSION_ALERT",
|
||||
"SSL_ERROR_UNSUPPORTED_VERSION",
|
||||
"SSL_ERROR_NO_CYPHER_OVERLAP",
|
||||
"SSL_ERROR_NO_CIPHERS_SUPPORTED"
|
||||
].some((substring) => getDescription().includes(substring));
|
||||
// If it looks like an error that is user config based
|
||||
if (getErrorCode() == "nssFailure2" && hasPrefStyleError && options && options.changedCertPrefs) {
|
||||
showPrefChangeContainer();
|
||||
}
|
||||
}
|
||||
if (getErrorCode() == "weakCryptoUsed" || getErrorCode() == "sslv3Used") {
|
||||
setupAdvancedButton(getErrorCode() == "weakCryptoUsed");
|
||||
}
|
||||
}.bind(this), true, true);
|
||||
|
||||
var event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
|
||||
if (err == "inadequateSecurityError") {
|
||||
// Remove the "Try again" button for HTTP/2 inadequate security as it
|
||||
// is useless.
|
||||
document.getElementById("errorTryAgain").style.display = "none";
|
||||
|
||||
var container = document.getElementById("errorLongDesc");
|
||||
for (var span of container.querySelectorAll("span.hostname")) {
|
||||
span.textContent = document.location.hostname;
|
||||
}
|
||||
}
|
||||
|
||||
addDomainErrorLink();
|
||||
}
|
||||
|
||||
function initPageCaptivePortal()
|
||||
{
|
||||
document.body.className = "captiveportal";
|
||||
document.title = document.getElementById("captivePortalPageTitle").textContent;
|
||||
|
||||
document.getElementById("openPortalLoginPageButton")
|
||||
.addEventListener("click", () => {
|
||||
let event = new CustomEvent("AboutNetErrorOpenCaptivePortal", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
|
||||
addAutofocus("openPortalLoginPageButton");
|
||||
setupAdvancedButton(true);
|
||||
|
||||
addDomainErrorLink();
|
||||
|
||||
// When the portal is freed, an event is generated by the frame script
|
||||
// that we can pick up and attempt to reload the original page.
|
||||
window.addEventListener("AboutNetErrorCaptivePortalFreed", () => {
|
||||
document.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function initPageCertError() {
|
||||
document.body.className = "certerror";
|
||||
document.title = document.getElementById("certErrorPageTitle").textContent;
|
||||
for (let host of document.querySelectorAll(".hostname")) {
|
||||
host.textContent = document.location.hostname;
|
||||
}
|
||||
|
||||
addAutofocus("returnButton");
|
||||
setupAdvancedButton(true);
|
||||
|
||||
let event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
|
||||
document.getElementById("advancedButton").dispatchEvent(event);
|
||||
|
||||
addDomainErrorLink();
|
||||
}
|
||||
|
||||
/* Only do autofocus if we're the toplevel frame; otherwise we
|
||||
don't want to call attention to ourselves! The key part is
|
||||
that autofocus happens on insertion into the tree, so we
|
||||
can remove the button, add @autofocus, and reinsert the
|
||||
button.
|
||||
*/
|
||||
function addAutofocus(buttonId, position = "afterbegin") {
|
||||
if (window.top == window) {
|
||||
var button = document.getElementById(buttonId);
|
||||
var parent = button.parentNode;
|
||||
button.remove();
|
||||
button.setAttribute("autofocus", "true");
|
||||
parent.insertAdjacentElement(position, button);
|
||||
}
|
||||
}
|
||||
|
||||
/* In the case of SSL error pages about domain mismatch, see if
|
||||
we can hyperlink the user to the correct site. We don't want
|
||||
to do this generically since it allows MitM attacks to redirect
|
||||
users to a site under attacker control, but in certain cases
|
||||
it is safe (and helpful!) to do so. Bug 402210
|
||||
*/
|
||||
function addDomainErrorLink() {
|
||||
// Rather than textContent, we need to treat description as HTML
|
||||
var sdid = gIsCertError ? "badCertTechnicalInfo" : "errorShortDescText";
|
||||
var sd = document.getElementById(sdid);
|
||||
if (sd) {
|
||||
var desc = getDescription();
|
||||
|
||||
// sanitize description text - see bug 441169
|
||||
|
||||
// First, find the index of the <a> tag we care about, being
|
||||
// careful not to use an over-greedy regex.
|
||||
var re = /<a id="cert_domain_link" title="([^"]+)">/;
|
||||
var result = domainRe.exec(desc);
|
||||
|
||||
if (!result)
|
||||
return;
|
||||
// Remove sd's existing children
|
||||
sd.textContent = "";
|
||||
|
||||
// Everything up to the link should be text content.
|
||||
sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
|
||||
|
||||
// Now create the link itself.
|
||||
var anchorEl = document.createElement("a");
|
||||
anchorEl.setAttribute("id", "cert_domain_link");
|
||||
anchorEl.setAttribute("title", result[1]);
|
||||
anchorEl.appendChild(document.createTextNode(result[1]));
|
||||
sd.appendChild(anchorEl);
|
||||
|
||||
// Finally, append text for anything after the closing </a>.
|
||||
sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
|
||||
}
|
||||
|
||||
// Initialize the cert domain link.
|
||||
var link = document.getElementById("cert_domain_link");
|
||||
if (!link)
|
||||
return;
|
||||
|
||||
var okHost = link.getAttribute("title");
|
||||
var thisHost = document.location.hostname;
|
||||
var proto = document.location.protocol;
|
||||
|
||||
// If okHost is a wildcard domain ("*.example.com") let's
|
||||
// use "www" instead. "*.example.com" isn't going to
|
||||
// get anyone anywhere useful. bug 432491
|
||||
okHost = okHost.replace(/^\*\./, "www.");
|
||||
|
||||
/* case #1:
|
||||
* example.com uses an invalid security certificate.
|
||||
*
|
||||
* The certificate is only valid for www.example.com
|
||||
*
|
||||
* Make sure to include the "." ahead of thisHost so that
|
||||
* a MitM attack on paypal.com doesn't hyperlink to "notpaypal.com"
|
||||
*
|
||||
* We'd normally just use a RegExp here except that we lack a
|
||||
* library function to escape them properly (bug 248062), and
|
||||
* domain names are famous for having '.' characters in them,
|
||||
* which would allow spurious and possibly hostile matches.
|
||||
*/
|
||||
if (okHost.endsWith("." + thisHost))
|
||||
link.href = proto + okHost;
|
||||
|
||||
/* case #2:
|
||||
* browser.garage.maemo.org uses an invalid security certificate.
|
||||
*
|
||||
* The certificate is only valid for garage.maemo.org
|
||||
*/
|
||||
if (thisHost.endsWith("." + okHost))
|
||||
link.href = proto + okHost;
|
||||
|
||||
// If we set a link, meaning there's something helpful for
|
||||
// the user here, expand the section by default
|
||||
if (link.href && getCSSClass() != "expertBadCert") {
|
||||
var panelId = gIsCertError ? "badCertAdvancedPanel" : "weakCryptoAdvancedPanel"
|
||||
toggleDisplay(document.getElementById(panelId));
|
||||
}
|
||||
}
|
||||
]]></script>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
<!-- Contains an alternate page title set on page init for cert errors. -->
|
||||
<div id="certErrorPageTitle" style="display: none;">&certerror.pagetitle1;</div>
|
||||
<div id="captivePortalPageTitle" style="display: none;">&captivePortal.title;</div>
|
||||
|
||||
<!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
|
||||
<div id="errorContainer">
|
||||
<div id="errorTitlesContainer">
|
||||
<h1 id="et_generic">&generic.title;</h1>
|
||||
<h1 id="et_captivePortal">&captivePortal.title;</h1>
|
||||
<h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
|
||||
<h1 id="et_fileNotFound">&fileNotFound.title;</h1>
|
||||
<h1 id="et_fileAccessDenied">&fileAccessDenied.title;</h1>
|
||||
<h1 id="et_malformedURI">&malformedURI.title;</h1>
|
||||
<h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
|
||||
<h1 id="et_connectionFailure">&connectionFailure.title;</h1>
|
||||
<h1 id="et_netTimeout">&netTimeout.title;</h1>
|
||||
<h1 id="et_redirectLoop">&redirectLoop.title;</h1>
|
||||
<h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
|
||||
<h1 id="et_netReset">&netReset.title;</h1>
|
||||
<h1 id="et_notCached">¬Cached.title;</h1>
|
||||
<h1 id="et_netOffline">&netOffline.title;</h1>
|
||||
<h1 id="et_netInterrupt">&netInterrupt.title;</h1>
|
||||
<h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
|
||||
<h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
|
||||
<h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
|
||||
<h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
|
||||
<h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
|
||||
<h1 id="et_nssFailure2">&nssFailure2.title;</h1>
|
||||
<h1 id="et_nssBadCert">&certerror.longpagetitle1;</h1>
|
||||
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
|
||||
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
|
||||
<h1 id="et_corruptedContentErrorv2">&corruptedContentErrorv2.title;</h1>
|
||||
<h1 id="et_sslv3Used">&sslv3Used.title;</h1>
|
||||
<h1 id="et_weakCryptoUsed">&weakCryptoUsed.title;</h1>
|
||||
<h1 id="et_inadequateSecurityError">&inadequateSecurityError.title;</h1>
|
||||
</div>
|
||||
<div id="errorDescriptionsContainer">
|
||||
<div id="ed_generic">&generic.longDesc;</div>
|
||||
<div id="ed_captivePortal">&captivePortal.longDesc;</div>
|
||||
<div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
|
||||
<div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
|
||||
<div id="ed_fileAccessDenied">&fileAccessDenied.longDesc;</div>
|
||||
<div id="ed_malformedURI">&malformedURI.longDesc;</div>
|
||||
<div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
|
||||
<div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
|
||||
<div id="ed_netTimeout">&netTimeout.longDesc;</div>
|
||||
<div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
|
||||
<div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
|
||||
<div id="ed_netReset">&netReset.longDesc;</div>
|
||||
<div id="ed_notCached">¬Cached.longDesc;</div>
|
||||
<div id="ed_netOffline">&netOffline.longDesc2;</div>
|
||||
<div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
|
||||
<div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
|
||||
<div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
|
||||
<div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
|
||||
<div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
|
||||
<div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
|
||||
<div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
|
||||
<div id="ed_nssBadCert">&certerror.introPara;</div>
|
||||
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
|
||||
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
|
||||
<div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>
|
||||
<div id="ed_sslv3Used">&sslv3Used.longDesc2;</div>
|
||||
<div id="ed_weakCryptoUsed">&weakCryptoUsed.longDesc2;</div>
|
||||
<div id="ed_inadequateSecurityError">&inadequateSecurityError.longDesc;</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PAGE CONTAINER (for styling purposes only) -->
|
||||
<div id="errorPageContainer" class="container">
|
||||
|
||||
<!-- Error Title -->
|
||||
<div class="title">
|
||||
<h1 class="title-text"/>
|
||||
</div>
|
||||
|
||||
<!-- LONG CONTENT (the section most likely to require scrolling) -->
|
||||
<div id="errorLongContent">
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorShortDesc">
|
||||
<p id="errorShortDescText" />
|
||||
</div>
|
||||
<p id="badStsCertExplanation" hidden="true">&certerror.whatShouldIDo.badStsCertExplanation;</p>
|
||||
|
||||
<div id="wrongSystemTimePanel" style="display: none;">
|
||||
&certerror.wrongSystemTime;
|
||||
</div>
|
||||
|
||||
<!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
|
||||
<div id="errorLongDesc" />
|
||||
|
||||
<div id="prefChangeContainer" class="button-container">
|
||||
<p>&prefReset.longDesc;</p>
|
||||
<button id="prefResetButton" class="primary" autocomplete="off">&prefReset.label;</button>
|
||||
</div>
|
||||
|
||||
<div id="certErrorAndCaptivePortalButtonContainer" class="button-container">
|
||||
<button id="returnButton" class="primary" autocomplete="off">&returnToPreviousPage.label;</button>
|
||||
<button id="openPortalLoginPageButton" class="primary" autocomplete="off">&openPortalLoginPage.label;</button>
|
||||
<div class="button-spacer"></div>
|
||||
<button id="advancedButton" autocomplete="off">&advanced.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="netErrorButtonContainer" class="button-container">
|
||||
<button id="errorTryAgain" class="primary" autocomplete="off" onclick="retryThis(this);">&retry.label;</button>
|
||||
</div>
|
||||
|
||||
<div id="advancedPanelContainer">
|
||||
<div id="weakCryptoAdvancedPanel" class="advanced-panel">
|
||||
<div id="weakCryptoAdvancedDescription">
|
||||
<p>&weakCryptoAdvanced.longDesc;</p>
|
||||
</div>
|
||||
<div id="advancedLongDesc" />
|
||||
<div id="overrideWeakCryptoPanel">
|
||||
<a id="overrideWeakCrypto" href="#">&weakCryptoAdvanced.override;</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="badCertAdvancedPanel" class="advanced-panel">
|
||||
<p id="badCertTechnicalInfo"/>
|
||||
<button id="exceptionDialogButton">&securityOverride.exceptionButtonLabel;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!--
|
||||
- Note: It is important to run the script this way, instead of using
|
||||
- an onload handler. This is because error pages are loaded as
|
||||
- LOAD_BACKGROUND, which means that onload handlers will not be executed.
|
||||
-->
|
||||
<script type="application/javascript">
|
||||
initPage();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % netErrorDTD
|
||||
SYSTEM "chrome://global/locale/netError.dtd">
|
||||
%netErrorDTD;
|
||||
<!ENTITY % globalDTD
|
||||
SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % aboutrobotsDTD
|
||||
SYSTEM "chrome://browser/locale/aboutRobots.dtd">
|
||||
%aboutrobotsDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&robots.pagetitle;</title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
|
||||
<link rel="icon" type="image/png" id="favicon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAACGFjVEwAAAASAAAAAJNtBPIAAAAaZmNUTAAAAAAAAAAQAAAAEAAAAAAAAAAALuAD6AABhIDeugAAALhJREFUOI2Nk8sNxCAMRDlGohauXFOMpfTiAlxICqAELltHLqlgctg1InzMRhpFAc%2BLGWTnmoeZYamt78zXdZmaQtQMADlnU0OIAlbmJUBEcO4bRKQY2rUXIPmAGnDuG%2FBx3%2FfvOPVaDUg%2BoAPUf1PArIMCSD5glMEsUGaG%2BkyAFWIBaCsKuA%2BHGCNijLgP133XgOEtaPFMy2vUolEGJoCIzBmoRUR9%2B7rxj16DZaW%2FmgtmxnJ8V3oAnApQwNS5zpcAAAAaZmNUTAAAAAEAAAAQAAAAEAAAAAAAAAAAAB4D6AIB52fclgAAACpmZEFUAAAAAjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9WF%2Bu8QAAABpmY1RMAAAAAwAAABAAAAAQAAAAAAAAAAAAHgPoAgEK8Q9%2FAAAAFmZkQVQAAAAEOI1jYBgFo2AUjAIIAAAEEAAB0xIn4wAAABpmY1RMAAAABQAAABAAAAAQAAAAAAAAAAAAHgPoAgHnO30FAAAAQGZkQVQAAAAGOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVfozYcAAAABpmY1RMAAAABwAAABAAAAAQAAAAAAAAAAAAHgPoAgEKra7sAAAAFmZkQVQAAAAIOI1jYBgFo2AUjAIIAAAEEAABM9s3hAAAABpmY1RMAAAACQAAABAAAAAQAAAAAAAAAAAAHgPoAgHn3p%2BwAAAAKmZkQVQAAAAKOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F1BhPl6AAAAGmZjVEwAAAALAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQpITFkAAAAWZmRBVAAAAAw4jWNgGAWjYBSMAggAAAQQAAHaszpmAAAAGmZjVEwAAAANAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeeCPiMAAABAZmRBVAAAAA44jWNgGJ5gpxrDf2LEcIL%2FpzAVYxPDavP%2FUwz%2FpW79%2F%2F%2F%2FFMP%2FnWoQjC5GOxcgu4QYsVEwCmAAAOE0KxUmBL0KAAAAGmZjVEwAAAAPAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAQoU7coAAAAWZmRBVAAAABA4jWNgGAWjYBSMAggAAAQQAAEpOBELAAAAGmZjVEwAAAARAAAAEAAAABAAAAAAAAAAAAAeA%2BgCAeYVWtoAAAAqZmRBVAAAABI4jWNgGAVYQXNz839ixHBq3qnG8B9ZAzYx2rlgFIwCcgAA8psX%2FWvpAecAAAAaZmNUTAAAABMAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC4OJMwAAABZmZEFUAAAAFDiNY2AYBaNgFIwCCAAABBAAAcBQHOkAAAAaZmNUTAAAABUAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5kn7SQAAAEBmZEFUAAAAFjiNY2AYnmCnGsN%2FYsRwgv%2BnMBVjE8Nq8%2F9TDP%2Blbv3%2F%2F%2F8Uw%2F%2BdahCMLkY7FyC7hBixUTAKYAAA4TQrFc%2BcEoQAAAAaZmNUTAAAABcAAAAQAAAAEAAAAAAAAAAAAB4D6AIBC98ooAAAABZmZEFUAAAAGDiNY2AYBaNgFIwCCAAABBAAASCZDI4AAAAaZmNUTAAAABkAAAAQAAAAEAAAAAAAAAAAAB4D6AIB5qwZ%2FAAAACpmZEFUAAAAGjiNY2AYBVhBc3Pzf2LEcGreqcbwH1kDNjHauWAUjAJyAADymxf9cjJWbAAAABpmY1RMAAAAGwAAABAAAAAQAAAAAAAAAAAAHgPoAgELOsoVAAAAFmZkQVQAAAAcOI1jYBgFo2AUjAIIAAAEEAAByfEBbAAAABpmY1RMAAAAHQAAABAAAAAQAAAAAAAAAAAAHgPoAgHm8LhvAAAAQGZkQVQAAAAeOI1jYBieYKcaw39ixHCC%2F6cwFWMTw2rz%2F1MM%2F6Vu%2Ff%2F%2F%2FxTD%2F51qEIwuRjsXILuEGLFRMApgAADhNCsVlxR3%2FgAAABpmY1RMAAAAHwAAABAAAAAQAAAAAAAAAAAAHgPoAgELZmuGAAAAFmZkQVQAAAAgOI1jYBgFo2AUjAIIAAAEEAABHP5cFQAAABpmY1RMAAAAIQAAABAAAAAQAAAAAAAAAAAAHgPoAgHlgtAOAAAAKmZkQVQAAAAiOI1jYBgFWEFzc%2FN%2FYsRwat6pxvAfWQM2Mdq5YBSMAnIAAPKbF%2F0%2FMvDdAAAAAElFTkSuQmCC"/>
|
||||
|
||||
<script type="application/javascript"><![CDATA[
|
||||
var buttonClicked = false;
|
||||
function robotButton()
|
||||
{
|
||||
var button = document.getElementById('errorTryAgain');
|
||||
if (buttonClicked) {
|
||||
button.style.visibility = "hidden";
|
||||
} else {
|
||||
var newLabel = button.getAttribute("label2");
|
||||
button.textContent = newLabel;
|
||||
buttonClicked = true;
|
||||
}
|
||||
}
|
||||
]]></script>
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
#errorPageContainer {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#errorPageContainer:before {
|
||||
content: url('chrome://browser/content/aboutRobots-icon.png');
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
body[dir=rtl] #icon,
|
||||
body[dir=rtl] #errorPageContainer:before {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
|
||||
<!-- PAGE CONTAINER (for styling purposes only) -->
|
||||
<div id="errorPageContainer">
|
||||
|
||||
<!-- Error Title -->
|
||||
<div id="errorTitle">
|
||||
<h1 id="errorTitleText">&robots.errorTitleText;</h1>
|
||||
</div>
|
||||
|
||||
<!-- LONG CONTENT (the section most likely to require scrolling) -->
|
||||
<div id="errorLongContent">
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorShortDesc">
|
||||
<p id="errorShortDescText">&robots.errorShortDescText;</p>
|
||||
</div>
|
||||
|
||||
<!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
|
||||
<div id="errorLongDesc">
|
||||
<ul>
|
||||
<li>&robots.errorLongDesc1;</li>
|
||||
<li>&robots.errorLongDesc2;</li>
|
||||
<li>&robots.errorLongDesc3;</li>
|
||||
<li>&robots.errorLongDesc4;</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorTrailerDesc">
|
||||
<p id="errorTrailerDescText">&robots.errorTrailerDescText;</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Button -->
|
||||
<button id="errorTryAgain"
|
||||
label2="&robots.dontpress;"
|
||||
onclick="robotButton();">&retry.label;</button>
|
||||
|
||||
<img src="chrome://browser/content/aboutRobots-widget-left.png"
|
||||
style="position: absolute; bottom: -12px; left: -10px;"/>
|
||||
<img src="chrome://browser/content/aboutRobots-widget-left.png"
|
||||
style="position: absolute; bottom: -12px; right: -10px; transform: scaleX(-1);"/>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
html:not(.crashDumpSubmitted) #reportSent,
|
||||
html:not(.crashDumpAvailable) #reportBox,
|
||||
.container[multiple="true"] > .offers > #offerHelpMessageSingle,
|
||||
.container[multiple="false"] > .offers > #offerHelpMessageMultiple,
|
||||
.container[multiple="false"] > .button-container > #restoreAll {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var AboutTabCrashed = {
|
||||
/**
|
||||
* This can be set to true once this page receives a message from the
|
||||
* parent saying whether or not a crash report is available.
|
||||
*/
|
||||
hasReport: false,
|
||||
|
||||
/**
|
||||
* The messages that we might receive from the parent.
|
||||
*/
|
||||
MESSAGES: [
|
||||
"SetCrashReportAvailable",
|
||||
"CrashReportSent",
|
||||
"UpdateCount",
|
||||
],
|
||||
|
||||
/**
|
||||
* Items for which we will listen for click events.
|
||||
*/
|
||||
CLICK_TARGETS: [
|
||||
"closeTab",
|
||||
"restoreTab",
|
||||
"restoreAll",
|
||||
"sendReport",
|
||||
],
|
||||
|
||||
/**
|
||||
* Returns information about this crashed tab.
|
||||
*
|
||||
* @return (Object) An object with the following properties:
|
||||
* title (String):
|
||||
* The title of the page that crashed.
|
||||
* URL (String):
|
||||
* The URL of the page that crashed.
|
||||
*/
|
||||
get pageData() {
|
||||
delete this.pageData;
|
||||
|
||||
let URL = document.documentURI;
|
||||
let queryString = URL.replace(/^about:tabcrashed?e=tabcrashed/, "");
|
||||
|
||||
let titleMatch = queryString.match(/d=([^&]*)/);
|
||||
let URLMatch = queryString.match(/u=([^&]*)/);
|
||||
|
||||
return this.pageData = {
|
||||
title: titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "",
|
||||
URL: URLMatch && URLMatch[1] ? decodeURIComponent(URLMatch[1]) : "",
|
||||
};
|
||||
},
|
||||
|
||||
init() {
|
||||
this.MESSAGES.forEach((msg) => addMessageListener(msg, this.receiveMessage.bind(this)));
|
||||
addEventListener("DOMContentLoaded", this);
|
||||
|
||||
document.title = this.pageData.title;
|
||||
},
|
||||
|
||||
receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
case "UpdateCount": {
|
||||
this.setMultiple(message.data.count > 1);
|
||||
break;
|
||||
}
|
||||
case "SetCrashReportAvailable": {
|
||||
this.onSetCrashReportAvailable(message);
|
||||
break;
|
||||
}
|
||||
case "CrashReportSent": {
|
||||
this.onCrashReportSent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "DOMContentLoaded": {
|
||||
this.onDOMContentLoaded();
|
||||
break;
|
||||
}
|
||||
case "click": {
|
||||
this.onClick(event);
|
||||
break;
|
||||
}
|
||||
case "input": {
|
||||
this.onInput(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onDOMContentLoaded() {
|
||||
this.CLICK_TARGETS.forEach((targetID) => {
|
||||
let el = document.getElementById(targetID);
|
||||
el.addEventListener("click", this);
|
||||
});
|
||||
|
||||
// For setting "emailMe" checkbox automatically on email value change.
|
||||
document.getElementById("email").addEventListener("input", this);
|
||||
|
||||
// Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
|
||||
let event = new CustomEvent("AboutTabCrashedLoad", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
|
||||
sendAsyncMessage("Load");
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
switch (event.target.id) {
|
||||
case "closeTab": {
|
||||
this.sendMessage("closeTab");
|
||||
break;
|
||||
}
|
||||
|
||||
case "restoreTab": {
|
||||
this.sendMessage("restoreTab");
|
||||
break;
|
||||
}
|
||||
|
||||
case "restoreAll": {
|
||||
this.sendMessage("restoreAll");
|
||||
break;
|
||||
}
|
||||
|
||||
case "sendReport": {
|
||||
this.showCrashReportUI(event.target.checked);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onInput(event) {
|
||||
switch (event.target.id) {
|
||||
case "email": {
|
||||
document.getElementById("emailMe").checked = !!event.target.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* After this page tells the parent that it has loaded, the parent
|
||||
* will respond with whether or not a crash report is available. This
|
||||
* method handles that message.
|
||||
*
|
||||
* @param message
|
||||
* The message from the parent, which should contain a data
|
||||
* Object property with the following properties:
|
||||
*
|
||||
* hasReport (bool):
|
||||
* Whether or not there is a crash report.
|
||||
*
|
||||
* sendReport (bool):
|
||||
* Whether or not the the user prefers to send the report
|
||||
* by default.
|
||||
*
|
||||
* includeURL (bool):
|
||||
* Whether or not the user prefers to send the URL of
|
||||
* the tab that crashed.
|
||||
*
|
||||
* emailMe (bool):
|
||||
* Whether or not to send the email address of the user
|
||||
* in the report.
|
||||
*
|
||||
* email (String):
|
||||
* The email address of the user (empty if emailMe is false).
|
||||
*
|
||||
* requestAutoSubmit (bool):
|
||||
* Whether or not we should ask the user to automatically
|
||||
* submit backlogged crash reports.
|
||||
*
|
||||
*/
|
||||
onSetCrashReportAvailable(message) {
|
||||
let data = message.data;
|
||||
|
||||
if (data.hasReport) {
|
||||
this.hasReport = true;
|
||||
document.documentElement.classList.add("crashDumpAvailable");
|
||||
|
||||
document.getElementById("sendReport").checked = data.sendReport;
|
||||
document.getElementById("includeURL").checked = data.includeURL;
|
||||
|
||||
if (data.requestEmail) {
|
||||
document.getElementById("requestEmail").hidden = false;
|
||||
document.getElementById("emailMe").checked = data.emailMe;
|
||||
if (data.emailMe) {
|
||||
document.getElementById("email").value = data.email;
|
||||
}
|
||||
}
|
||||
|
||||
this.showCrashReportUI(data.sendReport);
|
||||
} else {
|
||||
this.showCrashReportUI(false);
|
||||
}
|
||||
|
||||
if (data.requestAutoSubmit) {
|
||||
document.getElementById("requestAutoSubmit").hidden = false;
|
||||
}
|
||||
|
||||
let event = new CustomEvent("AboutTabCrashedReady", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for when the parent reports that the crash report associated
|
||||
* with this about:tabcrashed page has been sent.
|
||||
*/
|
||||
onCrashReportSent() {
|
||||
document.documentElement.classList.remove("crashDumpAvailable");
|
||||
document.documentElement.classList.add("crashDumpSubmitted");
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the display of the crash report form.
|
||||
*
|
||||
* @param shouldShow (bool)
|
||||
* True if the crash report form should be shown
|
||||
*/
|
||||
showCrashReportUI(shouldShow) {
|
||||
let options = document.getElementById("options");
|
||||
options.hidden = !shouldShow;
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles whether or not the page is one of several visible pages
|
||||
* showing the crash reporter. This controls some of the language
|
||||
* on the page, along with what the "primary" button is.
|
||||
*
|
||||
* @param hasMultiple (bool)
|
||||
* True if there are multiple crash report pages being shown.
|
||||
*/
|
||||
setMultiple(hasMultiple) {
|
||||
let main = document.getElementById("main");
|
||||
main.setAttribute("multiple", hasMultiple);
|
||||
|
||||
let restoreTab = document.getElementById("restoreTab");
|
||||
|
||||
// The "Restore All" button has the "primary" class by default, so
|
||||
// we only need to modify the "Restore Tab" button.
|
||||
if (hasMultiple) {
|
||||
restoreTab.classList.remove("primary");
|
||||
} else {
|
||||
restoreTab.classList.add("primary");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a message to the parent in response to the user choosing
|
||||
* one of the actions available on the page. This might also send up
|
||||
* crash report information if the user has chosen to submit a crash
|
||||
* report.
|
||||
*
|
||||
* @param messageName (String)
|
||||
* The message to send to the parent
|
||||
*/
|
||||
sendMessage(messageName) {
|
||||
let comments = "";
|
||||
let email = "";
|
||||
let URL = "";
|
||||
let sendReport = false;
|
||||
let emailMe = false;
|
||||
let includeURL = false;
|
||||
let autoSubmit = false;
|
||||
|
||||
if (this.hasReport) {
|
||||
sendReport = document.getElementById("sendReport").checked;
|
||||
if (sendReport) {
|
||||
comments = document.getElementById("comments").value.trim();
|
||||
|
||||
includeURL = document.getElementById("includeURL").checked;
|
||||
if (includeURL) {
|
||||
URL = this.pageData.URL.trim();
|
||||
}
|
||||
|
||||
if (!document.getElementById("requestEmail").hidden) {
|
||||
emailMe = document.getElementById("emailMe").checked;
|
||||
if (emailMe) {
|
||||
email = document.getElementById("email").value.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let requestAutoSubmit = document.getElementById("requestAutoSubmit");
|
||||
if (requestAutoSubmit.hidden) {
|
||||
// The checkbox is hidden if the user has already opted in to sending
|
||||
// backlogged crash reports.
|
||||
autoSubmit = true;
|
||||
} else {
|
||||
autoSubmit = document.getElementById("autoSubmit").checked;
|
||||
}
|
||||
|
||||
sendAsyncMessage(messageName, {
|
||||
sendReport,
|
||||
comments,
|
||||
email,
|
||||
emailMe,
|
||||
includeURL,
|
||||
URL,
|
||||
autoSubmit,
|
||||
hasReport: this.hasReport,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
AboutTabCrashed.init();
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % globalDTD
|
||||
SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % tabCrashedDTD
|
||||
SYSTEM "chrome://browser/locale/aboutTabCrashed.dtd">
|
||||
%tabCrashedDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://global/skin/in-content/info-pages.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/content/aboutTabCrashed.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/aboutTabCrashed.css"/>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
<div id="main" class="container" multiple="false">
|
||||
|
||||
<div class="title">
|
||||
<h1 class="title-text">&tabCrashed.header2;</h1>
|
||||
</div>
|
||||
|
||||
<div class="offers">
|
||||
<h2>&tabCrashed.offerHelp;</h2>
|
||||
<p id="offerHelpMessageSingle">&tabCrashed.single.offerHelpMessage;</p>
|
||||
<p id="offerHelpMessageMultiple">&tabCrashed.multiple.offerHelpMessage;</p>
|
||||
</div>
|
||||
|
||||
<div id="reportBox">
|
||||
<h2>&tabCrashed.requestHelp;</h2>
|
||||
<p>&tabCrashed.requestHelpMessage;</p>
|
||||
|
||||
<h2>&tabCrashed.requestReport;</h2>
|
||||
|
||||
<div class="checkbox-with-label">
|
||||
<input type="checkbox" id="sendReport"/>
|
||||
<label for="sendReport">&tabCrashed.sendReport2;</label>
|
||||
</div>
|
||||
|
||||
<ul id="options">
|
||||
<li>
|
||||
<textarea id="comments" placeholder="&tabCrashed.commentPlaceholder2;" rows="4"></textarea>
|
||||
</li>
|
||||
|
||||
<li class="checkbox-with-label">
|
||||
<input type="checkbox" id="includeURL"/>
|
||||
<label for="includeURL">&tabCrashed.includeURL2;</label>
|
||||
</li>
|
||||
|
||||
<li id="requestEmail" hidden="true">
|
||||
<div class="checkbox-with-label">
|
||||
<input type="checkbox" id="emailMe"/>
|
||||
<label for="emailMe">&tabCrashed.emailMe;</label>
|
||||
</div>
|
||||
<input type="text" id="email" placeholder="&tabCrashed.emailPlaceholder;"/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div id="requestAutoSubmit" hidden="true">
|
||||
<h2>&tabCrashed.requestAutoSubmit2;</h2>
|
||||
<div class="checkbox-with-label">
|
||||
<input type="checkbox" id="autoSubmit"/>
|
||||
<label for="autoSubmit">&tabCrashed.autoSubmit;</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p id="reportSent">&tabCrashed.reportSent;</p>
|
||||
|
||||
<div class="button-container">
|
||||
<button id="closeTab">
|
||||
&tabCrashed.closeTab;</button>
|
||||
<button id="restoreTab" class="primary">
|
||||
&tabCrashed.restoreTab;</button>
|
||||
<button id="restoreAll" autofocus="true" class="primary">
|
||||
&tabCrashed.restoreAll;</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript;version=1.8" src="chrome://browser/content/aboutTabCrashed.js"/>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#remote {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#networkError, #manage, #intro, #stage, #configError {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#oldsync {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: #0095dd;
|
||||
}
|
||||
|
||||
#oldsync:focus {
|
||||
outline: 1px dotted #0095dd;
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/FxAccounts.jsm");
|
||||
|
||||
var fxAccountsCommon = {};
|
||||
Cu.import("resource://gre/modules/FxAccountsCommon.js", fxAccountsCommon);
|
||||
|
||||
// for master-password utilities
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
||||
const PREF_SYNC_SHOW_CUSTOMIZATION = "services.sync-setup.ui.showCustomizationDialog";
|
||||
|
||||
const ACTION_URL_PARAM = "action";
|
||||
|
||||
const OBSERVER_TOPICS = [
|
||||
fxAccountsCommon.ONVERIFIED_NOTIFICATION,
|
||||
fxAccountsCommon.ONLOGOUT_NOTIFICATION,
|
||||
];
|
||||
|
||||
function log(msg) {
|
||||
// dump("FXA: " + msg + "\n");
|
||||
}
|
||||
|
||||
function error(msg) {
|
||||
console.log("Firefox Account Error: " + msg + "\n");
|
||||
}
|
||||
|
||||
function getPreviousAccountNameHash() {
|
||||
try {
|
||||
return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
|
||||
} catch (_) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function setPreviousAccountNameHash(acctName) {
|
||||
let string = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
string.data = sha256(acctName);
|
||||
Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
|
||||
}
|
||||
|
||||
function needRelinkWarning(acctName) {
|
||||
let prevAcctHash = getPreviousAccountNameHash();
|
||||
return prevAcctHash && prevAcctHash != sha256(acctName);
|
||||
}
|
||||
|
||||
// Given a string, returns the SHA265 hash in base64
|
||||
function sha256(str) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
// Data is an array of bytes.
|
||||
let data = converter.convertToByteArray(str, {});
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(hasher.SHA256);
|
||||
hasher.update(data, data.length);
|
||||
|
||||
return hasher.finish(true);
|
||||
}
|
||||
|
||||
function promptForRelink(acctName) {
|
||||
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
|
||||
let continueLabel = sb.GetStringFromName("continue.label");
|
||||
let title = sb.GetStringFromName("relinkVerify.title");
|
||||
let description = sb.formatStringFromName("relinkVerify.description",
|
||||
[acctName], 1);
|
||||
let body = sb.GetStringFromName("relinkVerify.heading") +
|
||||
"\n\n" + description;
|
||||
let ps = Services.prompt;
|
||||
let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
|
||||
(ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
|
||||
ps.BUTTON_POS_1_DEFAULT;
|
||||
let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
|
||||
continueLabel, null, null, null,
|
||||
{});
|
||||
return pressed == 0; // 0 is the "continue" button
|
||||
}
|
||||
|
||||
// If the last fxa account used for sync isn't this account, we display
|
||||
// a modal dialog checking they really really want to do this...
|
||||
// (This is sync-specific, so ideally would be in sync's identity module,
|
||||
// but it's a little more seamless to do here, and sync is currently the
|
||||
// only fxa consumer, so...
|
||||
function shouldAllowRelink(acctName) {
|
||||
return !needRelinkWarning(acctName) || promptForRelink(acctName);
|
||||
}
|
||||
|
||||
function updateDisplayedEmail(user) {
|
||||
let emailDiv = document.getElementById("email");
|
||||
if (emailDiv && user) {
|
||||
emailDiv.textContent = user.email;
|
||||
}
|
||||
}
|
||||
|
||||
var wrapper = {
|
||||
iframe: null,
|
||||
|
||||
init: function (url, urlParams) {
|
||||
// If a master-password is enabled, we want to encourage the user to
|
||||
// unlock it. Things still work if not, but the user will probably need
|
||||
// to re-auth next startup (in which case we will get here again and
|
||||
// re-prompt)
|
||||
Utils.ensureMPUnlocked();
|
||||
|
||||
let iframe = document.getElementById("remote");
|
||||
this.iframe = iframe;
|
||||
this.iframe.QueryInterface(Ci.nsIFrameLoaderOwner);
|
||||
let docShell = this.iframe.frameLoader.docShell;
|
||||
docShell.QueryInterface(Ci.nsIWebProgress);
|
||||
docShell.addProgressListener(this.iframeListener, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
iframe.addEventListener("load", this);
|
||||
|
||||
// Ideally we'd just merge urlParams with new URL(url).searchParams, but our
|
||||
// URLSearchParams implementation doesn't support iteration (bug 1085284).
|
||||
let urlParamStr = urlParams.toString();
|
||||
if (urlParamStr) {
|
||||
url += (url.includes("?") ? "&" : "?") + urlParamStr;
|
||||
}
|
||||
this.url = url;
|
||||
// Set the iframe's location with loadURI/LOAD_FLAGS_REPLACE_HISTORY to
|
||||
// avoid having a new history entry being added. REPLACE_HISTORY is used
|
||||
// to replace the current entry, which is `about:blank`.
|
||||
let webNav = iframe.frameLoader.docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
webNav.loadURI(url, Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY, null, null, null);
|
||||
},
|
||||
|
||||
retry: function () {
|
||||
let webNav = this.iframe.frameLoader.docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
webNav.loadURI(this.url, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, null, null, null);
|
||||
},
|
||||
|
||||
iframeListener: {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsISupports]),
|
||||
|
||||
onStateChange: function(aWebProgress, aRequest, aState, aStatus) {
|
||||
let failure = false;
|
||||
|
||||
// Captive portals sometimes redirect users
|
||||
if ((aState & Ci.nsIWebProgressListener.STATE_REDIRECTING)) {
|
||||
failure = true;
|
||||
} else if ((aState & Ci.nsIWebProgressListener.STATE_STOP)) {
|
||||
if (aRequest instanceof Ci.nsIHttpChannel) {
|
||||
try {
|
||||
failure = aRequest.responseStatus != 200;
|
||||
} catch (e) {
|
||||
failure = aStatus != Components.results.NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calling cancel() will raise some OnStateChange notifications by itself,
|
||||
// so avoid doing that more than once
|
||||
if (failure && aStatus != Components.results.NS_BINDING_ABORTED) {
|
||||
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
setErrorPage("networkError");
|
||||
}
|
||||
},
|
||||
|
||||
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
|
||||
if (aRequest && aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
|
||||
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
setErrorPage("networkError");
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
},
|
||||
|
||||
handleEvent: function (evt) {
|
||||
switch (evt.type) {
|
||||
case "load":
|
||||
this.iframe.contentWindow.addEventListener("FirefoxAccountsCommand", this);
|
||||
this.iframe.removeEventListener("load", this);
|
||||
break;
|
||||
case "FirefoxAccountsCommand":
|
||||
this.handleRemoteCommand(evt);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* onLogin handler receives user credentials from the jelly after a
|
||||
* sucessful login and stores it in the fxaccounts service
|
||||
*
|
||||
* @param accountData the user's account data and credentials
|
||||
*/
|
||||
onLogin: function (accountData) {
|
||||
log("Received: 'login'. Data:" + JSON.stringify(accountData));
|
||||
|
||||
if (accountData.customizeSync) {
|
||||
Services.prefs.setBoolPref(PREF_SYNC_SHOW_CUSTOMIZATION, true);
|
||||
}
|
||||
delete accountData.customizeSync;
|
||||
// sessionTokenContext is erroneously sent by the content server.
|
||||
// https://github.com/mozilla/fxa-content-server/issues/2766
|
||||
// To avoid having the FxA storage manager not knowing what to do with
|
||||
// it we delete it here.
|
||||
delete accountData.sessionTokenContext;
|
||||
|
||||
// We need to confirm a relink - see shouldAllowRelink for more
|
||||
let newAccountEmail = accountData.email;
|
||||
// The hosted code may have already checked for the relink situation
|
||||
// by sending the can_link_account command. If it did, then
|
||||
// it will indicate we don't need to ask twice.
|
||||
if (!accountData.verifiedCanLinkAccount && !shouldAllowRelink(newAccountEmail)) {
|
||||
// we need to tell the page we successfully received the message, but
|
||||
// then bail without telling fxAccounts
|
||||
this.injectData("message", { status: "login" });
|
||||
// after a successful login we return to preferences
|
||||
openPrefs();
|
||||
return;
|
||||
}
|
||||
delete accountData.verifiedCanLinkAccount;
|
||||
|
||||
// Remember who it was so we can log out next time.
|
||||
setPreviousAccountNameHash(newAccountEmail);
|
||||
|
||||
// A sync-specific hack - we want to ensure sync has been initialized
|
||||
// before we set the signed-in user.
|
||||
let xps = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject;
|
||||
xps.whenLoaded().then(() => {
|
||||
updateDisplayedEmail(accountData);
|
||||
return fxAccounts.setSignedInUser(accountData);
|
||||
}).then(() => {
|
||||
// If the user data is verified, we want it to immediately look like
|
||||
// they are signed in without waiting for messages to bounce around.
|
||||
if (accountData.verified) {
|
||||
openPrefs();
|
||||
}
|
||||
this.injectData("message", { status: "login" });
|
||||
// until we sort out a better UX, just leave the jelly page in place.
|
||||
// If the account email is not yet verified, it will tell the user to
|
||||
// go check their email, but then it will *not* change state after
|
||||
// the verification completes (the browser will begin syncing, but
|
||||
// won't notify the user). If the email has already been verified,
|
||||
// the jelly will say "Welcome! You are successfully signed in as
|
||||
// EMAIL", but it won't then say "syncing started".
|
||||
}, (err) => this.injectData("message", { status: "error", error: err })
|
||||
);
|
||||
},
|
||||
|
||||
onCanLinkAccount: function(accountData) {
|
||||
// We need to confirm a relink - see shouldAllowRelink for more
|
||||
let ok = shouldAllowRelink(accountData.email);
|
||||
this.injectData("message", { status: "can_link_account", data: { ok: ok } });
|
||||
},
|
||||
|
||||
/**
|
||||
* onSignOut handler erases the current user's session from the fxaccounts service
|
||||
*/
|
||||
onSignOut: function () {
|
||||
log("Received: 'sign_out'.");
|
||||
|
||||
fxAccounts.signOut().then(
|
||||
() => this.injectData("message", { status: "sign_out" }),
|
||||
(err) => this.injectData("message", { status: "error", error: err })
|
||||
);
|
||||
},
|
||||
|
||||
handleRemoteCommand: function (evt) {
|
||||
log('command: ' + evt.detail.command);
|
||||
let data = evt.detail.data;
|
||||
|
||||
switch (evt.detail.command) {
|
||||
case "login":
|
||||
this.onLogin(data);
|
||||
break;
|
||||
case "can_link_account":
|
||||
this.onCanLinkAccount(data);
|
||||
break;
|
||||
case "sign_out":
|
||||
this.onSignOut(data);
|
||||
break;
|
||||
default:
|
||||
log("Unexpected remote command received: " + evt.detail.command + ". Ignoring command.");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
injectData: function (type, content) {
|
||||
return fxAccounts.promiseAccountsSignUpURI().then(authUrl => {
|
||||
let data = {
|
||||
type: type,
|
||||
content: content
|
||||
};
|
||||
this.iframe.contentWindow.postMessage(data, authUrl);
|
||||
})
|
||||
.catch(e => {
|
||||
console.log("Failed to inject data", e);
|
||||
setErrorPage("configError");
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// Button onclick handlers
|
||||
function handleOldSync() {
|
||||
let chromeWin = window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow)
|
||||
.QueryInterface(Ci.nsIDOMChromeWindow);
|
||||
let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "old-sync";
|
||||
chromeWin.switchToTabHavingURI(url, true);
|
||||
}
|
||||
|
||||
function getStarted() {
|
||||
show("remote");
|
||||
}
|
||||
|
||||
function retry() {
|
||||
show("remote");
|
||||
wrapper.retry();
|
||||
}
|
||||
|
||||
function openPrefs() {
|
||||
// Bug 1199303 calls for this tab to always be replaced with Preferences
|
||||
// rather than it opening in a different tab.
|
||||
window.location = "about:preferences#sync";
|
||||
}
|
||||
|
||||
function init() {
|
||||
fxAccounts.getSignedInUser().then(user => {
|
||||
// tests in particular might cause the window to start closing before
|
||||
// getSignedInUser has returned.
|
||||
if (window.closed) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateDisplayedEmail(user);
|
||||
|
||||
// Ideally we'd use new URL(document.URL).searchParams, but for about: URIs,
|
||||
// searchParams is empty.
|
||||
let urlParams = new URLSearchParams(document.URL.split("?")[1] || "");
|
||||
let action = urlParams.get(ACTION_URL_PARAM);
|
||||
urlParams.delete(ACTION_URL_PARAM);
|
||||
|
||||
switch (action) {
|
||||
case "signin":
|
||||
if (user) {
|
||||
// asking to sign-in when already signed in just shows manage.
|
||||
show("stage", "manage");
|
||||
} else {
|
||||
return fxAccounts.promiseAccountsSignInURI().then(url => {
|
||||
show("remote");
|
||||
wrapper.init(url, urlParams);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "signup":
|
||||
if (user) {
|
||||
// asking to sign-up when already signed in just shows manage.
|
||||
show("stage", "manage");
|
||||
} else {
|
||||
return fxAccounts.promiseAccountsSignUpURI().then(url => {
|
||||
show("remote");
|
||||
wrapper.init(url, urlParams);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "reauth":
|
||||
// ideally we would only show this when we know the user is in a
|
||||
// "must reauthenticate" state - but we don't.
|
||||
// As the email address will be included in the URL returned from
|
||||
// promiseAccountsForceSigninURI, just always show it.
|
||||
return fxAccounts.promiseAccountsForceSigninURI().then(url => {
|
||||
show("remote");
|
||||
wrapper.init(url, urlParams);
|
||||
});
|
||||
default:
|
||||
// No action specified.
|
||||
if (user) {
|
||||
show("stage", "manage");
|
||||
} else {
|
||||
// Attempt a migration if enabled or show the introductory page
|
||||
// otherwise.
|
||||
return migrateToDevEdition(urlParams).then(migrated => {
|
||||
if (!migrated) {
|
||||
show("stage", "intro");
|
||||
// load the remote frame in the background
|
||||
return fxAccounts.promiseAccountsSignUpURI().then(uri =>
|
||||
wrapper.init(uri, urlParams));
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}).catch(err => {
|
||||
console.log("Configuration or sign in error", err);
|
||||
setErrorPage("configError");
|
||||
});
|
||||
}
|
||||
|
||||
function setErrorPage(errorType) {
|
||||
show("stage", errorType);
|
||||
}
|
||||
|
||||
// Causes the "top-level" element with |id| to be shown - all other top-level
|
||||
// elements are hidden. Optionally, ensures that only 1 "second-level" element
|
||||
// inside the top-level one is shown.
|
||||
function show(id, childId) {
|
||||
// top-level items are either <div> or <iframe>
|
||||
let allTop = document.querySelectorAll("body > div, iframe");
|
||||
for (let elt of allTop) {
|
||||
if (elt.getAttribute("id") == id) {
|
||||
elt.style.display = 'block';
|
||||
} else {
|
||||
elt.style.display = 'none';
|
||||
}
|
||||
}
|
||||
if (childId) {
|
||||
// child items are all <div>
|
||||
let allSecond = document.querySelectorAll("#" + id + " > div");
|
||||
for (let elt of allSecond) {
|
||||
if (elt.getAttribute("id") == childId) {
|
||||
elt.style.display = 'block';
|
||||
} else {
|
||||
elt.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate sync data from the default profile to the dev-edition profile.
|
||||
// Returns a promise of a true value if migration succeeded, or false if it
|
||||
// failed.
|
||||
function migrateToDevEdition(urlParams) {
|
||||
let defaultProfilePath;
|
||||
try {
|
||||
defaultProfilePath = window.getDefaultProfilePath();
|
||||
} catch (e) {} // no default profile.
|
||||
let migrateSyncCreds = false;
|
||||
if (defaultProfilePath) {
|
||||
try {
|
||||
migrateSyncCreds = Services.prefs.getBoolPref("identity.fxaccounts.migrateToDevEdition");
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (!migrateSyncCreds) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
let fxAccountsStorage = OS.Path.join(defaultProfilePath, fxAccountsCommon.DEFAULT_STORAGE_FILENAME);
|
||||
return OS.File.read(fxAccountsStorage, { encoding: "utf-8" }).then(text => {
|
||||
let accountData = JSON.parse(text).accountData;
|
||||
updateDisplayedEmail(accountData);
|
||||
return fxAccounts.setSignedInUser(accountData);
|
||||
}).then(() => {
|
||||
return fxAccounts.promiseAccountsForceSigninURI().then(url => {
|
||||
show("remote");
|
||||
wrapper.init(url, urlParams);
|
||||
});
|
||||
}).then(null, error => {
|
||||
log("Failed to migrate FX Account: " + error);
|
||||
show("stage", "intro");
|
||||
// load the remote frame in the background
|
||||
fxAccounts.promiseAccountsSignUpURI().then(uri => {
|
||||
wrapper.init(uri, urlParams)
|
||||
}).catch(e => {
|
||||
console.log("Failed to load signup page", e);
|
||||
setErrorPage("configError");
|
||||
});
|
||||
}).then(() => {
|
||||
// Reset the pref after migration.
|
||||
Services.prefs.setBoolPref("identity.fxaccounts.migrateToDevEdition", false);
|
||||
return true;
|
||||
}).then(null, err => {
|
||||
Cu.reportError("Failed to reset the migrateToDevEdition pref: " + err);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function that returns the path of the default profile on disk. Will be
|
||||
// overridden in tests.
|
||||
function getDefaultProfilePath() {
|
||||
let defaultProfile = Cc["@mozilla.org/toolkit/profile-service;1"]
|
||||
.getService(Ci.nsIToolkitProfileService)
|
||||
.defaultProfile;
|
||||
return defaultProfile.rootDir.path;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function onload() {
|
||||
document.removeEventListener("DOMContentLoaded", onload, true);
|
||||
init();
|
||||
var buttonGetStarted = document.getElementById('buttonGetStarted');
|
||||
buttonGetStarted.addEventListener('click', getStarted);
|
||||
|
||||
var buttonRetry = document.getElementById('buttonRetry');
|
||||
buttonRetry.addEventListener('click', retry);
|
||||
|
||||
var oldsync = document.getElementById('oldsync');
|
||||
oldsync.addEventListener('click', handleOldSync);
|
||||
|
||||
var buttonOpenPrefs = document.getElementById('buttonOpenPrefs')
|
||||
buttonOpenPrefs.addEventListener('click', openPrefs);
|
||||
}, true);
|
||||
|
||||
function initObservers() {
|
||||
function observe(subject, topic, data) {
|
||||
log("about:accounts observed " + topic);
|
||||
if (topic == fxAccountsCommon.ONLOGOUT_NOTIFICATION) {
|
||||
// All about:account windows get changed to action=signin on logout.
|
||||
window.location = "about:accounts?action=signin";
|
||||
return;
|
||||
}
|
||||
|
||||
// must be onverified - we want to open preferences.
|
||||
openPrefs();
|
||||
}
|
||||
|
||||
for (let topic of OBSERVER_TOPICS) {
|
||||
Services.obs.addObserver(observe, topic, false);
|
||||
}
|
||||
window.addEventListener("unload", function(event) {
|
||||
log("about:accounts unloading")
|
||||
for (let topic of OBSERVER_TOPICS) {
|
||||
Services.obs.removeObserver(observe, topic);
|
||||
}
|
||||
});
|
||||
}
|
||||
initObservers();
|
||||
@@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % aboutAccountsDTD SYSTEM "chrome://browser/locale/aboutAccounts.dtd">
|
||||
%aboutAccountsDTD;
|
||||
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
|
||||
%syncBrandDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" dir="&locale.dir;">
|
||||
<head>
|
||||
<title>&syncBrand.fullName.label;</title>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
|
||||
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet"
|
||||
href="chrome://browser/content/aboutaccounts/normalize.css"
|
||||
type="text/css" />
|
||||
<link rel="stylesheet"
|
||||
href="chrome://browser/content/aboutaccounts/main.css"
|
||||
type="text/css" />
|
||||
<link rel="stylesheet"
|
||||
href="chrome://browser/content/aboutaccounts/aboutaccounts.css"
|
||||
type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="stage">
|
||||
|
||||
<div id="manage">
|
||||
<header>
|
||||
<h1>&aboutAccounts.connected;</h1>
|
||||
<div id="email"></div>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="graphic graphic-sync-intro"> </div>
|
||||
|
||||
<div class="button-row">
|
||||
<button id="buttonOpenPrefs" class="button" href="#" tabindex="0">&aboutAccountsConfig.syncPreferences.label;</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="intro">
|
||||
<header>
|
||||
<h1>&aboutAccounts.welcome;</h1>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="graphic graphic-sync-intro"> </div>
|
||||
|
||||
<div class="description">&aboutAccountsConfig.description;</div>
|
||||
|
||||
<div class="button-row">
|
||||
<button id="buttonGetStarted" class="button" tabindex="1">&aboutAccountsConfig.startButton.label;</button>
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<button id="oldsync" tabindex="2">&aboutAccountsConfig.useOldSync.label;</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="networkError">
|
||||
<header>
|
||||
<h1>&aboutAccounts.noConnection.title;</h1>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="graphic graphic-sync-intro"> </div>
|
||||
|
||||
<div class="description">&aboutAccounts.noConnection.description;</div>
|
||||
|
||||
<div class="button-row">
|
||||
<button id="buttonRetry" class="button" tabindex="3">&aboutAccounts.noConnection.retry;</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="configError">
|
||||
<header>
|
||||
<h1>&aboutAccounts.badConfig.title;</h1>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="graphic graphic-sync-intro"> </div>
|
||||
|
||||
<div class="description">&aboutAccounts.badConfig.description;</div>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<iframe mozframetype="content" id="remote" />
|
||||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://browser/content/utilityOverlay.js"/>
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/aboutaccounts/aboutaccounts.js" />
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,166 @@
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: #F2F2F2;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #424f59;
|
||||
font: message-box;
|
||||
font-size: 14px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0095dd;
|
||||
cursor: pointer; /* Use the correct cursor for anchors without an href */
|
||||
}
|
||||
|
||||
a:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 1px dotted #0095dd;
|
||||
}
|
||||
|
||||
|
||||
a.no-underline {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#stage {
|
||||
background:#fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.25);
|
||||
margin: 0 auto;
|
||||
min-height: 300px;
|
||||
padding: 60px 40px 40px 40px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
top: 80px;
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
header h1
|
||||
{
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
#intro header h1 {
|
||||
margin: 0 0 32px 0;
|
||||
}
|
||||
|
||||
#manage header h1 {
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
#manage header #email {
|
||||
margin-bottom: 23px;
|
||||
color: rgb(138, 155, 168);
|
||||
font-size: 19px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
margin-top: 45px;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.button-row button,
|
||||
.button-row a.button {
|
||||
background: #0095dd;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
padding: 15px 0;
|
||||
transition-duration: 150ms;
|
||||
transition-property: background-color;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-row a.button {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.button-row a.button:active,
|
||||
.button-row a.button:hover,
|
||||
.button-row a.button:focus,
|
||||
.button-row button:active,
|
||||
.button-row button:hover,
|
||||
.button-row button:focus {
|
||||
background: #08c;
|
||||
}
|
||||
|
||||
|
||||
.graphic-sync-intro {
|
||||
background-image: url(images/graphic_sync_intro.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 150px 195px;
|
||||
height: 195px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
text-indent: 100%;
|
||||
white-space: nowrap;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.description,
|
||||
.button-row {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
html {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#stage {
|
||||
box-shadow: none;
|
||||
margin: 30px auto 0 auto;
|
||||
min-height: none;
|
||||
min-width: 320px;
|
||||
padding: 0 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.button-row button,
|
||||
.button-row a.button {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Retina */
|
||||
@media
|
||||
only screen and (min-device-pixel-ratio: 2),
|
||||
only screen and ( min-resolution: 192dpi),
|
||||
only screen and ( min-resolution: 2dppx) {
|
||||
.graphic-sync-intro {
|
||||
background-image: url(images/graphic_sync_intro@2x.png);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
|
||||
|
||||
/* ==========================================================================
|
||||
HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined in IE 8/9.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct `inline-block` display not defined in IE 8/9.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9.
|
||||
* Hide the `template` element in IE, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Base
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `outline` inconsistency between Chrome and other browsers.
|
||||
*/
|
||||
|
||||
a:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Typography
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct font family set oddly in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability of pre-formatted text in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set consistent quote types.
|
||||
*/
|
||||
|
||||
q {
|
||||
quotes: "\201C" "\201D" "\2018" "\2019";
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow displayed oddly in IE 9.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Figures
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari 5.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct font family not being inherited in all browsers.
|
||||
* 2. Correct font size not being inherited in all browsers.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
|
||||
* Correct `select` style inheritance in Firefox 4+ and Opera.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
box-sizing: content-box; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari 5 and Chrome
|
||||
* on OS X.
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove default vertical scrollbar in IE 8/9.
|
||||
* 2. Improve readability and alignment in all browsers.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto; /* 1 */
|
||||
vertical-align: top; /* 2 */
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#remote-report {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
display: flex;
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const prefs = new Preferences("datareporting.healthreport.");
|
||||
|
||||
const PREF_UNIFIED = "toolkit.telemetry.unified";
|
||||
const PREF_REPORTING_URL = "datareporting.healthreport.about.reportUrl";
|
||||
|
||||
var healthReportWrapper = {
|
||||
init: function () {
|
||||
let iframe = document.getElementById("remote-report");
|
||||
iframe.addEventListener("load", healthReportWrapper.initRemotePage, false);
|
||||
iframe.src = this._getReportURI().spec;
|
||||
prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
prefs.ignore("uploadEnabled", this.updatePrefState, healthReportWrapper);
|
||||
},
|
||||
|
||||
_getReportURI: function () {
|
||||
let url = Services.urlFormatter.formatURLPref(PREF_REPORTING_URL);
|
||||
return Services.io.newURI(url, null, null);
|
||||
},
|
||||
|
||||
setDataSubmission: function (enabled) {
|
||||
MozSelfSupport.healthReportDataSubmissionEnabled = enabled;
|
||||
this.updatePrefState();
|
||||
},
|
||||
|
||||
updatePrefState: function () {
|
||||
try {
|
||||
let prefs = {
|
||||
enabled: MozSelfSupport.healthReportDataSubmissionEnabled,
|
||||
};
|
||||
healthReportWrapper.injectData("prefs", prefs);
|
||||
}
|
||||
catch (ex) {
|
||||
healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PREFS_FAILED);
|
||||
}
|
||||
},
|
||||
|
||||
sendTelemetryPingList: function () {
|
||||
console.log("AboutHealthReport: Collecting Telemetry ping list.");
|
||||
MozSelfSupport.getTelemetryPingList().then((list) => {
|
||||
console.log("AboutHealthReport: Sending Telemetry ping list.");
|
||||
this.injectData("telemetry-ping-list", list);
|
||||
}).catch((ex) => {
|
||||
console.log("AboutHealthReport: Collecting ping list failed: " + ex);
|
||||
});
|
||||
},
|
||||
|
||||
sendTelemetryPingData: function (pingId) {
|
||||
console.log("AboutHealthReport: Collecting Telemetry ping data.");
|
||||
MozSelfSupport.getTelemetryPing(pingId).then((ping) => {
|
||||
console.log("AboutHealthReport: Sending Telemetry ping data.");
|
||||
this.injectData("telemetry-ping-data", {
|
||||
id: pingId,
|
||||
pingData: ping,
|
||||
});
|
||||
}).catch((ex) => {
|
||||
console.log("AboutHealthReport: Loading ping data failed: " + ex);
|
||||
this.injectData("telemetry-ping-data", {
|
||||
id: pingId,
|
||||
error: "error-generic",
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
sendCurrentEnvironment: function () {
|
||||
console.log("AboutHealthReport: Sending Telemetry environment data.");
|
||||
MozSelfSupport.getCurrentTelemetryEnvironment().then((environment) => {
|
||||
this.injectData("telemetry-current-environment-data", environment);
|
||||
}).catch((ex) => {
|
||||
console.log("AboutHealthReport: Collecting current environment data failed: " + ex);
|
||||
});
|
||||
},
|
||||
|
||||
sendCurrentPingData: function () {
|
||||
console.log("AboutHealthReport: Sending current Telemetry ping data.");
|
||||
MozSelfSupport.getCurrentTelemetrySubsessionPing().then((ping) => {
|
||||
this.injectData("telemetry-current-ping-data", ping);
|
||||
}).catch((ex) => {
|
||||
console.log("AboutHealthReport: Collecting current ping data failed: " + ex);
|
||||
});
|
||||
},
|
||||
|
||||
injectData: function (type, content) {
|
||||
let report = this._getReportURI();
|
||||
|
||||
// file URIs can't be used for targetOrigin, so we use "*" for this special case
|
||||
// in all other cases, pass in the URL to the report so we properly restrict the message dispatch
|
||||
let reportUrl = report.scheme == "file" ? "*" : report.spec;
|
||||
|
||||
let data = {
|
||||
type: type,
|
||||
content: content
|
||||
}
|
||||
|
||||
let iframe = document.getElementById("remote-report");
|
||||
iframe.contentWindow.postMessage(data, reportUrl);
|
||||
},
|
||||
|
||||
handleRemoteCommand: function (evt) {
|
||||
// Do an origin check to harden against the frame content being loaded from unexpected locations.
|
||||
let allowedPrincipal = Services.scriptSecurityManager.getCodebasePrincipal(this._getReportURI());
|
||||
let targetPrincipal = evt.target.nodePrincipal;
|
||||
if (!allowedPrincipal.equals(targetPrincipal)) {
|
||||
Cu.reportError(`Origin check failed for message "${evt.detail.command}": ` +
|
||||
`target origin is "${targetPrincipal.origin}", expected "${allowedPrincipal.origin}"`);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (evt.detail.command) {
|
||||
case "DisableDataSubmission":
|
||||
this.setDataSubmission(false);
|
||||
break;
|
||||
case "EnableDataSubmission":
|
||||
this.setDataSubmission(true);
|
||||
break;
|
||||
case "RequestCurrentPrefs":
|
||||
this.updatePrefState();
|
||||
break;
|
||||
case "RequestTelemetryPingList":
|
||||
this.sendTelemetryPingList();
|
||||
break;
|
||||
case "RequestTelemetryPingData":
|
||||
this.sendTelemetryPingData(evt.detail.id);
|
||||
break;
|
||||
case "RequestCurrentEnvironment":
|
||||
this.sendCurrentEnvironment();
|
||||
break;
|
||||
case "RequestCurrentPingData":
|
||||
this.sendCurrentPingData();
|
||||
break;
|
||||
default:
|
||||
Cu.reportError("Unexpected remote command received: " + evt.detail.command + ". Ignoring command.");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
initRemotePage: function () {
|
||||
let iframe = document.getElementById("remote-report").contentDocument;
|
||||
iframe.addEventListener("RemoteHealthReportCommand",
|
||||
function onCommand(e) { healthReportWrapper.handleRemoteCommand(e); },
|
||||
false);
|
||||
healthReportWrapper.updatePrefState();
|
||||
},
|
||||
|
||||
// error handling
|
||||
ERROR_INIT_FAILED: 1,
|
||||
ERROR_PAYLOAD_FAILED: 2,
|
||||
ERROR_PREFS_FAILED: 3,
|
||||
|
||||
reportFailure: function (error) {
|
||||
let details = {
|
||||
errorType: error,
|
||||
}
|
||||
healthReportWrapper.injectData("error", details);
|
||||
},
|
||||
|
||||
handleInitFailure: function () {
|
||||
healthReportWrapper.reportFailure(healthReportWrapper.ERROR_INIT_FAILED);
|
||||
},
|
||||
|
||||
handlePayloadFailure: function () {
|
||||
healthReportWrapper.reportFailure(healthReportWrapper.ERROR_PAYLOAD_FAILED);
|
||||
},
|
||||
}
|
||||
|
||||
window.addEventListener("load", function () { healthReportWrapper.init(); });
|
||||
window.addEventListener("unload", function () { healthReportWrapper.uninit(); });
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % securityPrefsDTD SYSTEM "chrome://browser/locale/preferences/security.dtd">
|
||||
%securityPrefsDTD;
|
||||
<!ENTITY % aboutHealthReportDTD SYSTEM "chrome://browser/locale/aboutHealthReport.dtd">
|
||||
%aboutHealthReportDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&abouthealth.pagetitle;</title>
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet"
|
||||
href="chrome://browser/content/abouthealthreport/abouthealth.css"
|
||||
type="text/css" />
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/abouthealthreport/abouthealth.js" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="remote-report"/>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
%if 0
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
%endif
|
||||
|
||||
html {
|
||||
font: message-box;
|
||||
font-size: 100%;
|
||||
background-color: hsl(0,0%,95%);
|
||||
color: #000;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
color: -moz-nativehyperlinktext;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#topSection {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#brandLogo {
|
||||
height: 192px;
|
||||
width: 192px;
|
||||
margin: 22px auto 31px;
|
||||
background-image: url("chrome://branding/content/about-logo.png");
|
||||
background-size: 192px auto;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#searchIconAndTextContainer {
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
#searchIconAndTextContainer {
|
||||
display: -moz-box;
|
||||
height: 36px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#searchIcon {
|
||||
border: 1px transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: url("chrome://browser/skin/search-indicator-magnifying-glass.svg") center center no-repeat;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#searchText {
|
||||
margin-left: 0;
|
||||
-moz-box-flex: 1;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-inline-start: 34px;
|
||||
padding-inline-end: 8px;
|
||||
background: hsla(0,0%,100%,.9) padding-box;
|
||||
border: 1px solid;
|
||||
border-radius: 2px 0 0 2px;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
|
||||
0 0 2px hsla(210,65%,9%,.1) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.2);
|
||||
color: inherit;
|
||||
unicode-bidi: plaintext;
|
||||
}
|
||||
|
||||
#searchText:dir(rtl) {
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#searchText[aria-expanded="true"] {
|
||||
border-radius: 2px 0 0 0;
|
||||
}
|
||||
|
||||
#searchText[aria-expanded="true"]:dir(rtl) {
|
||||
border-radius: 0 2px 0 0;
|
||||
}
|
||||
|
||||
#searchText[keepfocus],
|
||||
#searchText:focus,
|
||||
#searchText[autofocus] {
|
||||
border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
|
||||
}
|
||||
|
||||
#searchSubmit {
|
||||
margin-inline-start: -1px;
|
||||
color: transparent;
|
||||
background: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go") center center no-repeat, linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
|
||||
padding: 0;
|
||||
border: 1px solid;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
border-radius: 0 2px 2px 0;
|
||||
border-inline-start: 1px solid transparent;
|
||||
box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.2);
|
||||
cursor: pointer;
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 150ms;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
#searchSubmit:dir(rtl) {
|
||||
border-radius: 2px 0 0 2px;
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl"), linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1));
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit,
|
||||
#searchText[keepfocus] + #searchSubmit,
|
||||
#searchText + #searchSubmit:hover,
|
||||
#searchText[autofocus] + #searchSubmit {
|
||||
border-color: #59b5fc #45a3e7 #3294d5;
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit,
|
||||
#searchText[keepfocus] + #searchSubmit,
|
||||
#searchText[autofocus] + #searchSubmit {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-inverted"), linear-gradient(#4cb1ff, #1793e5);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.1) inset,
|
||||
0 1px 0 hsla(210,54%,20%,.03);
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit:dir(rtl),
|
||||
#searchText[keepfocus] + #searchSubmit:dir(rtl),
|
||||
#searchText[autofocus] + #searchSubmit:dir(rtl) {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl-inverted"), linear-gradient(#4cb1ff, #1793e5);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:hover {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-inverted"), linear-gradient(#66bdff, #0d9eff);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.1) inset,
|
||||
0 1px 0 hsla(210,54%,20%,.03),
|
||||
0 0 4px hsla(206,100%,20%,.2);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:dir(rtl):hover {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl-inverted"), linear-gradient(#66bdff, #0d9eff);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:hover:active {
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
|
||||
0 0 1px hsla(211,79%,6%,.2) inset;
|
||||
transition-duration: 0ms;
|
||||
}
|
||||
|
||||
#launcher {
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: center;
|
||||
width: 100%;
|
||||
background-color: hsla(0,0%,0%,.03);
|
||||
border-top: 1px solid hsla(0,0%,0%,.03);
|
||||
box-shadow: 0 1px 2px hsla(0,0%,0%,.02) inset,
|
||||
0 -1px 0 hsla(0,0%,100%,.25);
|
||||
}
|
||||
|
||||
#launcher:not([session]),
|
||||
body[narrow] #launcher[session] {
|
||||
display: block; /* display separator and restore button on separate lines */
|
||||
text-align: center;
|
||||
white-space: nowrap; /* prevent navigational buttons from wrapping */
|
||||
}
|
||||
|
||||
.launchButton {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
margin: 16px 1px;
|
||||
padding: 14px 6px;
|
||||
min-width: 88px;
|
||||
max-width: 176px;
|
||||
max-height: 85px;
|
||||
vertical-align: top;
|
||||
white-space: normal;
|
||||
background: transparent padding-box;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
color: #525c66;
|
||||
font-size: 75%;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
|
||||
body[narrow] #launcher[session] > .launchButton {
|
||||
margin: 4px 1px;
|
||||
}
|
||||
|
||||
.launchButton:hover {
|
||||
background-color: hsla(211,79%,6%,.03);
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
}
|
||||
|
||||
.launchButton:hover:active {
|
||||
background-image: linear-gradient(hsla(211,79%,6%,.02), hsla(211,79%,6%,.05));
|
||||
border-color: hsla(210,54%,20%,.2) hsla(210,54%,20%,.23) hsla(210,54%,20%,.25);
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.05) inset,
|
||||
0 0 1px hsla(211,79%,6%,.1) inset;
|
||||
transition-duration: 0ms;
|
||||
}
|
||||
|
||||
.launchButton[hidden],
|
||||
#launcher:not([session]) > #restorePreviousSessionSeparator,
|
||||
#launcher:not([session]) > #restorePreviousSession {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#restorePreviousSessionSeparator {
|
||||
width: 3px;
|
||||
height: 116px;
|
||||
margin: 0 10px;
|
||||
background-image: linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
|
||||
linear-gradient(hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
|
||||
linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
|
||||
background-position: left top, center, right bottom;
|
||||
background-size: 1px auto;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSessionSeparator {
|
||||
margin: 0 auto;
|
||||
width: 512px;
|
||||
height: 3px;
|
||||
background-image: linear-gradient(to right, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
|
||||
linear-gradient(to right, hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
|
||||
linear-gradient(to right, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
|
||||
background-size: auto 1px;
|
||||
}
|
||||
|
||||
#restorePreviousSession {
|
||||
max-width: none;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.launchButton::before {
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin: 0 auto 6px;
|
||||
line-height: 0; /* remove extra vertical space due to non-zero font-size */
|
||||
}
|
||||
|
||||
#downloads::before {
|
||||
content: url("chrome://browser/content/abouthome/downloads.png");
|
||||
}
|
||||
|
||||
#bookmarks::before {
|
||||
content: url("chrome://browser/content/abouthome/bookmarks.png");
|
||||
}
|
||||
|
||||
#history::before {
|
||||
content: url("chrome://browser/content/abouthome/history.png");
|
||||
}
|
||||
|
||||
#addons::before {
|
||||
content: url("chrome://browser/content/abouthome/addons.png");
|
||||
}
|
||||
|
||||
#sync::before {
|
||||
content: url("chrome://browser/content/abouthome/sync.png");
|
||||
}
|
||||
|
||||
#settings::before {
|
||||
content: url("chrome://browser/content/abouthome/settings.png");
|
||||
}
|
||||
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore-large.png");
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
display: inline-block; /* display on same line as text label */
|
||||
vertical-align: middle;
|
||||
margin-bottom: 0;
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
#restorePreviousSession:dir(rtl)::before {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore.png");
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
#aboutMozilla {
|
||||
display: block;
|
||||
position: relative; /* pin wordmark to edge of document, not of viewport */
|
||||
-moz-box-ordinal-group: 0;
|
||||
opacity: .5;
|
||||
transition: opacity 150ms;
|
||||
}
|
||||
|
||||
#aboutMozilla:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#aboutMozilla::before {
|
||||
content: url("chrome://browser/content/abouthome/mozilla.png");
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
width: 69px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
/* [HiDPI]
|
||||
* At resolutions above 1dppx, prefer downscaling the 2x Retina graphics
|
||||
* rather than upscaling the original-size ones (bug 818940).
|
||||
*/
|
||||
@media not all and (max-resolution: 1dppx) {
|
||||
#brandLogo {
|
||||
background-image: url("chrome://branding/content/about-logo@2x.png");
|
||||
}
|
||||
|
||||
.launchButton::before,
|
||||
#aboutMozilla::before {
|
||||
transform: scale(.5);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.launchButton:dir(rtl)::before,
|
||||
#aboutMozilla:dir(rtl)::before {
|
||||
transform: scale(.5) translateX(32px);
|
||||
}
|
||||
|
||||
#downloads::before {
|
||||
content: url("chrome://browser/content/abouthome/downloads@2x.png");
|
||||
}
|
||||
|
||||
#bookmarks::before {
|
||||
content: url("chrome://browser/content/abouthome/bookmarks@2x.png");
|
||||
}
|
||||
|
||||
#history::before {
|
||||
content: url("chrome://browser/content/abouthome/history@2x.png");
|
||||
}
|
||||
|
||||
#addons::before {
|
||||
content: url("chrome://browser/content/abouthome/addons@2x.png");
|
||||
}
|
||||
|
||||
#sync::before {
|
||||
content: url("chrome://browser/content/abouthome/sync@2x.png");
|
||||
}
|
||||
|
||||
#settings::before {
|
||||
content: url("chrome://browser/content/abouthome/settings@2x.png");
|
||||
}
|
||||
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore-large@2x.png");
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore@2x.png");
|
||||
}
|
||||
|
||||
#restorePreviousSession:dir(rtl)::before {
|
||||
transform: scale(-0.5, 0.5) translateX(24px);
|
||||
transform-origin: top center;
|
||||
}
|
||||
|
||||
#aboutMozilla::before {
|
||||
content: url("chrome://browser/content/abouthome/mozilla@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* import-globals-from ../contentSearchUI.js */
|
||||
|
||||
// IndexedDB storage constants.
|
||||
const DATABASE_NAME = "abouthome";
|
||||
const DATABASE_VERSION = 1;
|
||||
const DATABASE_STORAGE = "persistent";
|
||||
var searchText;
|
||||
|
||||
// This global tracks if the page has been set up before, to prevent double inits
|
||||
var gInitialized = false;
|
||||
var gObserver = new MutationObserver(function (mutations) {
|
||||
for (let mutation of mutations) {
|
||||
// The addition of the restore session button changes our width:
|
||||
if (mutation.attributeName == "session") {
|
||||
fitToWidth();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("pageshow", function () {
|
||||
// Delay search engine setup, cause browser.js::BrowserOnAboutPageLoad runs
|
||||
// later and may use asynchronous getters.
|
||||
window.gObserver.observe(document.documentElement, { attributes: true });
|
||||
window.gObserver.observe(document.getElementById("launcher"), { attributes: true });
|
||||
fitToWidth();
|
||||
setupSearch();
|
||||
window.addEventListener("resize", fitToWidth);
|
||||
|
||||
// Ask chrome to update snippets.
|
||||
var event = new CustomEvent("AboutHomeLoad", {bubbles:true});
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
|
||||
window.addEventListener("pagehide", function() {
|
||||
window.gObserver.disconnect();
|
||||
window.removeEventListener("resize", fitToWidth);
|
||||
});
|
||||
|
||||
window.addEventListener("keypress", ev => {
|
||||
if (ev.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't focus the search-box on keypress if something other than the
|
||||
// body or document element has focus - don't want to steal input from other elements
|
||||
// Make an exception for <a> and <button> elements (and input[type=button|submit])
|
||||
// which don't usefully take keypresses anyway.
|
||||
// (except space, which is handled below)
|
||||
if (document.activeElement && document.activeElement != document.body &&
|
||||
document.activeElement != document.documentElement &&
|
||||
!["a", "button"].includes(document.activeElement.localName) &&
|
||||
!document.activeElement.matches("input:-moz-any([type=button],[type=submit])")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let modifiers = ev.ctrlKey + ev.altKey + ev.metaKey;
|
||||
// ignore Ctrl/Cmd/Alt, but not Shift
|
||||
// also ignore Tab, Insert, PageUp, etc., and Space
|
||||
if (modifiers != 0 || ev.charCode == 0 || ev.charCode == 32)
|
||||
return;
|
||||
|
||||
searchText.focus();
|
||||
// need to send the first keypress outside the search-box manually to it
|
||||
searchText.value += ev.key;
|
||||
});
|
||||
|
||||
function onSearchSubmit(aEvent)
|
||||
{
|
||||
gContentSearchController.search(aEvent);
|
||||
}
|
||||
|
||||
|
||||
var gContentSearchController;
|
||||
|
||||
function setupSearch()
|
||||
{
|
||||
// Set submit button label for when CSS background are disabled (e.g.
|
||||
// high contrast mode).
|
||||
document.getElementById("searchSubmit").value =
|
||||
document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
|
||||
|
||||
// The "autofocus" attribute doesn't focus the form element
|
||||
// immediately when the element is first drawn, so the
|
||||
// attribute is also used for styling when the page first loads.
|
||||
searchText = document.getElementById("searchText");
|
||||
searchText.addEventListener("blur", function searchText_onBlur() {
|
||||
searchText.removeEventListener("blur", searchText_onBlur);
|
||||
searchText.removeAttribute("autofocus");
|
||||
});
|
||||
|
||||
if (!gContentSearchController) {
|
||||
gContentSearchController =
|
||||
new ContentSearchUIController(searchText, searchText.parentNode,
|
||||
"abouthome", "homepage");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the test harness that we're done loading the page.
|
||||
*/
|
||||
function loadCompleted()
|
||||
{
|
||||
}
|
||||
|
||||
function fitToWidth() {
|
||||
if (document.documentElement.scrollWidth > window.innerWidth) {
|
||||
document.body.setAttribute("narrow", "true");
|
||||
} else if (document.body.hasAttribute("narrow")) {
|
||||
document.body.removeAttribute("narrow");
|
||||
fitToWidth();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % aboutHomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
|
||||
%aboutHomeDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
|
||||
%browserDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&abouthome.pageTitle;</title>
|
||||
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/content/contentSearchUI.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all" defer="defer"
|
||||
href="chrome://browser/content/abouthome/aboutHome.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/abouthome/aboutHome.js"/>
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/contentSearchUI.js"/>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
<div class="spacer"/>
|
||||
<div id="topSection">
|
||||
<div id="brandLogo"></div>
|
||||
|
||||
<div id="searchIconAndTextContainer">
|
||||
<div id="searchIcon"/>
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256"
|
||||
aria-label="&contentSearchInput.label;" autofocus="autofocus"/>
|
||||
<input id="searchSubmit" type="button" onclick="onSearchSubmit(event)"
|
||||
title="&contentSearchSubmit.tooltip;"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer"/>
|
||||
|
||||
<div id="launcher">
|
||||
<button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button>
|
||||
<button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button>
|
||||
<button class="launchButton" id="history">&abouthome.historyButton.label;</button>
|
||||
<button class="launchButton" id="addons">&abouthome.addonsButton.label;</button>
|
||||
<button class="launchButton" id="sync">&abouthome.syncButton.label;</button>
|
||||
#ifdef XP_WIN
|
||||
<button class="launchButton" id="settings">&abouthome.preferencesButtonWin.label;</button>
|
||||
#else
|
||||
<button class="launchButton" id="settings">&abouthome.preferencesButtonUnix.label;</button>
|
||||
#endif
|
||||
<div id="restorePreviousSessionSeparator"/>
|
||||
<button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |