2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2013-02-07 12:08:58 +04:00
|
|
|
/* 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/. */
|
|
|
|
|
2014-03-17 10:56:54 +04:00
|
|
|
#include "mozilla/AsyncEventDispatcher.h"
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
#include "mozilla/dom/BindContext.h"
|
2013-02-07 12:08:58 +04:00
|
|
|
#include "mozilla/dom/HTMLMetaElement.h"
|
2013-02-07 12:08:58 +04:00
|
|
|
#include "mozilla/dom/HTMLMetaElementBinding.h"
|
2015-11-15 06:29:05 +03:00
|
|
|
#include "mozilla/dom/nsCSPService.h"
|
2019-07-30 10:14:09 +03:00
|
|
|
#include "mozilla/dom/nsCSPUtils.h"
|
2019-07-25 07:24:08 +03:00
|
|
|
#include "mozilla/dom/ViewportMetaData.h"
|
2018-01-11 11:57:00 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2019-07-26 04:10:23 +03:00
|
|
|
#include "mozilla/StaticPrefs_security.h"
|
2013-02-07 12:08:58 +04:00
|
|
|
#include "nsContentUtils.h"
|
2014-03-17 10:56:54 +04:00
|
|
|
#include "nsStyleConsts.h"
|
2013-02-07 12:08:58 +04:00
|
|
|
|
2018-01-11 11:57:00 +03:00
|
|
|
static mozilla::LazyLogModule gMetaElementLog("nsMetaElement");
|
|
|
|
#define LOG(msg) MOZ_LOG(gMetaElementLog, mozilla::LogLevel::Debug, msg)
|
|
|
|
#define LOG_ENABLED() MOZ_LOG_TEST(gMetaElementLog, mozilla::LogLevel::Debug)
|
|
|
|
|
2013-02-07 12:08:58 +04:00
|
|
|
NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
2018-09-21 23:45:49 +03:00
|
|
|
HTMLMetaElement::HTMLMetaElement(
|
|
|
|
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
|
|
|
: nsGenericHTMLElement(std::move(aNodeInfo)) {}
|
2013-02-07 12:08:58 +04:00
|
|
|
|
2020-02-20 19:19:15 +03:00
|
|
|
HTMLMetaElement::~HTMLMetaElement() = default;
|
2013-02-07 12:08:58 +04:00
|
|
|
|
|
|
|
NS_IMPL_ELEMENT_CLONE(HTMLMetaElement)
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
void HTMLMetaElement::SetMetaReferrer(Document* aDocument) {
|
2015-06-20 03:42:49 +03:00
|
|
|
if (!aDocument || !AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
|
|
|
nsGkAtoms::referrer, eIgnoreCase)) {
|
2018-03-13 23:24:01 +03:00
|
|
|
return;
|
2015-06-20 03:42:49 +03:00
|
|
|
}
|
|
|
|
nsAutoString content;
|
2018-03-13 23:24:01 +03:00
|
|
|
GetContent(content);
|
|
|
|
|
2015-06-20 03:42:49 +03:00
|
|
|
Element* headElt = aDocument->GetHeadElement();
|
2019-07-12 16:10:28 +03:00
|
|
|
if (headElt && IsInclusiveDescendantOf(headElt)) {
|
2015-06-20 03:42:49 +03:00
|
|
|
content = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
|
|
|
|
content);
|
2019-06-06 10:23:37 +03:00
|
|
|
aDocument->UpdateReferrerInfoFromMeta(content, false);
|
2015-06-20 03:42:49 +03:00
|
|
|
}
|
|
|
|
}
|
2013-02-07 12:08:58 +04:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
2017-05-19 00:09:01 +03:00
|
|
|
const nsAttrValue* aValue,
|
2017-10-10 00:33:38 +03:00
|
|
|
const nsAttrValue* aOldValue,
|
|
|
|
nsIPrincipal* aSubjectPrincipal,
|
|
|
|
bool aNotify) {
|
2014-07-12 15:28:48 +04:00
|
|
|
if (aNameSpaceID == kNameSpaceID_None) {
|
2019-01-02 16:05:23 +03:00
|
|
|
Document* document = GetUncomposedDoc();
|
2014-07-12 15:28:48 +04:00
|
|
|
if (aName == nsGkAtoms::content) {
|
2015-08-24 22:34:00 +03:00
|
|
|
if (document && AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
|
|
|
nsGkAtoms::viewport, eIgnoreCase)) {
|
2019-07-25 07:24:26 +03:00
|
|
|
ProcessViewportContent(document);
|
2015-08-24 22:34:00 +03:00
|
|
|
}
|
2014-07-12 15:28:48 +04:00
|
|
|
CreateAndDispatchEvent(document, NS_LITERAL_STRING("DOMMetaChanged"));
|
2019-07-25 07:26:04 +03:00
|
|
|
} else if (document && aName == nsGkAtoms::name) {
|
|
|
|
if (aValue && aValue->Equals(nsGkAtoms::viewport, eIgnoreCase)) {
|
|
|
|
ProcessViewportContent(document);
|
|
|
|
} else if (aOldValue &&
|
|
|
|
aOldValue->Equals(nsGkAtoms::viewport, eIgnoreCase)) {
|
|
|
|
DiscardViewportContent(document);
|
|
|
|
}
|
|
|
|
CreateAndDispatchEvent(document, NS_LITERAL_STRING("DOMMetaChanged"));
|
2014-07-12 15:28:48 +04:00
|
|
|
}
|
2015-06-20 03:42:49 +03:00
|
|
|
// Update referrer policy when it got changed from JS
|
2018-03-13 23:24:01 +03:00
|
|
|
SetMetaReferrer(document);
|
2014-07-12 15:28:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return nsGenericHTMLElement::AfterSetAttr(
|
2017-10-10 00:33:38 +03:00
|
|
|
aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
|
2014-07-12 15:28:48 +04:00
|
|
|
}
|
|
|
|
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
nsresult HTMLMetaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|
|
|
nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
|
2013-02-07 12:08:58 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2019-05-31 17:33:33 +03:00
|
|
|
if (!IsInUncomposedDoc()) {
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
return rv;
|
|
|
|
}
|
2019-05-31 17:33:33 +03:00
|
|
|
Document& doc = aContext.OwnerDoc();
|
Bug 1555216 - Change the signature of BindToTree to be (BindContext&, nsINode& aParentNode). r=bzbarsky
BindContext was going to have way more information at first, but then I realized
that most of the things I wanted to know were basically a flag away using the
parent node.
Still I think it's worth it, now experimenting with BindToTree will only mean
adding a field to a struct that's included from a couple cpp files, instead of a
massive pain.
I also think this is clearer, and doing this highlights quite a few
inconsistencies in our code which I've left untouched, but commented with
FIXMEs.
Steps are:
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsresult BindToTree(Document\* aDocument, nsIContent\* aParent,#nsresult BindToTree(BindContext\&, nsINode\& aParent)#g' $file; done
$ for file in $(rg 'nsresult BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's# nsIContent\* aBindingParent) override#override#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(Document\* aDocument, nsIContent\* aParent,#::BindToTree(BindContext\& aContext, nsINode\& aParent)#g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#nsIContent\* aBindingParent)##g' $file; done
$ for file in $(rg '::BindToTree\(' | cut -d : -f 1 | sort | uniq); do sed -i 's#::BindToTree(aDocument, aParent, aBindingParent)#::BindToTree(aContext, aParent)#g' $file; done
$ ./mach clang-format
Then manual fixups.
Depends on D32948
Differential Revision: https://phabricator.services.mozilla.com/D32949
2019-05-29 07:27:04 +03:00
|
|
|
if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::viewport,
|
|
|
|
eIgnoreCase)) {
|
2019-07-25 07:24:26 +03:00
|
|
|
ProcessViewportContent(&doc);
|
2014-11-18 16:46:29 +03:00
|
|
|
}
|
2015-11-15 06:29:05 +03:00
|
|
|
|
2019-07-30 10:14:09 +03:00
|
|
|
if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::httpEquiv, nsGkAtoms::headerCSP,
|
2015-11-15 06:29:05 +03:00
|
|
|
eIgnoreCase)) {
|
|
|
|
// only accept <meta http-equiv="Content-Security-Policy" content=""> if it
|
|
|
|
// appears in the <head> element.
|
2019-05-31 17:33:33 +03:00
|
|
|
Element* headElt = doc.GetHeadElement();
|
2019-07-12 16:10:28 +03:00
|
|
|
if (headElt && IsInclusiveDescendantOf(headElt)) {
|
2015-11-15 06:29:05 +03:00
|
|
|
nsAutoString content;
|
2018-03-13 23:24:01 +03:00
|
|
|
GetContent(content);
|
2018-01-11 11:57:00 +03:00
|
|
|
|
2019-07-30 10:14:09 +03:00
|
|
|
if (LOG_ENABLED()) {
|
|
|
|
nsAutoCString documentURIspec;
|
|
|
|
if (nsIURI* documentURI = doc.GetDocumentURI()) {
|
|
|
|
documentURI->GetAsciiSpec(documentURIspec);
|
2019-05-22 02:14:27 +03:00
|
|
|
}
|
2019-07-30 10:14:09 +03:00
|
|
|
|
|
|
|
LOG(
|
|
|
|
("HTMLMetaElement %p sets CSP '%s' on document=%p, "
|
|
|
|
"document-uri=%s",
|
|
|
|
this, NS_ConvertUTF16toUTF8(content).get(), &doc,
|
|
|
|
documentURIspec.get()));
|
2016-05-21 20:36:24 +03:00
|
|
|
}
|
2019-07-30 10:14:09 +03:00
|
|
|
CSP_ApplyMetaCSPToDoc(doc, content);
|
2015-11-15 06:29:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-20 03:42:49 +03:00
|
|
|
// Referrer Policy spec requires a <meta name="referrer" tag to be in the
|
|
|
|
// <head> element.
|
2019-05-31 17:33:33 +03:00
|
|
|
SetMetaReferrer(&doc);
|
|
|
|
CreateAndDispatchEvent(&doc, NS_LITERAL_STRING("DOMMetaAdded"));
|
2013-02-07 12:08:58 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2019-05-29 01:47:08 +03:00
|
|
|
void HTMLMetaElement::UnbindFromTree(bool aNullParent) {
|
2019-01-02 16:05:23 +03:00
|
|
|
nsCOMPtr<Document> oldDoc = GetUncomposedDoc();
|
2019-07-25 07:36:44 +03:00
|
|
|
if (oldDoc && AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
|
|
|
nsGkAtoms::viewport, eIgnoreCase)) {
|
2019-07-25 07:26:04 +03:00
|
|
|
DiscardViewportContent(oldDoc);
|
2019-07-25 07:36:44 +03:00
|
|
|
}
|
2013-02-07 12:08:58 +04:00
|
|
|
CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMMetaRemoved"));
|
2019-05-29 01:47:08 +03:00
|
|
|
nsGenericHTMLElement::UnbindFromTree(aNullParent);
|
2013-02-07 12:08:58 +04:00
|
|
|
}
|
|
|
|
|
2019-01-02 16:05:23 +03:00
|
|
|
void HTMLMetaElement::CreateAndDispatchEvent(Document* aDoc,
|
2013-02-07 12:08:58 +04:00
|
|
|
const nsAString& aEventName) {
|
|
|
|
if (!aDoc) return;
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher(
|
2018-06-25 19:23:50 +03:00
|
|
|
this, aEventName, CanBubble::eYes, ChromeOnlyDispatch::eYes);
|
2015-07-31 20:08:40 +03:00
|
|
|
asyncDispatcher->RunDOMEventWhenSafe();
|
2013-02-07 12:08:58 +04:00
|
|
|
}
|
|
|
|
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
JSObject* HTMLMetaElement::WrapNode(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) {
|
2018-06-26 00:20:54 +03:00
|
|
|
return HTMLMetaElement_Binding::Wrap(aCx, this, aGivenProto);
|
2013-02-07 12:08:58 +04:00
|
|
|
}
|
|
|
|
|
2019-07-25 07:24:26 +03:00
|
|
|
void HTMLMetaElement::ProcessViewportContent(Document* aDocument) {
|
|
|
|
nsAutoString content;
|
|
|
|
GetContent(content);
|
Bug 1498729 - Store each viewport meta data by the viewport meta tag and use the last one. r=smaug,botond
This is what Chrome and Safari do.
See https://webcompat.com/issues/20701#issuecomment-436054739
So for exmaple, if there are two viewport meta tags like this;
<meta name="viewport" content="width=980">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">
We will use "initial-scale=1,maximum-scale=1". Before this change we used to
use merged "width=980,initial-scale=1,maximum-scale=1".
Another example is to replace the content of a single viewport meta tag like this;
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1">
what will happen when this tag is replaced by below;
<meta id="viewport" name="viewport" content="width=1080">
We will use the replacing one (i.e. "width=1080"), before this change, we used
to use merged "width=1080,initial-scale=1".
As of this commit, we don't properly remove corresponding viewport meta data
when a) viewport meta tag is detached from document and b) `name` attribute is
changed from 'viewport'. These cases will be handled in subsequent commits.
Note that we no longer store invididual viewport meta data in Document::mHeaderData
so that nsIDOMWindowUtils.getDocumentMetadata doesn't work any more for the
invididual viewport meta data, but there is no use cases for them other than
two test cases which are removed in this commit.
Differential Revision: https://phabricator.services.mozilla.com/D38922
--HG--
extra : moz-landing-system : lando
2019-07-25 23:51:23 +03:00
|
|
|
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport, content);
|
|
|
|
|
|
|
|
ViewportMetaData data(content);
|
|
|
|
aDocument->AddMetaViewportElement(this, std::move(data));
|
2019-07-25 07:24:26 +03:00
|
|
|
}
|
|
|
|
|
2019-07-25 07:26:04 +03:00
|
|
|
void HTMLMetaElement::DiscardViewportContent(Document* aDocument) {
|
|
|
|
aDocument->RemoveMetaViewportElement(this);
|
|
|
|
}
|
|
|
|
|
2013-02-07 12:08:58 +04:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|