Merge mozilla-central to fx-team
11
.lldbinit
@ -5,6 +5,12 @@
|
||||
# and in the accompanying Python scripts, see python/lldbutils/README.txt.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Import the module that defines complex Gecko debugging commands. This assumes
|
||||
# you are either running lldb from the top level source directory, the objdir,
|
||||
# or the dist/bin directory. (.lldbinit files in the objdir and dist/bin set
|
||||
# topsrcdir appropriately.)
|
||||
script topsrcdir = topsrcdir if locals().has_key("topsrcdir") else "."; sys.path.append(os.path.join(topsrcdir, "python/lldbutils")); import lldbutils; lldbutils.init()
|
||||
|
||||
# Mozilla's use of UNIFIED_SOURCES to include multiple source files into a
|
||||
# single compiled file breaks lldb breakpoint setting. This works around that.
|
||||
# See http://lldb.llvm.org/troubleshooting.html for more info.
|
||||
@ -15,11 +21,6 @@ settings set target.inline-breakpoint-strategy always
|
||||
# object as being of type "nsBlockFrame *" rather than "nsIFrame *".
|
||||
settings set target.prefer-dynamic-value run-target
|
||||
|
||||
# Import the module that defines complex Gecko debugging commands. Rather
|
||||
# than do any kind of searching, this assumes that you are running lldb from
|
||||
# the top level source directory.
|
||||
script sys.path.append('python/lldbutils'); import lldbutils; lldbutils.init()
|
||||
|
||||
# Show the string value in atoms.
|
||||
type summary add nsIAtom --summary-string "${var.mString}"
|
||||
|
||||
|
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 917896 requires a clobber due to bug 961339.
|
||||
Bug 953381 requires a clobber due to bug 961339.
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsRange.h"
|
||||
@ -34,6 +33,7 @@
|
||||
|
||||
#include "nsITreeBoxObject.h"
|
||||
#include "nsITreeColumns.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -216,8 +216,8 @@ nsCoreUtils::GetRoleContent(nsINode *aNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
||||
if (!content) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(aNode));
|
||||
if (domDoc) {
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(aNode));
|
||||
if (htmlDoc) {
|
||||
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
|
||||
@ -225,9 +225,7 @@ nsCoreUtils::GetRoleContent(nsINode *aNode)
|
||||
content = do_QueryInterface(bodyElement);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDOMElement> docElement;
|
||||
domDoc->GetDocumentElement(getter_AddRefs(docElement));
|
||||
content = do_QueryInterface(docElement);
|
||||
return doc->GetDocumentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "TreeWalker.h"
|
||||
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNodeFilter.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
@ -83,6 +82,7 @@
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/TreeWalker.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
@ -3074,25 +3074,26 @@ Accessible::GetFirstAvailableAccessible(nsINode *aStartNode) const
|
||||
if (accessible)
|
||||
return accessible;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aStartNode->OwnerDoc());
|
||||
NS_ENSURE_TRUE(domDoc, nullptr);
|
||||
nsCOMPtr<nsIDocument> doc = aStartNode->OwnerDoc();
|
||||
|
||||
nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(aStartNode);
|
||||
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetNode());
|
||||
nsCOMPtr<nsIDOMTreeWalker> walker;
|
||||
domDoc->CreateTreeWalker(rootNode,
|
||||
nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
|
||||
nullptr, 1, getter_AddRefs(walker));
|
||||
nsCOMPtr<nsINode> currentNode = aStartNode;
|
||||
ErrorResult rv;
|
||||
nsRefPtr<dom::TreeWalker> walker =
|
||||
doc->CreateTreeWalker(*GetNode(),
|
||||
nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
|
||||
nullptr, rv);
|
||||
NS_ENSURE_TRUE(walker, nullptr);
|
||||
|
||||
walker->SetCurrentNode(currentNode);
|
||||
walker->SetCurrentNode(*currentNode, rv);
|
||||
if (rv.Failed())
|
||||
return nullptr;
|
||||
|
||||
while (true) {
|
||||
walker->NextNode(getter_AddRefs(currentNode));
|
||||
if (!currentNode)
|
||||
currentNode = walker->NextNode(rv);
|
||||
if (!currentNode || rv.Failed())
|
||||
return nullptr;
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(currentNode));
|
||||
Accessible* accessible = mDoc->GetAccessible(node);
|
||||
Accessible* accessible = mDoc->GetAccessible(currentNode);
|
||||
if (accessible)
|
||||
return accessible;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "nsIDOMAttr.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
@ -42,6 +41,7 @@
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/DocumentType.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
@ -352,29 +352,27 @@ DocAccessible::GetURL(nsAString& aURL)
|
||||
NS_IMETHODIMP
|
||||
DocAccessible::GetTitle(nsAString& aTitle)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentNode);
|
||||
if (!domDocument) {
|
||||
if (!mDocumentNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return domDocument->GetTitle(aTitle);
|
||||
nsString title;
|
||||
mDocumentNode->GetTitle(title);
|
||||
aTitle = title;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocAccessible::GetMimeType(nsAString& aMimeType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentNode);
|
||||
if (!domDocument) {
|
||||
if (!mDocumentNode) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return domDocument->GetContentType(aMimeType);
|
||||
return mDocumentNode->GetContentType(aMimeType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocAccessible::GetDocType(nsAString& aDocType)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(mDocumentNode));
|
||||
nsCOMPtr<nsIDOMDocumentType> docType;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
|
||||
if (xulDoc) {
|
||||
@ -382,8 +380,11 @@ DocAccessible::GetDocType(nsAString& aDocType)
|
||||
return NS_OK;
|
||||
} else
|
||||
#endif
|
||||
if (domDoc && NS_SUCCEEDED(domDoc->GetDoctype(getter_AddRefs(docType))) && docType) {
|
||||
return docType->GetPublicId(aDocType);
|
||||
if (mDocumentNode) {
|
||||
dom::DocumentType* docType = mDocumentNode->GetDoctype();
|
||||
if (docType) {
|
||||
return docType->GetPublicId(aDocType);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -84,9 +84,7 @@ RootAccessible::Name(nsString& aName)
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(mDocumentNode);
|
||||
NS_ENSURE_TRUE(document, eNameOK);
|
||||
document->GetTitle(aName);
|
||||
mDocumentNode->GetTitle(aName);
|
||||
return eNameOK;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "mozilla/dom/HTMLTableElement.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -334,8 +334,8 @@ this.TouchAdapter = {
|
||||
* of one single touch.
|
||||
*/
|
||||
function TouchPoint(aTouch, aTime, aDPI) {
|
||||
this.startX = this.x = aTouch.screenX * this.scaleFactor;
|
||||
this.startY = this.y = aTouch.screenY * this.scaleFactor;
|
||||
this.startX = this.x = aTouch.screenX;
|
||||
this.startY = this.y = aTouch.screenY;
|
||||
this.startTime = aTime;
|
||||
this.distanceTraveled = 0;
|
||||
this.dpi = aDPI;
|
||||
@ -346,8 +346,8 @@ TouchPoint.prototype = {
|
||||
update: function TouchPoint_update(aTouch, aTime) {
|
||||
let lastX = this.x;
|
||||
let lastY = this.y;
|
||||
this.x = aTouch.screenX * this.scaleFactor;
|
||||
this.y = aTouch.screenY * this.scaleFactor;
|
||||
this.x = aTouch.screenX;
|
||||
this.y = aTouch.screenY;
|
||||
this.time = aTime;
|
||||
|
||||
this.distanceTraveled += this.getDistanceToCoord(lastX, lastY);
|
||||
@ -357,20 +357,6 @@ TouchPoint.prototype = {
|
||||
return Math.sqrt(Math.pow(this.x - aX, 2) + Math.pow(this.y - aY, 2));
|
||||
},
|
||||
|
||||
get scaleFactor() {
|
||||
if (!this._scaleFactor) {
|
||||
// Android events come with the x, y coordinates affected by the widget
|
||||
// scaling; we restore it to normal here.
|
||||
if (Utils.MozBuildApp == 'mobile/android') {
|
||||
this._scaleFactor = Utils.win.devicePixelRatio;
|
||||
} else {
|
||||
this._scaleFactor = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return this._scaleFactor;
|
||||
},
|
||||
|
||||
finish: function TouchPoint_finish() {
|
||||
this.done = true;
|
||||
},
|
||||
|
@ -13,7 +13,6 @@
|
||||
// NOTE: alphabetically ordered
|
||||
#include "nsIAccessibleRelation.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMXULSelectCntrlEl.h"
|
||||
#include "nsIDOMXULSelectCntrlItemEl.h"
|
||||
#include "nsIDOMXULRelatedElement.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="221bcaecbbbc9d185f691471b64aed9e75b0c11d"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "6946a71605af13e0284fb6f5bbe38aa4c05155d7",
|
||||
"revision": "18e2adbabcfa967611077df5a9bff7f855041324",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="221bcaecbbbc9d185f691471b64aed9e75b0c11d"/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e218d17ae7d01a81d48f833cd6fafb4e11b26cd8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4c29941ae4adf800bac335e33e11a30a602c0e4a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -107,14 +107,14 @@ let AboutHomeListener = {
|
||||
}
|
||||
|
||||
doc.documentElement.setAttribute("hasBrowserHandlers", "true");
|
||||
let updateListener = this;
|
||||
addMessageListener("AboutHome:Update", updateListener);
|
||||
let self = this;
|
||||
addMessageListener("AboutHome:Update", self);
|
||||
addEventListener("click", this.onClick, true);
|
||||
addEventListener("pagehide", function onPageHide(event) {
|
||||
if (event.target.defaultView.frameElement)
|
||||
return;
|
||||
removeMessageListener("AboutHome:Update", updateListener);
|
||||
removeEventListener("click", this.onClick, true);
|
||||
removeMessageListener("AboutHome:Update", self);
|
||||
removeEventListener("click", self.onClick, true);
|
||||
removeEventListener("pagehide", onPageHide, true);
|
||||
if (event.target.documentElement)
|
||||
event.target.documentElement.removeAttribute("hasBrowserHandlers");
|
||||
@ -141,6 +141,11 @@ let AboutHomeListener = {
|
||||
|
||||
let originalTarget = aEvent.originalTarget;
|
||||
let ownerDoc = originalTarget.ownerDocument;
|
||||
if (ownerDoc.documentURI != "about:home") {
|
||||
// This shouldn't happen, but we're being defensive.
|
||||
return;
|
||||
}
|
||||
|
||||
let elmId = originalTarget.getAttribute("id");
|
||||
|
||||
switch (elmId) {
|
||||
|
@ -91,6 +91,7 @@ support-files =
|
||||
test_bug462673.html
|
||||
test_bug628179.html
|
||||
test_bug839103.html
|
||||
test_bug959531.html
|
||||
test_wyciwyg_copying.html
|
||||
title_test.svg
|
||||
video.ogg
|
||||
|
@ -329,7 +329,44 @@ let gTests = [
|
||||
Ci.nsISearchEngine.DATA_XML, null, false);
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Make sure that a page can't imitate about:home",
|
||||
setup: function () { },
|
||||
run: function (aSnippetsMap)
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
waitForLoad(() => {
|
||||
let button = browser.contentDocument.getElementById("settings");
|
||||
ok(button, "Found settings button in test page");
|
||||
button.click();
|
||||
|
||||
// It may take a few turns of the event loop before the window
|
||||
// is displayed, so we wait.
|
||||
function check(n) {
|
||||
let win = Services.wm.getMostRecentWindow("Browser:Preferences");
|
||||
ok(!win, "Preferences window not showing");
|
||||
if (win) {
|
||||
win.close();
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
executeSoon(() => check(n-1));
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
check(5);
|
||||
});
|
||||
|
||||
browser.loadURI("https://example.com/browser/browser/base/content/test/general/test_bug959531.html");
|
||||
return deferred.promise;
|
||||
}
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
|
9
browser/base/content/test/general/test_bug959531.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for content page with settings button</title>
|
||||
</head>
|
||||
<body>
|
||||
<button name="settings" id="settings">Settings</button>
|
||||
</body>
|
||||
</html>
|
2
build/.lldbinit.in
Normal file
@ -0,0 +1,2 @@
|
||||
#filter substitution
|
||||
script topsrcdir = "@topsrcdir@"; lldb.debugger.HandleCommand("command source -s true '%s'" % os.path.join(topsrcdir, ".lldbinit"))
|
@ -47,14 +47,18 @@ GDBINIT_FILES := $(topsrcdir)/.gdbinit
|
||||
GDBINIT_DEST = $(FINAL_TARGET)
|
||||
INSTALL_TARGETS += GDBINIT
|
||||
|
||||
# Put a useful .lldbinit in the bin directory, to be picked up automatically
|
||||
# by LLDB when we debug executables using that directory as the current working
|
||||
# directory.
|
||||
# NOTE: Keep .lldbinit in the topsrcdir for people who run LLDB from the
|
||||
# topsrcdir rather than the bin directory.
|
||||
LLDBINIT_FILES := $(topsrcdir)/.lldbinit
|
||||
LLDBINIT_DEST = $(FINAL_TARGET)
|
||||
INSTALL_TARGETS += LLDBINIT
|
||||
# Put a .lldbinit in the bin directory and the objdir, to be picked up
|
||||
# automatically by LLDB when we debug executables using either of those two
|
||||
# directories as the current working directory. The .lldbinit file will
|
||||
# load $(topsrcdir)/.lldbinit, which is where the actual debugging commands are.
|
||||
LLDBINIT_OBJDIR := .lldbinit.in
|
||||
LLDBINIT_OBJDIR_PATH = $(DEPTH)
|
||||
LLDBINIT_OBJDIR_FLAGS += -Dtopsrcdir=$(abspath $(topsrcdir))
|
||||
PP_TARGETS += LLDBINIT_OBJDIR
|
||||
|
||||
LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit
|
||||
LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET)
|
||||
INSTALL_TARGETS += LLDBINIT_FINAL_TARGET
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -17,6 +17,7 @@ EXPORTS += [
|
||||
'nsCrossSiteListenerProxy.h',
|
||||
'nsDOMAttributeMap.h',
|
||||
'nsFrameMessageManager.h',
|
||||
'nsGenericDOMDataNode.h',
|
||||
'nsGkAtomList.h',
|
||||
'nsGkAtoms.h',
|
||||
'nsImageLoadingContent.h',
|
||||
@ -31,6 +32,7 @@ EXPORTS += [
|
||||
'nsStubMutationObserver.h',
|
||||
'nsStyledElement.h',
|
||||
'nsTextFragment.h',
|
||||
'nsTraversal.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBRTC']:
|
||||
|
@ -41,7 +41,7 @@ SVGMotionSMILAttr::ClearAnimValue()
|
||||
nsresult
|
||||
SVGMotionSMILAttr::SetAnimValue(const nsSMILValue& aValue)
|
||||
{
|
||||
gfx::Matrix matrix = gfx::ToMatrix(SVGMotionSMILType::CreateMatrix(aValue));
|
||||
gfx::Matrix matrix = SVGMotionSMILType::CreateMatrix(aValue);
|
||||
mSVGElement->SetAnimateMotionTransform(&matrix);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -442,12 +442,12 @@ SVGMotionSMILType::Interpolate(const nsSMILValue& aStartVal,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ gfxMatrix
|
||||
/* static */ gfx::Matrix
|
||||
SVGMotionSMILType::CreateMatrix(const nsSMILValue& aSMILVal)
|
||||
{
|
||||
const MotionSegmentArray& arr = ExtractMotionSegmentArray(aSMILVal);
|
||||
|
||||
gfxMatrix matrix;
|
||||
gfx::Matrix matrix;
|
||||
uint32_t length = arr.Length();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
gfxPoint point; // initialized below
|
||||
@ -464,8 +464,8 @@ SVGMotionSMILType::CreateMatrix(const nsSMILValue& aSMILVal)
|
||||
arr[i].mRotateType,
|
||||
rotateAngle, point);
|
||||
}
|
||||
matrix.Translate(point);
|
||||
matrix.Rotate(rotateAngle);
|
||||
matrix.Translate(point.x, point.y);
|
||||
matrix = gfx::Matrix::Rotation(rotateAngle) * matrix;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
@ -10,13 +10,16 @@
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "nsISMILType.h"
|
||||
|
||||
class nsSMILValue;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
struct Matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* MotionRotateType: Enum to indicate the type of our "rotate" attribute.
|
||||
*/
|
||||
@ -63,7 +66,7 @@ protected:
|
||||
nsSMILValue& aResult) const MOZ_OVERRIDE;
|
||||
public:
|
||||
// Used to generate a transform matrix from an <animateMotion> nsSMILValue.
|
||||
static gfxMatrix CreateMatrix(const nsSMILValue& aSMILVal);
|
||||
static gfx::Matrix CreateMatrix(const nsSMILValue& aSMILVal);
|
||||
|
||||
// Used to generate a nsSMILValue for the point at the given distance along
|
||||
// the given path.
|
||||
|
@ -544,8 +544,7 @@ const ContentPanning = {
|
||||
rect.y = cssTapY - (rect.h / 2);
|
||||
}
|
||||
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
|
||||
Services.obs.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
|
||||
}
|
||||
},
|
||||
|
||||
@ -569,8 +568,7 @@ const ContentPanning = {
|
||||
|
||||
_zoomOut: function() {
|
||||
let rect = new Rect(0, 0, 0, 0);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
|
||||
Services.obs.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
|
||||
},
|
||||
|
||||
_isRectZoomedIn: function(aRect, aViewport) {
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
|
||||
struct gfxMatrix;
|
||||
class nsICachedFileDescriptorListener;
|
||||
class nsIDOMWindowUtils;
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "Units.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
struct gfxMatrix;
|
||||
class nsFrameLoader;
|
||||
class nsIContent;
|
||||
class nsIPrincipal;
|
||||
|
@ -238,10 +238,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
|
||||
]
|
||||
# left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually.
|
||||
SOURCES += [
|
||||
'src/ports/SkFontHost_android_old.cpp',
|
||||
'src/ports/SkFontHost_cairo.cpp',
|
||||
'src/ports/SkFontHost_FreeType.cpp',
|
||||
'src/ports/SkFontHost_FreeType_common.cpp',
|
||||
'src/ports/SkFontHost_linux.cpp',
|
||||
]
|
||||
DEFINES['SK_FONTHOST_CAIRO_STANDALONE'] = 0
|
||||
else:
|
||||
|
604
gfx/skia/src/ports/SkFontHost_android_old.cpp
Normal file
@ -0,0 +1,604 @@
|
||||
|
||||
/*
|
||||
* Copyright 2006 The Android Open Source Project
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "SkFontDescriptor.h"
|
||||
#include "SkFontHost.h"
|
||||
#include "SkFontHost_FreeType_common.h"
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkString.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkThread.h"
|
||||
#include "SkTSearch.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
|
||||
|
||||
#ifndef SK_FONT_FILE_PREFIX
|
||||
#define SK_FONT_FILE_PREFIX "/fonts/"
|
||||
#endif
|
||||
|
||||
bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style,
|
||||
bool* isFixedWidth);
|
||||
|
||||
static void GetFullPathForSysFonts(SkString* full, const char name[]) {
|
||||
full->set(getenv("ANDROID_ROOT"));
|
||||
full->append(SK_FONT_FILE_PREFIX);
|
||||
full->append(name);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct FamilyRec;
|
||||
|
||||
/* This guy holds a mapping of a name -> family, used for looking up fonts.
|
||||
Since it is stored in a stretchy array that doesn't preserve object
|
||||
semantics, we don't use constructor/destructors, but just have explicit
|
||||
helpers to manage our internal bookkeeping.
|
||||
*/
|
||||
struct NameFamilyPair {
|
||||
const char* fName; // we own this
|
||||
FamilyRec* fFamily; // we don't own this, we just reference it
|
||||
|
||||
void construct(const char name[], FamilyRec* family) {
|
||||
fName = strdup(name);
|
||||
fFamily = family; // we don't own this, so just record the referene
|
||||
}
|
||||
|
||||
void destruct() {
|
||||
free((char*)fName);
|
||||
// we don't own family, so just ignore our reference
|
||||
}
|
||||
};
|
||||
|
||||
// we use atomic_inc to grow this for each typeface we create
|
||||
static int32_t gUniqueFontID;
|
||||
|
||||
// this is the mutex that protects these globals
|
||||
static SkMutex gFamilyMutex;
|
||||
static FamilyRec* gFamilyHead;
|
||||
static SkTDArray<NameFamilyPair> gNameList;
|
||||
|
||||
struct FamilyRec {
|
||||
FamilyRec* fNext;
|
||||
SkTypeface* fFaces[4];
|
||||
|
||||
FamilyRec()
|
||||
{
|
||||
fNext = gFamilyHead;
|
||||
memset(fFaces, 0, sizeof(fFaces));
|
||||
gFamilyHead = this;
|
||||
}
|
||||
};
|
||||
|
||||
static SkTypeface* find_best_face(const FamilyRec* family,
|
||||
SkTypeface::Style style) {
|
||||
SkTypeface* const* faces = family->fFaces;
|
||||
|
||||
if (faces[style] != NULL) { // exact match
|
||||
return faces[style];
|
||||
}
|
||||
// look for a matching bold
|
||||
style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
|
||||
if (faces[style] != NULL) {
|
||||
return faces[style];
|
||||
}
|
||||
// look for the plain
|
||||
if (faces[SkTypeface::kNormal] != NULL) {
|
||||
return faces[SkTypeface::kNormal];
|
||||
}
|
||||
// look for anything
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (faces[i] != NULL) {
|
||||
return faces[i];
|
||||
}
|
||||
}
|
||||
// should never get here, since the faces list should not be empty
|
||||
SkASSERT(!"faces list is empty");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static FamilyRec* find_family(const SkTypeface* member) {
|
||||
FamilyRec* curr = gFamilyHead;
|
||||
while (curr != NULL) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (curr->fFaces[i] == member) {
|
||||
return curr;
|
||||
}
|
||||
}
|
||||
curr = curr->fNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt
|
||||
is not modified.
|
||||
*/
|
||||
static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
|
||||
FamilyRec* curr = gFamilyHead;
|
||||
while (curr != NULL) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
SkTypeface* face = curr->fFaces[i];
|
||||
if (face != NULL && face->uniqueID() == uniqueID) {
|
||||
return face;
|
||||
}
|
||||
}
|
||||
curr = curr->fNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove reference to this face from its family. If the resulting family
|
||||
is empty (has no faces), return that family, otherwise return NULL
|
||||
*/
|
||||
static FamilyRec* remove_from_family(const SkTypeface* face) {
|
||||
FamilyRec* family = find_family(face);
|
||||
SkASSERT(family->fFaces[face->style()] == face);
|
||||
family->fFaces[face->style()] = NULL;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (family->fFaces[i] != NULL) { // family is non-empty
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return family; // return the empty family
|
||||
}
|
||||
|
||||
// maybe we should make FamilyRec be doubly-linked
|
||||
static void detach_and_delete_family(FamilyRec* family) {
|
||||
FamilyRec* curr = gFamilyHead;
|
||||
FamilyRec* prev = NULL;
|
||||
|
||||
while (curr != NULL) {
|
||||
FamilyRec* next = curr->fNext;
|
||||
if (curr == family) {
|
||||
if (prev == NULL) {
|
||||
gFamilyHead = next;
|
||||
} else {
|
||||
prev->fNext = next;
|
||||
}
|
||||
SkDELETE(family);
|
||||
return;
|
||||
}
|
||||
prev = curr;
|
||||
curr = next;
|
||||
}
|
||||
SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
|
||||
}
|
||||
|
||||
static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
|
||||
NameFamilyPair* list = gNameList.begin();
|
||||
int count = gNameList.count();
|
||||
|
||||
int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
|
||||
|
||||
if (index >= 0) {
|
||||
return find_best_face(list[index].fFamily, style);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SkTypeface* find_typeface(const SkTypeface* familyMember,
|
||||
SkTypeface::Style style) {
|
||||
const FamilyRec* family = find_family(familyMember);
|
||||
return family ? find_best_face(family, style) : NULL;
|
||||
}
|
||||
|
||||
static void add_name(const char name[], FamilyRec* family) {
|
||||
SkAutoAsciiToLC tolc(name);
|
||||
name = tolc.lc();
|
||||
|
||||
NameFamilyPair* list = gNameList.begin();
|
||||
int count = gNameList.count();
|
||||
|
||||
int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
|
||||
|
||||
if (index < 0) {
|
||||
list = gNameList.insert(~index);
|
||||
list->construct(name, family);
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_from_names(FamilyRec* emptyFamily)
|
||||
{
|
||||
#ifdef SK_DEBUG
|
||||
for (int i = 0; i < 4; i++) {
|
||||
SkASSERT(emptyFamily->fFaces[i] == NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
SkTDArray<NameFamilyPair>& list = gNameList;
|
||||
|
||||
// must go backwards when removing
|
||||
for (int i = list.count() - 1; i >= 0; --i) {
|
||||
NameFamilyPair* pair = &list[i];
|
||||
if (pair->fFamily == emptyFamily) {
|
||||
pair->destruct();
|
||||
list.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FamilyTypeface : public SkTypeface_FreeType {
|
||||
public:
|
||||
FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember,
|
||||
bool isFixedWidth)
|
||||
: SkTypeface_FreeType(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
|
||||
fIsSysFont = sysFont;
|
||||
|
||||
SkAutoMutexAcquire ac(gFamilyMutex);
|
||||
|
||||
FamilyRec* rec = NULL;
|
||||
if (familyMember) {
|
||||
rec = find_family(familyMember);
|
||||
SkASSERT(rec);
|
||||
} else {
|
||||
rec = SkNEW(FamilyRec);
|
||||
}
|
||||
rec->fFaces[style] = this;
|
||||
}
|
||||
|
||||
virtual ~FamilyTypeface() {
|
||||
SkAutoMutexAcquire ac(gFamilyMutex);
|
||||
|
||||
// remove us from our family. If the family is now empty, we return
|
||||
// that and then remove that family from the name list
|
||||
FamilyRec* family = remove_from_family(this);
|
||||
if (NULL != family) {
|
||||
remove_from_names(family);
|
||||
detach_and_delete_family(family);
|
||||
}
|
||||
}
|
||||
|
||||
bool isSysFont() const { return fIsSysFont; }
|
||||
|
||||
virtual const char* getUniqueString() const = 0;
|
||||
virtual const char* getFilePath() const = 0;
|
||||
|
||||
protected:
|
||||
virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool fIsSysFont;
|
||||
|
||||
typedef SkTypeface INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class StreamTypeface : public FamilyTypeface {
|
||||
public:
|
||||
StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
|
||||
SkStream* stream, bool isFixedWidth)
|
||||
: INHERITED(style, sysFont, familyMember, isFixedWidth) {
|
||||
SkASSERT(stream);
|
||||
stream->ref();
|
||||
fStream = stream;
|
||||
}
|
||||
virtual ~StreamTypeface() {
|
||||
fStream->unref();
|
||||
}
|
||||
|
||||
// overrides
|
||||
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
|
||||
*ttcIndex = 0;
|
||||
// we just ref our existing stream, since the caller will call unref()
|
||||
// when they are through
|
||||
fStream->ref();
|
||||
// must rewind each time, since the caller assumes a "new" stream
|
||||
fStream->rewind();
|
||||
return fStream;
|
||||
}
|
||||
virtual const char* getUniqueString() const { return NULL; }
|
||||
virtual const char* getFilePath() const { return NULL; }
|
||||
|
||||
private:
|
||||
SkStream* fStream;
|
||||
|
||||
typedef FamilyTypeface INHERITED;
|
||||
};
|
||||
|
||||
class FileTypeface : public FamilyTypeface {
|
||||
public:
|
||||
FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
|
||||
const char path[], bool isFixedWidth)
|
||||
: INHERITED(style, sysFont, familyMember, isFixedWidth) {
|
||||
SkString fullpath;
|
||||
|
||||
if (sysFont) {
|
||||
GetFullPathForSysFonts(&fullpath, path);
|
||||
path = fullpath.c_str();
|
||||
}
|
||||
fPath.set(path);
|
||||
}
|
||||
|
||||
// overrides
|
||||
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
|
||||
*ttcIndex = 0;
|
||||
SkStream* stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
|
||||
|
||||
// check for failure
|
||||
if (stream->getLength() <= 0) {
|
||||
SkDELETE(stream);
|
||||
stream = NULL;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
virtual const char* getUniqueString() const {
|
||||
const char* str = strrchr(fPath.c_str(), '/');
|
||||
if (str) {
|
||||
str += 1; // skip the '/'
|
||||
}
|
||||
return str;
|
||||
}
|
||||
virtual const char* getFilePath() const {
|
||||
return fPath.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
SkString fPath;
|
||||
|
||||
typedef FamilyTypeface INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool get_name_and_style(const char path[], SkString* name,
|
||||
SkTypeface::Style* style,
|
||||
bool* isFixedWidth, bool isExpected) {
|
||||
SkString fullpath;
|
||||
GetFullPathForSysFonts(&fullpath, path);
|
||||
|
||||
SkFILEStream stream(fullpath.c_str());
|
||||
if (stream.getLength() > 0) {
|
||||
find_name_and_attributes(&stream, name, style, isFixedWidth);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
SkFILEStream stream(fullpath.c_str());
|
||||
if (stream.getLength() > 0) {
|
||||
find_name_and_attributes(&stream, name, style, isFixedWidth);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isExpected) {
|
||||
SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// used to record our notion of the pre-existing fonts
|
||||
struct FontInitRec {
|
||||
const char* fFileName;
|
||||
const char* const* fNames; // null-terminated list
|
||||
};
|
||||
|
||||
static const char* gSansNames[] = {
|
||||
"sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
|
||||
};
|
||||
|
||||
static const char* gSerifNames[] = {
|
||||
"serif", "times", "times new roman", "palatino", "georgia", "baskerville",
|
||||
"goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
|
||||
};
|
||||
|
||||
static const char* gMonoNames[] = {
|
||||
"monospace", "courier", "courier new", "monaco", NULL
|
||||
};
|
||||
|
||||
// deliberately empty, but we use the address to identify fallback fonts
|
||||
static const char* gFBNames[] = { NULL };
|
||||
|
||||
/* Fonts must be grouped by family, with the first font in a family having the
|
||||
list of names (even if that list is empty), and the following members having
|
||||
null for the list. The names list must be NULL-terminated
|
||||
*/
|
||||
static const FontInitRec gSystemFonts[] = {
|
||||
{ "DroidSans.ttf", gSansNames },
|
||||
{ "DroidSans-Bold.ttf", NULL },
|
||||
{ "DroidSerif-Regular.ttf", gSerifNames },
|
||||
{ "DroidSerif-Bold.ttf", NULL },
|
||||
{ "DroidSerif-Italic.ttf", NULL },
|
||||
{ "DroidSerif-BoldItalic.ttf", NULL },
|
||||
{ "DroidSansMono.ttf", gMonoNames },
|
||||
/* These are optional, and can be ignored if not found in the file system.
|
||||
These are appended to gFallbackFonts[] as they are seen, so we list
|
||||
them in the order we want them to be accessed by NextLogicalFont().
|
||||
*/
|
||||
{ "DroidSansArabic.ttf", gFBNames },
|
||||
{ "DroidSansHebrew.ttf", gFBNames },
|
||||
{ "DroidSansThai.ttf", gFBNames },
|
||||
{ "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font
|
||||
{ "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font
|
||||
{ "DroidSansJapanese.ttf", gFBNames },
|
||||
{ "DroidSansFallback.ttf", gFBNames }
|
||||
};
|
||||
|
||||
#define DEFAULT_NAMES gSansNames
|
||||
|
||||
// these globals are assigned (once) by load_system_fonts()
|
||||
static FamilyRec* gDefaultFamily;
|
||||
static SkTypeface* gDefaultNormal;
|
||||
|
||||
/* This is sized conservatively, assuming that it will never be a size issue.
|
||||
It will be initialized in load_system_fonts(), and will be filled with the
|
||||
fontIDs that can be used for fallback consideration, in sorted order (sorted
|
||||
meaning element[0] should be used first, then element[1], etc. When we hit
|
||||
a fontID==0 in the array, the list is done, hence our allocation size is
|
||||
+1 the total number of possible system fonts. Also see NextLogicalFont().
|
||||
*/
|
||||
static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
|
||||
|
||||
/* Called once (ensured by the sentinel check at the beginning of our body).
|
||||
Initializes all the globals, and register the system fonts.
|
||||
*/
|
||||
static void load_system_fonts() {
|
||||
// check if we've already be called
|
||||
if (NULL != gDefaultNormal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FontInitRec* rec = gSystemFonts;
|
||||
SkTypeface* firstInFamily = NULL;
|
||||
int fallbackCount = 0;
|
||||
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
|
||||
// if we're the first in a new family, clear firstInFamily
|
||||
if (rec[i].fNames != NULL) {
|
||||
firstInFamily = NULL;
|
||||
}
|
||||
|
||||
bool isFixedWidth;
|
||||
SkString name;
|
||||
SkTypeface::Style style;
|
||||
|
||||
// we expect all the fonts, except the "fallback" fonts
|
||||
bool isExpected = (rec[i].fNames != gFBNames);
|
||||
if (!get_name_and_style(rec[i].fFileName, &name, &style,
|
||||
&isFixedWidth, isExpected)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SkTypeface* tf = SkNEW_ARGS(FileTypeface,
|
||||
(style,
|
||||
true, // system-font (cannot delete)
|
||||
firstInFamily, // what family to join
|
||||
rec[i].fFileName,
|
||||
isFixedWidth) // filename
|
||||
);
|
||||
|
||||
if (rec[i].fNames != NULL) {
|
||||
// see if this is one of our fallback fonts
|
||||
if (rec[i].fNames == gFBNames) {
|
||||
// SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
|
||||
// rec[i].fFileName, fallbackCount, tf->uniqueID());
|
||||
gFallbackFonts[fallbackCount++] = tf->uniqueID();
|
||||
}
|
||||
|
||||
firstInFamily = tf;
|
||||
FamilyRec* family = find_family(tf);
|
||||
const char* const* names = rec[i].fNames;
|
||||
|
||||
// record the default family if this is it
|
||||
if (names == DEFAULT_NAMES) {
|
||||
gDefaultFamily = family;
|
||||
}
|
||||
// add the names to map to this family
|
||||
while (*names) {
|
||||
add_name(*names, family);
|
||||
names += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do this after all fonts are loaded. This is our default font, and it
|
||||
// acts as a sentinel so we only execute load_system_fonts() once
|
||||
gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
|
||||
// now terminate our fallback list with the sentinel value
|
||||
gFallbackFonts[fallbackCount] = 0;
|
||||
}
|
||||
|
||||
void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
|
||||
bool* isLocalStream) const {
|
||||
{
|
||||
SkAutoMutexAcquire ac(gFamilyMutex);
|
||||
//desc->setFamilyName(find_family_name(this));
|
||||
desc->setFontFileName(this->getUniqueString());
|
||||
}
|
||||
*isLocalStream = !this->isSysFont();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
||||
const char familyName[],
|
||||
SkTypeface::Style style) {
|
||||
load_system_fonts();
|
||||
|
||||
SkAutoMutexAcquire ac(gFamilyMutex);
|
||||
|
||||
// clip to legal style bits
|
||||
style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
|
||||
|
||||
SkTypeface* tf = NULL;
|
||||
|
||||
if (NULL != familyFace) {
|
||||
tf = find_typeface(familyFace, style);
|
||||
} else if (NULL != familyName) {
|
||||
// SkDebugf("======= familyName <%s>\n", familyName);
|
||||
tf = find_typeface(familyName, style);
|
||||
}
|
||||
|
||||
if (NULL == tf) {
|
||||
tf = find_best_face(gDefaultFamily, style);
|
||||
}
|
||||
|
||||
// we ref(), since the symantic is to return a new instance
|
||||
tf->ref();
|
||||
return tf;
|
||||
}
|
||||
|
||||
SkTypeface* SkAndroidNextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
|
||||
load_system_fonts();
|
||||
|
||||
/* First see if fontID is already one of our fallbacks. If so, return
|
||||
its successor. If fontID is not in our list, then return the first one
|
||||
in our list. Note: list is zero-terminated, and returning zero means
|
||||
we have no more fonts to use for fallbacks.
|
||||
*/
|
||||
const uint32_t* list = gFallbackFonts;
|
||||
for (int i = 0; list[i] != 0; i++) {
|
||||
if (list[i] == currFontID) {
|
||||
return find_from_uniqueID(list[i+1]);
|
||||
}
|
||||
}
|
||||
return find_from_uniqueID(list[0]);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||
if (NULL == stream || stream->getLength() <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool isFixedWidth;
|
||||
SkString name;
|
||||
SkTypeface::Style style;
|
||||
find_name_and_attributes(stream, &name, &style, &isFixedWidth);
|
||||
|
||||
if (!name.isEmpty()) {
|
||||
return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
||||
SkStream* stream = SkNEW_ARGS(SkFILEStream, (path));
|
||||
SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
|
||||
// since we created the stream, we let go of our ref() here
|
||||
stream->unref();
|
||||
return face;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkFontMgr.h"
|
||||
|
||||
SkFontMgr* SkFontMgr::Factory() {
|
||||
// todo
|
||||
return NULL;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx)
|
||||
|
||||
DrawTarget *dest = aDestinationCtx->GetDrawTarget();
|
||||
if (!dest) {
|
||||
NS_ERROR("Blurring not supported for Thebes contexts!");
|
||||
NS_WARNING("Blurring not supported for Thebes contexts!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxFont.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#define INCL_GPI
|
||||
|
@ -199,31 +199,6 @@ gfxWindowsSurface::GetAsImageSurface()
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxWindowsSurface>
|
||||
gfxWindowsSurface::OptimizeToDDB(HDC dc, const gfxIntSize& size, gfxImageFormat format)
|
||||
{
|
||||
if (mForPrinting)
|
||||
return nullptr;
|
||||
|
||||
if (format != gfxImageFormatRGB24)
|
||||
return nullptr;
|
||||
|
||||
nsRefPtr<gfxWindowsSurface> wsurf = new gfxWindowsSurface(dc, size, format);
|
||||
if (wsurf->CairoStatus() != 0)
|
||||
return nullptr;
|
||||
|
||||
gfxContext tmpCtx(wsurf);
|
||||
tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
tmpCtx.SetSource(this);
|
||||
tmpCtx.Paint();
|
||||
|
||||
// we let the new DDB surfaces be converted back to dibsections if
|
||||
// acquire_source_image is called on them
|
||||
cairo_win32_surface_set_can_convert_to_dib(wsurf->CairoSurface(), TRUE);
|
||||
|
||||
return wsurf.forget().downcast<gfxWindowsSurface>();
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxWindowsSurface::BeginPrinting(const nsAString& aTitle,
|
||||
const nsAString& aPrintToFileName)
|
||||
|
@ -57,10 +57,6 @@ public:
|
||||
|
||||
already_AddRefed<gfxImageSurface> GetAsImageSurface();
|
||||
|
||||
already_AddRefed<gfxWindowsSurface> OptimizeToDDB(HDC dc,
|
||||
const gfxIntSize& size,
|
||||
gfxImageFormat format);
|
||||
|
||||
nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
|
||||
nsresult EndPrinting();
|
||||
nsresult AbortPrinting();
|
||||
|
@ -28,13 +28,6 @@ static bool gDisableOptimize = false;
|
||||
/* Whether to use the windows surface; only for desktop win32 */
|
||||
#define USE_WIN_SURFACE 1
|
||||
|
||||
static uint32_t gTotalDDBs = 0;
|
||||
static uint32_t gTotalDDBSize = 0;
|
||||
// only use up a maximum of 64MB in DDBs
|
||||
#define kMaxDDBSize (64*1024*1024)
|
||||
// and don't let anything in that's bigger than 4MB
|
||||
#define kMaxSingleDDBSize (4*1024*1024)
|
||||
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
@ -113,9 +106,6 @@ imgFrame::imgFrame() :
|
||||
mFormatChanged(false),
|
||||
mCompositingFailed(false),
|
||||
mNonPremult(false),
|
||||
#ifdef USE_WIN_SURFACE
|
||||
mIsDDBSurface(false),
|
||||
#endif
|
||||
mInformedDiscardTracker(false),
|
||||
mDirty(false)
|
||||
{
|
||||
@ -132,12 +122,6 @@ imgFrame::~imgFrame()
|
||||
{
|
||||
moz_free(mPalettedImageData);
|
||||
mPalettedImageData = nullptr;
|
||||
#ifdef USE_WIN_SURFACE
|
||||
if (mIsDDBSurface) {
|
||||
gTotalDDBs--;
|
||||
gTotalDDBSize -= mSize.width * mSize.height * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mInformedDiscardTracker) {
|
||||
DiscardTracker::InformAllocation(-4 * mSize.height * mSize.width);
|
||||
@ -296,40 +280,8 @@ nsresult imgFrame::Optimize()
|
||||
mOptSurface = nullptr;
|
||||
|
||||
#ifdef USE_WIN_SURFACE
|
||||
// we need to special-case windows here, because windows has
|
||||
// a distinction between DIB and DDB and we want to use DDBs as much
|
||||
// as we can.
|
||||
if (mWinSurface) {
|
||||
// Don't do DDBs for large images; see bug 359147
|
||||
// Note that we bother with DDBs at all because they are much faster
|
||||
// on some systems; on others there isn't much of a speed difference
|
||||
// between DIBs and DDBs.
|
||||
//
|
||||
// Originally this just limited to 1024x1024; but that still
|
||||
// had us hitting overall total memory usage limits (which was
|
||||
// around 220MB on my intel shared memory system with 2GB RAM
|
||||
// and 16-128mb in use by the video card, so I can't make
|
||||
// heads or tails out of this limit).
|
||||
//
|
||||
// So instead, we clamp the max size to 64MB (this limit shuld
|
||||
// be made dynamic based on.. something.. as soon a we figure
|
||||
// out that something) and also limit each individual image to
|
||||
// be less than 4MB to keep very large images out of DDBs.
|
||||
|
||||
// assume (almost -- we don't quadword-align) worst-case size
|
||||
uint32_t ddbSize = mSize.width * mSize.height * 4;
|
||||
if (ddbSize <= kMaxSingleDDBSize &&
|
||||
ddbSize + gTotalDDBSize <= kMaxDDBSize)
|
||||
{
|
||||
nsRefPtr<gfxWindowsSurface> wsurf = mWinSurface->OptimizeToDDB(nullptr, gfxIntSize(mSize.width, mSize.height), mFormat);
|
||||
if (wsurf) {
|
||||
gTotalDDBs++;
|
||||
gTotalDDBSize += ddbSize;
|
||||
mIsDDBSurface = true;
|
||||
mOptSurface = wsurf;
|
||||
}
|
||||
}
|
||||
if (!mOptSurface && !mFormatChanged) {
|
||||
if (!mFormatChanged) {
|
||||
// just use the DIB if the format has not changed
|
||||
mOptSurface = mWinSurface;
|
||||
}
|
||||
|
@ -178,9 +178,6 @@ private: // data
|
||||
/** Have we called DiscardTracker::InformAllocation()? */
|
||||
bool mInformedDiscardTracker;
|
||||
|
||||
#ifdef XP_WIN
|
||||
bool mIsDDBSurface;
|
||||
#endif
|
||||
bool mDirty;
|
||||
};
|
||||
|
||||
|
@ -1,26 +0,0 @@
|
||||
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_FILE_VERSION_INFO_LINUX_H_
|
||||
#define BASE_FILE_VERSION_INFO_LINUX_H_
|
||||
|
||||
#define COMPANY_NAME L"@COMPANY_FULLNAME@"
|
||||
#define FILE_DESCRIPTION L"@PRODUCT_FULLNAME@"
|
||||
#define FILE_VERSION L"@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
|
||||
#define LEGAL_COPYRIGHT L"@COPYRIGHT@"
|
||||
#define PRODUCT_NAME L"@PRODUCT_FULLNAME@"
|
||||
#define PRODUCT_VERSION L"@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
|
||||
#define COMPANY_SHORT_NAME L"@COMPANY_SHORTNAME@"
|
||||
#define PRODUCT_SHORT_NAME L"@PRODUCT_SHORTNAME@"
|
||||
#define LAST_CHANGE L"@LASTCHANGE@"
|
||||
#define OFFICIAL_BUILD 1
|
||||
// TODO(mmoss) Do these have values for Linux?
|
||||
#define INTERNAL_NAME L""
|
||||
#define ORIGINAL_FILENAME L""
|
||||
#define PRIVATE_BUILD L""
|
||||
#define SPECIAL_BUILD L""
|
||||
#define COMMENTS L""
|
||||
#define LEGAL_TRADEMARKS L""
|
||||
|
||||
#endif // BASE_FILE_VERSION_INFO_LINUX_H_
|
@ -73,8 +73,6 @@ UNIFIED_SOURCES += [
|
||||
'src/chrome/common/child_process_host.cc',
|
||||
'src/chrome/common/child_process_info.cc',
|
||||
'src/chrome/common/child_thread.cc',
|
||||
'src/chrome/common/chrome_counters.cc',
|
||||
'src/chrome/common/chrome_paths.cc',
|
||||
'src/chrome/common/chrome_switches.cc',
|
||||
'src/chrome/common/debug_flags.cc',
|
||||
'src/chrome/common/env_vars.cc',
|
||||
@ -96,7 +94,6 @@ if os_win:
|
||||
'src/base/debug_util_win.cc',
|
||||
'src/base/event_recorder.cc',
|
||||
'src/base/file_util_win.cc',
|
||||
'src/base/file_version_info.cc',
|
||||
'src/base/idle_timer.cc',
|
||||
'src/base/lock_impl_win.cc',
|
||||
'src/base/message_pump_win.cc',
|
||||
@ -117,8 +114,6 @@ if os_win:
|
||||
'src/base/waitable_event_watcher_win.cc',
|
||||
'src/base/waitable_event_win.cc',
|
||||
'src/base/win_util.cc',
|
||||
'src/chrome/common/chrome_constants.cc',
|
||||
'src/chrome/common/chrome_paths_win.cc',
|
||||
'src/chrome/common/ipc_channel_win.cc',
|
||||
'src/chrome/common/process_watcher_win.cc',
|
||||
'src/chrome/common/transport_dib_win.cc',
|
||||
@ -195,7 +190,6 @@ if os_macosx:
|
||||
'src/base/base_paths_mac.mm',
|
||||
'src/base/chrome_application_mac.mm',
|
||||
'src/base/file_util_mac.mm',
|
||||
'src/base/file_version_info_mac.mm',
|
||||
'src/base/mac_util.mm',
|
||||
'src/base/message_pump_mac.mm',
|
||||
'src/base/platform_thread_mac.mm',
|
||||
@ -203,7 +197,6 @@ if os_macosx:
|
||||
'src/base/scoped_nsautorelease_pool.mm',
|
||||
'src/base/sys_string_conversions_mac.mm',
|
||||
'src/base/worker_pool_mac.mm',
|
||||
'src/chrome/common/chrome_paths_mac.mm',
|
||||
'src/chrome/common/mach_ipc_mac.mm',
|
||||
]
|
||||
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
@ -215,7 +208,6 @@ if os_linux:
|
||||
SOURCES += [
|
||||
'src/base/atomicops_internals_x86_gcc.cc',
|
||||
'src/base/base_paths_linux.cc',
|
||||
'src/base/file_version_info_linux.cc',
|
||||
'src/base/idle_timer_none.cc',
|
||||
'src/base/process_util_linux.cc',
|
||||
'src/base/time_posix.cc',
|
||||
|
@ -1,185 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "base/file_version_info.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/path_service.h"
|
||||
|
||||
// This has to be last.
|
||||
#include <strsafe.h>
|
||||
|
||||
FileVersionInfo::FileVersionInfo(void* data, int language, int code_page)
|
||||
: language_(language), code_page_(code_page) {
|
||||
data_.reset((char*) data);
|
||||
fixed_file_info_ = NULL;
|
||||
UINT size;
|
||||
::VerQueryValue(data_.get(), L"\\", (LPVOID*)&fixed_file_info_, &size);
|
||||
}
|
||||
|
||||
FileVersionInfo::~FileVersionInfo() {
|
||||
DCHECK(data_.get());
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
WORD language;
|
||||
WORD code_page;
|
||||
} LanguageAndCodePage;
|
||||
|
||||
// static
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfoForCurrentModule() {
|
||||
std::wstring app_path;
|
||||
if (!PathService::Get(base::FILE_MODULE, &app_path))
|
||||
return NULL;
|
||||
|
||||
return CreateFileVersionInfo(app_path);
|
||||
}
|
||||
|
||||
// static
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
|
||||
const FilePath& file_path) {
|
||||
DWORD dummy;
|
||||
const wchar_t* path = file_path.value().c_str();
|
||||
DWORD length = ::GetFileVersionInfoSize(path, &dummy);
|
||||
if (length == 0)
|
||||
return NULL;
|
||||
|
||||
void* data = calloc(length, 1);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
if (!::GetFileVersionInfo(path, dummy, length, data)) {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LanguageAndCodePage* translate = NULL;
|
||||
uint32_t page_count;
|
||||
BOOL query_result = VerQueryValue(data, L"\\VarFileInfo\\Translation",
|
||||
(void**) &translate, &page_count);
|
||||
|
||||
if (query_result && translate) {
|
||||
return new FileVersionInfo(data, translate->language,
|
||||
translate->code_page);
|
||||
|
||||
} else {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
|
||||
const std::wstring& file_path) {
|
||||
FilePath file_path_fp = FilePath::FromWStringHack(file_path);
|
||||
return CreateFileVersionInfo(file_path_fp);
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::company_name() {
|
||||
return GetStringValue(L"CompanyName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::company_short_name() {
|
||||
return GetStringValue(L"CompanyShortName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::internal_name() {
|
||||
return GetStringValue(L"InternalName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_name() {
|
||||
return GetStringValue(L"ProductName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_short_name() {
|
||||
return GetStringValue(L"ProductShortName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::comments() {
|
||||
return GetStringValue(L"Comments");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::legal_copyright() {
|
||||
return GetStringValue(L"LegalCopyright");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_version() {
|
||||
return GetStringValue(L"ProductVersion");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::file_description() {
|
||||
return GetStringValue(L"FileDescription");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::legal_trademarks() {
|
||||
return GetStringValue(L"LegalTrademarks");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::private_build() {
|
||||
return GetStringValue(L"PrivateBuild");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::file_version() {
|
||||
return GetStringValue(L"FileVersion");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::original_filename() {
|
||||
return GetStringValue(L"OriginalFilename");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::special_build() {
|
||||
return GetStringValue(L"SpecialBuild");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::last_change() {
|
||||
return GetStringValue(L"LastChange");
|
||||
}
|
||||
|
||||
bool FileVersionInfo::is_official_build() {
|
||||
return (GetStringValue(L"Official Build").compare(L"1") == 0);
|
||||
}
|
||||
|
||||
bool FileVersionInfo::GetValue(const wchar_t* name, std::wstring* value_str) {
|
||||
|
||||
WORD lang_codepage[8];
|
||||
int i = 0;
|
||||
// Use the language and codepage from the DLL.
|
||||
lang_codepage[i++] = language_;
|
||||
lang_codepage[i++] = code_page_;
|
||||
// Use the default language and codepage from the DLL.
|
||||
lang_codepage[i++] = ::GetUserDefaultLangID();
|
||||
lang_codepage[i++] = code_page_;
|
||||
// Use the language from the DLL and Latin codepage (most common).
|
||||
lang_codepage[i++] = language_;
|
||||
lang_codepage[i++] = 1252;
|
||||
// Use the default language and Latin codepage (most common).
|
||||
lang_codepage[i++] = ::GetUserDefaultLangID();
|
||||
lang_codepage[i++] = 1252;
|
||||
|
||||
i = 0;
|
||||
while (i < arraysize(lang_codepage)) {
|
||||
wchar_t sub_block[MAX_PATH];
|
||||
WORD language = lang_codepage[i++];
|
||||
WORD code_page = lang_codepage[i++];
|
||||
_snwprintf_s(sub_block, MAX_PATH, MAX_PATH,
|
||||
L"\\StringFileInfo\\%04x%04x\\%ls", language, code_page, name);
|
||||
LPVOID value = NULL;
|
||||
uint32_t size;
|
||||
BOOL r = ::VerQueryValue(data_.get(), sub_block, &value, &size);
|
||||
if (r && value) {
|
||||
value_str->assign(static_cast<wchar_t*>(value));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::GetStringValue(const wchar_t* name) {
|
||||
std::wstring str;
|
||||
if (GetValue(name, &str))
|
||||
return str;
|
||||
else
|
||||
return L"";
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_FILE_VERSION_INFO_H__
|
||||
#define BASE_FILE_VERSION_INFO_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/file_path.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
struct tagVS_FIXEDFILEINFO;
|
||||
typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO;
|
||||
#elif defined(OS_MACOSX)
|
||||
#ifdef __OBJC__
|
||||
@class NSBundle;
|
||||
#else
|
||||
class NSBundle;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Provides a way to access the version information for a file.
|
||||
// This is the information you access when you select a file in the Windows
|
||||
// explorer, right-click select Properties, then click the Version tab.
|
||||
|
||||
class FileVersionInfo {
|
||||
public:
|
||||
// Creates a FileVersionInfo for the specified path. Returns NULL if something
|
||||
// goes wrong (typically the file does not exit or cannot be opened). The
|
||||
// returned object should be deleted when you are done with it.
|
||||
static FileVersionInfo* CreateFileVersionInfo(const FilePath& file_path);
|
||||
// This version, taking a wstring, is deprecated and only kept around
|
||||
// until we can fix all callers.
|
||||
static FileVersionInfo* CreateFileVersionInfo(const std::wstring& file_path);
|
||||
|
||||
// Creates a FileVersionInfo for the current module. Returns NULL in case
|
||||
// of error. The returned object should be deleted when you are done with it.
|
||||
static FileVersionInfo* CreateFileVersionInfoForCurrentModule();
|
||||
|
||||
~FileVersionInfo();
|
||||
|
||||
// Accessors to the different version properties.
|
||||
// Returns an empty string if the property is not found.
|
||||
std::wstring company_name();
|
||||
std::wstring company_short_name();
|
||||
std::wstring product_name();
|
||||
std::wstring product_short_name();
|
||||
std::wstring internal_name();
|
||||
std::wstring product_version();
|
||||
std::wstring private_build();
|
||||
std::wstring special_build();
|
||||
std::wstring comments();
|
||||
std::wstring original_filename();
|
||||
std::wstring file_description();
|
||||
std::wstring file_version();
|
||||
std::wstring legal_copyright();
|
||||
std::wstring legal_trademarks();
|
||||
std::wstring last_change();
|
||||
bool is_official_build();
|
||||
|
||||
// Lets you access other properties not covered above.
|
||||
bool GetValue(const wchar_t* name, std::wstring* value);
|
||||
|
||||
// Similar to GetValue but returns a wstring (empty string if the property
|
||||
// does not exist).
|
||||
std::wstring GetStringValue(const wchar_t* name);
|
||||
|
||||
#ifdef OS_WIN
|
||||
// Get the fixed file info if it exists. Otherwise NULL
|
||||
VS_FIXEDFILEINFO* fixed_file_info() { return fixed_file_info_; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_WIN)
|
||||
FileVersionInfo(void* data, int language, int code_page);
|
||||
|
||||
scoped_ptr_malloc<char> data_;
|
||||
int language_;
|
||||
int code_page_;
|
||||
// This is a pointer into the data_ if it exists. Otherwise NULL.
|
||||
VS_FIXEDFILEINFO* fixed_file_info_;
|
||||
#elif defined(OS_MACOSX)
|
||||
explicit FileVersionInfo(NSBundle *bundle);
|
||||
|
||||
NSBundle *bundle_;
|
||||
#elif defined(OS_LINUX)
|
||||
FileVersionInfo();
|
||||
#endif
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(FileVersionInfo);
|
||||
};
|
||||
|
||||
#endif // BASE_FILE_VERSION_INFO_H__
|
@ -1,86 +0,0 @@
|
||||
// Copyright (c) 2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/file_version_info.h"
|
||||
#include "base/file_version_info_linux.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
// TODO(mmoss) This only provides version info for the current binary, but it's
|
||||
// also called for arbitrary files (e.g. plugins).
|
||||
// See http://code.google.com/p/chromium/issues/detail?id=8132 for a discussion
|
||||
// on what we should do with this module.
|
||||
|
||||
FileVersionInfo::FileVersionInfo() {}
|
||||
|
||||
FileVersionInfo::~FileVersionInfo() {}
|
||||
|
||||
// static
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfoForCurrentModule() {
|
||||
return new FileVersionInfo();
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::company_name() {
|
||||
return COMPANY_NAME;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::company_short_name() {
|
||||
return COMPANY_SHORT_NAME;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_name() {
|
||||
return PRODUCT_NAME;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_short_name() {
|
||||
return PRODUCT_SHORT_NAME;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::internal_name() {
|
||||
return INTERNAL_NAME;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_version() {
|
||||
return PRODUCT_VERSION;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::private_build() {
|
||||
return PRIVATE_BUILD;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::special_build() {
|
||||
return SPECIAL_BUILD;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::comments() {
|
||||
return COMMENTS;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::original_filename() {
|
||||
return ORIGINAL_FILENAME;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::file_description() {
|
||||
return FILE_DESCRIPTION;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::file_version() {
|
||||
return FILE_VERSION;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::legal_copyright() {
|
||||
return LEGAL_COPYRIGHT;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::legal_trademarks() {
|
||||
return LEGAL_TRADEMARKS;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::last_change() {
|
||||
return LAST_CHANGE;
|
||||
}
|
||||
|
||||
bool FileVersionInfo::is_official_build() {
|
||||
return OFFICIAL_BUILD;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_FILE_VERSION_INFO_LINUX_H_
|
||||
#define BASE_FILE_VERSION_INFO_LINUX_H_
|
||||
|
||||
#define COMPANY_NAME L"@COMPANY_FULLNAME@"
|
||||
#define FILE_DESCRIPTION L"@PRODUCT_FULLNAME@"
|
||||
#define FILE_VERSION L"@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
|
||||
#define LEGAL_COPYRIGHT L"@COPYRIGHT@"
|
||||
#define PRODUCT_NAME L"@PRODUCT_FULLNAME@"
|
||||
#define PRODUCT_VERSION L"@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
|
||||
#define COMPANY_SHORT_NAME L"@COMPANY_SHORTNAME@"
|
||||
#define PRODUCT_SHORT_NAME L"@PRODUCT_SHORTNAME@"
|
||||
#define LAST_CHANGE L"@LASTCHANGE@"
|
||||
#define OFFICIAL_BUILD @OFFICIAL_BUILD@
|
||||
// TODO(mmoss) Do these have values for Linux?
|
||||
#define INTERNAL_NAME L""
|
||||
#define ORIGINAL_FILENAME L""
|
||||
#define PRIVATE_BUILD L""
|
||||
#define SPECIAL_BUILD L""
|
||||
#define COMMENTS L""
|
||||
#define LEGAL_TRADEMARKS L""
|
||||
|
||||
#endif // BASE_FILE_VERSION_INFO_LINUX_H_
|
@ -1,131 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/file_version_info.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/string_util.h"
|
||||
|
||||
FileVersionInfo::FileVersionInfo(NSBundle *bundle) : bundle_(bundle) {
|
||||
[bundle_ retain];
|
||||
}
|
||||
|
||||
FileVersionInfo::~FileVersionInfo() {
|
||||
[bundle_ release];
|
||||
}
|
||||
|
||||
// static
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfoForCurrentModule() {
|
||||
// TODO(erikkay): this should really use bundleForClass, but we don't have
|
||||
// a class to hang onto yet.
|
||||
NSBundle* bundle = [NSBundle mainBundle];
|
||||
return new FileVersionInfo(bundle);
|
||||
}
|
||||
|
||||
// static
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
|
||||
const std::wstring& file_path) {
|
||||
NSString* path = [NSString stringWithCString:
|
||||
reinterpret_cast<const char*>(file_path.c_str())
|
||||
encoding:NSUTF32StringEncoding];
|
||||
return new FileVersionInfo([NSBundle bundleWithPath:path]);
|
||||
}
|
||||
|
||||
// static
|
||||
FileVersionInfo* FileVersionInfo::CreateFileVersionInfo(
|
||||
const FilePath& file_path) {
|
||||
NSString* path = [NSString stringWithUTF8String:file_path.value().c_str()];
|
||||
return new FileVersionInfo([NSBundle bundleWithPath:path]);
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::company_name() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::company_short_name() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::internal_name() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_name() {
|
||||
return GetStringValue(L"CFBundleName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_short_name() {
|
||||
return GetStringValue(L"CFBundleName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::comments() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::legal_copyright() {
|
||||
return GetStringValue(L"CFBundleGetInfoString");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::product_version() {
|
||||
return GetStringValue(L"CFBundleShortVersionString");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::file_description() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::legal_trademarks() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::private_build() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::file_version() {
|
||||
// CFBundleVersion has limitations that may not be honored by a
|
||||
// proper Chromium version number, so try KSVersion first.
|
||||
std::wstring version = GetStringValue(L"KSVersion");
|
||||
if (version == L"")
|
||||
version = GetStringValue(L"CFBundleVersion");
|
||||
return version;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::original_filename() {
|
||||
return GetStringValue(L"CFBundleName");
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::special_build() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::last_change() {
|
||||
return L"";
|
||||
}
|
||||
|
||||
bool FileVersionInfo::is_official_build() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileVersionInfo::GetValue(const wchar_t* name, std::wstring* value_str) {
|
||||
if (bundle_) {
|
||||
NSString* value = [bundle_ objectForInfoDictionaryKey:
|
||||
[NSString stringWithUTF8String:WideToUTF8(name).c_str()]];
|
||||
if (value) {
|
||||
*value_str = reinterpret_cast<const wchar_t*>(
|
||||
[value cStringUsingEncoding:NSUTF32StringEncoding]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring FileVersionInfo::GetStringValue(const wchar_t* name) {
|
||||
std::wstring str;
|
||||
if (GetValue(name, &str))
|
||||
return str;
|
||||
return L"";
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/common/chrome_constants.h"
|
||||
|
||||
#include "base/file_path.h"
|
||||
|
||||
#define FPL FILE_PATH_LITERAL
|
||||
|
||||
namespace chrome {
|
||||
|
||||
// The following should not be used for UI strings; they are meant
|
||||
// for system strings only. UI changes should be made in the GRD.
|
||||
#if defined(OS_WIN)
|
||||
const wchar_t kBrowserProcessExecutableName[] = L"chrome.exe";
|
||||
#elif defined(OS_LINUX)
|
||||
const wchar_t kBrowserProcessExecutableName[] = L"chrome";
|
||||
#elif defined(OS_MACOSX)
|
||||
const wchar_t kBrowserProcessExecutableName[] =
|
||||
#if defined(GOOGLE_CHROME_BUILD)
|
||||
L"Chrome";
|
||||
#else
|
||||
L"Chromium";
|
||||
#endif // GOOGLE_CHROME_BUILD
|
||||
#endif // OS_*
|
||||
#if defined(OS_WIN)
|
||||
const wchar_t kBrowserProcessExecutablePath[] = L"chrome.exe";
|
||||
#elif defined(OS_LINUX)
|
||||
const wchar_t kBrowserProcessExecutablePath[] = L"chrome";
|
||||
#elif defined(OS_MACOSX)
|
||||
const wchar_t kBrowserProcessExecutablePath[] =
|
||||
#if defined(GOOGLE_CHROME_BUILD)
|
||||
L"Chrome.app/Contents/MacOS/Chrome";
|
||||
#else
|
||||
L"Chromium.app/Contents/MacOS/Chromium";
|
||||
#endif // GOOGLE_CHROME_BUILD
|
||||
#endif // OS_*
|
||||
#if defined(GOOGLE_CHROME_BUILD)
|
||||
const wchar_t kBrowserAppName[] = L"Chrome";
|
||||
const char kStatsFilename[] = "ChromeStats2";
|
||||
#else
|
||||
const wchar_t kBrowserAppName[] = L"Chromium";
|
||||
const char kStatsFilename[] = "ChromiumStats2";
|
||||
#endif
|
||||
const wchar_t kExternalTabWindowClass[] = L"Chrome_ExternalTabContainer";
|
||||
const wchar_t kMessageWindowClass[] = L"Chrome_MessageWindow";
|
||||
const wchar_t kCrashReportLog[] = L"Reported Crashes.txt";
|
||||
const wchar_t kTestingInterfaceDLL[] = L"testing_interface.dll";
|
||||
const wchar_t kNotSignedInProfile[] = L"Default";
|
||||
const wchar_t kNotSignedInID[] = L"not-signed-in";
|
||||
const wchar_t kBrowserResourcesDll[] = L"chrome.dll";
|
||||
const FilePath::CharType kExtensionFileExtension[] = FPL("crx");
|
||||
|
||||
// filenames
|
||||
const FilePath::CharType kArchivedHistoryFilename[] = FPL("Archived History");
|
||||
const FilePath::CharType kCacheDirname[] = FPL("Cache");
|
||||
const FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache");
|
||||
const FilePath::CharType kOffTheRecordMediaCacheDirname[] =
|
||||
FPL("Incognito Media Cache");
|
||||
const wchar_t kChromePluginDataDirname[] = L"Plugin Data";
|
||||
const FilePath::CharType kCookieFilename[] = FPL("Cookies");
|
||||
const FilePath::CharType kHistoryFilename[] = FPL("History");
|
||||
const FilePath::CharType kLocalStateFilename[] = FPL("Local State");
|
||||
const FilePath::CharType kPreferencesFilename[] = FPL("Preferences");
|
||||
const FilePath::CharType kSafeBrowsingFilename[] = FPL("Safe Browsing");
|
||||
// WARNING: SingletonSocket can't contain spaces, because otherwise
|
||||
// chrome_process_util_linux would be broken.
|
||||
const FilePath::CharType kSingletonSocketFilename[] = FPL("SingletonSocket");
|
||||
const FilePath::CharType kThumbnailsFilename[] = FPL("Thumbnails");
|
||||
const wchar_t kUserDataDirname[] = L"User Data";
|
||||
const FilePath::CharType kUserScriptsDirname[] = FPL("User Scripts");
|
||||
const FilePath::CharType kWebDataFilename[] = FPL("Web Data");
|
||||
const FilePath::CharType kBookmarksFileName[] = FPL("Bookmarks");
|
||||
const FilePath::CharType kHistoryBookmarksFileName[] =
|
||||
FPL("Bookmarks From History");
|
||||
const FilePath::CharType kCustomDictionaryFileName[] =
|
||||
FPL("Custom Dictionary.txt");
|
||||
|
||||
// This number used to be limited to 32 in the past (see b/535234).
|
||||
const unsigned int kMaxRendererProcessCount = 42;
|
||||
const int kStatsMaxThreads = 32;
|
||||
const int kStatsMaxCounters = 300;
|
||||
|
||||
// We don't enable record mode in the released product because users could
|
||||
// potentially be tricked into running a product in record mode without
|
||||
// knowing it. Enable in debug builds. Playback mode is allowed always,
|
||||
// because it is useful for testing and not hazardous by itself.
|
||||
#ifndef NDEBUG
|
||||
const bool kRecordModeEnabled = true;
|
||||
#else
|
||||
const bool kRecordModeEnabled = false;
|
||||
#endif
|
||||
|
||||
} // namespace chrome
|
@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// A handful of resource-like constants related to the Chrome application.
|
||||
|
||||
#ifndef CHROME_COMMON_CHROME_CONSTANTS_H_
|
||||
#define CHROME_COMMON_CHROME_CONSTANTS_H_
|
||||
|
||||
#include "base/file_path.h"
|
||||
|
||||
namespace chrome {
|
||||
|
||||
extern const wchar_t kBrowserProcessExecutableName[];
|
||||
extern const wchar_t kBrowserProcessExecutablePath[];
|
||||
extern const wchar_t kBrowserAppName[];
|
||||
extern const wchar_t kMessageWindowClass[];
|
||||
extern const wchar_t kExternalTabWindowClass[];
|
||||
extern const wchar_t kCrashReportLog[];
|
||||
extern const wchar_t kTestingInterfaceDLL[];
|
||||
extern const wchar_t kNotSignedInProfile[];
|
||||
extern const wchar_t kNotSignedInID[];
|
||||
extern const char kStatsFilename[];
|
||||
extern const wchar_t kBrowserResourcesDll[];
|
||||
extern const FilePath::CharType kExtensionFileExtension[];
|
||||
|
||||
// filenames
|
||||
extern const FilePath::CharType kArchivedHistoryFilename[];
|
||||
extern const FilePath::CharType kCacheDirname[];
|
||||
extern const FilePath::CharType kMediaCacheDirname[];
|
||||
extern const FilePath::CharType kOffTheRecordMediaCacheDirname[];
|
||||
extern const wchar_t kChromePluginDataDirname[];
|
||||
extern const FilePath::CharType kCookieFilename[];
|
||||
extern const FilePath::CharType kHistoryFilename[];
|
||||
extern const FilePath::CharType kLocalStateFilename[];
|
||||
extern const FilePath::CharType kPreferencesFilename[];
|
||||
extern const FilePath::CharType kSafeBrowsingFilename[];
|
||||
extern const FilePath::CharType kSingletonSocketFilename[];
|
||||
extern const FilePath::CharType kThumbnailsFilename[];
|
||||
extern const wchar_t kUserDataDirname[];
|
||||
extern const FilePath::CharType kUserScriptsDirname[];
|
||||
extern const FilePath::CharType kWebDataFilename[];
|
||||
extern const FilePath::CharType kBookmarksFileName[];
|
||||
extern const FilePath::CharType kHistoryBookmarksFileName[];
|
||||
extern const FilePath::CharType kCustomDictionaryFileName[];
|
||||
|
||||
extern const unsigned int kMaxRendererProcessCount;
|
||||
extern const int kStatsMaxThreads;
|
||||
extern const int kStatsMaxCounters;
|
||||
|
||||
extern const bool kRecordModeEnabled;
|
||||
|
||||
} // namespace chrome
|
||||
|
||||
#endif // CHROME_COMMON_CHROME_CONSTANTS_H_
|
@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/common/chrome_counters.h"
|
||||
|
||||
#include "base/stats_counters.h"
|
||||
|
||||
namespace chrome {
|
||||
|
||||
// Note: We use the construct-on-first-use pattern here, because we don't
|
||||
// want to fight with any static initializer ordering problems later.
|
||||
// The downside of this is that the objects don't ever get cleaned up.
|
||||
// But they are small and this is okay.
|
||||
|
||||
// Note: Because these are constructed on-first-use, there is a slight
|
||||
// race condition - two threads could initialize the same counter.
|
||||
// If this happened, the stats table would still work just fine;
|
||||
// we'd leak the extraneous StatsCounter object once, and that
|
||||
// would be it. But these are small objects, so this is ok.
|
||||
|
||||
StatsCounter& Counters::ipc_send_counter() {
|
||||
static StatsCounter* ctr = new StatsCounter("IPC.SendMsgCount");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
StatsCounterTimer& Counters::chrome_main() {
|
||||
static StatsCounterTimer* ctr = new StatsCounterTimer("Chrome.Init");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
StatsCounterTimer& Counters::renderer_main() {
|
||||
static StatsCounterTimer* ctr = new StatsCounterTimer("Chrome.RendererInit");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
StatsCounterTimer& Counters::spellcheck_init() {
|
||||
static StatsCounterTimer* ctr = new StatsCounterTimer("SpellCheck.Init");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
StatsRate& Counters::spellcheck_lookup() {
|
||||
static StatsRate* ctr = new StatsRate("SpellCheck.Lookup");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
StatsCounterTimer& Counters::plugin_load() {
|
||||
static StatsCounterTimer* ctr = new StatsCounterTimer("ChromePlugin.Load");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
StatsRate& Counters::plugin_intercept() {
|
||||
static StatsRate* ctr = new StatsRate("ChromePlugin.Intercept");
|
||||
return *ctr;
|
||||
}
|
||||
|
||||
} // namespace chrome
|
@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Counters used within the browser.
|
||||
|
||||
#ifndef CHROME_COMMON_CHROME_COUNTERS_H_
|
||||
#define CHROME_COMMON_CHROME_COUNTERS_H_
|
||||
|
||||
class StatsCounter;
|
||||
class StatsCounterTimer;
|
||||
class StatsRate;
|
||||
|
||||
namespace chrome {
|
||||
|
||||
class Counters {
|
||||
public:
|
||||
// The number of messages sent on IPC channels.
|
||||
static StatsCounter& ipc_send_counter();
|
||||
|
||||
// The amount of time spent in chrome initialization.
|
||||
static StatsCounterTimer& chrome_main();
|
||||
|
||||
// The amount of time spent in renderer initialization.
|
||||
static StatsCounterTimer& renderer_main();
|
||||
|
||||
// Time spent in spellchecker initialization.
|
||||
static StatsCounterTimer& spellcheck_init();
|
||||
|
||||
// Time/Count of spellcheck lookups.
|
||||
static StatsRate& spellcheck_lookup();
|
||||
|
||||
// Time spent loading the Chrome plugins.
|
||||
static StatsCounterTimer& plugin_load();
|
||||
|
||||
// Time/Count of plugin network interception.
|
||||
static StatsRate& plugin_intercept();
|
||||
};
|
||||
|
||||
} // namespace chrome
|
||||
|
||||
#endif // CHROME_COMMON_CHROME_COUNTERS_H_
|
@ -1,44 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/file_path.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/string_util.h"
|
||||
#include "base/sys_info.h"
|
||||
#include "chrome/common/chrome_constants.h"
|
||||
#include "chrome/common/chrome_paths_internal.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
|
||||
namespace chrome {
|
||||
|
||||
bool GetGearsPluginPathFromCommandLine(FilePath* path) {
|
||||
#ifndef NDEBUG
|
||||
// for debugging, support a cmd line based override
|
||||
std::wstring plugin_path = CommandLine::ForCurrentProcess()->GetSwitchValue(
|
||||
switches::kGearsPluginPathOverride);
|
||||
// TODO(tc): After GetSwitchNativeValue lands, we don't need to use
|
||||
// FromWStringHack.
|
||||
*path = FilePath::FromWStringHack(plugin_path);
|
||||
return !plugin_path.empty();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PathProvider(int key, FilePath* result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// This cannot be done as a static initializer sadly since Visual Studio will
|
||||
// eliminate this object file if there is no direct entry point into it.
|
||||
void RegisterPathProvider() {
|
||||
PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
|
||||
}
|
||||
|
||||
} // namespace chrome
|
@ -1,53 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_COMMON_CHROME_PATHS_H__
|
||||
#define CHROME_COMMON_CHROME_PATHS_H__
|
||||
|
||||
// This file declares path keys for the chrome module. These can be used with
|
||||
// the PathService to access various special directories and files.
|
||||
|
||||
namespace chrome {
|
||||
|
||||
enum {
|
||||
PATH_START = 1000,
|
||||
|
||||
DIR_APP = PATH_START, // directory where dlls and data reside
|
||||
DIR_LOGS, // directory where logs should be written
|
||||
DIR_USER_DATA, // directory where user data can be written
|
||||
DIR_CRASH_DUMPS, // directory where crash dumps are written
|
||||
DIR_USER_DESKTOP, // directory that correspond to the desktop
|
||||
DIR_RESOURCES, // directory where application resources are stored
|
||||
DIR_INSPECTOR, // directory where web inspector is located
|
||||
DIR_THEMES, // directory where theme dll files are stored
|
||||
DIR_LOCALES, // directory where locale resources are stored
|
||||
DIR_APP_DICTIONARIES, // directory where the global dictionaries are
|
||||
DIR_USER_DOCUMENTS, // directory for a user's "My Documents"
|
||||
DIR_DEFAULT_DOWNLOADS, // directory for a user's "My Documents/Downloads"
|
||||
FILE_RESOURCE_MODULE, // full path and filename of the module that contains
|
||||
// embedded resources (version, strings, images, etc.)
|
||||
FILE_LOCAL_STATE, // path and filename to the file in which machine/
|
||||
// installation-specific state is saved
|
||||
FILE_RECORDED_SCRIPT, // full path to the script.log file that contains
|
||||
// recorded browser events for playback.
|
||||
FILE_GEARS_PLUGIN, // full path to the gears.dll plugin file.
|
||||
FILE_LIBAVCODEC, // full path to libavcodec media decoding library.
|
||||
FILE_LIBAVFORMAT, // full path to libavformat media parsing library.
|
||||
FILE_LIBAVUTIL, // full path to libavutil media utility library.
|
||||
|
||||
// Valid only in development environment; TODO(darin): move these
|
||||
DIR_TEST_DATA, // directory where unit test data resides
|
||||
DIR_TEST_TOOLS, // directory where unit test tools reside
|
||||
FILE_TEST_SERVER, // simple HTTP server for testing the network stack
|
||||
FILE_PYTHON_RUNTIME, // Python runtime, used for running the test server
|
||||
|
||||
PATH_END
|
||||
};
|
||||
|
||||
// Call once to register the provider for the path keys defined above.
|
||||
void RegisterPathProvider();
|
||||
|
||||
} // namespace chrome
|
||||
|
||||
#endif // CHROME_COMMON_CHROME_PATHS_H__
|
@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
|
||||
#define CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
|
||||
|
||||
class FilePath;
|
||||
|
||||
namespace chrome {
|
||||
|
||||
// Get the path to the user's data directory, regardless of whether
|
||||
// DIR_USER_DATA has been overridden by a command-line option.
|
||||
bool GetDefaultUserDataDirectory(FilePath* result);
|
||||
|
||||
// Get the path to the user's documents directory.
|
||||
bool GetUserDocumentsDirectory(FilePath* result);
|
||||
|
||||
// Get the path to the user's downloads directory.
|
||||
bool GetUserDownloadsDirectory(FilePath* result);
|
||||
|
||||
// The path to the user's desktop.
|
||||
bool GetUserDesktop(FilePath* result);
|
||||
|
||||
} // namespace chrome
|
||||
|
||||
|
||||
#endif // CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
|
@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "chrome/common/chrome_paths_internal.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "base/base_paths.h"
|
||||
#import "base/file_path.h"
|
||||
#import "base/logging.h"
|
||||
#import "base/path_service.h"
|
||||
|
||||
namespace chrome {
|
||||
|
||||
bool GetDefaultUserDataDirectory(FilePath* result) {
|
||||
bool success = false;
|
||||
NSArray* dirs =
|
||||
NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,
|
||||
NSUserDomainMask, YES);
|
||||
if ([dirs count] && result) {
|
||||
NSString* base = [dirs objectAtIndex:0];
|
||||
#if defined(GOOGLE_CHROME_BUILD)
|
||||
base = [base stringByAppendingPathComponent:@"Google"];
|
||||
NSString* tail = @"Chrome";
|
||||
#else
|
||||
NSString* tail = @"Chromium";
|
||||
#endif
|
||||
NSString* path = [base stringByAppendingPathComponent:tail];
|
||||
*result = FilePath([path fileSystemRepresentation]);
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GetUserDocumentsDirectory(FilePath* result) {
|
||||
bool success = false;
|
||||
NSArray* docArray =
|
||||
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
|
||||
NSUserDomainMask,
|
||||
YES);
|
||||
if ([docArray count] && result) {
|
||||
*result = FilePath([[docArray objectAtIndex:0] fileSystemRepresentation]);
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GetUserDownloadsDirectory(FilePath* result) {
|
||||
bool success = false;
|
||||
NSArray* docArray =
|
||||
NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory,
|
||||
NSUserDomainMask,
|
||||
YES);
|
||||
if ([docArray count] && result) {
|
||||
*result = FilePath([[docArray objectAtIndex:0] fileSystemRepresentation]);
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GetUserDesktop(FilePath* result) {
|
||||
bool success = false;
|
||||
NSArray* docArray =
|
||||
NSSearchPathForDirectoriesInDomains(NSDesktopDirectory,
|
||||
NSUserDomainMask,
|
||||
YES);
|
||||
if ([docArray count] && result) {
|
||||
*result = FilePath([[docArray objectAtIndex:0] fileSystemRepresentation]);
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace chrome
|
@ -1,66 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/common/chrome_paths_internal.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "base/file_path.h"
|
||||
#include "base/path_service.h"
|
||||
#include "chrome/common/chrome_constants.h"
|
||||
|
||||
namespace chrome {
|
||||
|
||||
bool GetDefaultUserDataDirectory(FilePath* result) {
|
||||
if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result))
|
||||
return false;
|
||||
#if defined(GOOGLE_CHROME_BUILD)
|
||||
*result = result->Append(FILE_PATH_LITERAL("Google"));
|
||||
#endif
|
||||
*result = result->Append(chrome::kBrowserAppName);
|
||||
*result = result->Append(chrome::kUserDataDirname);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetUserDocumentsDirectory(FilePath* result) {
|
||||
wchar_t path_buf[MAX_PATH];
|
||||
if (FAILED(SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL,
|
||||
SHGFP_TYPE_CURRENT, path_buf)))
|
||||
return false;
|
||||
*result = FilePath(path_buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
// On Vista, we can get the download path using a Win API
|
||||
// (http://msdn.microsoft.com/en-us/library/bb762584(VS.85).aspx),
|
||||
// but it can be set to Desktop, which is dangerous. Instead,
|
||||
// we just use 'Downloads' under DIR_USER_DOCUMENTS. Localizing
|
||||
// 'downloads' is not a good idea because Chrome's UI language
|
||||
// can be changed.
|
||||
bool GetUserDownloadsDirectory(FilePath* result) {
|
||||
if (!GetUserDocumentsDirectory(result))
|
||||
return false;
|
||||
|
||||
*result = result->Append(L"Downloads");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetUserDesktop(FilePath* result) {
|
||||
// We need to go compute the value. It would be nice to support paths
|
||||
// with names longer than MAX_PATH, but the system functions don't seem
|
||||
// to be designed for it either, with the exception of GetTempPath
|
||||
// (but other things will surely break if the temp path is too long,
|
||||
// so we don't bother handling it.
|
||||
wchar_t system_buffer[MAX_PATH];
|
||||
system_buffer[0] = 0;
|
||||
if (FAILED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL,
|
||||
SHGFP_TYPE_CURRENT, system_buffer)))
|
||||
return false;
|
||||
*result = FilePath(system_buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace chrome
|
@ -26,7 +26,6 @@
|
||||
#include "base/string_util.h"
|
||||
#include "base/singleton.h"
|
||||
#include "base/stats_counters.h"
|
||||
#include "chrome/common/chrome_counters.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
#include "chrome/common/file_descriptor_set_posix.h"
|
||||
#include "chrome/common/ipc_logging.h"
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "base/non_thread_safe.h"
|
||||
#include "base/stats_counters.h"
|
||||
#include "base/win_util.h"
|
||||
#include "chrome/common/chrome_counters.h"
|
||||
#include "chrome/common/ipc_logging.h"
|
||||
#include "chrome/common/ipc_message_utils.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
@ -127,7 +126,6 @@ bool Channel::ChannelImpl::Send(Message* message) {
|
||||
if (thread_check_.get()) {
|
||||
DCHECK(thread_check_->CalledOnValidThread());
|
||||
}
|
||||
chrome::Counters::ipc_send_counter().Increment();
|
||||
#ifdef IPC_MESSAGE_DEBUG_EXTRA
|
||||
DLOG(INFO) << "sending message @" << message << " on channel @" << this
|
||||
<< " with type " << message->type()
|
||||
|
@ -13,12 +13,12 @@
|
||||
#include "base/string_util.h"
|
||||
#include "base/string16.h"
|
||||
#include "base/tuple.h"
|
||||
#include "base/time.h"
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
#include "chrome/common/file_descriptor_set_posix.h"
|
||||
#endif
|
||||
#include "chrome/common/ipc_sync_message.h"
|
||||
#include "chrome/common/thumbnail_score.h"
|
||||
#include "chrome/common/transport_dib.h"
|
||||
|
||||
namespace IPC {
|
||||
@ -731,17 +731,6 @@ struct ParamTraitsIPC<FilePath> {
|
||||
static void Log(const param_type& p, std::wstring* l);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraitsIPC<ThumbnailScore> {
|
||||
typedef ThumbnailScore param_type;
|
||||
static void Write(Message* m, const param_type& p);
|
||||
static bool Read(const Message* m, void** iter, param_type* r);
|
||||
static void Log(const param_type& p, std::wstring* l) {
|
||||
l->append(StringPrintf(L"(%f, %d, %d)",
|
||||
p.boring_score, p.good_clipping, p.at_top));
|
||||
}
|
||||
};
|
||||
|
||||
struct LogData {
|
||||
std::wstring channel;
|
||||
int32_t routing_id;
|
||||
@ -1045,32 +1034,6 @@ ParamTraitsIPC<FilePath>::Log(const param_type& p, std::wstring* l) {
|
||||
ParamTraits<FilePath::StringType>::Log(p.value(), l);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
ParamTraitsIPC<ThumbnailScore>::Write(Message* m, const param_type& p) {
|
||||
IPC::ParamTraits<double>::Write(m, p.boring_score);
|
||||
IPC::ParamTraits<bool>::Write(m, p.good_clipping);
|
||||
IPC::ParamTraits<bool>::Write(m, p.at_top);
|
||||
IPC::ParamTraits<base::Time>::Write(m, p.time_at_snapshot);
|
||||
}
|
||||
inline bool
|
||||
ParamTraitsIPC<ThumbnailScore>::Read(const Message* m, void** iter, param_type* r) {
|
||||
double boring_score;
|
||||
bool good_clipping, at_top;
|
||||
base::Time time_at_snapshot;
|
||||
if (!IPC::ParamTraits<double>::Read(m, iter, &boring_score) ||
|
||||
!IPC::ParamTraits<bool>::Read(m, iter, &good_clipping) ||
|
||||
!IPC::ParamTraits<bool>::Read(m, iter, &at_top) ||
|
||||
!IPC::ParamTraits<base::Time>::Read(m, iter, &time_at_snapshot))
|
||||
return false;
|
||||
|
||||
r->boring_score = boring_score;
|
||||
r->good_clipping = good_clipping;
|
||||
r->at_top = at_top;
|
||||
r->time_at_snapshot = time_at_snapshot;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generic message subclasses
|
||||
|
||||
|
@ -1,67 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_BROWSER_COMMON_THUMBNAIL_SCORE_H__
|
||||
#define CHROME_BROWSER_COMMON_THUMBNAIL_SCORE_H__
|
||||
|
||||
#include "base/time.h"
|
||||
|
||||
// A set of metadata about a Thumbnail.
|
||||
struct ThumbnailScore {
|
||||
// Initializes the ThumbnailScore to the absolute worst possible
|
||||
// values except for time, which is set to Now().
|
||||
ThumbnailScore();
|
||||
|
||||
// Builds a ThumbnailScore with the passed in values, and sets the
|
||||
// thumbnail generation time to Now().
|
||||
ThumbnailScore(double score, bool clipping, bool top);
|
||||
|
||||
// Builds a ThumbnailScore with the passed in values.
|
||||
ThumbnailScore(double score, bool clipping, bool top,
|
||||
const base::Time& time);
|
||||
~ThumbnailScore();
|
||||
|
||||
// Tests for equivalence between two ThumbnailScore objects.
|
||||
bool Equals(const ThumbnailScore& rhs) const;
|
||||
|
||||
// How "boring" a thumbnail is. The boring score is the 0,1 ranged
|
||||
// percentage of pixels that are the most common luma. Higher boring
|
||||
// scores indicate that a higher percentage of a bitmap are all the
|
||||
// same brightness (most likely the same color).
|
||||
double boring_score;
|
||||
|
||||
// Whether the thumbnail was taken with height greater then
|
||||
// width. In cases where we don't have |good_clipping|, the
|
||||
// thumbnails are either clipped from the horizontal center of the
|
||||
// window, or are otherwise weirdly stretched.
|
||||
bool good_clipping;
|
||||
|
||||
// Whether this thumbnail was taken while the renderer was
|
||||
// displaying the top of the page. Most pages are more recognizable
|
||||
// by their headers then by a set of random text half way down the
|
||||
// page; i.e. most MediaWiki sites would be indistinguishable by
|
||||
// thumbnails with |at_top| set to false.
|
||||
bool at_top;
|
||||
|
||||
// Record the time when a thumbnail was taken. This is used to make
|
||||
// sure thumbnails are kept fresh.
|
||||
base::Time time_at_snapshot;
|
||||
|
||||
// How bad a thumbnail needs to be before we completely ignore it.
|
||||
static const double kThumbnailMaximumBoringness;
|
||||
|
||||
// Time before we take a worse thumbnail (subject to
|
||||
// kThumbnailMaximumBoringness) over what's currently in the database
|
||||
// for freshness.
|
||||
static const base::TimeDelta kUpdateThumbnailTime;
|
||||
|
||||
// Penalty of how much more boring a thumbnail should be per hour.
|
||||
static const double kThumbnailDegradePerHour;
|
||||
};
|
||||
|
||||
// Checks whether we should replace one thumbnail with another.
|
||||
bool ShouldReplaceThumbnailWith(const ThumbnailScore& current,
|
||||
const ThumbnailScore& replacement);
|
||||
|
||||
#endif // CHROME_BROWSER_COMMON_THUMBNAIL_SCORE_H__
|
@ -15,7 +15,6 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
|
||||
var canvases = [];
|
||||
function callbackTestCanvas(canvas)
|
||||
@ -60,7 +59,6 @@ const MAX_ITERATIONS = 1000;
|
||||
|
||||
function createIframe(url,next) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.focus();
|
||||
iframe.src = url;
|
||||
iframe.remotePageLoaded = remotePageLoaded;
|
||||
var me = this;
|
||||
@ -84,6 +82,7 @@ function createIframe(url,next) {
|
||||
}
|
||||
iframe.addEventListener("load", iframeLoadCompleted, false);
|
||||
window.document.body.appendChild(iframe);
|
||||
iframe.focus();
|
||||
};
|
||||
|
||||
function refTest(test,ref) {
|
||||
@ -191,8 +190,10 @@ function runTests() {
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTests()">
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
|
@ -127,6 +127,23 @@ FontSizeInflationListMarginAdjustment(const nsIFrame* aFrame)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: If we ever want to use nsCSSOffsetState for a flex item or a grid
|
||||
// item, we need to make it take the containing-block height as well as the
|
||||
// width, since flex items and grid items resolve vertical percent margins
|
||||
// and padding against the containing-block height, rather than its width.
|
||||
nsCSSOffsetState::nsCSSOffsetState(nsIFrame *aFrame,
|
||||
nsRenderingContext *aRenderingContext,
|
||||
nscoord aContainingBlockWidth)
|
||||
: frame(aFrame)
|
||||
, rendContext(aRenderingContext)
|
||||
, mWritingMode(aFrame->GetWritingMode())
|
||||
{
|
||||
MOZ_ASSERT(!aFrame->IsFlexItem(),
|
||||
"We're about to resolve vertical percent margin & padding "
|
||||
"values against CB width, which is incorrect for flex items");
|
||||
InitOffsets(aContainingBlockWidth, aContainingBlockWidth, frame->GetType());
|
||||
}
|
||||
|
||||
// Initialize a reflow state for a child frame's reflow. Some state
|
||||
// is copied from the parent reflow state; the remaining state is
|
||||
// computed.
|
||||
|
@ -151,21 +151,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: If we ever want to use nsCSSOffsetState for a flex item or a grid
|
||||
// item, we need to make it take the containing-block height as well as the
|
||||
// width, since flex items and grid items resolve vertical percent margins
|
||||
// and padding against the containing-block height, rather than its width.
|
||||
nsCSSOffsetState(nsIFrame *aFrame, nsRenderingContext *aRenderingContext,
|
||||
nscoord aContainingBlockWidth)
|
||||
: frame(aFrame)
|
||||
, rendContext(aRenderingContext)
|
||||
, mWritingMode(aFrame->GetWritingMode())
|
||||
{
|
||||
MOZ_ASSERT(!aFrame->IsFlexItem(),
|
||||
"We're about to resolve vertical percent margin & padding "
|
||||
"values against CB width, which is incorrect for flex items");
|
||||
InitOffsets(aContainingBlockWidth, aContainingBlockWidth, frame->GetType());
|
||||
}
|
||||
nscoord aContainingBlockWidth);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Reflow trace methods. Defined in nsFrame.cpp so they have access
|
||||
|
@ -2227,12 +2227,6 @@ public:
|
||||
*/
|
||||
virtual bool IsLeaf() const;
|
||||
|
||||
/**
|
||||
* Is this a flex item? (Is the parent a flex container frame?)
|
||||
*/
|
||||
bool IsFlexItem() const
|
||||
{ return mParent && mParent->GetType() == nsGkAtoms::flexContainerFrame; }
|
||||
|
||||
/**
|
||||
* Marks all display items created by this frame as needing a repaint,
|
||||
* and calls SchedulePaint() if requested and one is not already pending.
|
||||
@ -2972,6 +2966,11 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty()))
|
||||
virtual void FindCloserFrameForSelection(nsPoint aPoint,
|
||||
FrameWithDistance* aCurrentBestFrame);
|
||||
|
||||
/**
|
||||
* Is this a flex item? (i.e. a non-abs-pos child of a flex container)
|
||||
*/
|
||||
inline bool IsFlexItem() const;
|
||||
|
||||
inline bool IsBlockInside() const;
|
||||
inline bool IsBlockOutside() const;
|
||||
inline bool IsInlineOutside() const;
|
||||
|
@ -10,6 +10,14 @@
|
||||
#include "nsIFrame.h"
|
||||
#include "nsStyleStructInlines.h"
|
||||
|
||||
bool
|
||||
nsIFrame::IsFlexItem() const
|
||||
{
|
||||
return mParent &&
|
||||
mParent->GetType() == nsGkAtoms::flexContainerFrame &&
|
||||
!IsAbsolutelyPositioned();
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::IsFloating() const
|
||||
{
|
||||
|
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.tealBlock {
|
||||
background: teal;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="tealBlock"></div>
|
||||
<div class="tealBlock"></div>
|
||||
<div class="tealBlock"></div>
|
||||
<div class="tealBlock"></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Testing that "min-width", "max-width", "min-height", and "max-height" are applied on absolutely positioned children of a horizontal flex container</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#abspos-items">
|
||||
<link rel="match" href="flexbox-abspos-child-1-ref.html">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
background: purple;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
}
|
||||
.absPos {
|
||||
position: absolute;
|
||||
background: teal;
|
||||
}
|
||||
.testMinWidth {
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
min-width: 20px;
|
||||
}
|
||||
.testMaxWidth {
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
max-width: 20px;
|
||||
}
|
||||
.testMinHeight {
|
||||
width: 20px;
|
||||
height: 10px;
|
||||
min-height: 20px;
|
||||
}
|
||||
.testMaxHeight {
|
||||
width: 20px;
|
||||
height: 50px;
|
||||
max-height: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flexContainer"><div class="absPos testMinWidth"></div></div>
|
||||
<div class="flexContainer"><div class="absPos testMaxWidth"></div></div>
|
||||
<div class="flexContainer"><div class="absPos testMinHeight"></div></div>
|
||||
<div class="flexContainer"><div class="absPos testMaxHeight"></div></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: Testing that "min-width", "max-width", "min-height", and "max-height" are applied on absolutely positioned children of a vertical flex container</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-flexbox/#abspos-items">
|
||||
<link rel="match" href="flexbox-abspos-child-1-ref.html">
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.flexContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
background: purple;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
}
|
||||
.absPos {
|
||||
position: absolute;
|
||||
background: teal;
|
||||
}
|
||||
.testMinWidth {
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
min-width: 20px;
|
||||
}
|
||||
.testMaxWidth {
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
max-width: 20px;
|
||||
}
|
||||
.testMinHeight {
|
||||
width: 20px;
|
||||
height: 10px;
|
||||
min-height: 20px;
|
||||
}
|
||||
.testMaxHeight {
|
||||
width: 20px;
|
||||
height: 50px;
|
||||
max-height: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="flexContainer"><div class="absPos testMinWidth"></div></div>
|
||||
<div class="flexContainer"><div class="absPos testMaxWidth"></div></div>
|
||||
<div class="flexContainer"><div class="absPos testMinHeight"></div></div>
|
||||
<div class="flexContainer"><div class="absPos testMaxHeight"></div></div>
|
||||
</body>
|
||||
</html>
|
@ -1,3 +1,7 @@
|
||||
# Tests for absolutely-positioned children of a flex container
|
||||
== flexbox-abpos-child-1a.html flexbox-abpos-child-1-ref.html
|
||||
== flexbox-abpos-child-1b.html flexbox-abpos-child-1-ref.html
|
||||
|
||||
# Tests for handling anonymous flex items
|
||||
== flexbox-anonymous-items-1.html flexbox-anonymous-items-1-ref.html
|
||||
|
||||
|
@ -274,6 +274,9 @@ pref("browser.search.noCurrentEngine", true);
|
||||
pref("browser.search.official", true);
|
||||
#endif
|
||||
|
||||
// Control media casting feature
|
||||
pref("browser.casting.enabled", false);
|
||||
|
||||
// Enable sparse localization by setting a few package locale overrides
|
||||
pref("chrome.override_package.global", "browser");
|
||||
pref("chrome.override_package.mozapps", "browser");
|
||||
|
@ -156,6 +156,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
};
|
||||
|
||||
private FindInPageBar mFindInPageBar;
|
||||
private MediaCastingBar mMediaCastingBar;
|
||||
|
||||
private boolean mAccessibilityEnabled = false;
|
||||
|
||||
@ -530,6 +531,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
|
||||
mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
|
||||
mMediaCastingBar = (MediaCastingBar) findViewById(R.id.media_casting);
|
||||
|
||||
registerEventListener("CharEncoding:Data");
|
||||
registerEventListener("CharEncoding:State");
|
||||
@ -830,6 +832,11 @@ abstract public class BrowserApp extends GeckoApp
|
||||
mFindInPageBar = null;
|
||||
}
|
||||
|
||||
if (mMediaCastingBar != null) {
|
||||
mMediaCastingBar.onDestroy();
|
||||
mMediaCastingBar = null;
|
||||
}
|
||||
|
||||
if (mSharedPreferencesHelper != null) {
|
||||
mSharedPreferencesHelper.uninit();
|
||||
mSharedPreferencesHelper = null;
|
||||
|
118
mobile/android/base/MediaCastingBar.java
Normal file
@ -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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MediaCastingBar extends RelativeLayout implements View.OnClickListener, GeckoEventListener {
|
||||
private static final String LOGTAG = "MediaCastingBar";
|
||||
|
||||
private TextView mCastingTo;
|
||||
private ImageButton mMediaPlay;
|
||||
private ImageButton mMediaPause;
|
||||
private ImageButton mMediaStop;
|
||||
|
||||
private boolean mInflated = false;
|
||||
|
||||
public MediaCastingBar(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
GeckoAppShell.getEventDispatcher().registerEventListener("Casting:Started", this);
|
||||
GeckoAppShell.getEventDispatcher().registerEventListener("Casting:Stopped", this);
|
||||
}
|
||||
|
||||
public void inflateContent() {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View content = inflater.inflate(R.layout.media_casting, this);
|
||||
|
||||
mMediaPlay = (ImageButton) content.findViewById(R.id.media_play);
|
||||
mMediaPlay.setOnClickListener(this);
|
||||
mMediaPause = (ImageButton) content.findViewById(R.id.media_pause);
|
||||
mMediaPause.setOnClickListener(this);
|
||||
mMediaStop = (ImageButton) content.findViewById(R.id.media_stop);
|
||||
mMediaStop.setOnClickListener(this);
|
||||
|
||||
mCastingTo = (TextView) content.findViewById(R.id.media_casting_to);
|
||||
|
||||
// Capture clicks on the rest of the view to prevent them from
|
||||
// leaking into other views positioned below.
|
||||
content.setOnClickListener(this);
|
||||
|
||||
mInflated = true;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (!mInflated)
|
||||
inflateContent();
|
||||
|
||||
setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
setVisibility(GONE);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
GeckoAppShell.getEventDispatcher().unregisterEventListener("Casting:Started", this);
|
||||
GeckoAppShell.getEventDispatcher().unregisterEventListener("Casting:Stopped", this);
|
||||
}
|
||||
|
||||
// View.OnClickListener implementation
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final int viewId = v.getId();
|
||||
|
||||
if (viewId == R.id.media_play) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Play", ""));
|
||||
mMediaPlay.setVisibility(GONE);
|
||||
mMediaPause.setVisibility(VISIBLE);
|
||||
} else if (viewId == R.id.media_pause) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Pause", ""));
|
||||
mMediaPause.setVisibility(GONE);
|
||||
mMediaPlay.setVisibility(VISIBLE);
|
||||
} else if (viewId == R.id.media_stop) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Stop", ""));
|
||||
}
|
||||
}
|
||||
|
||||
// GeckoEventListener implementation
|
||||
@Override
|
||||
public void handleMessage(final String event, final JSONObject message) {
|
||||
final String device = message.optString("device");
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (event.equals("Casting:Started")) {
|
||||
show();
|
||||
if (!TextUtils.isEmpty(device)) {
|
||||
mCastingTo.setText(device);
|
||||
} else {
|
||||
// Should not happen
|
||||
mCastingTo.setText("");
|
||||
Log.d(LOGTAG, "Device name is empty.");
|
||||
}
|
||||
mMediaPlay.setVisibility(GONE);
|
||||
mMediaPause.setVisibility(VISIBLE);
|
||||
} else if (event.equals("Casting:Stopped")) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -219,6 +219,13 @@ size. -->
|
||||
<!ENTITY find_next "Next">
|
||||
<!ENTITY find_close "Close">
|
||||
|
||||
<!-- Localization note (media_casting_to, media_play, media_pause, media_stop) : These strings are used
|
||||
as alternate text for accessibility. They are not visible in the UI. -->
|
||||
<!ENTITY media_casting_to "Casting to Device">
|
||||
<!ENTITY media_play "Play">
|
||||
<!ENTITY media_pause "Pause">
|
||||
<!ENTITY media_stop "Stop">
|
||||
|
||||
<!ENTITY contextmenu_open_new_tab "Open in New Tab">
|
||||
<!ENTITY contextmenu_open_private_tab "Open in Private Tab">
|
||||
<!ENTITY contextmenu_open_in_reader "Open in Reader">
|
||||
|
@ -248,6 +248,7 @@ gbjar.sources += [
|
||||
'LightweightTheme.java',
|
||||
'LightweightThemeDrawable.java',
|
||||
'LocaleManager.java',
|
||||
'MediaCastingBar.java',
|
||||
'MemoryMonitor.java',
|
||||
'menu/GeckoMenu.java',
|
||||
'menu/GeckoMenuInflater.java',
|
||||
|
BIN
mobile/android/base/resources/drawable-hdpi/media_bar_pause.png
Normal file
After Width: | Height: | Size: 362 B |
BIN
mobile/android/base/resources/drawable-hdpi/media_bar_play.png
Normal file
After Width: | Height: | Size: 670 B |
BIN
mobile/android/base/resources/drawable-hdpi/media_bar_stop.png
Normal file
After Width: | Height: | Size: 763 B |
BIN
mobile/android/base/resources/drawable-mdpi/media_bar_pause.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
mobile/android/base/resources/drawable-mdpi/media_bar_play.png
Normal file
After Width: | Height: | Size: 463 B |
BIN
mobile/android/base/resources/drawable-mdpi/media_bar_stop.png
Normal file
After Width: | Height: | Size: 497 B |
BIN
mobile/android/base/resources/drawable-xhdpi/media_bar_pause.png
Normal file
After Width: | Height: | Size: 389 B |
BIN
mobile/android/base/resources/drawable-xhdpi/media_bar_play.png
Normal file
After Width: | Height: | Size: 853 B |
BIN
mobile/android/base/resources/drawable-xhdpi/media_bar_stop.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
@ -48,6 +48,13 @@
|
||||
style="@style/FindBar"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<org.mozilla.gecko.MediaCastingBar android:id="@+id/media_casting"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
style="@style/FindBar"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<RelativeLayout android:id="@+id/camera_layout"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
|
41
mobile/android/base/resources/layout/media_casting.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<RelativeLayout android:id="@+id/media_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true">
|
||||
|
||||
<ImageButton android:id="@+id/media_play"
|
||||
style="@style/FindBar.ImageButton"
|
||||
android:contentDescription="@string/media_play"
|
||||
android:src="@drawable/media_bar_play"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageButton android:id="@+id/media_pause"
|
||||
style="@style/FindBar.ImageButton"
|
||||
android:contentDescription="@string/media_pause"
|
||||
android:src="@drawable/media_bar_pause"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView android:id="@+id/media_casting_to"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginRight="5dip"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@id/media_controls"
|
||||
android:layout_centerVertical="true"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:textColor="#FFFFFFFF"
|
||||
android:contentDescription="@string/media_casting_to"/>
|
||||
|
||||
<ImageButton android:id="@+id/media_stop"
|
||||
style="@style/FindBar.ImageButton"
|
||||
android:contentDescription="@string/media_stop"
|
||||
android:layout_alignParentRight="true"
|
||||
android:src="@drawable/media_bar_stop"/>
|
||||
|
||||
</merge>
|
@ -83,6 +83,11 @@
|
||||
<string name="find_next">&find_next;</string>
|
||||
<string name="find_close">&find_close;</string>
|
||||
|
||||
<string name="media_casting_to">&media_casting_to;</string>
|
||||
<string name="media_play">&media_play;</string>
|
||||
<string name="media_pause">&media_pause;</string>
|
||||
<string name="media_stop">&media_stop;</string>
|
||||
|
||||
<string name="settings">&settings;</string>
|
||||
<string name="settings_title">&settings_title;</string>
|
||||
<string name="pref_category_advanced">&pref_category_advanced;</string>
|
||||
|
@ -79,6 +79,7 @@ skip-if = processor == "x86"
|
||||
[testSharedPreferences]
|
||||
[testSimpleDiscovery]
|
||||
[testUITelemetry]
|
||||
[testVideoDiscovery]
|
||||
|
||||
# Used for Talos, please don't use in mochitest
|
||||
#[testPan]
|
||||
|
10
mobile/android/base/tests/testVideoDiscovery.java
Normal file
@ -0,0 +1,10 @@
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
|
||||
public class testVideoDiscovery extends JavascriptTest {
|
||||
public testVideoDiscovery() {
|
||||
super("testVideoDiscovery.js");
|
||||
}
|
||||
}
|
84
mobile/android/base/tests/testVideoDiscovery.js
Normal file
@ -0,0 +1,84 @@
|
||||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function ok(passed, text) {
|
||||
do_report_result(passed, text, Components.stack.caller, false);
|
||||
}
|
||||
|
||||
// The chrome window
|
||||
let chromeWin;
|
||||
|
||||
// Track the <browser> where the tests are happening
|
||||
let browser;
|
||||
|
||||
function middle(element) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
let x = (rect.right - rect.left) / 2 + rect.left;
|
||||
let y = (rect.bottom - rect.top) / 2 + rect.top;
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
add_test(function setup_browser() {
|
||||
chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let BrowserApp = chromeWin.BrowserApp;
|
||||
|
||||
do_register_cleanup(function cleanup() {
|
||||
BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
|
||||
});
|
||||
|
||||
let url = "http://mochi.test:8888/tests/robocop/video_discovery.html";
|
||||
browser = BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id }).browser;
|
||||
browser.addEventListener("load", function startTests(event) {
|
||||
browser.removeEventListener("load", startTests, true);
|
||||
Services.tm.mainThread.dispatch(run_next_test, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}, true);
|
||||
});
|
||||
|
||||
let videoDiscoveryTests = [
|
||||
{ id: "simple-mp4", source: "http://mochi.test:8888/simple.mp4", poster: "http://mochi.test:8888/simple.png", text: "simple video with mp4 src" },
|
||||
{ id: "simple-fail", pass: false, text: "simple video with no mp4 src" },
|
||||
{ id: "with-sources-mp4", source: "http://mochi.test:8888/simple.mp4", text: "video with mp4 extension source child" },
|
||||
{ id: "with-sources-fail", pass: false, text: "video with no mp4 extension source child" },
|
||||
{ id: "with-sources-mimetype", source: "http://mochi.test:8888/simple-video-mp4", text: "video with mp4 mimetype source child" },
|
||||
{ id: "video-overlay", source: "http://mochi.test:8888/simple.mp4", text: "div overlay covering a simple video with mp4 src" }
|
||||
];
|
||||
|
||||
function execute_video_test(test) {
|
||||
let element = browser.contentDocument.getElementById(test.id);
|
||||
if (element) {
|
||||
let [x, y] = middle(element);
|
||||
let video = chromeWin.CastingApps.getVideo(element, x, y);
|
||||
if (video) {
|
||||
let matchPoster = (test.poster == video.poster);
|
||||
let matchSource = (test.source == video.source);
|
||||
ok(matchPoster && matchSource && test.pass, test.text);
|
||||
} else {
|
||||
ok(!test.pass, test.text);
|
||||
}
|
||||
} else {
|
||||
ok(false, "test element not found: [" + test.id + "]");
|
||||
}
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
let videoTest;
|
||||
while ((videoTest = videoDiscoveryTests.shift())) {
|
||||
if (!("poster" in videoTest)) {
|
||||
videoTest.poster = "";
|
||||
}
|
||||
if (!("pass" in videoTest)) {
|
||||
videoTest.pass = true;
|
||||
}
|
||||
|
||||
add_test(execute_video_test.bind(this, videoTest));
|
||||
}
|
||||
|
||||
run_next_test();
|
60
mobile/android/base/tests/video_discovery.html
Normal file
@ -0,0 +1,60 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Video Discovery Test</title>
|
||||
<style type="text/css">
|
||||
#video-box {
|
||||
float: left;
|
||||
}
|
||||
#video-overlay, #video-player {
|
||||
width: 640px;
|
||||
min-height: 370px;
|
||||
}
|
||||
#video-overlay {
|
||||
position: absolute;
|
||||
float: left;
|
||||
background-color:#f00;
|
||||
z-index:10;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- PASS: src uses a mp4 extension -->
|
||||
<video id="simple-mp4" poster="/simple.png" src="/simple.mp4"></video>
|
||||
|
||||
<!-- FAIL: src uses a ogg extension -->
|
||||
<video id="simple-fail" src="/simple.ogg"></video>
|
||||
|
||||
<!-- PASS: source list uses a mp4 extension -->
|
||||
<video id="with-sources-mp4">
|
||||
<source src="/simple.ogg">
|
||||
<source src="/simple.mp4">
|
||||
</video>
|
||||
|
||||
<!-- FAIL: source list uses a mp4 extension -->
|
||||
<video id="with-sources-fail">
|
||||
<source src="/simple.ogg">
|
||||
<source src="/simple.webm">
|
||||
</video>
|
||||
|
||||
<!-- PASS: source list uses a mp4 mimetype -->
|
||||
<video id="with-sources-mimetype">
|
||||
<source src="/simple-video-ogg" type="video/ogg">
|
||||
<source src="/simple-video-mp4" type="video/mp4">
|
||||
</video>
|
||||
|
||||
<!-- PASS: source list uses a mp4 mimetype and extra data -->
|
||||
<video id="with-sources-mimetype-plus">
|
||||
<source src="/simple-video-ogg" type="video/ogg">
|
||||
<source src="/simple-video-mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'">
|
||||
</video>
|
||||
|
||||
<!-- PASS: div overlay covers a video with mp4 src -->
|
||||
<div id="video-box">
|
||||
<div id="video-overlay"></div>
|
||||
<div>
|
||||
<video id="video-player" src="/simple.mp4"></video>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
243
mobile/android/chrome/content/CastingApps.js
Normal file
@ -0,0 +1,243 @@
|
||||
/* 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 CastingApps = {
|
||||
_castMenuId: -1,
|
||||
|
||||
init: function ca_init() {
|
||||
if (!this.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for devices continuously every 120 seconds
|
||||
SimpleServiceDiscovery.search(120 * 1000);
|
||||
|
||||
this._castMenuId = NativeWindow.contextmenus.add(
|
||||
Strings.browser.GetStringFromName("contextmenu.castToScreen"),
|
||||
this.filterCast,
|
||||
this.openExternal.bind(this)
|
||||
);
|
||||
|
||||
Services.obs.addObserver(this, "Casting:Play", false);
|
||||
Services.obs.addObserver(this, "Casting:Pause", false);
|
||||
Services.obs.addObserver(this, "Casting:Stop", false);
|
||||
},
|
||||
|
||||
uninit: function ca_uninit() {
|
||||
Services.obs.removeObserver(this, "Casting:Play");
|
||||
Services.obs.removeObserver(this, "Casting:Pause");
|
||||
Services.obs.removeObserver(this, "Casting:Stop");
|
||||
|
||||
NativeWindow.contextmenus.remove(this._castMenuId);
|
||||
},
|
||||
|
||||
isEnabled: function isEnabled() {
|
||||
return Services.prefs.getBoolPref("browser.casting.enabled");
|
||||
},
|
||||
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "Casting:Play":
|
||||
if (this.session && this.session.remoteMedia.status == "paused") {
|
||||
this.session.remoteMedia.play();
|
||||
}
|
||||
break;
|
||||
case "Casting:Pause":
|
||||
if (this.session && this.session.remoteMedia.status == "started") {
|
||||
this.session.remoteMedia.pause();
|
||||
}
|
||||
break;
|
||||
case "Casting:Stop":
|
||||
if (this.session) {
|
||||
this.closeExternal();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
makeURI: function makeURI(aURL, aOriginCharset, aBaseURI) {
|
||||
return Services.io.newURI(aURL, aOriginCharset, aBaseURI);
|
||||
},
|
||||
|
||||
getVideo: function(aElement, aX, aY) {
|
||||
// Fast path: Is the given element a video element
|
||||
let video = this._getVideo(aElement);
|
||||
if (video) {
|
||||
return video;
|
||||
}
|
||||
|
||||
// The context menu system will keep walking up the DOM giving us a chance
|
||||
// to find an element we match. When it hits <html> things can go BOOM.
|
||||
try {
|
||||
// Maybe this is an overlay, with the video element under it
|
||||
// Use the (x, y) location to guess at a <video> element
|
||||
let elements = aElement.ownerDocument.querySelectorAll("video");
|
||||
for (let element of elements) {
|
||||
// Look for a video element contained in the overlay bounds
|
||||
let rect = element.getBoundingClientRect();
|
||||
if (aY >= rect.top && aX >= rect.left && aY <= rect.bottom && aX <= rect.right) {
|
||||
video = this._getVideo(element);
|
||||
if (video) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
// Could be null
|
||||
return video;
|
||||
},
|
||||
|
||||
_getVideo: function(aElement) {
|
||||
// Given the hardware support for H264, let's only look for 'mp4' sources
|
||||
if (!aElement instanceof HTMLVideoElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function allowableExtension(aURI) {
|
||||
if (aURI && aURI instanceof Ci.nsIURL) {
|
||||
return (aURI.fileExtension == "mp4");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the poster attribute from the <video>
|
||||
let posterURL = aElement.poster;
|
||||
|
||||
// First, look to see if the <video> has a src attribute
|
||||
let sourceURL = aElement.src;
|
||||
|
||||
// If empty, try the currentSrc
|
||||
if (!sourceURL) {
|
||||
sourceURL = aElement.currentSrc;
|
||||
}
|
||||
|
||||
if (sourceURL) {
|
||||
// Use the file extension to guess the mime type
|
||||
let sourceURI = this.makeURI(sourceURL, null, this.makeURI(aElement.baseURI));
|
||||
if (allowableExtension(sourceURI)) {
|
||||
return { video: aElement, source: sourceURI.spec, poster: posterURL };
|
||||
}
|
||||
}
|
||||
|
||||
// Next, look to see if there is a <source> child element that meets
|
||||
// our needs
|
||||
let sourceNodes = aElement.getElementsByTagName("source");
|
||||
for (let sourceNode of sourceNodes) {
|
||||
let sourceURI = this.makeURI(sourceNode.src, null, this.makeURI(sourceNode.baseURI));
|
||||
|
||||
// Using the type attribute is our ideal way to guess the mime type. Otherwise,
|
||||
// fallback to using the file extension to guess the mime type
|
||||
if (sourceNode.type == "video/mp4" || allowableExtension(sourceURI)) {
|
||||
return { video: aElement, source: sourceURI.spec, poster: posterURL };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
filterCast: {
|
||||
matches: function(aElement, aX, aY) {
|
||||
if (SimpleServiceDiscovery.services.length == 0)
|
||||
return false;
|
||||
let video = CastingApps.getVideo(aElement, aX, aY);
|
||||
if (CastingApps.session) {
|
||||
return (video && CastingApps.session.data.source != video.source);
|
||||
}
|
||||
return (video != null);
|
||||
}
|
||||
},
|
||||
|
||||
prompt: function(aCallback) {
|
||||
let items = [];
|
||||
SimpleServiceDiscovery.services.forEach(function(aService) {
|
||||
let item = {
|
||||
label: aService.friendlyName,
|
||||
selected: false
|
||||
};
|
||||
items.push(item);
|
||||
});
|
||||
|
||||
let prompt = new Prompt({
|
||||
title: Strings.browser.GetStringFromName("casting.prompt")
|
||||
}).setSingleChoiceItems(items).show(function(data) {
|
||||
let selected = data.button;
|
||||
let service = selected == -1 ? null : SimpleServiceDiscovery.services[selected];
|
||||
if (aCallback)
|
||||
aCallback(service);
|
||||
});
|
||||
},
|
||||
|
||||
openExternal: function(aElement, aX, aY) {
|
||||
// Start a second screen media service
|
||||
let video = this.getVideo(aElement, aX, aY);
|
||||
if (!video) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.prompt(function(aService) {
|
||||
if (!aService)
|
||||
return;
|
||||
|
||||
// Make sure we have a player app for the given service
|
||||
let app = SimpleServiceDiscovery.findAppForService(aService, "video-sharing");
|
||||
if (!app)
|
||||
return;
|
||||
|
||||
video.title = aElement.ownerDocument.defaultView.top.document.title;
|
||||
if (video.element) {
|
||||
// If the video is currently playing on the device, pause it
|
||||
if (!video.element.paused) {
|
||||
video.element.pause();
|
||||
}
|
||||
}
|
||||
|
||||
app.stop(function() {
|
||||
app.start("", function() {
|
||||
app.remoteMedia(function(aRemoteMedia) {
|
||||
this.session = {
|
||||
service: aService,
|
||||
app: app,
|
||||
remoteMedia: aRemoteMedia,
|
||||
data: {
|
||||
title: video.title,
|
||||
source: video.source,
|
||||
poster: video.poster
|
||||
}
|
||||
};
|
||||
}.bind(this), this);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// RemoteMedia callback API methods
|
||||
onRemoteMediaStart: function(aRemoteMedia) {
|
||||
if (!this.session) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRemoteMedia.load(this.session.data);
|
||||
sendMessageToJava({ type: "Casting:Started", device: this.session.service.friendlyName });
|
||||
},
|
||||
|
||||
onRemoteMediaStop: function(aRemoteMedia) {
|
||||
sendMessageToJava({ type: "Casting:Stopped" });
|
||||
},
|
||||
|
||||
onRemoteMediaStatus: function(aRemoteMedia) {
|
||||
if (!this.session) {
|
||||
return;
|
||||
}
|
||||
|
||||
let status = aRemoteMedia.status;
|
||||
if (status == "completed") {
|
||||
aRemoteMedia.shutdown();
|
||||
this.session.app.stop();
|
||||
delete this.session;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -63,6 +63,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
|
||||
"resource://gre/modules/SimpleServiceDiscovery.jsm");
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ShumwayUtils",
|
||||
"resource://shumway/ShumwayUtils.jsm");
|
||||
@ -82,6 +85,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
|
||||
["PluginHelper", "chrome://browser/content/PluginHelper.js"],
|
||||
["OfflineApps", "chrome://browser/content/OfflineApps.js"],
|
||||
["Linkifier", "chrome://browser/content/Linkify.js"],
|
||||
["CastingApps", "chrome://browser/content/CastingApps.js"],
|
||||
].forEach(function (aScript) {
|
||||
let [name, script] = aScript;
|
||||
XPCOMUtils.defineLazyGetter(window, name, function() {
|
||||
@ -386,6 +390,7 @@ var BrowserApp = {
|
||||
Reader.init();
|
||||
UserAgentOverrides.init();
|
||||
DesktopUserAgent.init();
|
||||
CastingApps.init();
|
||||
Distribution.init();
|
||||
Tabs.init();
|
||||
#ifdef ACCESSIBILITY
|
||||
@ -727,6 +732,7 @@ var BrowserApp = {
|
||||
UserAgentOverrides.uninit();
|
||||
DesktopUserAgent.uninit();
|
||||
ExternalApps.uninit();
|
||||
CastingApps.uninit();
|
||||
Distribution.uninit();
|
||||
Tabs.uninit();
|
||||
},
|
||||
|
@ -53,6 +53,7 @@ chrome.jar:
|
||||
content/FeedHandler.js (content/FeedHandler.js)
|
||||
content/Feedback.js (content/Feedback.js)
|
||||
content/Linkify.js (content/Linkify.js)
|
||||
content/CastingApps.js (content/CastingApps.js)
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
content/aboutHealthReport.xhtml (content/aboutHealthReport.xhtml)
|
||||
* content/aboutHealthReport.js (content/aboutHealthReport.js)
|
||||
|
@ -159,6 +159,9 @@ intl.charsetmenu.browser.static=iso-8859-1,utf-8,big5,iso-2022-jp,shift_jis,euc-
|
||||
# Text Selection
|
||||
selectionHelper.textCopied=Text copied to clipboard
|
||||
|
||||
# Casting
|
||||
casting.prompt=Cast to Device
|
||||
|
||||
# Context menu
|
||||
contextmenu.openInNewTab=Open Link in New Tab
|
||||
contextmenu.openInPrivateTab=Open Link in Private Tab
|
||||
@ -191,6 +194,7 @@ contextmenu.unmute=Unmute
|
||||
contextmenu.saveVideo=Save Video
|
||||
contextmenu.saveAudio=Save Audio
|
||||
contextmenu.addToContacts=Add to Contacts
|
||||
contextmenu.castToScreen=Cast to Screen
|
||||
|
||||
contextmenu.copy=Copy
|
||||
contextmenu.cut=Cut
|
||||
|
@ -36,7 +36,7 @@ interface nsIZipEntry;
|
||||
* entries within them, however it is possible that some zip programs may
|
||||
* experience problems what that.
|
||||
*/
|
||||
[scriptable, uuid(6d4ef074-206c-4649-9884-57bc355864d6)]
|
||||
[scriptable, uuid(3ca10750-797e-4a22-bcfe-66170b5e96dd)]
|
||||
interface nsIZipWriter : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -206,4 +206,15 @@ interface nsIZipWriter : nsISupports
|
||||
* @throws <other-error> on failure to complete the zip file
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Make all stored(uncompressed) files align to given alignment size.
|
||||
*
|
||||
* @param aAlignSize is the alignment size, valid values from 2 to 32768, and
|
||||
must be power of 2.
|
||||
*
|
||||
* @throws NS_ERROR_INVALID_ARG if aAlignSize is invalid
|
||||
* @throws <other-error> on failure to update the zip file
|
||||
*/
|
||||
void alignStoredFiles(in uint16_t aAlignSize);
|
||||
};
|
||||
|
@ -342,3 +342,54 @@ const uint8_t * nsZipHeader::GetExtraField(uint16_t aTag, bool aLocal, uint16_t
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pad extra field to align data starting position to specified size.
|
||||
*/
|
||||
nsresult nsZipHeader::PadExtraField(uint32_t aOffset, uint16_t aAlignSize)
|
||||
{
|
||||
uint32_t pad_size;
|
||||
uint32_t pa_offset;
|
||||
uint32_t pa_end;
|
||||
|
||||
// Check for range and power of 2.
|
||||
if (aAlignSize < 2 || aAlignSize > 32768 ||
|
||||
(aAlignSize & (aAlignSize - 1)) != 0) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Point to current starting data position.
|
||||
aOffset += ZIP_FILE_HEADER_SIZE + mName.Length() + mLocalFieldLength;
|
||||
|
||||
// Calculate aligned offset.
|
||||
pa_offset = aOffset & ~(aAlignSize - 1);
|
||||
pa_end = pa_offset + aAlignSize;
|
||||
pad_size = pa_end - aOffset;
|
||||
if (pad_size == 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Leave enough room(at least 4 bytes) for valid values in extra field.
|
||||
while (pad_size < 4) {
|
||||
pad_size += aAlignSize;
|
||||
}
|
||||
// Extra field length is 2 bytes.
|
||||
if (mLocalFieldLength + pad_size > 65535) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoArrayPtr<uint8_t> field = mLocalExtraField;
|
||||
uint32_t pos = mLocalFieldLength;
|
||||
|
||||
mLocalExtraField = new uint8_t[mLocalFieldLength + pad_size];
|
||||
memcpy(mLocalExtraField.get(), field, mLocalFieldLength);
|
||||
// Use 0xFFFF as tag ID to avoid conflict with other IDs.
|
||||
// For more information, please read "Extensible data fields" section in:
|
||||
// http://www.pkware.com/documents/casestudies/APPNOTE.TXT
|
||||
WRITE16(mLocalExtraField.get(), &pos, 0xFFFF);
|
||||
WRITE16(mLocalExtraField.get(), &pos, pad_size - 4);
|
||||
memset(mLocalExtraField.get() + pos, 0, pad_size - 4);
|
||||
mLocalFieldLength += pad_size;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
nsresult WriteCDSHeader(nsIOutputStream *aStream);
|
||||
nsresult ReadCDSHeader(nsIInputStream *aStream);
|
||||
const uint8_t * GetExtraField(uint16_t aTag, bool aLocal, uint16_t *aBlockSize);
|
||||
nsresult PadExtraField(uint32_t aOffset, uint16_t aAlignSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3,8 +3,11 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "StreamFunctions.h"
|
||||
#include "nsZipWriter.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "StreamFunctions.h"
|
||||
#include "nsZipDataStream.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsIAsyncStreamCopier.h"
|
||||
@ -551,10 +554,7 @@ NS_IMETHODIMP nsZipWriter::RemoveEntry(const nsACString & aZipEntry,
|
||||
uint32_t read = 0;
|
||||
char buf[4096];
|
||||
while (count > 0) {
|
||||
if (count < sizeof(buf))
|
||||
read = count;
|
||||
else
|
||||
read = sizeof(buf);
|
||||
read = std::min(count, (uint32_t) sizeof(buf));
|
||||
|
||||
rv = inputStream->Read(buf, read, &read);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -737,6 +737,128 @@ NS_IMETHODIMP nsZipWriter::OnStopRequest(nsIRequest *aRequest,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make all stored(uncompressed) files align to given alignment size.
|
||||
*/
|
||||
NS_IMETHODIMP nsZipWriter::AlignStoredFiles(uint16_t aAlignSize)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Check for range and power of 2.
|
||||
if (aAlignSize < 2 || aAlignSize > 32768 ||
|
||||
(aAlignSize & (aAlignSize - 1)) != 0) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mHeaders.Count(); i++) {
|
||||
nsZipHeader *header = mHeaders[i];
|
||||
|
||||
// Check whether this entry is file and compression method is stored.
|
||||
bool isdir;
|
||||
rv = header->GetIsDirectory(&isdir);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (isdir || header->mMethod != 0) {
|
||||
continue;
|
||||
}
|
||||
// Pad extra field to align data starting position to specified size.
|
||||
uint32_t old_len = header->mLocalFieldLength;
|
||||
rv = header->PadExtraField(header->mOffset, aAlignSize);
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
}
|
||||
// No padding means data already aligned.
|
||||
uint32_t shift = header->mLocalFieldLength - old_len;
|
||||
if (shift == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Flush any remaining data before we start.
|
||||
rv = mStream->Flush();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Open zip file for reading.
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), mFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISeekableStream> in_seekable = do_QueryInterface(inputStream);
|
||||
nsCOMPtr<nsISeekableStream> out_seekable = do_QueryInterface(mStream);
|
||||
|
||||
uint32_t data_offset = header->mOffset + header->GetFileHeaderLength() - shift;
|
||||
uint32_t count = mCDSOffset - data_offset;
|
||||
uint32_t read;
|
||||
char buf[4096];
|
||||
|
||||
// Shift data to aligned postion.
|
||||
while (count > 0) {
|
||||
read = std::min(count, (uint32_t) sizeof(buf));
|
||||
|
||||
rv = in_seekable->Seek(nsISeekableStream::NS_SEEK_SET,
|
||||
data_offset + count - read);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
rv = inputStream->Read(buf, read, &read);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
rv = out_seekable->Seek(nsISeekableStream::NS_SEEK_SET,
|
||||
data_offset + count - read + shift);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
rv = ZW_WriteData(mStream, buf, read);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
count -= read;
|
||||
}
|
||||
inputStream->Close();
|
||||
if (NS_FAILED(rv)) {
|
||||
Cleanup();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Update current header
|
||||
rv = out_seekable->Seek(nsISeekableStream::NS_SEEK_SET,
|
||||
header->mOffset);
|
||||
if (NS_FAILED(rv)) {
|
||||
Cleanup();
|
||||
return rv;
|
||||
}
|
||||
rv = header->WriteFileHeader(mStream);
|
||||
if (NS_FAILED(rv)) {
|
||||
Cleanup();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Update offset of all other headers
|
||||
int pos = i + 1;
|
||||
while (pos < mHeaders.Count()) {
|
||||
mHeaders[pos]->mOffset += shift;
|
||||
pos++;
|
||||
}
|
||||
mCDSOffset += shift;
|
||||
rv = SeekCDS();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
mCDSDirty = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsZipWriter::InternalAddEntryDirectory(const nsACString & aZipEntry,
|
||||
PRTime aModTime,
|
||||
uint32_t aPermissions)
|
||||
|
113
modules/libjar/zipwriter/test/unit/test_alignment.js
Normal file
@ -0,0 +1,113 @@
|
||||
/* 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/.
|
||||
*/
|
||||
|
||||
const DATA = "ZIP WRITER TEST DATA";
|
||||
const FILENAME = "test_data.txt";
|
||||
const CRC = 0xe6164331;
|
||||
const time = 1199145600000; // Jan 1st 2008
|
||||
|
||||
var TESTS = [
|
||||
{
|
||||
name: "test.txt",
|
||||
compression: Ci.nsIZipWriter.COMPRESSION_DEFAULT
|
||||
},
|
||||
{
|
||||
name: "test.png",
|
||||
compression: Ci.nsIZipWriter.COMPRESSION_NONE
|
||||
}
|
||||
];
|
||||
|
||||
function swap16(n)
|
||||
{
|
||||
return (((n >> 8) & 0xFF) << 0) |
|
||||
(((n >> 0) & 0xFF) << 8);
|
||||
}
|
||||
|
||||
function swap32(n)
|
||||
{
|
||||
return (((n >> 24) & 0xFF) << 0) |
|
||||
(((n >> 16) & 0xFF) << 8) |
|
||||
(((n >> 8) & 0xFF) << 16) |
|
||||
(((n >> 0) & 0xFF) << 24);
|
||||
}
|
||||
|
||||
function move_to_data(bis, offset)
|
||||
{
|
||||
bis.readBytes(18); // Move to compressed size
|
||||
var size = swap32(bis.read32());
|
||||
bis.readBytes(4);
|
||||
var file_len = swap16(bis.read16());
|
||||
var extra_len = swap16(bis.read16());
|
||||
var file = bis.readBytes(file_len);
|
||||
bis.readBytes(extra_len);
|
||||
offset += ZIP_FILE_HEADER_SIZE + file_len + extra_len;
|
||||
|
||||
return {offset: offset, size: size};
|
||||
}
|
||||
|
||||
function test_alignment(align_size)
|
||||
{
|
||||
// Create zip for testing.
|
||||
zipW.open(tmpFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
for (var i = 0; i < TESTS.length; i++) {
|
||||
var source = do_get_file(DATA_DIR + TESTS[i].name);
|
||||
zipW.addEntryFile(TESTS[i].name, TESTS[i].compression, source, false);
|
||||
}
|
||||
var stream = Cc["@mozilla.org/io/string-input-stream;1"]
|
||||
.createInstance(Ci.nsIStringInputStream);
|
||||
stream.setData(DATA, DATA.length);
|
||||
zipW.addEntryStream(FILENAME, time * PR_USEC_PER_MSEC,
|
||||
Ci.nsIZipWriter.COMPRESSION_NONE, stream, false);
|
||||
zipW.alignStoredFiles(align_size);
|
||||
zipW.close();
|
||||
|
||||
// Check data can be decompressed.
|
||||
var zipR = new ZipReader(tmpFile);
|
||||
var stream = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
stream.init(zipR.getInputStream(FILENAME));
|
||||
var result = stream.read(DATA.length);
|
||||
do_check_eq(result, DATA);
|
||||
stream.close();
|
||||
zipR.close();
|
||||
|
||||
// Check data is correct and aligned.
|
||||
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fis.init(tmpFile, -1, -1, null);
|
||||
let bis = Cc["@mozilla.org/binaryinputstream;1"]
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
bis.setInputStream(fis);
|
||||
var offset = 0;
|
||||
|
||||
var ret = move_to_data(bis, offset); // "test.txt"
|
||||
offset = ret.offset;
|
||||
bis.readBytes(ret.size);
|
||||
offset += ret.size;
|
||||
|
||||
ret = move_to_data(bis, offset); // "test.png"
|
||||
offset = ret.offset;
|
||||
do_check_eq(offset % align_size, 0);
|
||||
bis.readBytes(ret.size);
|
||||
offset += ret.size;
|
||||
|
||||
ret = move_to_data(bis, offset); // "test_data.txt"
|
||||
offset = ret.offset;
|
||||
var result = bis.readBytes(DATA.length);
|
||||
do_check_eq(result, DATA);
|
||||
do_check_eq(offset % align_size, 0);
|
||||
|
||||
fis.close();
|
||||
bis.close();
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
test_alignment(2);
|
||||
test_alignment(4);
|
||||
test_alignment(16);
|
||||
test_alignment(4096);
|
||||
test_alignment(32768);
|
||||
}
|