Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2016-09-06 15:46:44 +02:00
Родитель b2e0ff7828 a1c780edbb
Коммит a113face7e
402 изменённых файлов: 16808 добавлений и 15820 удалений

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

@ -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 1289951 maybe needed a clobber to fix xpcshell tests?
Bug 1287426 - Clobber required because of Linux Chromium sandbox file moves.

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

@ -526,6 +526,8 @@ pref("privacy.sanitize.migrateFx3Prefs", false);
pref("privacy.panicButton.enabled", true);
pref("privacy.firstparty.isolate", false);
pref("network.proxy.share_proxy_settings", false); // use the same proxy settings for all protocols
// simple gestures support

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

@ -2,9 +2,23 @@
skip-if = buildapp == "mulet"
tags = usercontextid firstpartyisolation originattributes
support-files =
dummy.html
file_firstPartyBasic.html
head.js
test.js
test.js^headers^
test.html
test2.html
test2.js
test2.js^headers^
test_firstParty.html
test_firstParty_cookie.html
test_firstParty_html_redirect.html
test_firstParty_http_redirect.html
test_firstParty_http_redirect.html^headers^
test_firstParty_iframe_http_redirect.html
test_firstParty_postMessage.html
window.html
[browser_dummy.js]
skip-if = true
[browser_firstPartyIsolation.js]
[browser_localStorageIsolation.js]

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

@ -1,10 +0,0 @@
/*
* This is a dummy test case which makes this could be built.
* Should be removed after actual tests landed.
*/
"use strict";
add_task(function* () {
ok(true, "Make this test pass anyway.");
});

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

@ -0,0 +1,174 @@
const BASE_URL = "http://mochi.test:8888/browser/browser/components/originattributes/test/browser/";
const BASE_DOMAIN = "mochi.test";
add_task(function* setup() {
Services.prefs.setBoolPref("privacy.firstparty.isolate", true);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("privacy.firstparty.isolate");
});
});
/**
* Test for the top-level document and child iframes should have the
* firstPartyDomain attribute.
*/
add_task(function* principal_test() {
let tab = gBrowser.addTab(BASE_URL + "test_firstParty.html");
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser, true, function (url) {
return url == BASE_URL + "test_firstParty.html";
});
yield ContentTask.spawn(tab.linkedBrowser, { firstPartyDomain: BASE_DOMAIN }, function* (attrs) {
info("document principal: " + content.document.nodePrincipal.origin);
Assert.equal(docShell.getOriginAttributes().firstPartyDomain, "",
"top-level docShell shouldn't have firstPartyDomain attribute.");
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "The document should have firstPartyDomain");
for (let i = 1; i < 4; i++) {
let iframe = content.document.getElementById("iframe" + i);
info("iframe principal: " + iframe.contentDocument.nodePrincipal.origin);
Assert.equal(iframe.frameLoader.docShell.getOriginAttributes().firstPartyDomain,
attrs.firstPartyDomain, "iframe's docshell should have firstPartyDomain");
Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "iframe should have firstPartyDomain");
}
});
gBrowser.removeTab(tab);
});
/**
* Test for the cookie jars of the top-level document and child iframe should be
* isolated by firstPartyDomain.
*/
add_task(function* cookie_test() {
let tab = gBrowser.addTab(BASE_URL + "test_firstParty_cookie.html");
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser, true);
let iter = Services.cookies.enumerator;
let count = 0;
while (iter.hasMoreElements()) {
count++;
let cookie = iter.getNext().QueryInterface(Ci.nsICookie2);
Assert.equal(cookie.value, "foo", "Cookie value should be foo");
Assert.equal(cookie.originAttributes.firstPartyDomain, BASE_DOMAIN, "Cookie's origin attributes should be " + BASE_DOMAIN);
}
// one cookie is from requesting test.js from top-level doc, and the other from
// requesting test2.js from iframe test2.html.
Assert.equal(count, 2, "Should have two cookies");
gBrowser.removeTab(tab);
});
/**
* Test for after redirect, the top-level document should update the firstPartyDomain
* attribute. However if the redirect is happening on the iframe, the attribute
* should remain the same.
*/
add_task(function* redirect_test() {
let tab = gBrowser.addTab(BASE_URL + "test_firstParty_http_redirect.html");
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield ContentTask.spawn(tab.linkedBrowser, { firstPartyDomain: "example.com" }, function* (attrs) {
info("document principal: " + content.document.nodePrincipal.origin);
info("document uri: " + content.document.documentURI);
Assert.equal(content.document.documentURI, "http://example.com/browser/browser/components/originattributes/test/browser/dummy.html",
"The page should have been redirected to http://example.com/browser/browser/components/originattributes/test/browser/dummy.html");
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "The document should have firstPartyDomain");
});
// Since this is a HTML redirect, we wait until the final page is loaded.
let tab2 = gBrowser.addTab(BASE_URL + "test_firstParty_html_redirect.html");
yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, function(url) {
return url == "http://example.com/";
});
yield ContentTask.spawn(tab2.linkedBrowser, { firstPartyDomain: "example.com" }, function* (attrs) {
info("2nd tab document principal: " + content.document.nodePrincipal.origin);
info("2nd tab document uri: " + content.document.documentURI);
Assert.equal(content.document.documentURI, "http://example.com/",
"The page should have been redirected to http://example.com");
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "The document should have firstPartyDomain");
});
let tab3 = gBrowser.addTab(BASE_URL + "test_firstParty_iframe_http_redirect.html");
yield BrowserTestUtils.browserLoaded(tab3.linkedBrowser, true, function(url) {
return url == (BASE_URL + "test_firstParty_iframe_http_redirect.html");
});
// This redirect happens on the iframe, so unlike the two redirect tests above,
// the firstPartyDomain should still stick to the current top-level document,
// which is mochi.test.
yield ContentTask.spawn(tab3.linkedBrowser, { firstPartyDomain: "mochi.test" }, function* (attrs) {
let iframe = content.document.getElementById("iframe1");
info("iframe document principal: " + iframe.contentDocument.nodePrincipal.origin);
info("iframe document uri: " + iframe.contentDocument.documentURI);
Assert.equal(iframe.contentDocument.documentURI, "http://example.com/browser/browser/components/originattributes/test/browser/dummy.html",
"The page should have been redirected to http://example.com/browser/browser/components/originattributes/test/browser/dummy.html");
Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "The iframe should have firstPartyDomain: " + attrs.firstPartyDomain);
});
gBrowser.removeTab(tab);
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab3);
});
/**
* Test for postMessage between document and iframe.
*/
add_task(function* postMessage_test() {
let tab = gBrowser.addTab(BASE_URL + "test_firstParty_postMessage.html");
// The top-level page will post a message to its child iframe, and wait for
// another message from the iframe, once it receives the message, it will
// create another iframe, dummy.html.
// So we wait until dummy.html is loaded
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser, true, function (url) {
return url == BASE_URL + "dummy.html";
});
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
info("document principal: " + content.document.nodePrincipal.origin);
let value = content.document.getElementById("message").textContent;
Assert.equal(value, "OK");
});
gBrowser.removeTab(tab);
});
/**
* When the web page calls window.open, the new window should have the same
* firstPartyDomain attribute.
*/
add_task(function* openWindow_test() {
Services.prefs.setIntPref("browser.link.open_newwindow", 2);
registerCleanupFunction(function () {
Services.prefs.clearUserPref("browser.link.open_newwindow");
});
let tab = gBrowser.addTab(BASE_URL + "window.html");
let win = yield BrowserTestUtils.waitForNewWindow();
yield ContentTask.spawn(win.gBrowser.selectedBrowser, { firstPartyDomain: "mochi.test" }, function* (attrs) {
Assert.equal(docShell.getOriginAttributes().firstPartyDomain, attrs.firstPartyDomain,
"window.open() should have firstPartyDomain attribute");
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "The document should have firstPartyDomain");
let iframe = content.document.getElementById("iframe1");
Assert.equal(iframe.frameLoader.docShell.getOriginAttributes().firstPartyDomain,
attrs.firstPartyDomain, "iframe's docshell should have firstPartyDomain");
Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
attrs.firstPartyDomain, "iframe should have firstPartyDomain");
});
gBrowser.removeTab(tab);
yield BrowserTestUtils.closeWindow(win);
});

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

@ -0,0 +1,9 @@
<html>
<head>
<title>Dummy test page</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
</head>
<body>
<p>Dummy test page</p>
</body>
</html>

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

@ -0,0 +1,25 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for Bug 1260931</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script>
window.onmessage = function (evt) {
if (evt.data != "HI") {
return;
}
window.parent.postMessage("OK", "http://mochi.test:8888");
};
setTimeout(function() {
window.parent.postMessage("KO", "http://mochi.test:8888");
}, 1000);
</script>
</head>
<body>
Hello World.
</body>
</html>

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

@ -0,0 +1 @@
var i = 1;

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

@ -0,0 +1 @@
Set-Cookie: test=foo

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

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for Bug 1260931</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="test2.js"></script>
</head>
<body>
Hello World.
</body>
</html>

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

@ -0,0 +1 @@
var i = 1;

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

@ -0,0 +1 @@
Set-Cookie: test2=foo

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

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Test for Bug 1260931</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div>
<iframe id="iframe1" src="http://example.com"></iframe>
<iframe id="iframe2" sandbox="" src="http://example.com"></iframe>
<iframe id="iframe3" sandbox="allow-same-origin" src="http://example.com"></iframe>
</div>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for Bug 1260931</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="test.js"></script>
</head>
<body>
Hello World.
<iframe id="iframe1" src="test2.html"></iframe>
</body>
</html>

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

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf8" http-equiv="refresh" content="0; url=http://example.com/"/>
<title>Test for Bug 1260931</title>
</head>
<body>
</body>
</html>

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

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Test for Bug 1260931</title>
</head>
<body>
</body>
</html>

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

@ -0,0 +1,2 @@
HTTP 302 Found
Location: http://example.com/browser/browser/components/originattributes/test/browser/dummy.html

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Test for Bug 1260931</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div>
<iframe id="iframe1" src="test_firstParty_http_redirect.html"></iframe>
</div>
</body>
</html>

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

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Test for Bug 1260931</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<script>
function onload() {
let iframe1 = document.getElementById("iframe1");
iframe1.contentWindow.postMessage("HI", "http://mochi.test:8888");
}
window.onmessage = function (evt) {
document.getElementById("message").textContent = evt.data;
let iframe2 = document.createElement("iframe");
iframe2.src = "dummy.html";
document.body.appendChild(iframe2);
};
</script>
<body onload="onload()">
<div>
<iframe id="iframe1" src="test.html"></iframe>
<span id="message"></span>
</div>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta charset="utf8">
<title>Page creating a popup</title>
</head>
<body>
<script type="text/javascript">
var w = window.open();
w.document.body.innerHTML = "<iframe id='iframe1' src='data:text/plain,test2'></iframe>";
</script>
</body>
</html>

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

@ -269,6 +269,11 @@ bool isIgnoredPathForImplicitConversion(const Decl *Declaration) {
if (Begin->compare_lower(StringRef("graphite2")) == 0) {
return true;
}
if (Begin->compare_lower(StringRef("chromium")) == 0) {
// Ignore security/sandbox/chromium but not ipc/chromium.
++Begin;
return Begin != End && Begin->compare_lower(StringRef("sandbox")) == 0;
}
}
return false;
}

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

@ -12,6 +12,7 @@
#endif
#include "nsIAddonPolicyService.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIEffectiveTLDService.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
@ -47,6 +48,7 @@ PrincipalOriginAttributes::InheritFromDocShellToDoc(const DocShellOriginAttribut
mSignedPkg = aAttrs.mSignedPkg;
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
void
@ -60,6 +62,7 @@ PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
mSignedPkg = aAttrs.mSignedPkg;
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
void
@ -77,6 +80,7 @@ DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAtt
mSignedPkg = aAttrs.mSignedPkg;
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
void
@ -93,10 +97,13 @@ NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aA
// mSignedPkg accordingly by mSignedPkgInBrowser
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
void
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs,
const bool aIsTopLevelDocument,
nsIURI* aURI)
{
mAppId = aAttrs.mAppId;
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
@ -109,6 +116,24 @@ NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes
// mSignedPkg accordingly by mSignedPkgInBrowser
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
bool isFirstPartyEnabled = IsFirstPartyEnabled();
// When the pref is on, we also compute the firstPartyDomain attribute
// if this is for top-level document.
if (isFirstPartyEnabled && aIsTopLevelDocument) {
nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
MOZ_ASSERT(tldService);
if (!tldService) {
return;
}
nsAutoCString baseDomain;
tldService->GetBaseDomain(aURI, 0, baseDomain);
mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain);
} else {
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
}
void
@ -161,6 +186,11 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
params->Set(NS_LITERAL_STRING("privateBrowsingId"), value);
}
if (!mFirstPartyDomain.IsEmpty()) {
MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
params->Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain);
}
aStr.Truncate();
params->Serialize(value);
@ -247,6 +277,12 @@ public:
return true;
}
if (aName.EqualsLiteral("firstPartyDomain")) {
MOZ_RELEASE_ASSERT(mOriginAttributes->mFirstPartyDomain.IsEmpty());
mOriginAttributes->mFirstPartyDomain.Assign(aValue);
return true;
}
// No other attributes are supported.
return false;
}
@ -307,6 +343,21 @@ OriginAttributes::SetFromGenericAttributes(const GenericOriginAttributes& aAttrs
mUserContextId = aAttrs.mUserContextId;
mSignedPkg = aAttrs.mSignedPkg;
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
}
bool
OriginAttributes::IsFirstPartyEnabled()
{
// Cache the privacy.firstparty.isolate pref.
static bool sFirstPartyIsolation = false;
static bool sCachedFirstPartyPref = false;
if (!sCachedFirstPartyPref) {
sCachedFirstPartyPref = true;
Preferences::AddBoolVarCache(&sFirstPartyIsolation, "privacy.firstparty.isolate");
}
return sFirstPartyIsolation;
}
BasePrincipal::BasePrincipal()

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

@ -37,7 +37,8 @@ public:
mAddonId == aOther.mAddonId &&
mUserContextId == aOther.mUserContextId &&
mSignedPkg == aOther.mSignedPkg &&
mPrivateBrowsingId == aOther.mPrivateBrowsingId;
mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
mFirstPartyDomain == aOther.mFirstPartyDomain;
}
bool operator!=(const OriginAttributes& aOther) const
{
@ -65,6 +66,9 @@ protected:
OriginAttributes() {}
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
: OriginAttributesDictionary(aOther) {}
// check if "privacy.firstparty.isolate" is enabled.
bool IsFirstPartyEnabled();
};
class PrincipalOriginAttributes;
@ -136,7 +140,11 @@ public:
// is made.
void InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs);
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs);
// Inheriting OriginAttributes from a docshell when loading a top-level
// document.
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs,
const bool aIsTopLevelDocument = false,
nsIURI* aURI = nullptr);
};
// For operating on OriginAttributes not associated with any data structure.
@ -189,6 +197,10 @@ public:
return false;
}
if (mFirstPartyDomain.WasPassed() && mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
return false;
}
return true;
}
@ -225,6 +237,11 @@ public:
return false;
}
if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
return false;
}
return true;
}
};

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

@ -436,37 +436,20 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILoadContext> loadContext;
NS_QueryNotificationCallbacks(aChannel, loadContext);
nsCOMPtr<nsILoadInfo> loadInfo;
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INVALID;
if (loadInfo) {
contentPolicyType = loadInfo->GetExternalContentPolicyType();
}
// Inherit the origin attributes from loadInfo.
// If this is a top-level document load, the origin attributes of the
// loadInfo will be set from nsDocShell::DoURILoad.
// For subresource loading, the origin attributes of the loadInfo is from
// its loadingPrincipal.
PrincipalOriginAttributes attrs;
if (nsIContentPolicy::TYPE_DOCUMENT == contentPolicyType ||
nsIContentPolicy::TYPE_SUBDOCUMENT == contentPolicyType) {
// If it's document or sub-document, inherit originAttributes from
// the document.
if (loadContext) {
DocShellOriginAttributes docShellAttrs;
loadContext->GetOriginAttributes(docShellAttrs);
attrs.InheritFromDocShellToDoc(docShellAttrs, uri);
}
} else {
// Inherit origin attributes from loading principal if any.
nsCOMPtr<nsIPrincipal> loadingPrincipal;
if (loadInfo) {
loadInfo->GetLoadingPrincipal(getter_AddRefs(loadingPrincipal));
}
if (loadingPrincipal) {
attrs = BasePrincipal::Cast(loadingPrincipal)->OriginAttributesRef();
}
}
// For addons loadInfo might be null.
if (loadInfo) {
attrs.InheritFromNecko(loadInfo->GetOriginAttributes());
}
rv = MaybeSetAddonIdFromURI(attrs, uri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);

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

@ -42,7 +42,9 @@ function printAttrs(name, attrs) {
"\tuserContextId: " + attrs.userContextId + ",\n" +
"\tinIsolatedMozBrowser: " + attrs.inIsolatedMozBrowser + ",\n" +
"\taddonId: '" + attrs.addonId + "',\n" +
"\tsignedPkg: '" + attrs.signedPkg + "'\n}");
"\tsignedPkg: '" + attrs.signedPkg + "',\n" +
"\tprivateBrowsingId: '" + attrs.privateBrowsingId + "',\n" +
"\tfirstPartyDomain: '" + attrs.firstPartyDomain + "'\n}");
}
@ -55,6 +57,8 @@ function checkValues(attrs, values) {
do_check_eq(attrs.inIsolatedMozBrowser, values.inIsolatedMozBrowser || false);
do_check_eq(attrs.addonId, values.addonId || '');
do_check_eq(attrs.signedPkg, values.signedPkg || '');
do_check_eq(attrs.privateBrowsingId, values.privateBrowsingId || '');
do_check_eq(attrs.firstPartyDomain, values.firstPartyDomain || '');
}
function run_test() {
@ -122,6 +126,11 @@ function run_test() {
checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '^addonId=dummy');
do_check_eq(exampleOrg_addon.origin, 'http://example.org^addonId=dummy');
// First party Uri
var exampleOrg_firstPartyDomain = ssm.createCodebasePrincipal(makeURI('http://example.org'), {firstPartyDomain: 'example.org'});
checkOriginAttributes(exampleOrg_firstPartyDomain, { firstPartyDomain: "example.org" }, '^firstPartyDomain=example.org');
do_check_eq(exampleOrg_firstPartyDomain.origin, 'http://example.org^firstPartyDomain=example.org');
// Make sure we don't crash when serializing principals with UNKNOWN_APP_ID.
try {
let binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].
@ -177,6 +186,7 @@ function run_test() {
checkCrossOrigin(exampleOrg_appBrowser, nullPrin_appBrowser);
checkCrossOrigin(exampleOrg_appBrowser, exampleCom_appBrowser);
checkCrossOrigin(exampleOrg_addon, exampleOrg);
checkCrossOrigin(exampleOrg_firstPartyDomain, exampleOrg);
checkCrossOrigin(exampleOrg_userContext, exampleOrg);
checkCrossOrigin(exampleOrg_userContextAddon, exampleOrg);
checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextAddon);
@ -203,7 +213,7 @@ function run_test() {
// check that we can create an empty origin attributes dict with default
// members and values.
emptyAttrs = ChromeUtils.fillNonDefaultOriginAttributes({});
var emptyAttrs = ChromeUtils.fillNonDefaultOriginAttributes({});
checkValues(emptyAttrs);
var uri = "http://example.org";
@ -213,19 +223,20 @@ function run_test() {
[ "^userContextId=3", {userContextId: 3} ],
[ "^addonId=fooBar", {addonId: "fooBar"} ],
[ "^inBrowser=1", {inIsolatedMozBrowser: true} ],
[ "^firstPartyDomain=example.org", {firstPartyDomain: "example.org"} ],
[ "^signedPkg=bazQux", {signedPkg: "bazQux"} ],
[ "^appId=3&inBrowser=1&userContextId=6",
{appId: 3, userContextId: 6, inIsolatedMozBrowser: true} ] ];
// check that we can create an origin attributes from an origin properly
tests.forEach(function(t) {
tests.forEach(t => {
let attrs = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
checkValues(attrs, t[1]);
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), t[0]);
});
// check that we can create an origin attributes from a dict properly
tests.forEach(function(t) {
tests.forEach(t => {
let attrs = ChromeUtils.fillNonDefaultOriginAttributes(t[1]);
checkValues(attrs, t[1]);
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), t[0]);
@ -244,7 +255,7 @@ function run_test() {
[ "^appId=5", {appId: 5}, {appId: 3, userContextId: 7}, {appId: 3, userContextId: 7}, "^appId=3&userContextId=7" ] ];
// check that we can set origin attributes values properly
set_tests.forEach(function(t) {
set_tests.forEach(t => {
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
checkValues(orig, t[1]);
let mod = orig;
@ -267,7 +278,7 @@ function run_test() {
[ "^appId=5&userContextId=3", {appId: 5, userContextId: 3}, {appId: 5}, "^appId=5" ] ];
// check that we can set the userContextId to default properly
dflt_tests.forEach(function(t) {
dflt_tests.forEach(t => {
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
checkValues(orig, t[1]);
let mod = orig;
@ -275,4 +286,26 @@ function run_test() {
checkValues(mod, t[2]);
do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
});
// each row in the dflt2_tests array has these values:
// [0] - the suffix used to create an origin attribute from
// [1] - the expected result of creating an origin attributes from [0]
// [2] - the expected result after setting firstPartyUri to the default
// [3] - the expected result of creating a suffix from [2]
var dflt2_tests = [
[ "", {}, {}, "" ],
[ "^firstPartyDomain=foo.com", {firstPartyDomain: "foo.com"}, {}, "" ],
[ "^appId=5", {appId: 5}, {appId: 5}, "^appId=5" ],
[ "^appId=5&firstPartyDomain=foo.com", {appId: 5, firstPartyDomain: "foo.com"}, {appId: 5}, "^appId=5" ] ];
// check that we can set the userContextId to default properly
dflt2_tests.forEach(t => {
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
checkValues(orig, t[1]);
let mod = orig;
mod['firstPartyDomain'] = "";
checkValues(mod, t[2]);
do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
});
}

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

@ -10812,7 +10812,10 @@ nsDocShell::DoURILoad(nsIURI* aURI,
// OriginAttributes of the parent document. Or in case there isn't a
// parent document.
NeckoOriginAttributes neckoAttrs;
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes());
bool isTopLevelDoc = aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT &&
mItemType == typeContent &&
!GetIsMozBrowserOrApp();
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes(), isTopLevelDoc, aURI);
rv = loadInfo->SetOriginAttributes(neckoAttrs);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

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

@ -2098,6 +2098,38 @@ nsFrameLoader::MaybeCreateDocShell()
attrs = nsDocShell::Cast(docShell)->GetOriginAttributes();
}
// Inherit origin attributes from parent document if
// 1. It's in a content docshell.
// 2. its nodePrincipal is not a SystemPrincipal.
// 3. It's not a mozbrowser nor mozapp frame.
//
// For example, firstPartyDomain is computed from top-level document, it
// doesn't exist in the top-level docshell.
if (parentType == nsIDocShellTreeItem::typeContent &&
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
!OwnerIsMozBrowserOrAppFrame()) {
PrincipalOriginAttributes poa = BasePrincipal::Cast(doc->NodePrincipal())->OriginAttributesRef();
// Assert on the firstPartyDomain from top-level docshell should be empty
if (mIsTopLevelContent) {
MOZ_ASSERT(attrs.mFirstPartyDomain.IsEmpty(),
"top-level docshell shouldn't have firstPartyDomain attribute.");
}
// So far we want to make sure InheritFromDocToChildDocShell doesn't override
// any other origin attribute than firstPartyDomain.
MOZ_ASSERT(attrs.mAppId == poa.mAppId,
"docshell and document should have the same appId attribute.");
MOZ_ASSERT(attrs.mUserContextId == poa.mUserContextId,
"docshell and document should have the same userContextId attribute.");
MOZ_ASSERT(attrs.mInIsolatedMozBrowser == poa.mInIsolatedMozBrowser,
"docshell and document should have the same inIsolatedMozBrowser attribute.");
MOZ_ASSERT(attrs.mPrivateBrowsingId == poa.mPrivateBrowsingId,
"docshell and document should have the same privateBrowsingId attribute.");
attrs.InheritFromDocToChildDocShell(poa);
}
if (OwnerIsAppFrame()) {
// You can't be both an app and a browser frame.
MOZ_ASSERT(!OwnerIsMozBrowserFrame());

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

@ -543,11 +543,7 @@ skip-if = buildapp == 'b2g'
[test_bug698381.html]
[test_bug698384.html]
[test_bug704063.html]
[test_bug704320_http_http.html]
[test_bug704320_http_https.html]
[test_bug704320_https_http.html]
skip-if = buildapp == 'b2g' # b2g (https://example.com not working bug 1162353)
[test_bug704320_https_https.html]
[test_bug704320.html]
skip-if = buildapp == 'b2g' # b2g (https://example.com not working bug 1162353)
[test_bug704320_policyset.html]
[test_bug704320_policyset2.html]

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

@ -5,21 +5,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=704320
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 704320 - HTTPS to HTTPS</title>
<title>Test for Bug 704320</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="referrerHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.7">
var testIframeUrls = [
// HTTPS to HTTPS
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin'
];
//generates URLs to test
var generateURLArray = (function(from, to){
const baseURL = '://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=';
const schemeTo = '&scheme-to=';
return [
from + baseURL + from + schemeTo + to + '&policy=no-referrer-when-downgrade',
from + baseURL + from + schemeTo + to + '&policy=no-referrer',
from + baseURL + from + schemeTo + to + '&policy=unsafe-url',
from + baseURL + from + schemeTo + to + '&policy=origin',
from + baseURL + from + schemeTo + to + '&policy=origin-when-cross-origin',
];
});
var testIframeUrls = generateURLArray('http', 'http');
testIframeUrls = testIframeUrls.concat(generateURLArray('https', 'https'));
testIframeUrls = testIframeUrls.concat(generateURLArray('http', 'https'));
testIframeUrls = testIframeUrls.concat(generateURLArray('https', 'http'));
SimpleTest.waitForExplicitFinish();
var advance = function() { tests.next(); };
@ -51,12 +61,11 @@ var tests = (function() {
</head>
<body onload="tests.next();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=704320">Mozilla Bug 704320 - HTTPS to HTTPS</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=704320">Mozilla Bug 704320 - HTTP/HTTPS to HTTPS/HTTP</a>
<p id="display"></p>
<pre id="content">
</pre>
<iframe id="testframe"></iframe>
</body>
</html>
</html>

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

@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=704320
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 704320 - HTTP to HTTP</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="referrerHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.7">
var testIframeUrls = [
// HTTP to HTTP
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin',
];
SimpleTest.waitForExplicitFinish();
var advance = function() { tests.next(); };
/**
* This is the main test routine -- serialized by use of a generator.
* It performs all tests in sequence using in the same iframe.
*/
var tests = (function() {
var iframe = document.getElementById("testframe");
iframe.onload = function() {
advance();
}
// load the test frame from testIframeUrls[url]
// it will call back into this function via postMessage when it finishes loading.
// and continue beyond the yield.
for(url in testIframeUrls) {
yield iframe.src = testIframeUrls[url];
// run test and check result for loaded test URL
yield checkExpectedGlobalResults();
}
// complete. Be sure to yield so we don't call this twice.
yield SimpleTest.finish();
})();
</script>
</head>
<body onload="tests.next();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=704320">Mozilla Bug 704320 - HTTP to HTTP</a>
<p id="display"></p>
<pre id="content">
</pre>
<iframe id="testframe"></iframe>
</body>
</html>

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

@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=704320
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 704320 - HTTP to HTTPS</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="referrerHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.7">
var testIframeUrls = [
// HTTP to HTTPS
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin',
'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin-when-cross-origin',
];
SimpleTest.waitForExplicitFinish();
var advance = function() { tests.next(); };
/**
* This is the main test routine -- serialized by use of a generator.
* It performs all tests in sequence using in the same iframe.
*/
var tests = (function() {
var iframe = document.getElementById("testframe");
iframe.onload = function() {
advance();
}
// load the test frame from testIframeUrls[url]
// it will call back into this function via postMessage when it finishes loading.
// and continue beyond the yield.
for(url in testIframeUrls) {
yield iframe.src = testIframeUrls[url];
// run test and check result for loaded test URL
yield checkExpectedGlobalResults();
}
// complete. Be sure to yield so we don't call this twice.
yield SimpleTest.finish();
})();
</script>
</head>
<body onload="tests.next();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=704320">Mozilla Bug 704320 - HTTP to HTTPS</a>
<p id="display"></p>
<pre id="content">
</pre>
<iframe id="testframe"></iframe>
</body>
</html>

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

@ -1,62 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=704320
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 704320 - HTTPS to HTTP</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="referrerHelper.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.7">
var testIframeUrls = [
// HTTPS to HTTP
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=no-referrer-when-downgrade',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=no-referrer',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=origin',
'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=origin-when-cross-origin',
];
SimpleTest.waitForExplicitFinish();
var advance = function() { tests.next(); };
/**
* This is the main test routine -- serialized by use of a generator.
* It performs all tests in sequence using in the same iframe.
*/
var tests = (function() {
var iframe = document.getElementById("testframe");
iframe.onload = function() {
advance();
}
// load the test frame from testIframeUrls[url]
// it will call back into this function via postMessage when it finishes loading.
// and continue beyond the yield.
for(url in testIframeUrls) {
yield iframe.src = testIframeUrls[url];
// run test and check result for loaded test URL
yield checkExpectedGlobalResults();
}
// complete. Be sure to yield so we don't call this twice.
yield SimpleTest.finish();
})();
</script>
</head>
<body onload="tests.next();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=704320">Mozilla Bug 704320 - HTTPS to HTTP</a>
<p id="display"></p>
<pre id="content">
</pre>
<iframe id="testframe"></iframe>
</body>
</html>

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

@ -509,7 +509,7 @@ TabChild::Create(nsIContentChild* aManager,
child->mManager = aManager;
child->SetTabId(aTabId);
child->SetTabContext(aContext);
child->NotifyTabContextUpdated();
child->NotifyTabContextUpdated(true);
return child.forget();
}
@ -727,6 +727,7 @@ TabChild::Init()
}
webBrowser->SetContainerWindow(this);
webBrowser->SetOriginAttributes(OriginAttributesRef());
mWebNav = do_QueryInterface(webBrowser);
NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
@ -755,7 +756,7 @@ TabChild::Init()
baseWindow->Create();
// Set the tab context attributes then pass to docShell
NotifyTabContextUpdated();
NotifyTabContextUpdated(false);
// IPC uses a WebBrowser object for which DNS prefetching is turned off
// by default. But here we really want it, so enable it explicitly
@ -825,7 +826,7 @@ TabChild::Init()
}
void
TabChild::NotifyTabContextUpdated()
TabChild::NotifyTabContextUpdated(bool aIsPreallocated)
{
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
MOZ_ASSERT(docShell);
@ -835,7 +836,10 @@ TabChild::NotifyTabContextUpdated()
}
UpdateFrameType();
nsDocShell::Cast(docShell)->SetOriginAttributes(OriginAttributesRef());
if (aIsPreallocated) {
nsDocShell::Cast(docShell)->SetOriginAttributes(OriginAttributesRef());
}
// Set SANDBOXED_AUXILIARY_NAVIGATION flag if this is a receiver page.
if (!PresentationURL().IsEmpty()) {

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

@ -687,12 +687,13 @@ private:
void HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid);
// Notify others that our TabContext has been updated. (At the moment, this
// sets the appropriate origin attributes on our docshell.)
// Notify others that our TabContext has been updated.
//
// You should call this after calling TabContext::SetTabContext(). We also
// call this during Init().
void NotifyTabContextUpdated();
//
// @param aIsPreallocated true if this is called for Preallocated Tab.
void NotifyTabContextUpdated(bool aIsPreallocated);
// Update the frameType on our docshell.
void UpdateFrameType();

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

@ -81,6 +81,7 @@ dictionary OriginAttributesDictionary {
DOMString addonId = "";
DOMString signedPkg = "";
unsigned long privateBrowsingId = 0;
DOMString firstPartyDomain = "";
};
dictionary OriginAttributesPatternDictionary {
unsigned long appId;
@ -89,4 +90,5 @@ dictionary OriginAttributesPatternDictionary {
DOMString addonId;
DOMString signedPkg;
unsigned long privateBrowsingId;
DOMString firstPartyDomain;
};

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

@ -716,12 +716,12 @@ WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread()
MOZ_ASSERT(aRunnable);
}
// We must call RunBackOnWorkerThread() also if the runnable is cancelled.
// We must call RunBackOnWorkerThread() also if the runnable is canceled.
nsresult
Cancel() override
{
WorkerRun(nullptr, mWorkerPrivate);
return NS_OK;
return MainThreadWorkerControlRunnable::Cancel();
}
virtual bool
@ -730,10 +730,14 @@ WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread()
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
mRunnable->RunBackOnWorkerThread();
if (mRunnable) {
mRunnable->RunBackOnWorkerThread();
// Let's release the worker thread.
mRunnable->ReleaseWorker();
mRunnable = nullptr;
}
// Let's release the worker thread.
mRunnable->ReleaseWorker();
return true;
}

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

@ -48,6 +48,7 @@ UNIFIED_SOURCES += [
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/docshell/base',
'/dom/base',
'/dom/svg',
'/layout/style',

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

@ -13,6 +13,14 @@ interface nsIDOMWindow;
interface mozIDOMWindowProxy;
interface nsIWeakReference;
%{C++
namespace mozilla {
class DocShellOriginAttributes;
}
%}
[ref] native const_OriginAttributesRef(const mozilla::DocShellOriginAttributes);
/**
* The nsIWebBrowser interface is implemented by web browser objects.
* Embedders use this interface during initialisation to associate
@ -144,4 +152,12 @@ interface nsIWebBrowser : nsISupports
* appropriate.
*/
attribute boolean isActive;
/**
* Set Origin Attributes on the nsIWebBrowser.
* The Origin Attributes will be passed to the docshell once it has been
* created
*/
[noscript, notxpcom, nostdcall, binaryname(SetOriginAttributes)]
void binarySetOriginAttributes(in const_OriginAttributesRef aOriginAttrs);
};

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

@ -39,6 +39,7 @@
#include "Layers.h"
#include "gfxContext.h"
#include "nsILoadContext.h"
#include "nsDocShell.h"
// for painting the background window
#include "mozilla/LookAndFeel.h"
@ -388,6 +389,12 @@ nsWebBrowser::SetIsActive(bool aIsActive)
return NS_OK;
}
void
nsWebBrowser::SetOriginAttributes(const DocShellOriginAttributes& aAttrs)
{
mOriginAttributes = aAttrs;
}
//*****************************************************************************
// nsWebBrowser::nsIDocShellTreeItem
//*****************************************************************************
@ -1193,6 +1200,7 @@ nsWebBrowser::Create()
nsCOMPtr<nsIDocShell> docShell(
do_CreateInstance("@mozilla.org/docshell;1", &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsDocShell::Cast(docShell)->SetOriginAttributes(mOriginAttributes);
rv = SetDocShell(docShell);
NS_ENSURE_SUCCESS(rv, rv);

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

@ -38,6 +38,7 @@
#include "nsEmbedStream.h"
#include "nsIWidgetListener.h"
#include "mozilla/BasePrincipal.h"
#include "nsTArray.h"
#include "nsWeakPtr.h"
@ -132,6 +133,7 @@ protected:
nsCOMPtr<nsIWebNavigation> mDocShellAsNav;
nsCOMPtr<nsIScrollable> mDocShellAsScrollable;
nsCOMPtr<nsITextScroll> mDocShellAsTextScroll;
mozilla::DocShellOriginAttributes mOriginAttributes;
nsCOMPtr<nsIWidget> mInternalWidget;
nsCOMPtr<nsIWindowWatcher> mWWatch;

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

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "libyuv.h"
#include "MacIOSurfaceHelpers.h"
#include "mozilla/gfx/MacIOSurface.h"
#include "YCbCrUtils.h"
@ -84,58 +85,13 @@ CreateSourceSurfaceFromLockedMacIOSurface(MacIOSurface* aSurface)
ConvertYCbCrToRGB(data, SurfaceFormat::B8G8R8X8, IntSize::Truncate(ioWidth, ioHeight), mappedSurface.mData, mappedSurface.mStride);
} else if (ioFormat == SurfaceFormat::YUV422) {
/* Convert to YV16 */
size_t cbCrWidth = (ioWidth+1)>>1;
size_t cbCrHeight = ioHeight;
// Ensure our stride is a multiple of 32 to allow for memory aligned rows.
size_t cbCrStride = ALIGNED_32(cbCrWidth);
size_t strideDelta = cbCrStride - cbCrWidth;
MOZ_ASSERT(strideDelta <= 31);
auto yPlane = MakeUnique<uint8_t[]>(cbCrStride * 2 * ioHeight + 31);
auto cbPlane = MakeUnique<uint8_t[]>(cbCrStride * cbCrHeight + 31);
auto crPlane = MakeUnique<uint8_t[]>(cbCrStride * cbCrHeight + 31);
uint8_t* src = (uint8_t*)aSurface->GetBaseAddress();
uint8_t* yDest = ALIGNEDPTR_32(yPlane.get());
uint8_t* cbDest = ALIGNEDPTR_32(cbPlane.get());
uint8_t* crDest = ALIGNEDPTR_32(crPlane.get());
for (size_t i = 0; i < ioHeight; i++) {
uint8_t* rowSrc = src + bytesPerRow * i;
for (size_t j = 0; j < cbCrWidth; j++) {
*cbDest = *rowSrc;
cbDest++;
rowSrc++;
*yDest = *rowSrc;
yDest++;
rowSrc++;
*crDest = *rowSrc;
crDest++;
rowSrc++;
*yDest = *rowSrc;
yDest++;
rowSrc++;
}
if (strideDelta) {
cbDest += strideDelta;
crDest += strideDelta;
yDest += strideDelta << 1;
}
}
/* Convert to RGB */
PlanarYCbCrData data;
data.mYChannel = ALIGNEDPTR_32(yPlane.get());
data.mYStride = cbCrStride * 2;
data.mYSize = IntSize::Truncate(ioWidth, ioHeight);
data.mCbChannel = ALIGNEDPTR_32(cbPlane.get());
data.mCrChannel = ALIGNEDPTR_32(crPlane.get());
data.mCbCrStride = cbCrStride;
data.mCbCrSize = IntSize::Truncate(cbCrWidth, cbCrHeight);
data.mPicSize = data.mYSize;
ConvertYCbCrToRGB(data, SurfaceFormat::B8G8R8X8, IntSize::Truncate(ioWidth, ioHeight), mappedSurface.mData, mappedSurface.mStride);
IntSize size = IntSize::Truncate(ioWidth, ioHeight);
libyuv::ConvertToARGB((uint8_t*)aSurface->GetBaseAddress(), 0 /* not used */,
mappedSurface.mData, mappedSurface.mStride,
0, 0,
size.width, size.height,
size.width, size.height,
libyuv::kRotate0, libyuv::FOURCC_UYVY);
} else {
unsigned char* ioData = (unsigned char*)aSurface->GetBaseAddress();

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

@ -394,12 +394,21 @@ public:
* Lock the texture host for compositing.
*/
virtual bool Lock() { return true; }
/**
* Unlock the texture host after compositing.
* Unlock the texture host after compositing. Lock() and Unlock() should be
* called in pair.
*/
virtual void Unlock() {}
/**
* Lock the texture host for compositing without using compositor.
*/
virtual bool LockWithoutCompositor() { return true; }
/**
* Similar to Unlock(), but it should be called with LockWithoutCompositor().
*/
virtual void UnlockWithoutCompositor() {}
/**
* Note that the texture host format can be different from its corresponding
* texture source's. For example a ShmemTextureHost can have the ycbcr
@ -811,6 +820,29 @@ private:
bool mLocked;
};
class MOZ_STACK_CLASS AutoLockTextureHostWithoutCompositor
{
public:
explicit AutoLockTextureHostWithoutCompositor(TextureHost* aTexture)
: mTexture(aTexture)
{
mLocked = mTexture ? mTexture->LockWithoutCompositor() : false;
}
~AutoLockTextureHostWithoutCompositor()
{
if (mTexture && mLocked) {
mTexture->UnlockWithoutCompositor();
}
}
bool Failed() { return mTexture && !mLocked; }
private:
RefPtr<TextureHost> mTexture;
bool mLocked;
};
/**
* This can be used as an offscreen rendering target by the compositor, and
* subsequently can be used as a source by the compositor.

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

@ -733,11 +733,40 @@ DXGITextureHostD3D11::GetCompositor()
bool
DXGITextureHostD3D11::Lock()
{
/**
* Note: This function may be called when mCompositor is null
* such as during WebVR frame submission.
**/
if (!mCompositor) {
// Make an early return here if we call SetCompositor() with an incompatible
// compositor. This check tries to prevent the problem where we use that
// incompatible compositor to compose this texture.
return false;
}
return LockInternal();
}
bool
DXGITextureHostD3D11::LockWithoutCompositor()
{
// Unlike the normal Lock() function, this function may be called when
// mCompositor is nullptr such as during WebVR frame submission. So, there is
// no 'mCompositor' checking here.
return LockInternal();
}
void
DXGITextureHostD3D11::Unlock()
{
UnlockInternal();
}
void
DXGITextureHostD3D11::UnlockWithoutCompositor()
{
UnlockInternal();
}
bool
DXGITextureHostD3D11::LockInternal()
{
if (!GetDevice()) {
NS_WARNING("trying to lock a TextureHost without a D3D device");
return false;
@ -758,7 +787,7 @@ DXGITextureHostD3D11::Lock()
}
void
DXGITextureHostD3D11::Unlock()
DXGITextureHostD3D11::UnlockInternal()
{
UnlockD3DTexture(mTextureSource->GetD3D11Texture());
}

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

@ -296,9 +296,11 @@ public:
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual bool Lock() override;
virtual void Unlock() override;
virtual bool LockWithoutCompositor() override;
virtual void UnlockWithoutCompositor() override;
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
@ -307,6 +309,9 @@ public:
}
protected:
bool LockInternal();
void UnlockInternal();
RefPtr<ID3D11Device> GetDevice();
bool OpenSharedHandle();

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

@ -83,7 +83,9 @@ VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, const int32_t& aInputFrameID,
// compensate.
TextureHost* th = TextureHost::AsTextureHost(aTexture);
AutoLockTextureHost autoLock(th);
// WebVR doesn't use the compositor to compose the frame, so use
// AutoLockTextureHostWithoutCompositor here.
AutoLockTextureHostWithoutCompositor autoLock(th);
if (autoLock.Failed()) {
NS_WARNING("Failed to lock the VR layer texture");
return;

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

@ -350,6 +350,20 @@ SVGDocumentWrapper::SetupViewer(nsIRequest* aRequest,
NS_ENSURE_TRUE(viewer, NS_ERROR_UNEXPECTED);
// Create a navigation time object and pass it to the SVG document through
// the viewer.
// The timeline(DocumentTimeline, used in CSS animation) of this SVG
// document needs this navigation timing object for time computation, such
// as to calculate current time stamp based on the start time of navigation
// time object.
//
// For a root document, DocShell would do these sort of things
// automatically. Since there is no DocShell for this wrapped SVG document,
// we must set it up manually.
RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming();
timing->NotifyNavigationStart();
viewer->SetNavigationTiming(timing);
nsCOMPtr<nsIParser> parser = do_QueryInterface(listener);
NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);

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

@ -525,6 +525,12 @@ VectorImage::RequestRefresh(const TimeStamp& aTime)
return;
}
PendingAnimationTracker* tracker =
mSVGDocumentWrapper->GetDocument()->GetPendingAnimationTracker();
if (tracker && ShouldAnimate()) {
tracker->TriggerPendingAnimationsOnNextTick(aTime);
}
EvaluateAnimation();
mSVGDocumentWrapper->TickRefreshDriver();

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

@ -0,0 +1,19 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="100" height="100">
<defs>
<style>
#myRect {
animation-duration: 0.1s;
animation-name: fade;
animation-fill-mode: forwards;
}
@keyframes fade {
0% { fill-opacity: 0 }
100% { fill-opacity: 1 }
}
</style>
</defs>
<rect width="100%" height="100%" fill="red"/>
<rect id="myRect" width="100%" height="100%" fill="lime" fill-opacity="0"/>
</svg>

После

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

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

@ -62,6 +62,7 @@ support-files =
lime100x100.svg
lime-anim-100x100.svg
lime-anim-100x100-2.svg
lime-css-anim-100x100.svg
opaque.bmp
purple.gif
red.gif

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

@ -33,7 +33,11 @@ var gMyDecoderObserver; // value will be set in main()
var gReferenceSnapshot; // value will be set in takeReferenceSnapshot()
var gPollCounter = 0;
var gIsTestFinished = false;
var gSVGImages = [
"lime-anim-100x100.svg", // SMIL animation
"lime-css-anim-100x100.svg" // CSS animation
]
var gSVGCurrentImage = 0;
function takeReferenceSnapshot() {
// Take a snapshot of the initial (essentially blank) page
@ -53,6 +57,13 @@ function takeReferenceSnapshot() {
"reference div should disappear when it becomes display:none");
}
function loadNextImageAndPoll()
{
setTimeout(myPoll, 1);
// kick off image-loading! myPoll handles the rest.
gImg.setAttribute("src", gSVGImages[gSVGCurrentImage]);
}
function myPoll() {
gPollCounter++;
ok(true, "myPoll called");
@ -61,7 +72,12 @@ function myPoll() {
// SUCCESS!
ok(true, "Animated image looks correct, " +
"at call #" + gPollCounter + " to myPoll");
cleanUpAndFinish();
if (++gSVGCurrentImage > gSVGImages.length) {
cleanUpAndFinish();
} else {
loadNextImageAndPoll();
}
}
else
setTimeout(myPoll, 1);
@ -91,10 +107,7 @@ function main() {
// earlier test got our image in there already.
clearAllImageCaches();
setTimeout(myPoll, 1);
// kick off image-loading! myPoll handles the rest.
gImg.setAttribute("src", "lime-anim-100x100.svg");
loadNextImageAndPoll();
// In case something goes wrong, fail earlier than mochitest timeout,
// and with more information.

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

@ -10,7 +10,6 @@
// This file is only meant to compile on windows
#include <windows.h>
#include "base/basictypes.h"
#include "nsISupportsImpl.h"
namespace mozilla {

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

@ -3,6 +3,7 @@ asm.js/testParallelCompile.js
auto-regress/bug653395.js
auto-regress/bug654392.js
auto-regress/bug675251.js
auto-regress/bug729797.js
baseline/bug847446.js
baseline/bug852175.js
basic/bug632964-regexp.js

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

@ -51,6 +51,7 @@ js1_5/GC/regress-203278-2.js
js1_5/GC/regress-203278-3.js
js1_5/GC/regress-278725.js
js1_5/Regress/regress-312588.js
js1_5/Regress/regress-321971.js
js1_5/Regress/regress-360969-01.js
js1_5/Regress/regress-360969-02.js
js1_5/Regress/regress-360969-03.js

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

@ -1782,7 +1782,7 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
nsIFrame* frame = aBuilder->RootReferenceFrame();
nsPresContext* presContext = frame->PresContext();
nsIPresShell* presShell = presContext->GetPresShell();
nsIPresShell* presShell = presContext->PresShell();
nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
NotifySubDocInvalidationFunc computeInvalidFunc =
@ -1809,10 +1809,7 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this,
containerParameters, nullptr);
nsIDocument* document = nullptr;
if (presShell) {
document = presShell->GetDocument();
}
nsIDocument* document = presShell->GetDocument();
if (!root) {
layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);

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

@ -148,6 +148,7 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
aAttrs.mSignedPkg = aSerialized.mOriginAttributes.mSignedPkg;
aAttrs.mUserContextId = aSerialized.mOriginAttributes.mUserContextId;
aAttrs.mPrivateBrowsingId = aSerialized.mOriginAttributes.mPrivateBrowsingId;
aAttrs.mFirstPartyDomain = aSerialized.mOriginAttributes.mFirstPartyDomain;
return nullptr;
}

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

@ -2901,6 +2901,36 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
if (mLoadInfo) {
nsCOMPtr<nsILoadInfo> newLoadInfo =
static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
// re-compute the origin attributes of the loadInfo if it's top-level load.
bool isTopLevelDoc =
newLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT;
if (isTopLevelDoc) {
nsCOMPtr<nsILoadContext> loadContext;
NS_QueryNotificationCallbacks(this, loadContext);
DocShellOriginAttributes docShellAttrs;
if (loadContext) {
loadContext->GetOriginAttributes(docShellAttrs);
}
MOZ_ASSERT(docShellAttrs.mFirstPartyDomain.IsEmpty(),
"top-level docshell shouldn't have firstPartyDomain attribute.");
NeckoOriginAttributes attrs = newLoadInfo->GetOriginAttributes();
MOZ_ASSERT(docShellAttrs.mAppId == attrs.mAppId,
"docshell and necko should have the same appId attribute.");
MOZ_ASSERT(docShellAttrs.mUserContextId == attrs.mUserContextId,
"docshell and necko should have the same userContextId attribute.");
MOZ_ASSERT(docShellAttrs.mInIsolatedMozBrowser == attrs.mInIsolatedMozBrowser,
"docshell and necko should have the same inIsolatedMozBrowser attribute.");
MOZ_ASSERT(docShellAttrs.mPrivateBrowsingId == attrs.mPrivateBrowsingId,
"docshell and necko should have the same privateBrowsingId attribute.");
attrs.InheritFromDocShellToNecko(docShellAttrs, true, newURI);
newLoadInfo->SetOriginAttributes(attrs);
}
bool isInternalRedirect =
(redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
nsIChannelEventSink::REDIRECT_STS_UPGRADE));

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

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a copy of a file that is generated by the chromium build.
// Generated by build/write_buildflag_header.py
// From "//base:debugging_flags"
#ifndef BASE_DEBUG_DEBUGGING_FLAGS_H_
#define BASE_DEBUG_DEBUGGING_FLAGS_H_
#include "build/buildflag.h"
#define BUILDFLAG_INTERNAL_ENABLE_PROFILING() (0)
#endif // BASE_DEBUG_DEBUGGING_FLAGS_H_

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

@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a dummy version of Chromium source file base/file_version_info_win.h
// Within our copy of Chromium files FileVersionInfoWin is only used in
// base/win/windows_version.cc in GetVersionFromKernel32, which we don't use.
#ifndef BASE_FILE_VERSION_INFO_WIN_H_
#define BASE_FILE_VERSION_INFO_WIN_H_
struct tagVS_FIXEDFILEINFO;
typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO;
namespace base {
class FilePath;
}
class FileVersionInfoWin {
public:
static FileVersionInfoWin*
CreateFileVersionInfo(const base::FilePath& file_path) { return nullptr; }
VS_FIXEDFILEINFO* fixed_file_info() { return nullptr; }
};
#endif // BASE_FILE_VERSION_INFO_WIN_H_

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

@ -0,0 +1,19 @@
// Copyright (c) 2012 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.
// This is a dummy version of Chromium source file base/file/file_path.cc.
// To provide the functions required in base/win/windows_version.cc
// GetVersionFromKernel32, which we don't use.
#include "base/files/file_path.h"
namespace base {
FilePath::FilePath(FilePath::StringPieceType path) {
}
FilePath::~FilePath() {
}
} // namespace base

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

@ -26,16 +26,41 @@
#include "base/strings/utf_string_conversions.h"
#endif
#include <algorithm>
namespace logging {
namespace {
int min_log_level = 0;
int g_min_log_level = 0;
LoggingDestination g_logging_destination = LOG_DEFAULT;
// For LOG_ERROR and above, always print to stderr.
const int kAlwaysPrintErrorLevel = LOG_ERROR;
// A log message handler that gets notified of every log message we process.
LogMessageHandlerFunction log_message_handler = nullptr;
} // namespace
void SetMinLogLevel(int level) {
g_min_log_level = std::min(LOG_FATAL, level);
}
int GetMinLogLevel() {
return min_log_level;
return g_min_log_level;
}
bool ShouldCreateLogMessage(int severity) {
if (severity < g_min_log_level)
return false;
// Return true here unless we know ~LogMessage won't do anything. Note that
// ~LogMessage writes to stderr if severity_ >= kAlwaysPrintErrorLevel, even
// when g_logging_destination is LOG_NONE.
return g_logging_destination != LOG_NONE || log_message_handler ||
severity >= kAlwaysPrintErrorLevel;
}
int GetVlogLevelHelper(const char* file, size_t N) {
@ -67,6 +92,10 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
: severity_(severity), file_(file), line_(line) {
}
LogMessage::LogMessage(const char* file, int line, const char* condition)
: severity_(LOG_FATAL), file_(file), line_(line) {
}
LogMessage::LogMessage(const char* file, int line, std::string* result)
: severity_(LOG_FATAL), file_(file), line_(line) {
delete result;

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

@ -48,6 +48,24 @@ typedef LPSTARTUPINFOEXA LPSTARTUPINFOEX;
#define PROCESS_DEP_ENABLE 0x00000001
#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
// They dynamically load these, but they still use the functions to describe the
// function pointers!
WINBASEAPI
int
WINAPI
GetUserDefaultLocaleName(
_Out_writes_(cchLocaleName) LPWSTR lpLocaleName,
_In_ int cchLocaleName
);
WINBASEAPI
BOOL
WINAPI
QueryThreadCycleTime(
_In_ HANDLE ThreadHandle,
_Out_ PULONG64 CycleTime
);
#endif // (_WIN32_WINNT >= 0x0600)
#if (_WIN32_WINNT < 0x0601)

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

@ -1,4 +1,4 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Copyright 2015 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are

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

@ -8,8 +8,8 @@
#include <stack>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
namespace base {

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

@ -4,9 +4,6 @@
// This is a low level implementation of atomic semantics for reference
// counting. Please use base/memory/ref_counted.h directly instead.
//
// The implementation includes annotations to avoid some false positives
// when using data race detection tools.
#ifndef BASE_ATOMIC_REF_COUNT_H_
#define BASE_ATOMIC_REF_COUNT_H_

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

@ -6,7 +6,7 @@
#define BASE_ATOMIC_SEQUENCE_NUM_H_
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/macros.h"
namespace base {

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

@ -28,10 +28,14 @@
#ifndef BASE_ATOMICOPS_H_
#define BASE_ATOMICOPS_H_
#include <cassert> // Small C++ header which defines implementation specific
// macros used to identify the STL implementation.
#include <stdint.h>
// Small C++ header which defines implementation specific macros used to
// identify the STL implementation.
// - libc++: captures __config for _LIBCPP_VERSION
// - libstdc++: captures bits/c++config.h for __GLIBCXX__
#include <cstddef>
#include "base/base_export.h"
#include "build/build_config.h"
@ -140,65 +144,13 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
} // namespace subtle
} // namespace base
// The following x86 CPU features are used in atomicops_internals_x86_gcc.h, but
// this file is duplicated inside of Chrome: protobuf and tcmalloc rely on the
// struct being present at link time. Some parts of Chrome can currently use the
// portable interface whereas others still use GCC one. The include guards are
// the same as in atomicops_internals_x86_gcc.cc.
#if defined(__i386__) || defined(__x86_64__)
// This struct is not part of the public API of this module; clients may not
// use it. (However, it's exported via BASE_EXPORT because clients implicitly
// do use it at link time by inlining these functions.)
// Features of this x86. Values may not be correct before main() is run,
// but are set conservatively.
struct AtomicOps_x86CPUFeatureStruct {
bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
// after acquire compare-and-swap.
// The following fields are unused by Chrome's base implementation but are
// still used by copies of the same code in other parts of the code base. This
// causes an ODR violation, and the other code is likely reading invalid
// memory.
// TODO(jfb) Delete these fields once the rest of the Chrome code base doesn't
// depend on them.
bool has_sse2; // Processor has SSE2.
bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction.
};
BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct
AtomicOps_Internalx86CPUFeatures;
#endif
// Try to use a portable implementation based on C++11 atomics.
//
// Some toolchains support C++11 language features without supporting library
// features (recent compiler, older STL). Whitelist libstdc++ and libc++ that we
// know will have <atomic> when compiling C++11.
#if ((__cplusplus >= 201103L) && \
((defined(__GLIBCXX__) && (__GLIBCXX__ > 20110216)) || \
(defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER >= 11))))
#if defined(OS_WIN)
// TODO(jfb): The MSVC header includes windows.h, which other files end up
// relying on. Fix this as part of crbug.com/559247.
# include "base/atomicops_internals_x86_msvc.h"
#else
# include "base/atomicops_internals_portable.h"
#else // Otherwise use a platform specific implementation.
# if defined(THREAD_SANITIZER)
# error "Thread sanitizer must use the portable atomic operations"
# elif (defined(OS_WIN) && defined(COMPILER_MSVC) && \
defined(ARCH_CPU_X86_FAMILY))
# include "base/atomicops_internals_x86_msvc.h"
# elif defined(OS_MACOSX)
# include "base/atomicops_internals_mac.h"
# elif defined(OS_NACL)
# include "base/atomicops_internals_gcc.h"
# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL)
# include "base/atomicops_internals_arm_gcc.h"
# elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64)
# include "base/atomicops_internals_arm64_gcc.h"
# elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
# include "base/atomicops_internals_x86_gcc.h"
# elif (defined(COMPILER_GCC) && \
(defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY)))
# include "base/atomicops_internals_mips_gcc.h"
# else
# error "Atomic operations are not supported on your platform"
# endif
#endif // Portable / non-portable includes.
#endif
// On some platforms we need additional declarations to make
// AtomicWord compatible with our other Atomic* types.

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

@ -1,294 +0,0 @@
// Copyright 2013 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.
// This file is an internal atomic implementation, use base/atomicops.h instead.
//
// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
#if defined(OS_QNX)
#include <sys/cpuinline.h>
#endif
namespace base {
namespace subtle {
// Memory barriers on ARM are funky, but the kernel is here to help:
//
// * ARMv5 didn't support SMP, there is no memory barrier instruction at
// all on this architecture, or when targeting its machine code.
//
// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by
// writing a random value to a very specific coprocessor register.
//
// * On ARMv7, the "dmb" instruction is used to perform a full memory
// barrier (though writing to the co-processor will still work).
// However, on single core devices (e.g. Nexus One, or Nexus S),
// this instruction will take up to 200 ns, which is huge, even though
// it's completely un-needed on these devices.
//
// * There is no easy way to determine at runtime if the device is
// single or multi-core. However, the kernel provides a useful helper
// function at a fixed memory address (0xffff0fa0), which will always
// perform a memory barrier in the most efficient way. I.e. on single
// core devices, this is an empty function that exits immediately.
// On multi-core devices, it implements a full memory barrier.
//
// * This source could be compiled to ARMv5 machine code that runs on a
// multi-core ARMv6 or ARMv7 device. In this case, memory barriers
// are needed for correct execution. Always call the kernel helper, even
// when targeting ARMv5TE.
//
inline void MemoryBarrier() {
#if defined(OS_LINUX) || defined(OS_ANDROID)
// Note: This is a function call, which is also an implicit compiler barrier.
typedef void (*KernelMemoryBarrierFunc)();
((KernelMemoryBarrierFunc)0xffff0fa0)();
#elif defined(OS_QNX)
__cpu_membarrier();
#else
#error MemoryBarrier() is not implemented on this platform.
#endif
}
// An ARM toolchain would only define one of these depending on which
// variant of the target architecture is being used. This tests against
// any known ARMv6 or ARMv7 variant, where it is possible to directly
// use ldrex/strex instructions to implement fast atomic operations.
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
int reloop;
do {
// The following is equivalent to:
//
// prev_value = LDREX(ptr)
// reloop = 0
// if (prev_value != old_value)
// reloop = STREX(ptr, new_value)
__asm__ __volatile__(" ldrex %0, [%3]\n"
" mov %1, #0\n"
" cmp %0, %4\n"
#ifdef __thumb2__
" it eq\n"
#endif
" strexeq %1, %5, [%3]\n"
: "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr)
: "r"(ptr), "r"(old_value), "r"(new_value)
: "cc", "memory");
} while (reloop != 0);
return prev_value;
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
MemoryBarrier();
return result;
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
MemoryBarrier();
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
Atomic32 value;
int reloop;
do {
// Equivalent to:
//
// value = LDREX(ptr)
// value += increment
// reloop = STREX(ptr, value)
//
__asm__ __volatile__(" ldrex %0, [%3]\n"
" add %0, %0, %4\n"
" strex %1, %0, [%3]\n"
: "=&r"(value), "=&r"(reloop), "+m"(*ptr)
: "r"(ptr), "r"(increment)
: "cc", "memory");
} while (reloop);
return value;
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
// TODO(digit): Investigate if it's possible to implement this with
// a single MemoryBarrier() operation between the LDREX and STREX.
// See http://crbug.com/246514
MemoryBarrier();
Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
MemoryBarrier();
return result;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
Atomic32 old_value;
int reloop;
do {
// old_value = LDREX(ptr)
// reloop = STREX(ptr, new_value)
__asm__ __volatile__(" ldrex %0, [%3]\n"
" strex %1, %4, [%3]\n"
: "=&r"(old_value), "=&r"(reloop), "+m"(*ptr)
: "r"(ptr), "r"(new_value)
: "cc", "memory");
} while (reloop != 0);
return old_value;
}
// This tests against any known ARMv5 variant.
#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
// The kernel also provides a helper function to perform an atomic
// compare-and-swap operation at the hard-wired address 0xffff0fc0.
// On ARMv5, this is implemented by a special code path that the kernel
// detects and treats specially when thread pre-emption happens.
// On ARMv6 and higher, it uses LDREX/STREX instructions instead.
//
// Note that this always perform a full memory barrier, there is no
// need to add calls MemoryBarrier() before or after it. It also
// returns 0 on success, and 1 on exit.
//
// Available and reliable since Linux 2.6.24. Both Android and ChromeOS
// use newer kernel revisions, so this should not be a concern.
namespace {
inline int LinuxKernelCmpxchg(Atomic32 old_value,
Atomic32 new_value,
volatile Atomic32* ptr) {
typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*);
return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr);
}
} // namespace
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
for (;;) {
prev_value = *ptr;
if (prev_value != old_value)
return prev_value;
if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
return old_value;
}
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
Atomic32 old_value;
do {
old_value = *ptr;
} while (LinuxKernelCmpxchg(old_value, new_value, ptr));
return old_value;
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return Barrier_AtomicIncrement(ptr, increment);
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
for (;;) {
// Atomic exchange the old value with an incremented one.
Atomic32 old_value = *ptr;
Atomic32 new_value = old_value + increment;
if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) {
// The exchange took place as expected.
return new_value;
}
// Otherwise, *ptr changed mid-loop and we need to retry.
}
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
for (;;) {
prev_value = *ptr;
if (prev_value != old_value) {
// Always ensure acquire semantics.
MemoryBarrier();
return prev_value;
}
if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
return old_value;
}
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
// This could be implemented as:
// MemoryBarrier();
// return NoBarrier_CompareAndSwap();
//
// But would use 3 barriers per succesful CAS. To save performance,
// use Acquire_CompareAndSwap(). Its implementation guarantees that:
// - A succesful swap uses only 2 barriers (in the kernel helper).
// - An early return due to (prev_value != old_value) performs
// a memory barrier with no store, which is equivalent to the
// generic implementation above.
return Acquire_CompareAndSwap(ptr, old_value, new_value);
}
#else
# error "Your CPU's ARM architecture is not supported yet"
#endif
// NOTE: Atomicity of the following load and store operations is only
// guaranteed in case of 32-bit alignement of |ptr| values.
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; }
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr;
MemoryBarrier();
return value;
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return *ptr;
}
} // namespace base::subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_

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

@ -34,6 +34,8 @@
#include <atomic>
#include "build/build_config.h"
namespace base {
namespace subtle {
@ -221,7 +223,7 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
}
#endif // defined(ARCH_CPU_64_BITS)
}
} // namespace base::subtle
} // namespace subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_

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

@ -1,228 +0,0 @@
// Copyright (c) 2011 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.
// This file is an internal atomic implementation, use base/atomicops.h instead.
#ifndef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
#define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
namespace base {
namespace subtle {
// 32-bit low-level operations on any platform.
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev;
__asm__ __volatile__("lock; cmpxchgl %1,%2"
: "=a" (prev)
: "q" (new_value), "m" (*ptr), "0" (old_value)
: "memory");
return prev;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
__asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg.
: "=r" (new_value)
: "m" (*ptr), "0" (new_value)
: "memory");
return new_value; // Now it's the previous value.
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
Atomic32 temp = increment;
__asm__ __volatile__("lock; xaddl %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now holds the old value of *ptr
return temp + increment;
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
Atomic32 temp = increment;
__asm__ __volatile__("lock; xaddl %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now holds the old value of *ptr
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return temp + increment;
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return x;
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void MemoryBarrier() {
__asm__ __volatile__("mfence" : : : "memory");
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
ATOMICOPS_COMPILER_BARRIER();
*ptr = value; // An x86 store acts as a release barrier.
// See comments in Atomic64 version of Release_Store(), below.
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
return *ptr;
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
// See comments in Atomic64 version of Release_Store(), below.
ATOMICOPS_COMPILER_BARRIER();
return value;
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return *ptr;
}
#if defined(__x86_64__)
// 64-bit low-level operations on 64-bit platform.
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev;
__asm__ __volatile__("lock; cmpxchgq %1,%2"
: "=a" (prev)
: "q" (new_value), "m" (*ptr), "0" (old_value)
: "memory");
return prev;
}
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
__asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg.
: "=r" (new_value)
: "m" (*ptr), "0" (new_value)
: "memory");
return new_value; // Now it's the previous value.
}
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
Atomic64 temp = increment;
__asm__ __volatile__("lock; xaddq %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now contains the previous value of *ptr
return temp + increment;
}
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
Atomic64 temp = increment;
__asm__ __volatile__("lock; xaddq %0,%1"
: "+r" (temp), "+m" (*ptr)
: : "memory");
// temp now contains the previous value of *ptr
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return temp + increment;
}
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
ATOMICOPS_COMPILER_BARRIER();
*ptr = value; // An x86 store acts as a release barrier
// for current AMD/Intel chips as of Jan 2008.
// See also Acquire_Load(), below.
// When new chips come out, check:
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
// System Programming Guide, Chatper 7: Multiple-processor management,
// Section 7.2, Memory Ordering.
// Last seen at:
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
//
// x86 stores/loads fail to act as barriers for a few instructions (clflush
// maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
// not generated by the compiler, and are rare. Users of these instructions
// need to know about cache behaviour in any case since all of these involve
// either flushing cache lines or non-temporal cache hints.
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
return *ptr;
}
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
// for current AMD/Intel chips as of Jan 2008.
// See also Release_Store(), above.
ATOMICOPS_COMPILER_BARRIER();
return value;
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
MemoryBarrier();
return *ptr;
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
__asm__ __volatile__("lfence" : : : "memory");
}
return x;
}
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
#endif // defined(__x86_64__)
} // namespace base::subtle
} // namespace base
#undef ATOMICOPS_COMPILER_BARRIER
#endif // BASE_ATOMICOPS_INTERNALS_X86_GCC_H_

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

@ -12,6 +12,7 @@
#include <intrin.h>
#include "base/macros.h"
#include "build/build_config.h"
#if defined(ARCH_CPU_64_BITS)
// windows.h #defines this (only on x64). This causes problems because the
@ -55,9 +56,6 @@ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
return Barrier_AtomicIncrement(ptr, increment);
}
#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
#error "We require at least vs2005 for MemoryBarrier"
#endif
inline void MemoryBarrier() {
#if defined(ARCH_CPU_64_BITS)
// See #undef and note at the top of this file.
@ -112,7 +110,7 @@ inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
// 64-bit low-level operations on 64-bit platform.
COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic);
static_assert(sizeof(Atomic64) == sizeof(PVOID), "atomic word is atomic");
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
@ -192,7 +190,7 @@ inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
#endif // defined(_WIN64)
} // namespace base::subtle
} // namespace subtle
} // namespace base
#endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_

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

@ -10,25 +10,20 @@
#if defined(BASE_IMPLEMENTATION)
#define BASE_EXPORT __declspec(dllexport)
#define BASE_EXPORT_PRIVATE __declspec(dllexport)
#else
#define BASE_EXPORT __declspec(dllimport)
#define BASE_EXPORT_PRIVATE __declspec(dllimport)
#endif // defined(BASE_IMPLEMENTATION)
#else // defined(WIN32)
#if defined(BASE_IMPLEMENTATION)
#define BASE_EXPORT __attribute__((visibility("default")))
#define BASE_EXPORT_PRIVATE __attribute__((visibility("default")))
#else
#define BASE_EXPORT
#define BASE_EXPORT_PRIVATE
#endif // defined(BASE_IMPLEMENTATION)
#endif
#else // defined(COMPONENT_BUILD)
#define BASE_EXPORT
#define BASE_EXPORT_PRIVATE
#endif
#endif // BASE_BASE_EXPORT_H_

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

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_BASE_PATHS_WIN_H__
#define BASE_BASE_PATHS_WIN_H__
#ifndef BASE_BASE_PATHS_WIN_H_
#define BASE_BASE_PATHS_WIN_H_
// This file declares windows-specific path keys for the base module.
// These can be used with the PathService to access various special
@ -16,8 +16,14 @@ enum {
DIR_WINDOWS, // Windows directory, usually "c:\windows"
DIR_SYSTEM, // Usually c:\windows\system32"
DIR_PROGRAM_FILES, // Usually c:\program files
DIR_PROGRAM_FILESX86, // Usually c:\program files or c:\program files (x86)
// 32-bit 32-bit on 64-bit 64-bit on 64-bit
// DIR_PROGRAM_FILES 1 2 1
// DIR_PROGRAM_FILESX86 1 2 2
// DIR_PROGRAM_FILES6432 1 1 1
// 1 - C:\Program Files 2 - C:\Program Files (x86)
DIR_PROGRAM_FILES, // See table above.
DIR_PROGRAM_FILESX86, // See table above.
DIR_PROGRAM_FILES6432, // See table above.
DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory.
DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\
@ -36,8 +42,8 @@ enum {
DIR_COMMON_DESKTOP, // Directory for the common desktop (visible
// on all user's Desktop).
DIR_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts.
DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar via
// base::win::TaskbarPinShortcutLink().
DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar
// (Win7-8) via base::win::PinShortcutToTaskbar().
DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts.
PATH_WIN_END
@ -45,4 +51,4 @@ enum {
} // namespace base
#endif // BASE_BASE_PATHS_WIN_H__
#endif // BASE_BASE_PATHS_WIN_H_

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

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/base_switches.h"
#include "build/build_config.h"
namespace switches {
@ -14,13 +15,29 @@ const char kDisableBreakpad[] = "disable-breakpad";
// generated internally.
const char kEnableCrashReporter[] = "enable-crash-reporter";
// Makes memory allocators keep track of their allocations and context, so a
// detailed breakdown of memory usage can be presented in chrome://tracing when
// the memory-infra category is enabled.
const char kEnableHeapProfiling[] = "enable-heap-profiling";
// Generates full memory crash dump.
const char kFullMemoryCrashReport[] = "full-memory-crash-report";
// Force low-end device when set to 1;
// Auto-detect low-end device when set to 2;
// Force non-low-end device when set to other values or empty;
const char kLowEndDeviceMode[] = "low-end-device-mode";
// Force low-end device mode when set.
const char kEnableLowEndDeviceMode[] = "enable-low-end-device-mode";
// Force disabling of low-end device mode when set.
const char kDisableLowEndDeviceMode[] = "disable-low-end-device-mode";
// This option can be used to force field trials when testing changes locally.
// The argument is a list of name and value pairs, separated by slashes. If a
// trial name is prefixed with an asterisk, that trial will start activated.
// For example, the following argument defines two trials, with the second one
// activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/" This option can
// also be used by the browser process to send the list of trials to a
// non-browser process, using the same format. See
// FieldTrialList::CreateTrialsFromString() in field_trial.h for details.
const char kForceFieldTrials[] = "force-fieldtrials";
// Suppresses all error dialogs when present.
const char kNoErrorDialogs[] = "noerrdialogs";
@ -47,9 +64,6 @@ const char kVModule[] = "vmodule";
// Will wait for 60 seconds for a debugger to come to attach to the process.
const char kWaitForDebugger[] = "wait-for-debugger";
// Sends a pretty-printed version of tracing info to the console.
const char kTraceToConsole[] = "trace-to-console";
// Sends trace events from these categories to a file.
// --trace-to-file on its own sends to default categories.
const char kTraceToFile[] = "trace-to-file";
@ -66,6 +80,11 @@ const char kProfilerTiming[] = "profiler-timing";
// chrome://profiler.
const char kProfilerTimingDisabledValue[] = "0";
#if defined(OS_WIN)
// Disables the USB keyboard detection for blocking the OSK on Win8+.
const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect";
#endif
#if defined(OS_POSIX)
// Used for turning on Breakpad crash reporting in a debug environment where
// crash reporting is typically compiled but disabled.

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

@ -12,20 +12,26 @@
namespace switches {
extern const char kDisableBreakpad[];
extern const char kDisableLowEndDeviceMode[];
extern const char kEnableCrashReporter[];
extern const char kEnableHeapProfiling[];
extern const char kEnableLowEndDeviceMode[];
extern const char kForceFieldTrials[];
extern const char kFullMemoryCrashReport[];
extern const char kLowEndDeviceMode[];
extern const char kNoErrorDialogs[];
extern const char kProfilerTiming[];
extern const char kProfilerTimingDisabledValue[];
extern const char kTestChildProcess[];
extern const char kTraceToConsole[];
extern const char kTraceToFile[];
extern const char kTraceToFileName[];
extern const char kV[];
extern const char kVModule[];
extern const char kWaitForDebugger[];
#if defined(OS_WIN)
extern const char kDisableUsbKeyboardDetect[];
#endif
#if defined(OS_POSIX)
extern const char kEnableCrashReporterForTesting[];
#endif

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

@ -1,45 +0,0 @@
// Copyright 2013 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.
// This file contains definitions of our old basic integral types
// ((u)int{8,16,32,64}) and further includes. I recommend that you use the C99
// standard types instead, and include <stdint.h>/<stddef.h>/etc. as needed.
// Note that the macros and macro-like constructs that were formerly defined in
// this file are now available separately in base/macros.h.
#ifndef BASE_BASICTYPES_H_
#define BASE_BASICTYPES_H_
#include <limits.h> // So we can set the bounds of our types.
#include <stddef.h> // For size_t.
#include <stdint.h> // For intptr_t.
#include "base/macros.h"
#include "base/port.h" // Types that only need exist on certain systems.
// DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include <stdint.h>).
typedef int8_t int8;
typedef uint8_t uint8;
typedef int16_t int16;
typedef uint16_t uint16;
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
// DEPRECATED: Please use std::numeric_limits (from <limits>) instead.
const uint8 kuint8max = 0xFF;
const uint16 kuint16max = 0xFFFF;
const uint32 kuint32max = 0xFFFFFFFF;
const uint64 kuint64max = 0xFFFFFFFFFFFFFFFFULL;
const int8 kint8min = -0x7F - 1;
const int8 kint8max = 0x7F;
const int16 kint16min = -0x7FFF - 1;
const int16 kint16max = 0x7FFF;
const int32 kint32min = -0x7FFFFFFF - 1;
const int32 kint32max = 0x7FFFFFFF;
const int64 kint64min = -0x7FFFFFFFFFFFFFFFLL - 1;
const int64 kint64max = 0x7FFFFFFFFFFFFFFFLL;
#endif // BASE_BASICTYPES_H_

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

@ -1,8 +1,3 @@
// This file was GENERATED by command:
// pump.py bind.h.pump
// DO NOT EDIT BY HAND!!!
// Copyright (c) 2011 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.
@ -46,464 +41,59 @@
//
// TODO(ajwong): We might be able to avoid this now, but need to test.
//
// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>,
// but it feels a little nicer to have the asserts here so people do not
// need to crack open bind_internal.h. On the other hand, it makes Bind()
// harder to read.
// It is possible to move most of the static_assert into BindState<>, but it
// feels a little nicer to have the asserts here so people do not need to crack
// open bind_internal.h. On the other hand, it makes Bind() harder to read.
namespace base {
template <typename Functor>
template <typename Functor, typename... Args>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void()>
typename internal::CallbackParamTraits<Args>::StorageType...>
::UnboundRunType>
Bind(Functor functor) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
typedef internal::BindState<RunnableType, RunType, void()> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor)));
}
template <typename Functor, typename P1>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
Bind(Functor functor, const Args&... args) {
// Type aliases for how to store and run the functor.
using RunnableType = typename internal::FunctorTraits<Functor>::RunnableType;
using RunType = typename internal::FunctorTraits<Functor>::RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// checks below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
using BoundRunType = typename RunnableType::RunType;
using BoundArgs =
internal::TakeTypeListItem<sizeof...(Args),
internal::ExtractArgs<BoundRunType>>;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ),
do_not_bind_functions_with_nonconst_ref);
static_assert(!internal::HasNonConstReferenceItem<BoundArgs>::value,
"do not bind functions with nonconst ref");
const bool is_method = internal::HasIsMethodTag<RunnableType>::value;
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType)> BindState;
static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value,
"first bound argument to method cannot be array");
static_assert(
!internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value,
"a parameter is a refcounted type and needs scoped_refptr");
using BindState = internal::BindState<
RunnableType, RunType,
typename internal::CallbackParamTraits<Args>::StorageType...>;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1));
}
template <typename Functor, typename P1, typename P2>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2));
}
template <typename Functor, typename P1, typename P2, typename P3>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5, const P6& p6) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6));
}
template <typename Functor, typename P1, typename P2, typename P3, typename P4,
typename P5, typename P6, typename P7>
base::Callback<
typename internal::BindState<
typename internal::FunctorTraits<Functor>::RunnableType,
typename internal::FunctorTraits<Functor>::RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)>
::UnboundRunType>
Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4,
const P5& p5, const P6& p6, const P7& p7) {
// Typedefs for how to store and run the functor.
typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
typedef typename internal::FunctorTraits<Functor>::RunType RunType;
// Use RunnableType::RunType instead of RunType above because our
// checks should below for bound references need to know what the actual
// functor is going to interpret the argument as.
typedef internal::FunctionTraits<typename RunnableType::RunType>
BoundFunctorTraits;
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
// non-const reference parameter can make for subtle bugs because the
// invoked function will receive a reference to the stored copy of the
// argument and not the original.
COMPILE_ASSERT(
!(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A2Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A3Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A4Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A5Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A6Type>::value ||
is_non_const_reference<typename BoundFunctorTraits::A7Type>::value ),
do_not_bind_functions_with_nonconst_ref);
// For methods, we need to be careful for parameter 1. We do not require
// a scoped_refptr because BindState<> itself takes care of AddRef() for
// methods. We also disallow binding of an array as the method's target
// object.
COMPILE_ASSERT(
internal::HasIsMethodTag<RunnableType>::value ||
!internal::NeedsScopedRefptrButGetsRawPtr<P1>::value,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
!is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value,
p2_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value,
p3_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value,
p4_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value,
p5_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value,
p6_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P7>::value,
p7_is_refcounted_type_and_needs_scoped_refptr);
typedef internal::BindState<RunnableType, RunType,
void(typename internal::CallbackParamTraits<P1>::StorageType,
typename internal::CallbackParamTraits<P2>::StorageType,
typename internal::CallbackParamTraits<P3>::StorageType,
typename internal::CallbackParamTraits<P4>::StorageType,
typename internal::CallbackParamTraits<P5>::StorageType,
typename internal::CallbackParamTraits<P6>::StorageType,
typename internal::CallbackParamTraits<P7>::StorageType)> BindState;
return Callback<typename BindState::UnboundRunType>(
new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6,
p7));
new BindState(internal::MakeRunnable(functor), args...));
}
} // namespace base

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

@ -111,7 +111,7 @@
// scoped_ptr<Foo> f(new Foo());
//
// // |cb| is given ownership of Foo(). |f| is now NULL.
// // You can use f.Pass() in place of &f, but it's more verbose.
// // You can use std::move(f) in place of &f, but it's more verbose.
// Closure cb = Bind(&TakesOwnership, Passed(&f));
//
// // Run was never called so |cb| still owns Foo() and deletes
@ -129,7 +129,7 @@
// Passed() is particularly useful with PostTask() when you are transferring
// ownership of an argument into a task, but don't necessarily know if the
// task will always be executed. This can happen if the task is cancellable
// or if it is posted to a MessageLoopProxy.
// or if it is posted to a TaskRunner.
//
//
// SIMPLE FUNCTIONS AND UTILITIES.
@ -143,10 +143,15 @@
#ifndef BASE_BIND_HELPERS_H_
#define BASE_BIND_HELPERS_H_
#include "base/basictypes.h"
#include <stddef.h>
#include <type_traits>
#include <utility>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"
namespace base {
namespace internal {
@ -185,7 +190,7 @@ namespace internal {
// want to probe for. Then we create a class Base that inherits from both T
// (the class we wish to probe) and BaseMixin. Note that the function
// signature in BaseMixin does not need to match the signature of the function
// we are probing for; thus it's easiest to just use void(void).
// we are probing for; thus it's easiest to just use void().
//
// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
// ambiguous resolution between BaseMixin and T. This lets us write the
@ -222,8 +227,8 @@ namespace internal {
// See http://crbug.com/82038.
template <typename T>
class SupportsAddRefAndRelease {
typedef char Yes[1];
typedef char No[2];
using Yes = char[1];
using No = char[2];
struct BaseMixin {
void AddRef();
@ -242,7 +247,7 @@ class SupportsAddRefAndRelease {
#pragma warning(pop)
#endif
template <void(BaseMixin::*)(void)> struct Helper {};
template <void(BaseMixin::*)()> struct Helper {};
template <typename C>
static No& Check(Helper<&C::AddRef>*);
@ -276,8 +281,8 @@ struct UnsafeBindtoRefCountedArg<T*>
template <typename T>
class HasIsMethodTag {
typedef char Yes[1];
typedef char No[2];
using Yes = char[1];
using No = char[2];
template <typename U>
static Yes& Check(typename U::IsMethod*);
@ -359,22 +364,24 @@ class OwnedWrapper {
// created when we are explicitly trying to do a destructive move.
//
// Two notes:
// 1) PassedWrapper supports any type that has a "Pass()" function.
// This is intentional. The whitelisting of which specific types we
// support is maintained by CallbackParamTraits<>.
// 1) PassedWrapper supports any type that has a move constructor, however
// the type will need to be specifically whitelisted in order for it to be
// bound to a Callback. We guard this explicitly at the call of Passed()
// to make for clear errors. Things not given to Passed() will be forwarded
// and stored by value which will not work for general move-only types.
// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
// scoper to a Callback and allow the Callback to execute once.
template <typename T>
class PassedWrapper {
public:
explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {}
explicit PassedWrapper(T&& scoper)
: is_valid_(true), scoper_(std::move(scoper)) {}
PassedWrapper(const PassedWrapper& other)
: is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {
}
: is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {}
T Pass() const {
CHECK(is_valid_);
is_valid_ = false;
return scoper_.Pass();
return std::move(scoper_);
}
private:
@ -385,13 +392,13 @@ class PassedWrapper {
// Unwrap the stored parameters for the wrappers above.
template <typename T>
struct UnwrapTraits {
typedef const T& ForwardType;
using ForwardType = const T&;
static ForwardType Unwrap(const T& o) { return o; }
};
template <typename T>
struct UnwrapTraits<UnretainedWrapper<T> > {
typedef T* ForwardType;
using ForwardType = T*;
static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
return unretained.get();
}
@ -399,7 +406,7 @@ struct UnwrapTraits<UnretainedWrapper<T> > {
template <typename T>
struct UnwrapTraits<ConstRefWrapper<T> > {
typedef const T& ForwardType;
using ForwardType = const T&;
static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
return const_ref.get();
}
@ -407,19 +414,19 @@ struct UnwrapTraits<ConstRefWrapper<T> > {
template <typename T>
struct UnwrapTraits<scoped_refptr<T> > {
typedef T* ForwardType;
using ForwardType = T*;
static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
};
template <typename T>
struct UnwrapTraits<WeakPtr<T> > {
typedef const WeakPtr<T>& ForwardType;
using ForwardType = const WeakPtr<T>&;
static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
};
template <typename T>
struct UnwrapTraits<OwnedWrapper<T> > {
typedef T* ForwardType;
using ForwardType = T*;
static ForwardType Unwrap(const OwnedWrapper<T>& o) {
return o.get();
}
@ -427,7 +434,7 @@ struct UnwrapTraits<OwnedWrapper<T> > {
template <typename T>
struct UnwrapTraits<PassedWrapper<T> > {
typedef T ForwardType;
using ForwardType = T;
static T Unwrap(PassedWrapper<T>& o) {
return o.Pass();
}
@ -435,45 +442,46 @@ struct UnwrapTraits<PassedWrapper<T> > {
// Utility for handling different refcounting semantics in the Bind()
// function.
template <bool is_method, typename T>
struct MaybeRefcount;
template <bool is_method, typename... T>
struct MaybeScopedRefPtr;
template <typename T>
struct MaybeRefcount<false, T> {
static void AddRef(const T&) {}
static void Release(const T&) {}
template <bool is_method>
struct MaybeScopedRefPtr<is_method> {
MaybeScopedRefPtr() {}
};
template <typename T, size_t n>
struct MaybeRefcount<false, T[n]> {
static void AddRef(const T*) {}
static void Release(const T*) {}
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<false, T, Rest...> {
MaybeScopedRefPtr(const T&, const Rest&...) {}
};
template <typename T>
struct MaybeRefcount<true, T> {
static void AddRef(const T&) {}
static void Release(const T&) {}
template <typename T, size_t n, typename... Rest>
struct MaybeScopedRefPtr<false, T[n], Rest...> {
MaybeScopedRefPtr(const T*, const Rest&...) {}
};
template <typename T>
struct MaybeRefcount<true, T*> {
static void AddRef(T* o) { o->AddRef(); }
static void Release(T* o) { o->Release(); }
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, T, Rest...> {
MaybeScopedRefPtr(const T& o, const Rest&...) {}
};
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, T*, Rest...> {
MaybeScopedRefPtr(T* o, const Rest&...) : ref_(o) {}
scoped_refptr<T> ref_;
};
// No need to additionally AddRef() and Release() since we are storing a
// scoped_refptr<> inside the storage object already.
template <typename T>
struct MaybeRefcount<true, scoped_refptr<T> > {
static void AddRef(const scoped_refptr<T>& o) {}
static void Release(const scoped_refptr<T>& o) {}
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, scoped_refptr<T>, Rest...> {
MaybeScopedRefPtr(const scoped_refptr<T>&, const Rest&...) {}
};
template <typename T>
struct MaybeRefcount<true, const T*> {
static void AddRef(const T* o) { o->AddRef(); }
static void Release(const T* o) { o->Release(); }
template <typename T, typename... Rest>
struct MaybeScopedRefPtr<true, const T*, Rest...> {
MaybeScopedRefPtr(const T* o, const Rest&...) : ref_(o) {}
scoped_refptr<const T> ref_;
};
// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
@ -481,15 +489,113 @@ struct MaybeRefcount<true, const T*> {
// InvokeHelper that will no-op itself in the event the WeakPtr<> for
// the target object is invalidated.
//
// P1 should be the type of the object that will be received of the method.
template <bool IsMethod, typename P1>
// The first argument should be the type of the object that will be received by
// the method.
template <bool IsMethod, typename... Args>
struct IsWeakMethod : public false_type {};
template <typename T>
struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
template <typename T, typename... Args>
struct IsWeakMethod<true, WeakPtr<T>, Args...> : public true_type {};
template <typename T>
struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
template <typename T, typename... Args>
struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>, Args...>
: public true_type {};
// Packs a list of types to hold them in a single type.
template <typename... Types>
struct TypeList {};
// Used for DropTypeListItem implementation.
template <size_t n, typename List>
struct DropTypeListItemImpl;
// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
template <size_t n, typename T, typename... List>
struct DropTypeListItemImpl<n, TypeList<T, List...>>
: DropTypeListItemImpl<n - 1, TypeList<List...>> {};
template <typename T, typename... List>
struct DropTypeListItemImpl<0, TypeList<T, List...>> {
using Type = TypeList<T, List...>;
};
template <>
struct DropTypeListItemImpl<0, TypeList<>> {
using Type = TypeList<>;
};
// A type-level function that drops |n| list item from given TypeList.
template <size_t n, typename List>
using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
// Used for TakeTypeListItem implementation.
template <size_t n, typename List, typename... Accum>
struct TakeTypeListItemImpl;
// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
template <size_t n, typename T, typename... List, typename... Accum>
struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
: TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
template <typename T, typename... List, typename... Accum>
struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
using Type = TypeList<Accum...>;
};
template <typename... Accum>
struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
using Type = TypeList<Accum...>;
};
// A type-level function that takes first |n| list item from given TypeList.
// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
// TypeList<A, B, C>.
template <size_t n, typename List>
using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
// Used for ConcatTypeLists implementation.
template <typename List1, typename List2>
struct ConcatTypeListsImpl;
template <typename... Types1, typename... Types2>
struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
using Type = TypeList<Types1..., Types2...>;
};
// A type-level function that concats two TypeLists.
template <typename List1, typename List2>
using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
// Used for MakeFunctionType implementation.
template <typename R, typename ArgList>
struct MakeFunctionTypeImpl;
template <typename R, typename... Args>
struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R Type(Args...);
};
// A type-level function that constructs a function type that has |R| as its
// return type and has TypeLists items as its arguments.
template <typename R, typename ArgList>
using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
// Used for ExtractArgs.
template <typename Signature>
struct ExtractArgsImpl;
template <typename R, typename... Args>
struct ExtractArgsImpl<R(Args...)> {
using Type = TypeList<Args...>;
};
// A type-level function that extracts function arguments into a TypeList.
// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
template <typename Signature>
using ExtractArgs = typename ExtractArgsImpl<Signature>::Type;
} // namespace internal
@ -508,17 +614,25 @@ static inline internal::OwnedWrapper<T> Owned(T* o) {
return internal::OwnedWrapper<T>(o);
}
// We offer 2 syntaxes for calling Passed(). The first takes a temporary and
// is best suited for use with the return value of a function. The second
// takes a pointer to the scoper and is just syntactic sugar to avoid having
// to write Passed(scoper.Pass()).
template <typename T>
static inline internal::PassedWrapper<T> Passed(T scoper) {
return internal::PassedWrapper<T>(scoper.Pass());
// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and
// is best suited for use with the return value of a function or other temporary
// rvalues. The second takes a pointer to the scoper and is just syntactic sugar
// to avoid having to write Passed(std::move(scoper)).
//
// Both versions of Passed() prevent T from being an lvalue reference. The first
// via use of enable_if, and the second takes a T* which will not bind to T&.
template <typename T,
typename std::enable_if<internal::IsMoveOnlyType<T>::value &&
!std::is_lvalue_reference<T>::value>::type* =
nullptr>
static inline internal::PassedWrapper<T> Passed(T&& scoper) {
return internal::PassedWrapper<T>(std::move(scoper));
}
template <typename T>
template <typename T,
typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* =
nullptr>
static inline internal::PassedWrapper<T> Passed(T* scoper) {
return internal::PassedWrapper<T>(scoper->Pass());
return internal::PassedWrapper<T>(std::move(*scoper));
}
template <typename T>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -8,6 +8,8 @@
#ifndef BASE_BIND_INTERNAL_WIN_H_
#define BASE_BIND_INTERNAL_WIN_H_
#include "build/build_config.h"
// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all
// the same as __cdecl which would turn the following specializations into
// multiple definitions.
@ -23,7 +25,9 @@ class RunnableAdapter;
template <typename R, typename... Args>
class RunnableAdapter<R(__stdcall *)(Args...)> {
public:
typedef R (RunType)(Args...);
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R RunType(Args...);
explicit RunnableAdapter(R(__stdcall *function)(Args...))
: function_(function) {
@ -41,7 +45,9 @@ class RunnableAdapter<R(__stdcall *)(Args...)> {
template <typename R, typename... Args>
class RunnableAdapter<R(__fastcall *)(Args...)> {
public:
typedef R (RunType)(Args...);
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R RunType(Args...);
explicit RunnableAdapter(R(__fastcall *function)(Args...))
: function_(function) {

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

@ -0,0 +1,71 @@
// Copyright 2016 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_BIT_CAST_H_
#define BASE_BIT_CAST_H_
#include <string.h>
// bit_cast<Dest,Source> is a template function that implements the equivalent
// of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level
// functions like the protobuf library and fast math support.
//
// float f = 3.14159265358979;
// int i = bit_cast<int32_t>(f);
// // i = 0x40490fdb
//
// The classical address-casting method is:
//
// // WRONG
// float f = 3.14159265358979; // WRONG
// int i = * reinterpret_cast<int*>(&f); // WRONG
//
// The address-casting method actually produces undefined behavior according to
// the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15.
// (This did not substantially change in C++11.) Roughly, this section says: if
// an object in memory has one type, and a program accesses it with a different
// type, then the result is undefined behavior for most values of "different
// type".
//
// This is true for any cast syntax, either *(int*)&f or
// *reinterpret_cast<int*>(&f). And it is particularly true for conversions
// between integral lvalues and floating-point lvalues.
//
// The purpose of this paragraph is to allow optimizing compilers to assume that
// expressions with different types refer to different memory. Compilers are
// known to take advantage of this. So a non-conforming program quietly
// produces wildly incorrect output.
//
// The problem is not the use of reinterpret_cast. The problem is type punning:
// holding an object in memory of one type and reading its bits back using a
// different type.
//
// The C++ standard is more subtle and complex than this, but that is the basic
// idea.
//
// Anyways ...
//
// bit_cast<> calls memcpy() which is blessed by the standard, especially by the
// example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty
// logic in one place.
//
// Fortunately memcpy() is very fast. In optimized mode, compilers replace
// calls to memcpy() with inline object code when the size argument is a
// compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one
// load and one store, and memcpy(d,s,8) compiles to two loads and two stores.
//
// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
// is likely to surprise you.
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source),
"bit_cast requires source and destination to be the same size");
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
#endif // BASE_BIT_CAST_H_

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

@ -1,8 +1,3 @@
// This file was GENERATED by command:
// pump.py callback.h.pump
// DO NOT EDIT BY HAND!!!
// Copyright (c) 2012 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.
@ -31,7 +26,7 @@
// much like lexical closures are used in other languages. For example, it
// is used in Chromium code to schedule tasks on different MessageLoops.
//
// A callback with no unbound input parameters (base::Callback<void(void)>)
// A callback with no unbound input parameters (base::Callback<void()>)
// is called a base::Closure. Note that this is NOT the same as what other
// languages refer to as a closure -- it does not retain a reference to its
// enclosing environment.
@ -53,7 +48,7 @@
// BINDING A BARE FUNCTION
//
// int Return5() { return 5; }
// base::Callback<int(void)> func_cb = base::Bind(&Return5);
// base::Callback<int()> func_cb = base::Bind(&Return5);
// LOG(INFO) << func_cb.Run(); // Prints 5.
//
// BINDING A CLASS METHOD
@ -67,7 +62,7 @@
// void PrintBye() { LOG(INFO) << "bye."; }
// };
// scoped_refptr<Ref> ref = new Ref();
// base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref);
// base::Callback<void()> ref_cb = base::Bind(&Ref::Foo, ref);
// LOG(INFO) << ref_cb.Run(); // Prints out 3.
//
// By default the object must support RefCounted or you will get a compiler
@ -109,10 +104,10 @@
// calling.
//
// void MyFunc(int i, const std::string& str) {}
// base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world");
// base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world");
// cb.Run();
//
// A callback with no unbound input parameters (base::Callback<void(void)>)
// A callback with no unbound input parameters (base::Callback<void()>)
// is called a base::Closure. So we could have also written:
//
// base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
@ -170,7 +165,7 @@
// that doesn't expect a return value.
//
// int DoSomething(int arg) { cout << arg << endl; }
// base::Callback<void<int>) cb =
// base::Callback<void(int)> cb =
// base::Bind(base::IgnoreResult(&DoSomething));
//
//
@ -180,7 +175,7 @@
//
// Bound parameters are specified as arguments to Bind() and are passed to the
// function. A callback with no parameters or no unbound parameters is called a
// Closure (base::Callback<void(void)> and base::Closure are the same thing).
// Closure (base::Callback<void()> and base::Closure are the same thing).
//
// PASSING PARAMETERS OWNED BY THE CALLBACK
//
@ -359,33 +354,30 @@ namespace base {
//
// If you are thinking of forward declaring Callback in your own header file,
// please include "base/callback_forward.h" instead.
template <typename Sig>
class Callback;
namespace internal {
template <typename Runnable, typename RunType, typename BoundArgsType>
template <typename Runnable, typename RunType, typename... BoundArgsType>
struct BindState;
} // namespace internal
template <typename R>
class Callback<R(void)> : public internal::CallbackBase {
template <typename R, typename... Args>
class Callback<R(Args...)> : public internal::CallbackBase {
public:
typedef R(RunType)();
// MSVC 2013 doesn't support Type Alias of function types.
// Revisit this after we update it to newer version.
typedef R RunType(Args...);
Callback() : CallbackBase(NULL) { }
Callback() : CallbackBase(nullptr) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
template <typename Runnable, typename BindRunType, typename... BoundArgsType>
explicit Callback(
internal::BindState<Runnable, BindRunType, BoundArgsType...>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
&internal::BindState<Runnable, BindRunType, BoundArgsType...>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
@ -394,377 +386,20 @@ class Callback<R(void)> : public internal::CallbackBase {
return CallbackBase::Equals(other);
}
R Run() const {
R Run(typename internal::CallbackParamTraits<Args>::ForwardType... args)
const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get());
return f(bind_state_.get(), internal::CallbackForward(args)...);
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*);
using PolymorphicInvoke =
R(*)(internal::BindStateBase*,
typename internal::CallbackParamTraits<Args>::ForwardType...);
};
template <typename R, typename A1>
class Callback<R(A1)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType);
};
template <typename R, typename A1, typename A2>
class Callback<R(A1, A2)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3>
class Callback<R(A1, A2, A3)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5>
class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4, A5);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6>
class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4, A5, A6);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5),
internal::CallbackForward(a6));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType,
typename internal::CallbackParamTraits<A6>::ForwardType);
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7>
class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public internal::CallbackBase {
public:
typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7);
Callback() : CallbackBase(NULL) { }
// Note that this constructor CANNOT be explicit, and that Bind() CANNOT
// return the exact Callback<> type. See base/bind.h for details.
template <typename Runnable, typename BindRunType, typename BoundArgsType>
Callback(internal::BindState<Runnable, BindRunType,
BoundArgsType>* bind_state)
: CallbackBase(bind_state) {
// Force the assignment to a local variable of PolymorphicInvoke
// so the compiler will typecheck that the passed in Run() method has
// the correct type.
PolymorphicInvoke invoke_func =
&internal::BindState<Runnable, BindRunType, BoundArgsType>
::InvokerType::Run;
polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func);
}
bool Equals(const Callback& other) const {
return CallbackBase::Equals(other);
}
R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1,
typename internal::CallbackParamTraits<A2>::ForwardType a2,
typename internal::CallbackParamTraits<A3>::ForwardType a3,
typename internal::CallbackParamTraits<A4>::ForwardType a4,
typename internal::CallbackParamTraits<A5>::ForwardType a5,
typename internal::CallbackParamTraits<A6>::ForwardType a6,
typename internal::CallbackParamTraits<A7>::ForwardType a7) const {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);
return f(bind_state_.get(), internal::CallbackForward(a1),
internal::CallbackForward(a2),
internal::CallbackForward(a3),
internal::CallbackForward(a4),
internal::CallbackForward(a5),
internal::CallbackForward(a6),
internal::CallbackForward(a7));
}
private:
typedef R(*PolymorphicInvoke)(
internal::BindStateBase*,
typename internal::CallbackParamTraits<A1>::ForwardType,
typename internal::CallbackParamTraits<A2>::ForwardType,
typename internal::CallbackParamTraits<A3>::ForwardType,
typename internal::CallbackParamTraits<A4>::ForwardType,
typename internal::CallbackParamTraits<A5>::ForwardType,
typename internal::CallbackParamTraits<A6>::ForwardType,
typename internal::CallbackParamTraits<A7>::ForwardType);
};
// Syntactic sugar to make Callback<void(void)> easier to declare since it
// will be used in a lot of APIs with delayed execution.
typedef Callback<void(void)> Closure;
} // namespace base
#endif // BASE_CALLBACK_H
#endif // BASE_CALLBACK_H_

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

@ -10,8 +10,10 @@ namespace base {
template <typename Sig>
class Callback;
typedef Callback<void(void)> Closure;
// Syntactic sugar to make Callback<void()> easier to declare since it
// will be used in a lot of APIs with delayed execution.
using Closure = Callback<void()>;
} // namespace base
#endif // BASE_CALLBACK_FORWARD_H
#endif // BASE_CALLBACK_FORWARD_H_

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

@ -9,6 +9,18 @@
namespace base {
namespace internal {
void BindStateBase::AddRef() {
AtomicRefCountInc(&ref_count_);
}
void BindStateBase::Release() {
if (!AtomicRefCountDec(&ref_count_))
destructor_(this);
}
CallbackBase::CallbackBase(const CallbackBase& c) = default;
CallbackBase& CallbackBase::operator=(const CallbackBase& c) = default;
void CallbackBase::Reset() {
polymorphic_invoke_ = NULL;
// NULL the bind_state_ last, since it may be holding the last ref to whatever
@ -24,7 +36,7 @@ bool CallbackBase::Equals(const CallbackBase& other) const {
CallbackBase::CallbackBase(BindStateBase* bind_state)
: bind_state_(bind_state),
polymorphic_invoke_(NULL) {
DCHECK(!bind_state_.get() || bind_state_->HasOneRef());
DCHECK(!bind_state_.get() || bind_state_->ref_count_ == 1);
}
CallbackBase::~CallbackBase() {

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

@ -9,16 +9,19 @@
#define BASE_CALLBACK_INTERNAL_H_
#include <stddef.h>
#include <memory>
#include <type_traits>
#include "base/atomic_ref_count.h"
#include "base/base_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
template <typename T>
class ScopedVector;
#include "base/template_util.h"
namespace base {
namespace internal {
class CallbackBase;
// BindStateBase is used to provide an opaque handle that the Callback
// class can use to represent a function object with bound arguments. It
@ -26,16 +29,39 @@ namespace internal {
// DoInvoke function to perform the function execution. This allows
// us to shield the Callback class from the types of the bound argument via
// "type erasure."
class BindStateBase : public RefCountedThreadSafe<BindStateBase> {
// At the base level, the only task is to add reference counting data. Don't use
// RefCountedThreadSafe since it requires the destructor to be a virtual method.
// Creating a vtable for every BindState template instantiation results in a lot
// of bloat. Its only task is to call the destructor which can be done with a
// function pointer.
class BindStateBase {
protected:
friend class RefCountedThreadSafe<BindStateBase>;
virtual ~BindStateBase() {}
explicit BindStateBase(void (*destructor)(BindStateBase*))
: ref_count_(0), destructor_(destructor) {}
~BindStateBase() = default;
private:
friend class scoped_refptr<BindStateBase>;
friend class CallbackBase;
void AddRef();
void Release();
AtomicRefCount ref_count_;
// Pointer to a function that will properly destroy |this|.
void (*destructor_)(BindStateBase*);
DISALLOW_COPY_AND_ASSIGN(BindStateBase);
};
// Holds the Callback methods that don't require specialization to reduce
// template bloat.
class BASE_EXPORT CallbackBase {
public:
CallbackBase(const CallbackBase& c);
CallbackBase& operator=(const CallbackBase& c);
// Returns true if Callback is null (doesn't refer to anything).
bool is_null() const { return bind_state_.get() == NULL; }
@ -47,7 +73,7 @@ class BASE_EXPORT CallbackBase {
// another type. It is not okay to use void*. We create a InvokeFuncStorage
// that that can store our function pointer, and then cast it back to
// the original type on usage.
typedef void(*InvokeFuncStorage)(void);
using InvokeFuncStorage = void(*)();
// Returns true if this callback equals |other|. |other| may be null.
bool Equals(const CallbackBase& other) const;
@ -68,8 +94,14 @@ class BASE_EXPORT CallbackBase {
};
// A helper template to determine if given type is non-const move-only-type,
// i.e. if a value of the given type should be passed via .Pass() in a
// destructive way.
// i.e. if a value of the given type should be passed via std::move() in a
// destructive way. Types are considered to be move-only if they have a
// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using
// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro.
// It would be easy to generalize this trait to all move-only types... but this
// confuses template deduction in VS2013 with certain types such as
// std::unique_ptr.
// TODO(dcheng): Revisit this when Windows switches to VS2015 by default.
template <typename T> struct IsMoveOnlyType {
template <typename U>
static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
@ -81,6 +113,21 @@ template <typename T> struct IsMoveOnlyType {
!is_const<T>::value;
};
// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered
// move-only, even without the sentinel member.
template <typename T>
struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {};
template <typename>
struct CallbackParamTraitsForMoveOnlyType;
template <typename>
struct CallbackParamTraitsForNonMoveOnlyType;
// TODO(tzik): Use a default parameter once MSVS supports variadic templates
// with default values.
// http://connect.microsoft.com/VisualStudio/feedbackdetail/view/957801/compilation-error-with-variadic-templates
//
// This is a typetraits object that's used to take an argument type, and
// extract a suitable type for storing and forwarding arguments.
//
@ -92,10 +139,17 @@ template <typename T> struct IsMoveOnlyType {
// parameters by const reference. In this case, we end up passing an actual
// array type in the initializer list which C++ does not allow. This will
// break passing of C-string literals.
template <typename T, bool is_move_only = IsMoveOnlyType<T>::value>
struct CallbackParamTraits {
typedef const T& ForwardType;
typedef T StorageType;
template <typename T>
struct CallbackParamTraits
: std::conditional<IsMoveOnlyType<T>::value,
CallbackParamTraitsForMoveOnlyType<T>,
CallbackParamTraitsForNonMoveOnlyType<T>>::type {
};
template <typename T>
struct CallbackParamTraitsForNonMoveOnlyType {
using ForwardType = const T&;
using StorageType = T;
};
// The Storage should almost be impossible to trigger unless someone manually
@ -104,9 +158,9 @@ struct CallbackParamTraits {
//
// The ForwardType should only be used for unbound arguments.
template <typename T>
struct CallbackParamTraits<T&, false> {
typedef T& ForwardType;
typedef T StorageType;
struct CallbackParamTraitsForNonMoveOnlyType<T&> {
using ForwardType = T&;
using StorageType = T;
};
// Note that for array types, we implicitly add a const in the conversion. This
@ -115,16 +169,16 @@ struct CallbackParamTraits<T&, false> {
// T[n]" does not seem to match correctly, so we are stuck with this
// restriction.
template <typename T, size_t n>
struct CallbackParamTraits<T[n], false> {
typedef const T* ForwardType;
typedef const T* StorageType;
struct CallbackParamTraitsForNonMoveOnlyType<T[n]> {
using ForwardType = const T*;
using StorageType = const T*;
};
// See comment for CallbackParamTraits<T[n]>.
template <typename T>
struct CallbackParamTraits<T[], false> {
typedef const T* ForwardType;
typedef const T* StorageType;
struct CallbackParamTraitsForNonMoveOnlyType<T[]> {
using ForwardType = const T*;
using StorageType = const T*;
};
// Parameter traits for movable-but-not-copyable scopers.
@ -141,9 +195,9 @@ struct CallbackParamTraits<T[], false> {
// reference cannot be used with temporaries which means the result of a
// function or a cast would not be usable with Callback<> or Bind().
template <typename T>
struct CallbackParamTraits<T, true> {
typedef T ForwardType;
typedef T StorageType;
struct CallbackParamTraitsForMoveOnlyType {
using ForwardType = T;
using StorageType = T;
};
// CallbackForward() is a very limited simulation of C++11's std::forward()
@ -155,7 +209,7 @@ struct CallbackParamTraits<T, true> {
// default template compiles out to be a no-op.
//
// In C++11, std::forward would replace all uses of this function. However, it
// is impossible to implement a general std::forward with C++11 due to a lack
// is impossible to implement a general std::forward without C++11 due to a lack
// of rvalue references.
//
// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to
@ -163,13 +217,15 @@ struct CallbackParamTraits<T, true> {
// parameter to another callback. This is to support Callbacks that return
// the movable-but-not-copyable types whitelisted above.
template <typename T>
typename enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) {
typename std::enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(
T& t) {
return t;
}
template <typename T>
typename enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) {
return t.Pass();
typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(
T& t) {
return std::move(t);
}
} // namespace internal

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

@ -9,6 +9,9 @@
#if defined(COMPILER_MSVC)
// For _Printf_format_string_.
#include <sal.h>
// Macros for suppressing and disabling warnings on MSVC.
//
// Warning numbers are enumerated at:
@ -57,6 +60,7 @@
#else // Not MSVC
#define _Printf_format_string_
#define MSVC_SUPPRESS_WARNING(n)
#define MSVC_PUSH_DISABLE_WARNING(n)
#define MSVC_PUSH_WARNING_LEVEL(n)
@ -68,28 +72,6 @@
#endif // COMPILER_MSVC
// The C++ standard requires that static const members have an out-of-class
// definition (in a single compilation unit), but MSVC chokes on this (when
// language extensions, which are required, are enabled). (You're only likely to
// notice the need for a definition if you take the address of the member or,
// more commonly, pass it to a function that takes it as a reference argument --
// probably an STL function.) This macro makes MSVC do the right thing. See
// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more
// information. Use like:
//
// In .h file:
// struct Foo {
// static const int kBar = 5;
// };
//
// In .cc file:
// STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar;
#if defined(COMPILER_MSVC)
#define STATIC_CONST_MEMBER_DEFINITION __declspec(selectany)
#else
#define STATIC_CONST_MEMBER_DEFINITION
#endif
// Annotate a variable indicating it's ok if the variable is not used.
// (Typically used to silence a compiler warning when the assignment
// is important for some other reason.)
@ -101,7 +83,7 @@
// Annotate a typedef or function indicating it's ok if it's not used.
// Use like:
// typedef Foo Bar ALLOW_UNUSED_TYPE;
#if defined(COMPILER_GCC)
#if defined(COMPILER_GCC) || defined(__clang__)
#define ALLOW_UNUSED_TYPE __attribute__((unused))
#else
#define ALLOW_UNUSED_TYPE
@ -128,13 +110,11 @@
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#endif
// Return the byte alignment of the given type (available at compile time). Use
// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
// http://goo.gl/isH0C
// Return the byte alignment of the given type (available at compile time).
// Use like:
// ALIGNOF(int32) // this would be 4
// ALIGNOF(int32_t) // this would be 4
#if defined(COMPILER_MSVC)
#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
#define ALIGNOF(type) __alignof(type)
#elif defined(COMPILER_GCC)
#define ALIGNOF(type) __alignof__(type)
#endif
@ -142,8 +122,9 @@
// Annotate a function indicating the caller must examine the return value.
// Use like:
// int foo() WARN_UNUSED_RESULT;
// To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
#if defined(COMPILER_GCC)
// To explicitly ignore a result, see |ignore_result()| in base/macros.h.
#undef WARN_UNUSED_RESULT
#if defined(COMPILER_GCC) || defined(__clang__)
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
@ -175,9 +156,17 @@
// Mark a memory region fully initialized.
// Use this to annotate code that deliberately reads uninitialized data, for
// example a GC scavenging root set pointers from the stack.
#define MSAN_UNPOISON(p, s) __msan_unpoison(p, s)
#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size)
// Check a memory region for initializedness, as if it was being used here.
// If any bits are uninitialized, crash with an MSan report.
// Use this to sanitize data which MSan won't be able to track, e.g. before
// passing data to another process via shared memory.
#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \
__msan_check_mem_is_initialized(p, size)
#else // MEMORY_SANITIZER
#define MSAN_UNPOISON(p, s)
#define MSAN_UNPOISON(p, size)
#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size)
#endif // MEMORY_SANITIZER
// Macro useful for writing cross-platform function pointers.

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

@ -21,9 +21,11 @@
#ifndef BASE_CONTAINERS_HASH_TABLES_H_
#define BASE_CONTAINERS_HASH_TABLES_H_
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "base/basictypes.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
@ -45,15 +47,9 @@
#undef __DEPRECATED
#endif
#if defined(OS_ANDROID) && !defined(MOZ_WIDGET_GONK)
#include <hash_map>
#include <hash_set>
#define BASE_HASH_IMPL_NAMESPACE std
#else
#include <ext/hash_map>
#include <ext/hash_set>
#define BASE_HASH_IMPL_NAMESPACE __gnu_cxx
#endif
#include <string>
@ -84,7 +80,6 @@ struct hash<T*> {
}
};
#if !defined(OS_ANDROID)
// The GNU C++ library provides identity hash functions for many integral types,
// but not for |long long|. This hash function will truncate if |size_t| is
// narrower than |long long|. This is probably good enough for what we will
@ -102,7 +97,6 @@ DEFINE_TRIVIAL_HASH(long long);
DEFINE_TRIVIAL_HASH(unsigned long long);
#undef DEFINE_TRIVIAL_HASH
#endif // !defined(OS_ANDROID)
// Implement string hash functions so that strings of various flavors can
// be used as keys in STL maps and sets. The hash algorithm comes from the
@ -204,19 +198,19 @@ using hash_set = BASE_HASH_IMPL_NAMESPACE::hash_set<Key, Hash, Pred, Alloc>;
// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
//
// Contact danakj@chromium.org for any questions.
inline std::size_t HashInts32(uint32 value1, uint32 value2) {
uint64 value1_64 = value1;
uint64 hash64 = (value1_64 << 32) | value2;
inline std::size_t HashInts32(uint32_t value1, uint32_t value2) {
uint64_t value1_64 = value1;
uint64_t hash64 = (value1_64 << 32) | value2;
if (sizeof(std::size_t) >= sizeof(uint64))
if (sizeof(std::size_t) >= sizeof(uint64_t))
return static_cast<std::size_t>(hash64);
uint64 odd_random = 481046412LL << 32 | 1025306955LL;
uint32 shift_random = 10121U << 16;
uint64_t odd_random = 481046412LL << 32 | 1025306955LL;
uint32_t shift_random = 10121U << 16;
hash64 = hash64 * odd_random + shift_random;
std::size_t high_bits = static_cast<std::size_t>(
hash64 >> (8 * (sizeof(uint64) - sizeof(std::size_t))));
hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t))));
return high_bits;
}
@ -225,87 +219,46 @@ inline std::size_t HashInts32(uint32 value1, uint32 value2) {
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
inline std::size_t HashInts64(uint64 value1, uint64 value2) {
uint32 short_random1 = 842304669U;
uint32 short_random2 = 619063811U;
uint32 short_random3 = 937041849U;
uint32 short_random4 = 3309708029U;
inline std::size_t HashInts64(uint64_t value1, uint64_t value2) {
uint32_t short_random1 = 842304669U;
uint32_t short_random2 = 619063811U;
uint32_t short_random3 = 937041849U;
uint32_t short_random4 = 3309708029U;
uint32 value1a = static_cast<uint32>(value1 & 0xffffffff);
uint32 value1b = static_cast<uint32>((value1 >> 32) & 0xffffffff);
uint32 value2a = static_cast<uint32>(value2 & 0xffffffff);
uint32 value2b = static_cast<uint32>((value2 >> 32) & 0xffffffff);
uint32_t value1a = static_cast<uint32_t>(value1 & 0xffffffff);
uint32_t value1b = static_cast<uint32_t>((value1 >> 32) & 0xffffffff);
uint32_t value2a = static_cast<uint32_t>(value2 & 0xffffffff);
uint32_t value2b = static_cast<uint32_t>((value2 >> 32) & 0xffffffff);
uint64 product1 = static_cast<uint64>(value1a) * short_random1;
uint64 product2 = static_cast<uint64>(value1b) * short_random2;
uint64 product3 = static_cast<uint64>(value2a) * short_random3;
uint64 product4 = static_cast<uint64>(value2b) * short_random4;
uint64_t product1 = static_cast<uint64_t>(value1a) * short_random1;
uint64_t product2 = static_cast<uint64_t>(value1b) * short_random2;
uint64_t product3 = static_cast<uint64_t>(value2a) * short_random3;
uint64_t product4 = static_cast<uint64_t>(value2b) * short_random4;
uint64 hash64 = product1 + product2 + product3 + product4;
uint64_t hash64 = product1 + product2 + product3 + product4;
if (sizeof(std::size_t) >= sizeof(uint64))
if (sizeof(std::size_t) >= sizeof(uint64_t))
return static_cast<std::size_t>(hash64);
uint64 odd_random = 1578233944LL << 32 | 194370989LL;
uint32 shift_random = 20591U << 16;
uint64_t odd_random = 1578233944LL << 32 | 194370989LL;
uint32_t shift_random = 20591U << 16;
hash64 = hash64 * odd_random + shift_random;
std::size_t high_bits = static_cast<std::size_t>(
hash64 >> (8 * (sizeof(uint64) - sizeof(std::size_t))));
hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t))));
return high_bits;
}
#define DEFINE_32BIT_PAIR_HASH(Type1, Type2) \
inline std::size_t HashPair(Type1 value1, Type2 value2) { \
return HashInts32(value1, value2); \
template<typename T1, typename T2>
inline std::size_t HashPair(T1 value1, T2 value2) {
// This condition is expected to be compile-time evaluated and optimised away
// in release builds.
if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t)))
return HashInts64(value1, value2);
return HashInts32(value1, value2);
}
DEFINE_32BIT_PAIR_HASH(int16, int16);
DEFINE_32BIT_PAIR_HASH(int16, uint16);
DEFINE_32BIT_PAIR_HASH(int16, int32);
DEFINE_32BIT_PAIR_HASH(int16, uint32);
DEFINE_32BIT_PAIR_HASH(uint16, int16);
DEFINE_32BIT_PAIR_HASH(uint16, uint16);
DEFINE_32BIT_PAIR_HASH(uint16, int32);
DEFINE_32BIT_PAIR_HASH(uint16, uint32);
DEFINE_32BIT_PAIR_HASH(int32, int16);
DEFINE_32BIT_PAIR_HASH(int32, uint16);
DEFINE_32BIT_PAIR_HASH(int32, int32);
DEFINE_32BIT_PAIR_HASH(int32, uint32);
DEFINE_32BIT_PAIR_HASH(uint32, int16);
DEFINE_32BIT_PAIR_HASH(uint32, uint16);
DEFINE_32BIT_PAIR_HASH(uint32, int32);
DEFINE_32BIT_PAIR_HASH(uint32, uint32);
#undef DEFINE_32BIT_PAIR_HASH
#define DEFINE_64BIT_PAIR_HASH(Type1, Type2) \
inline std::size_t HashPair(Type1 value1, Type2 value2) { \
return HashInts64(value1, value2); \
}
DEFINE_64BIT_PAIR_HASH(int16, int64);
DEFINE_64BIT_PAIR_HASH(int16, uint64);
DEFINE_64BIT_PAIR_HASH(uint16, int64);
DEFINE_64BIT_PAIR_HASH(uint16, uint64);
DEFINE_64BIT_PAIR_HASH(int32, int64);
DEFINE_64BIT_PAIR_HASH(int32, uint64);
DEFINE_64BIT_PAIR_HASH(uint32, int64);
DEFINE_64BIT_PAIR_HASH(uint32, uint64);
DEFINE_64BIT_PAIR_HASH(int64, int16);
DEFINE_64BIT_PAIR_HASH(int64, uint16);
DEFINE_64BIT_PAIR_HASH(int64, int32);
DEFINE_64BIT_PAIR_HASH(int64, uint32);
DEFINE_64BIT_PAIR_HASH(int64, int64);
DEFINE_64BIT_PAIR_HASH(int64, uint64);
DEFINE_64BIT_PAIR_HASH(uint64, int16);
DEFINE_64BIT_PAIR_HASH(uint64, uint16);
DEFINE_64BIT_PAIR_HASH(uint64, int32);
DEFINE_64BIT_PAIR_HASH(uint64, uint32);
DEFINE_64BIT_PAIR_HASH(uint64, int64);
DEFINE_64BIT_PAIR_HASH(uint64, uint64);
#undef DEFINE_64BIT_PAIR_HASH
} // namespace base
namespace BASE_HASH_NAMESPACE {
@ -320,7 +273,7 @@ struct hash<std::pair<Type1, Type2> > {
}
};
}
} // namespace BASE_HASH_NAMESPACE
#undef DEFINE_PAIR_HASH_FUNCTION_START
#undef DEFINE_PAIR_HASH_FUNCTION_END

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

@ -4,12 +4,15 @@
#include "base/cpu.h"
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include "base/basictypes.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
@ -43,7 +46,7 @@ CPU::CPU()
has_sse41_(false),
has_sse42_(false),
has_avx_(false),
has_avx_hardware_(false),
has_avx2_(false),
has_aesni_(false),
has_non_stop_time_stamp_counter_(false),
has_broken_neon_(false),
@ -72,7 +75,7 @@ void __cpuid(int cpu_info[4], int info_type) {
void __cpuid(int cpu_info[4], int info_type) {
__asm__ volatile (
"cpuid \n\t"
"cpuid\n"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type)
);
@ -82,11 +85,12 @@ void __cpuid(int cpu_info[4], int info_type) {
// _xgetbv returns the value of an Intel Extended Control Register (XCR).
// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
uint64 _xgetbv(uint32 xcr) {
uint32 eax, edx;
uint64_t _xgetbv(uint32_t xcr) {
uint32_t eax, edx;
__asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr));
return (static_cast<uint64>(edx) << 32) | eax;
__asm__ volatile (
"xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
return (static_cast<uint64_t>(edx) << 32) | eax;
}
#endif // !_MSC_VER
@ -110,7 +114,7 @@ class LazyCpuInfoValue {
revision = 0;
const struct {
const char key[17];
unsigned *result;
unsigned int* result;
} kUnsignedValues[] = {
{"CPU implementer", &implementer},
{"CPU architecture", &architecture},
@ -156,7 +160,7 @@ class LazyCpuInfoValue {
// The string may have leading "0x" or not, so we use strtoul to
// handle that.
char *endptr;
char* endptr;
std::string value(value_sp.as_string());
unsigned long int result = strtoul(value.c_str(), &endptr, 0);
if (*endptr == 0 && result <= UINT_MAX) {
@ -211,7 +215,11 @@ void CPU::Initialize() {
// Interpret CPU feature information.
if (num_ids > 0) {
int cpu_info7[4] = {0};
__cpuid(cpu_info, 1);
if (num_ids >= 7) {
__cpuid(cpu_info7, 7);
}
signature_ = cpu_info[0];
stepping_ = cpu_info[0] & 0xf;
model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
@ -226,8 +234,6 @@ void CPU::Initialize() {
has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
has_avx_hardware_ =
(cpu_info[2] & 0x10000000) != 0;
// AVX instructions will generate an illegal instruction exception unless
// a) they are supported by the CPU,
// b) XSAVE is supported by the CPU and
@ -239,11 +245,12 @@ void CPU::Initialize() {
// Because of that, we also test the XSAVE bit because its description in
// the CPUID documentation suggests that it signals xgetbv support.
has_avx_ =
has_avx_hardware_ &&
(cpu_info[2] & 0x10000000) != 0 &&
(cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
(cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
(_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
has_aesni_ = (cpu_info[2] & 0x02000000) != 0;
has_avx2_ = has_avx_ && (cpu_info7[1] & 0x00000020) != 0;
}
// Get the brand string of the cpu.
@ -275,6 +282,7 @@ void CPU::Initialize() {
}
CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const {
if (has_avx2()) return AVX2;
if (has_avx()) return AVX;
if (has_sse42()) return SSE42;
if (has_sse41()) return SSE41;

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

@ -26,6 +26,7 @@ class BASE_EXPORT CPU {
SSE41,
SSE42,
AVX,
AVX2,
MAX_INTEL_MICRO_ARCHITECTURE
};
@ -46,12 +47,7 @@ class BASE_EXPORT CPU {
bool has_sse41() const { return has_sse41_; }
bool has_sse42() const { return has_sse42_; }
bool has_avx() const { return has_avx_; }
// has_avx_hardware returns true when AVX is present in the CPU. This might
// differ from the value of |has_avx()| because |has_avx()| also tests for
// operating system support needed to actually call AVX instuctions.
// Note: you should never need to call this function. It was added in order
// to workaround a bug in NSS but |has_avx()| is what you want.
bool has_avx_hardware() const { return has_avx_hardware_; }
bool has_avx2() const { return has_avx2_; }
bool has_aesni() const { return has_aesni_; }
bool has_non_stop_time_stamp_counter() const {
return has_non_stop_time_stamp_counter_;
@ -83,7 +79,7 @@ class BASE_EXPORT CPU {
bool has_sse41_;
bool has_sse42_;
bool has_avx_;
bool has_avx_hardware_;
bool has_avx2_;
bool has_aesni_;
bool has_non_stop_time_stamp_counter_;
bool has_broken_neon_;

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

@ -6,8 +6,8 @@
// debuggers. You should use this to test if you're running under a debugger,
// and if you would like to yield (breakpoint) into the debugger.
#ifndef BASE_DEBUG_DEBUGGER_H
#define BASE_DEBUG_DEBUGGER_H
#ifndef BASE_DEBUG_DEBUGGER_H_
#define BASE_DEBUG_DEBUGGER_H_
#include "base/base_export.h"
@ -41,4 +41,4 @@ BASE_EXPORT bool IsDebugUISuppressed();
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_DEBUGGER_H
#endif // BASE_DEBUG_DEBUGGER_H_

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

@ -5,7 +5,7 @@
#ifndef BASE_DEBUG_LEAK_ANNOTATIONS_H_
#define BASE_DEBUG_LEAK_ANNOTATIONS_H_
#include "base/basictypes.h"
#include "base/macros.h"
#include "build/build_config.h"
// This file defines macros which can be used to annotate intentional memory
@ -21,15 +21,7 @@
#if defined(LEAK_SANITIZER) && !defined(OS_NACL)
// Public LSan API from <sanitizer/lsan_interface.h>.
extern "C" {
void __lsan_disable();
void __lsan_enable();
void __lsan_ignore_object(const void *p);
// Invoke leak detection immediately. If leaks are found, the process will exit.
void __lsan_do_leak_check();
} // extern "C"
#include <sanitizer/lsan_interface.h>
class ScopedLeakSanitizerDisabler {
public:
@ -46,7 +38,6 @@ class ScopedLeakSanitizerDisabler {
#else
// If neither HeapChecker nor LSan are used, the annotations should be no-ops.
#define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0)
#define ANNOTATE_LEAKING_OBJECT_PTR(X) ((void)0)

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

@ -6,16 +6,18 @@
#include <string>
#include "base/debug/debugging_flags.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "base/win/pe_image.h"
#endif // defined(OS_WIN)
// TODO(peria): Enable profiling on Windows.
#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h"
#endif
@ -23,15 +25,15 @@ namespace base {
namespace debug {
// TODO(peria): Enable profiling on Windows.
#if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
static int profile_count = 0;
void StartProfiling(const std::string& name) {
++profile_count;
std::string full_name(name);
std::string pid = StringPrintf("%d", GetCurrentProcId());
std::string count = StringPrintf("%d", profile_count);
std::string pid = IntToString(GetCurrentProcId());
std::string count = IntToString(profile_count);
ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
ProfilerStart(full_name.c_str());

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

@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_DEBUG_PROFILER_H
#define BASE_DEBUG_PROFILER_H
#ifndef BASE_DEBUG_PROFILER_H_
#define BASE_DEBUG_PROFILER_H_
#include <stddef.h>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
// The Profiler functions allow usage of the underlying sampling based
// profiler. If the application has not been built with the necessary
@ -87,4 +88,4 @@ BASE_EXPORT MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc();
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_DEBUGGER_H
#endif // BASE_DEBUG_PROFILER_H_

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

@ -14,9 +14,16 @@ namespace base {
// We introduct a special structure for file descriptors in order that we are
// able to use template specialisation to special-case their handling.
//
// WARNING: (Chromium only) There are subtleties to consider if serialising
// these objects over IPC. See comments in ipc/ipc_message_utils.h
// above the template specialisation for this structure.
// IMPORTANT: This is primarily intended for use when sending file descriptors
// over IPC. Even if |auto_close| is true, base::FileDescriptor does NOT close()
// |fd| when going out of scope. Instead, a consumer of a base::FileDescriptor
// must invoke close() on |fd| if |auto_close| is true.
//
// In the case of IPC, the the IPC subsystem knows to close() |fd| after sending
// a message that contains a base::FileDescriptor if auto_close == true. On the
// other end, the receiver must make sure to close() |fd| after it has finished
// processing the IPC message. See the IPC::ParamTraits<> specialization in
// ipc/ipc_message_utils.h for all the details.
// -----------------------------------------------------------------------------
struct FileDescriptor {
FileDescriptor() : fd(-1), auto_close(false) {}

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

@ -53,7 +53,7 @@
// between char[]-based pathnames on POSIX systems and wchar_t[]-based
// pathnames on Windows.
//
// Paths can't contain NULs as a precaution agaist premature truncation.
// As a precaution against premature truncation, paths can't contain NULs.
//
// Because a FilePath object should not be instantiated at the global scope,
// instead, use a FilePath::CharType[] and initialize it with
@ -83,9 +83,9 @@
// in case it ever comes across such a system. FilePath needs this support
// for Windows UNC paths, anyway.
// References:
// The Open Group Base Specifications Issue 7, sections 3.266 ("Pathname")
// The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname")
// and 4.12 ("Pathname Resolution"), available at:
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_266
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
//
// - Windows treats c:\\ the same way it treats \\. This was intended to
@ -103,13 +103,17 @@
#define BASE_FILES_FILE_PATH_H_
#include <stddef.h>
#include <iosfwd>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h" // For implicit conversions.
#include "base/strings/string_piece.h"
#include "build/build_config.h"
// Windows-style drive letter support and pathname separator characters can be
@ -121,11 +125,20 @@
#define FILE_PATH_USES_WIN_SEPARATORS
#endif // OS_WIN
class Pickle;
class PickleIterator;
// To print path names portably use PRIsFP (based on PRIuS and friends from
// C99 and format_macros.h) like this:
// base::StringPrintf("Path is %" PRIsFP ".\n", path.value().c_str());
#if defined(OS_POSIX)
#define PRIsFP "s"
#elif defined(OS_WIN)
#define PRIsFP "ls"
#endif // OS_WIN
namespace base {
class Pickle;
class PickleIterator;
// An abstraction to isolate users from the differences between native
// pathnames on different platforms.
class BASE_EXPORT FilePath {
@ -141,6 +154,7 @@ class BASE_EXPORT FilePath {
typedef std::wstring StringType;
#endif // OS_WIN
typedef BasicStringPiece<StringType> StringPieceType;
typedef StringType::value_type CharType;
// Null-terminated array of separators used to separate components in
@ -163,7 +177,7 @@ class BASE_EXPORT FilePath {
FilePath();
FilePath(const FilePath& that);
explicit FilePath(const StringType& path);
explicit FilePath(StringPieceType path);
~FilePath();
FilePath& operator=(const FilePath& that);
@ -237,7 +251,7 @@ class BASE_EXPORT FilePath {
// ASSERT(new_path == path.value());
// NOTE: this is different from the original file_util implementation which
// returned the extension without a leading "." ("jpg" instead of ".jpg")
StringType Extension() const;
StringType Extension() const WARN_UNUSED_RESULT;
// Returns the path's file extension, as in Extension(), but will
// never return a double extension.
@ -246,7 +260,7 @@ class BASE_EXPORT FilePath {
// we can rename this to Extension() and the other to something like
// LongExtension(), defaulting to short extensions and leaving the
// long "extensions" to logic like base::GetUniquePathNumber().
StringType FinalExtension() const;
StringType FinalExtension() const WARN_UNUSED_RESULT;
// Returns "C:\pics\jojo" for path "C:\pics\jojo.jpg"
// NOTE: this is slightly different from the similar file_util implementation
@ -265,25 +279,23 @@ class BASE_EXPORT FilePath {
// path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)"
// path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)"
FilePath InsertBeforeExtension(
const StringType& suffix) const WARN_UNUSED_RESULT;
StringPieceType suffix) const WARN_UNUSED_RESULT;
FilePath InsertBeforeExtensionASCII(
const base::StringPiece& suffix) const WARN_UNUSED_RESULT;
StringPiece suffix) const WARN_UNUSED_RESULT;
// Adds |extension| to |file_name|. Returns the current FilePath if
// |extension| is empty. Returns "" if BaseName() == "." or "..".
FilePath AddExtension(
const StringType& extension) const WARN_UNUSED_RESULT;
FilePath AddExtension(StringPieceType extension) const WARN_UNUSED_RESULT;
// Replaces the extension of |file_name| with |extension|. If |file_name|
// does not have an extension, then |extension| is added. If |extension| is
// empty, then the extension is removed from |file_name|.
// Returns "" if BaseName() == "." or "..".
FilePath ReplaceExtension(
const StringType& extension) const WARN_UNUSED_RESULT;
FilePath ReplaceExtension(StringPieceType extension) const WARN_UNUSED_RESULT;
// Returns true if the file path matches the specified extension. The test is
// case insensitive. Don't forget the leading period if appropriate.
bool MatchesExtension(const StringType& extension) const;
bool MatchesExtension(StringPieceType extension) const;
// Returns a FilePath by appending a separator and the supplied path
// component to this object's path. Append takes care to avoid adding
@ -291,7 +303,7 @@ class BASE_EXPORT FilePath {
// If this object's path is kCurrentDirectory, a new FilePath corresponding
// only to |component| is returned. |component| must be a relative path;
// it is an error to pass an absolute path.
FilePath Append(const StringType& component) const WARN_UNUSED_RESULT;
FilePath Append(StringPieceType component) const WARN_UNUSED_RESULT;
FilePath Append(const FilePath& component) const WARN_UNUSED_RESULT;
// Although Windows StringType is std::wstring, since the encoding it uses for
@ -300,8 +312,7 @@ class BASE_EXPORT FilePath {
// On Linux, although it can use any 8-bit encoding for paths, we assume that
// ASCII is a valid subset, regardless of the encoding, since many operating
// system paths will always be ASCII.
FilePath AppendASCII(const base::StringPiece& component)
const WARN_UNUSED_RESULT;
FilePath AppendASCII(StringPiece component) const WARN_UNUSED_RESULT;
// Returns true if this FilePath contains an absolute path. On Windows, an
// absolute path begins with either a drive letter specification followed by
@ -385,14 +396,14 @@ class BASE_EXPORT FilePath {
// on parts of a file path, e.g., just the extension.
// CompareIgnoreCase() returns -1, 0 or 1 for less-than, equal-to and
// greater-than respectively.
static int CompareIgnoreCase(const StringType& string1,
const StringType& string2);
static bool CompareEqualIgnoreCase(const StringType& string1,
const StringType& string2) {
static int CompareIgnoreCase(StringPieceType string1,
StringPieceType string2);
static bool CompareEqualIgnoreCase(StringPieceType string1,
StringPieceType string2) {
return CompareIgnoreCase(string1, string2) == 0;
}
static bool CompareLessIgnoreCase(const StringType& string1,
const StringType& string2) {
static bool CompareLessIgnoreCase(StringPieceType string1,
StringPieceType string2) {
return CompareIgnoreCase(string1, string2) < 0;
}
@ -402,14 +413,14 @@ class BASE_EXPORT FilePath {
// http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSubtleties
// for further comments.
// Returns the epmty string if the conversion failed.
static StringType GetHFSDecomposedForm(const FilePath::StringType& string);
static StringType GetHFSDecomposedForm(StringPieceType string);
// Special UTF-8 version of FastUnicodeCompare. Cf:
// http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm
// IMPORTANT: The input strings must be in the special HFS decomposed form!
// (cf. above GetHFSDecomposedForm method)
static int HFSFastUnicodeCompare(const StringType& string1,
const StringType& string2);
static int HFSFastUnicodeCompare(StringPieceType string1,
StringPieceType string2);
#endif
#if defined(OS_ANDROID)
@ -432,21 +443,22 @@ class BASE_EXPORT FilePath {
StringType path_;
};
} // namespace base
// This is required by googletest to print a readable output on test failures.
BASE_EXPORT extern void PrintTo(const base::FilePath& path, std::ostream* out);
// This is declared here for use in gtest-based unit tests but is defined in
// the test_support_base target. Depend on that to use this in your unit test.
// This should not be used in production code - call ToString() instead.
void PrintTo(const FilePath& path, std::ostream* out);
} // namespace base
// Macros for string literal initialization of FilePath::CharType[], and for
// using a FilePath::CharType[] in a printf-style format string.
#if defined(OS_POSIX)
#define FILE_PATH_LITERAL(x) x
#define PRFilePath "s"
#define PRFilePathLiteral "%s"
#elif defined(OS_WIN)
#define FILE_PATH_LITERAL(x) L ## x
#define PRFilePath "ls"
#define PRFilePathLiteral L"%ls"
#endif // OS_WIN
// Provide a hash function so that hash_sets and maps can contain FilePath

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

@ -1,36 +0,0 @@
// Copyright (c) 2012 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_FLOAT_UTIL_H_
#define BASE_FLOAT_UTIL_H_
#include "build/build_config.h"
#include <float.h>
#include <cmath>
namespace base {
template <typename Float>
inline bool IsFinite(const Float& number) {
#if defined(OS_POSIX)
return std::isfinite(number) != 0;
#elif defined(OS_WIN)
return _finite(number) != 0;
#endif
}
template <typename Float>
inline bool IsNaN(const Float& number) {
#if defined(OS_POSIX)
return std::isnan(number) != 0;
#elif defined(OS_WIN)
return _isnan(number) != 0;
#endif
}
} // namespace base
#endif // BASE_FLOAT_UTIL_H_

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

@ -5,10 +5,11 @@
#ifndef BASE_GUID_H_
#define BASE_GUID_H_
#include <stdint.h>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "build/build_config.h"
namespace base {
@ -24,7 +25,7 @@ BASE_EXPORT bool IsValidGUID(const std::string& guid);
#if defined(OS_POSIX)
// For unit testing purposes only. Do not use outside of tests.
BASE_EXPORT std::string RandomDataToGUIDString(const uint64 bytes[2]);
BASE_EXPORT std::string RandomDataToGUIDString(const uint64_t bytes[2]);
#endif
} // namespace base

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

@ -11,7 +11,7 @@ extern "C" uint32_t SuperFastHash(const char* data, int len);
namespace base {
uint32 SuperFastHash(const char* data, int len) {
uint32_t SuperFastHash(const char* data, int len) {
return ::SuperFastHash(data, len);
}

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

@ -5,21 +5,23 @@
#ifndef BASE_HASH_H_
#define BASE_HASH_H_
#include <stddef.h>
#include <stdint.h>
#include <limits>
#include <string>
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/logging.h"
namespace base {
// WARNING: This hash function should not be used for any cryptographic purpose.
BASE_EXPORT uint32 SuperFastHash(const char* data, int len);
BASE_EXPORT uint32_t SuperFastHash(const char* data, int len);
// Computes a hash of a memory buffer |data| of a given |length|.
// WARNING: This hash function should not be used for any cryptographic purpose.
inline uint32 Hash(const char* data, size_t length) {
inline uint32_t Hash(const char* data, size_t length) {
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
@ -29,7 +31,7 @@ inline uint32 Hash(const char* data, size_t length) {
// Computes a hash of a string |str|.
// WARNING: This hash function should not be used for any cryptographic purpose.
inline uint32 Hash(const std::string& str) {
inline uint32_t Hash(const std::string& str) {
return Hash(str.data(), str.size());
}

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

@ -6,7 +6,6 @@
#include "base/at_exit.h"
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/threading/platform_thread.h"
namespace base {

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

@ -39,7 +39,6 @@
#include "base/atomicops.h"
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/debug/leak_annotations.h"
#include "base/logging.h"
#include "base/memory/aligned_memory.h"

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