Merge autoland to mozilla-central. a=merge

This commit is contained in:
shindli 2019-01-09 23:40:48 +02:00
Родитель 56680c0c2c 65938f22af
Коммит 20a70f9169
38 изменённых файлов: 605 добавлений и 152 удалений

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

@ -1282,11 +1282,7 @@ pref("browser.newtabpage.activity-stream.fxaccounts.endpoint", "https://accounts
pref("browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts", true);
// ASRouter provider configuration
#if defined(NIGHTLY_BUILD)
pref("browser.newtabpage.activity-stream.asrouter.providers.cfr", "{\"id\":\"cfr\",\"enabled\":true,\"type\":\"local\",\"localProvider\":\"CFRMessageProvider\",\"frequency\":{\"custom\":[{\"period\":\"daily\",\"cap\":1}]}}");
#else
pref("browser.newtabpage.activity-stream.asrouter.providers.cfr", "{\"id\":\"cfr\",\"enabled\":false,\"type\":\"local\",\"localProvider\":\"CFRMessageProvider\",\"frequency\":{\"custom\":[{\"period\":\"daily\",\"cap\":1}]}}");
#endif
#ifdef EARLY_BETA_OR_EARLIER
pref("browser.newtabpage.activity-stream.asrouter.providers.snippets", "{\"id\":\"snippets\",\"enabled\":true,\"type\":\"remote\",\"url\":\"https://snippets.cdn.mozilla.net/%STARTPAGE_VERSION%/%NAME%/%VERSION%/%APPBUILDID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/\",\"updateCycleInMs\":14400000}");

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

@ -14,6 +14,9 @@ XPCOMUtils.defineLazyModuleGetters(this, {
UrlbarProvidersManager: "resource:///modules/UrlbarProvidersManager.jsm",
});
const TELEMETRY_1ST_RESULT = "PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS";
const TELEMETRY_6_FIRST_RESULTS = "PLACES_AUTOCOMPLETE_6_FIRST_RESULTS_TIME_MS";
/**
* The address bar controller handles queries from the address bar, obtains
* results and returns them to the UI for display.
@ -88,6 +91,10 @@ class UrlbarController {
queryContext.autoFill = UrlbarPrefs.get("autoFill");
queryContext.lastTelemetryResultCount = 0;
TelemetryStopwatch.start(TELEMETRY_1ST_RESULT, queryContext);
TelemetryStopwatch.start(TELEMETRY_6_FIRST_RESULTS, queryContext);
this._notify("onQueryStarted", queryContext);
await this.manager.startQuery(queryContext, this);
this._notify("onQueryFinished", queryContext);
@ -103,6 +110,10 @@ class UrlbarController {
if (queryContext === this._lastQueryContext) {
delete this._lastQueryContext;
}
TelemetryStopwatch.cancel(TELEMETRY_1ST_RESULT, queryContext);
TelemetryStopwatch.cancel(TELEMETRY_6_FIRST_RESULTS, queryContext);
this.manager.cancelQuery(queryContext);
this._notify("onQueryCancelled", queryContext);
}
@ -113,6 +124,16 @@ class UrlbarController {
* @param {QueryContext} queryContext The query details.
*/
receiveResults(queryContext) {
if (queryContext.lastTelemetryResultCount < 1 &&
queryContext.results.length >= 1) {
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT, queryContext);
}
if (queryContext.lastTelemetryResultCount < 6 &&
queryContext.results.length >= 6) {
TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS, queryContext);
}
queryContext.lastTelemetryResultCount = queryContext.results.length;
this._notify("onQueryResults", queryContext);
}

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

@ -96,6 +96,9 @@ class ProviderUnifiedComplete extends UrlbarProvider {
// This is necessary because we insert matches one by one, thus we don't
// want UnifiedComplete to reuse results.
params.push(`insert-method:${UrlbarUtils.INSERTMETHOD.APPEND}`);
// The Quantum Bar has its own telemetry measurement, thus disable old
// telemetry logged by UnifiedComplete.
params.push("disable-telemetry");
if (queryContext.isPrivate) {
params.push("private-window");
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {

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

@ -87,7 +87,7 @@ class TestProvider extends UrlbarProvider {
constructor(matches, cancelCallback) {
super();
this._name = "TestProvider" + Math.floor(Math.random() * 100000);
this._cancel = cancelCallback;
this._cancelCallback = cancelCallback;
this._matches = matches;
}
get name() {

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

@ -61,12 +61,12 @@ add_task(async function test_basic_search() {
});
add_task(async function test_cancel_search() {
let providerCanceledPromise = PromiseUtils.defer();
let providerName = registerBasicTestProvider([match], providerCanceledPromise.resolve);
let providerCanceledDeferred = PromiseUtils.defer();
let providerName = registerBasicTestProvider([match], providerCanceledDeferred.resolve);
const context = createContext(TEST_URL, {providers: [providerName]});
let startedPromise = promiseControllerNotification(controller, "onQueryStarted");
let cancelPromise = promiseControllerNotification(controller, "onQueryResults");
let cancelPromise = promiseControllerNotification(controller, "onQueryCancelled");
await controller.startQuery(context);
@ -77,7 +77,7 @@ add_task(async function test_cancel_search() {
Assert.equal(params[0], context);
info("Should tell the provider the query is canceled");
await providerCanceledPromise;
await providerCanceledDeferred.promise;
params = await cancelPromise;
});

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

@ -0,0 +1,193 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* These tests unit test the functionality of UrlbarController by stubbing out the
* model and providing stubs to be called.
*/
"use strict";
const TEST_URL = "http://example.com";
const MATCH = new UrlbarMatch(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
UrlbarUtils.MATCH_SOURCE.TABS,
{ url: TEST_URL });
const TELEMETRY_1ST_RESULT = "PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS";
const TELEMETRY_6_FIRST_RESULTS = "PLACES_AUTOCOMPLETE_6_FIRST_RESULTS_TIME_MS";
let controller;
let firstHistogram;
let sixthHistogram;
/**
* A delayed test provider, allowing the query to be delayed for an amount of time.
*/
class DelayedProvider extends UrlbarProvider {
constructor() {
super();
this._name = "TestProvider" + Math.floor(Math.random() * 100000);
}
get name() {
return this._name;
}
get type() {
return UrlbarUtils.PROVIDER_TYPE.PROFILE;
}
get sources() {
return [UrlbarUtils.MATCH_SOURCE.TABS];
}
async startQuery(context, add) {
Assert.ok(context, "context is passed-in");
Assert.equal(typeof add, "function", "add is a callback");
this._context = context;
this._add = add;
}
cancelQuery(context) {
Assert.ok(false, "cancelQuery should not be called");
}
addResults(matches) {
for (const match of matches) {
this._add(this, match);
}
}
}
/**
* Returns the number of reports sent recorded within the histogram results.
*
* @param {object} results a snapshot of histogram results to check.
* @returns {number} The count of reports recorded in the histogram.
*/
function getHistogramReportsCount(results) {
let sum = 0;
for (let [, value] of Object.entries(results.values)) {
sum += value;
}
return sum;
}
add_task(function setup() {
controller = new UrlbarController({
browserWindow: {
location: {
href: AppConstants.BROWSER_CHROME_URL,
},
},
});
firstHistogram = Services.telemetry.getHistogramById(TELEMETRY_1ST_RESULT);
sixthHistogram = Services.telemetry.getHistogramById(TELEMETRY_6_FIRST_RESULTS);
});
add_task(async function test_n_autocomplete_cancel() {
firstHistogram.clear();
sixthHistogram.clear();
let providerCanceledDeferred = PromiseUtils.defer();
let provider = new TestProvider([], providerCanceledDeferred.resolve);
UrlbarProvidersManager.registerProvider(provider);
const context = createContext(TEST_URL, {providers: [provider.name]});
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should not have started first result stopwatch");
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should not have started first 6 results stopwatch");
await controller.startQuery(context);
Assert.ok(TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should have started first result stopwatch");
Assert.ok(TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should have started first 6 results stopwatch");
controller.cancelQuery(context);
await providerCanceledDeferred.promise;
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should have canceled first result stopwatch");
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should have canceled first 6 results stopwatch");
let results = firstHistogram.snapshot();
Assert.equal(results.sum, 0, "Should not have recorded any times (first result)");
results = sixthHistogram.snapshot();
Assert.equal(results.sum, 0, "Should not have recorded any times (first 6 results)");
});
add_task(async function test_n_autocomplete_results() {
firstHistogram.clear();
sixthHistogram.clear();
let provider = new DelayedProvider();
UrlbarProvidersManager.registerProvider(provider);
const context = createContext(TEST_URL, {providers: [provider.name]});
let resultsPromise = promiseControllerNotification(controller, "onQueryResults");
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should not have started first result stopwatch");
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should not have started first 6 results stopwatch");
await controller.startQuery(context);
Assert.ok(TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should have started first result stopwatch");
Assert.ok(TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should have started first 6 results stopwatch");
provider.addResults([MATCH]);
await resultsPromise;
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should have stopped the first stopwatch");
Assert.ok(TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should have kept the first 6 results stopwatch running");
let firstResults = firstHistogram.snapshot();
let first6Results = sixthHistogram.snapshot();
Assert.equal(getHistogramReportsCount(firstResults), 1,
"Should have recorded one time for the first result");
Assert.equal(getHistogramReportsCount(first6Results), 0,
"Should not have recorded any times (first 6 results)");
// Now add 5 more results, so that the first 6 results is triggered.
for (let i = 0; i < 5; i++) {
resultsPromise = promiseControllerNotification(controller, "onQueryResults");
provider.addResults([
new UrlbarMatch(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
UrlbarUtils.MATCH_SOURCE.TABS,
{ url: TEST_URL + "/i" }),
]);
await resultsPromise;
}
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_1ST_RESULT, context),
"Should have stopped the first stopwatch");
Assert.ok(!TelemetryStopwatch.running(TELEMETRY_6_FIRST_RESULTS, context),
"Should have stopped the first 6 results stopwatch");
let updatedResults = firstHistogram.snapshot();
let updated6Results = sixthHistogram.snapshot();
Assert.deepEqual(updatedResults, firstResults,
"Should not have changed the histogram for the first result");
Assert.equal(getHistogramReportsCount(updated6Results), 1,
"Should have recorded one time for the first 6 results");
// Add one more, to check neither are updated.
resultsPromise = promiseControllerNotification(controller, "onQueryResults");
provider.addResults([
new UrlbarMatch(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
UrlbarUtils.MATCH_SOURCE.TABS,
{ url: TEST_URL + "/6" }),
]);
await resultsPromise;
let secondUpdateResults = firstHistogram.snapshot();
let secondUpdate6Results = sixthHistogram.snapshot();
Assert.deepEqual(secondUpdateResults, firstResults,
"Should not have changed the histogram for the first result");
Assert.equal(getHistogramReportsCount(secondUpdate6Results), 1,
"Should not have changed the histogram for the first 6 results");
});

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

@ -192,6 +192,7 @@ add_task(function test_cancel_query() {
add_task(function test_receiveResults() {
const context = createContext();
context.results = [];
controller.receiveResults(context);
Assert.equal(generalListener.onQueryResults.callCount, 1,
@ -204,6 +205,7 @@ add_task(function test_receiveResults() {
add_task(function test_autocomplete_enabled() {
const context = createContext();
context.results = [];
controller.receiveResults(context);
Assert.equal(generalListener.onQueryResults.callCount, 1,
@ -213,4 +215,3 @@ add_task(function test_autocomplete_enabled() {
sandbox.resetHistory();
});

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

@ -13,6 +13,7 @@ support-files =
[test_QueryContext.js]
[test_tokenizer.js]
[test_UrlbarController_unit.js]
[test_UrlbarController_telemetry.js]
[test_UrlbarController_integration.js]
[test_UrlbarUtils_addToUrlbarHistory.js]
[test_UrlbarUtils_getShortcutOrURIAndPostData.js]

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

@ -102,8 +102,8 @@ bool WrapResult(JSContext* aCx, JS::Handle<JSObject*> aProxy,
if (!ToJSValue(aCx, WindowProxyHolder(aResult), &v)) {
return false;
}
aDesc.object().set(aProxy);
aDesc.setDataDescriptor(v, attrs);
aDesc.object().set(aProxy);
return true;
}

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

@ -1407,12 +1407,11 @@ bool nsImageLoadingContent::HaveSize(imgIRequest* aImage) {
void nsImageLoadingContent::BindToTree(Document* aDocument, nsIContent* aParent,
nsIContent* aBindingParent) {
// We may be entering the document, so if our image should be tracked,
// track it.
if (!aDocument) return;
TrackImage(mCurrentRequest);
TrackImage(mPendingRequest);
// We may be getting connected, if so our image should be tracked,
if (GetOurCurrentDoc()) {
TrackImage(mCurrentRequest);
TrackImage(mPendingRequest);
}
}
void nsImageLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent) {

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

@ -1559,25 +1559,6 @@ nsresult HTMLFormElement::GetActionURL(nsIURI** aActionURL,
NodePrincipal(), actionURL, nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS(rv, rv);
// Check if CSP allows this form-action
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
bool permitsFormAction = true;
// form-action is only enforced if explicitly defined in the
// policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src
rv = csp->Permits(this, nullptr /* nsICSPEventListener */, actionURL,
nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE, true,
&permitsFormAction);
NS_ENSURE_SUCCESS(rv, rv);
if (!permitsFormAction) {
return NS_ERROR_CSP_FORM_ACTION_VIOLATION;
}
}
// Potentially the page uses the CSP directive 'upgrade-insecure-requests'. In
// such a case we have to upgrade the action url from http:// to https://.
// If the actionURL is not http, then there is nothing to do.

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

@ -823,6 +823,25 @@ void GetEnumAttr(nsGenericHTMLElement* aContent, nsAtom* atom,
rv = aForm->GetActionURL(getter_AddRefs(actionURL), aOriginatingElement);
NS_ENSURE_SUCCESS(rv, rv);
// Check if CSP allows this form-action
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = aForm->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
bool permitsFormAction = true;
// form-action is only enforced if explicitly defined in the
// policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src
rv = csp->Permits(aForm, nullptr /* nsICSPEventListener */, actionURL,
nsIContentSecurityPolicy::FORM_ACTION_DIRECTIVE, true,
&permitsFormAction);
NS_ENSURE_SUCCESS(rv, rv);
if (!permitsFormAction) {
return NS_ERROR_CSP_FORM_ACTION_VIOLATION;
}
}
// Get target
// The target is the originating element formtarget attribute if the element
// is a submit control and has such an attribute.

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

@ -500,8 +500,9 @@ nsresult HTMLImageElement::BindToTree(Document* aDocument, nsIContent* aParent,
}
if (HaveSrcsetOrInPicture()) {
if (aDocument && !mInDocResponsiveContent) {
aDocument->AddResponsiveContent(this);
Document* doc = GetComposedDoc();
if (doc && !mInDocResponsiveContent) {
doc->AddResponsiveContent(this);
mInDocResponsiveContent = true;
}

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

@ -98,9 +98,8 @@ void ProfilerScreenshots::SubmitScreenshot(
// Encode surf to a JPEG data URL.
nsCString dataURL;
nsresult rv = gfxUtils::EncodeSourceSurface(
surf, NS_LITERAL_CSTRING("image/jpeg"),
NS_LITERAL_STRING("quality=85"), gfxUtils::eDataURIEncode,
nullptr, &dataURL);
surf, ImageType::JPEG, NS_LITERAL_STRING("quality=85"),
gfxUtils::eDataURIEncode, nullptr, &dataURL);
if (NS_SUCCEEDED(rv)) {
// Add a marker with the data URL.
profiler_add_marker_for_thread(

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

@ -23,6 +23,10 @@
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/image/nsBMPEncoder.h"
#include "mozilla/image/nsICOEncoder.h"
#include "mozilla/image/nsJPEGEncoder.h"
#include "mozilla/image/nsPNGEncoder.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtrExtensions.h"
@ -35,6 +39,7 @@
#include "nsIFile.h"
#include "nsIGfxInfo.h"
#include "nsIPresShell.h"
#include "nsMimeTypes.h"
#include "nsPresContext.h"
#include "nsRegion.h"
#include "nsServiceManagerUtils.h"
@ -896,7 +901,7 @@ const uint32_t gfxUtils::sNumFrameColors = 8;
}
/* static */ nsresult gfxUtils::EncodeSourceSurface(
SourceSurface* aSurface, const nsACString& aMimeType,
SourceSurface* aSurface, const ImageType aImageType,
const nsAString& aOutputOptions, BinaryOrData aBinaryOrData, FILE* aFile,
nsACString* aStrOut) {
MOZ_ASSERT(aBinaryOrData == gfxUtils::eDataURIEncode || aFile || aStrOut,
@ -925,25 +930,31 @@ const uint32_t gfxUtils::sNumFrameColors = 8;
return NS_ERROR_FAILURE;
}
nsAutoCString encoderCID(
NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
if (!encoder) {
#ifdef DEBUG
int32_t w = std::min(size.width, 8);
int32_t h = std::min(size.height, 8);
printf("Could not create encoder. Top-left %dx%d pixels contain:\n", w, h);
for (int32_t y = 0; y < h; ++y) {
for (int32_t x = 0; x < w; ++x) {
printf("%x ",
reinterpret_cast<uint32_t*>(map.mData)[y * map.mStride + x]);
}
}
#endif
dataSurface->Unmap();
return NS_ERROR_FAILURE;
RefPtr<imgIEncoder> encoder = nullptr;
switch (aImageType) {
case ImageType::BMP:
encoder = MakeRefPtr<nsBMPEncoder>();
break;
case ImageType::ICO:
encoder = MakeRefPtr<nsICOEncoder>();
break;
case ImageType::JPEG:
encoder = MakeRefPtr<nsJPEGEncoder>();
break;
case ImageType::PNG:
encoder = MakeRefPtr<nsPNGEncoder>();
break;
default:
break;
}
MOZ_RELEASE_ASSERT(encoder != nullptr);
nsresult rv = encoder->InitFromData(
map.mData, BufferSizeFromStrideAndHeight(map.mStride, size.height),
size.width, size.height, map.mStride, imgIEncoder::INPUT_FORMAT_HOSTARGB,
@ -1006,17 +1017,37 @@ const uint32_t gfxUtils::sNumFrameColors = 8;
NS_ENSURE_SUCCESS(rv, rv);
nsCString stringBuf;
nsACString& string = aStrOut ? *aStrOut : stringBuf;
string.AppendLiteral("data:");
string.Append(aMimeType);
string.AppendLiteral(";base64,");
string.Append(encodedImg);
nsACString& dataURI = aStrOut ? *aStrOut : stringBuf;
dataURI.AppendLiteral("data:");
switch (aImageType) {
case ImageType::BMP:
dataURI.AppendLiteral(IMAGE_BMP);
break;
case ImageType::ICO:
dataURI.AppendLiteral(IMAGE_ICO_MS);
break;
case ImageType::JPEG:
dataURI.AppendLiteral(IMAGE_JPEG);
break;
case ImageType::PNG:
dataURI.AppendLiteral(IMAGE_PNG);
break;
default:
break;
}
dataURI.AppendLiteral(";base64,");
dataURI.Append(encodedImg);
if (aFile) {
#ifdef ANDROID
if (aFile == stdout || aFile == stderr) {
// ADB logcat cuts off long strings so we will break it down
const char* cStr = string.BeginReading();
const char* cStr = dataURI.BeginReading();
size_t len = strlen(cStr);
while (true) {
printf_stderr("IMG: %.140s\n", cStr);
@ -1026,12 +1057,12 @@ const uint32_t gfxUtils::sNumFrameColors = 8;
}
}
#endif
fprintf(aFile, "%s", string.BeginReading());
fprintf(aFile, "%s", dataURI.BeginReading());
} else if (!aStrOut) {
nsCOMPtr<nsIClipboardHelper> clipboard(
do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
if (clipboard) {
clipboard->CopyString(NS_ConvertASCIItoUTF16(string));
clipboard->CopyString(NS_ConvertASCIItoUTF16(dataURI));
}
}
return NS_OK;
@ -1039,9 +1070,8 @@ const uint32_t gfxUtils::sNumFrameColors = 8;
static nsCString EncodeSourceSurfaceAsPNGURI(SourceSurface* aSurface) {
nsCString string;
gfxUtils::EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
EmptyString(), gfxUtils::eDataURIEncode,
nullptr, &string);
gfxUtils::EncodeSourceSurface(aSurface, ImageType::PNG, EmptyString(),
gfxUtils::eDataURIEncode, nullptr, &string);
return string;
}
@ -1154,8 +1184,8 @@ const float kBT709NarrowYCbCrToRGB_RowMajor[16] = {
}
}
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"), EmptyString(),
eBinaryEncode, file);
EncodeSourceSurface(aSurface, ImageType::PNG, EmptyString(), eBinaryEncode,
file);
fclose(file);
}
@ -1192,8 +1222,8 @@ const float kBT709NarrowYCbCrToRGB_RowMajor[16] = {
/* static */ void gfxUtils::DumpAsDataURI(SourceSurface* aSurface,
FILE* aFile) {
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"), EmptyString(),
eDataURIEncode, aFile);
EncodeSourceSurface(aSurface, ImageType::PNG, EmptyString(), eDataURIEncode,
aFile);
}
/* static */ nsCString gfxUtils::GetAsDataURI(SourceSurface* aSurface) {
@ -1245,8 +1275,8 @@ const float kBT709NarrowYCbCrToRGB_RowMajor[16] = {
}
/* static */ void gfxUtils::CopyAsDataURI(SourceSurface* aSurface) {
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"), EmptyString(),
eDataURIEncode, nullptr);
EncodeSourceSurface(aSurface, ImageType::PNG, EmptyString(), eDataURIEncode,
nullptr);
}
/* static */ void gfxUtils::CopyAsDataURI(DrawTarget* aDT) {

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

@ -41,6 +41,13 @@ class DisplayListBuilder;
} // namespace wr
} // namespace mozilla
enum class ImageType {
BMP,
ICO,
JPEG,
PNG,
};
class gfxUtils {
public:
typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
@ -225,9 +232,8 @@ class gfxUtils {
* If both aFile and aString are null, the encoded data is copied to the
* clipboard.
*
* @param aMimeType The MIME-type of the image type that the surface is to
* be encoded to. Used to create an appropriate imgIEncoder instance to
* do the encoding.
* @param aImageType The image type that the surface is to be encoded to.
* Used to create an appropriate imgIEncoder instance to do the encoding.
*
* @param aOutputOptions Passed directly to imgIEncoder::InitFromData as
* the value of the |outputOptions| parameter. Callers are responsible
@ -246,7 +252,7 @@ class gfxUtils {
* supported.
*/
static nsresult EncodeSourceSurface(SourceSurface* aSurface,
const nsACString& aMimeType,
const ImageType aImageType,
const nsAString& aOutputOptions,
BinaryOrData aBinaryOrData, FILE* aFile,
nsACString* aString = nullptr);

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

@ -11,6 +11,7 @@
#include "nsStreamUtils.h"
#include "nsTArray.h"
#include "mozilla/CheckedInt.h"
#include "BMPHeaders.h"
using namespace mozilla;
using namespace mozilla::image;

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

@ -11,7 +11,6 @@
#include "mozilla/UniquePtr.h"
#include "imgIEncoder.h"
#include "BMPHeaders.h"
#include "nsCOMPtr.h"

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

@ -5,6 +5,7 @@
#include "nsCRT.h"
#include "mozilla/EndianUtils.h"
#include "nsBMPEncoder.h"
#include "BMPHeaders.h"
#include "nsPNGEncoder.h"
#include "nsICOEncoder.h"
#include "nsString.h"

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

@ -7,11 +7,11 @@
#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/image/ICOFileHeaders.h"
#include "imgIEncoder.h"
#include "nsCOMPtr.h"
#include "ICOFileHeaders.h"
#define NS_ICOENCODER_CID \
{ /*92AE3AB2-8968-41B1-8709-B6123BCEAF21 */ \

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

@ -3,7 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsPNGEncoder_h
#ifndef mozilla_image_encoders_png_nsPNGEncoder_h
#define mozilla_image_encoders_png_nsPNGEncoder_h
#include <png.h>
@ -74,4 +75,4 @@ class nsPNGEncoder final : public imgIEncoder {
// AsyncWait.
ReentrantMonitor mReentrantMonitor;
};
#endif // nsPNGEncoder_h
#endif // mozilla_image_encoders_png_nsPNGEncoder_h

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

@ -54,7 +54,11 @@ EXPORTS += [
]
EXPORTS.mozilla.image += [
'encoders/bmp/nsBMPEncoder.h',
'encoders/ico/nsICOEncoder.h',
'encoders/jpeg/nsJPEGEncoder.h',
'encoders/png/nsPNGEncoder.h',
'ICOFileHeaders.h',
'ImageMemoryReporter.h',
'RecyclingSourceSurface.h',
]

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

@ -957,7 +957,8 @@ pref("gfx.webrender.debug.show-overdraw", false);
pref("gfx.webrender.debug.slow-frame-indicator", false);
pref("gfx.webrender.dl.dump-parent", false);
pref("gfx.webrender.dl.dump-content", false);
pref("gfx.webrender.picture-caching", false);
pref("gfx.webrender.picture-caching", true);
#ifdef EARLY_BETA_OR_EARLIER
pref("performance.adjust_to_machine", true);
@ -1080,6 +1081,8 @@ pref("toolkit.scrollbox.verticalScrollDistance", 3);
pref("toolkit.scrollbox.horizontalScrollDistance", 5);
pref("toolkit.scrollbox.clickToScroll.scrollDelay", 150);
pref("toolkit.tabbox.switchByScrolling", false);
// Telemetry settings.
// Server to submit telemetry pings to.
pref("toolkit.telemetry.server", "https://incoming.telemetry.mozilla.org");

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

@ -164,7 +164,12 @@ linux64-clang-tidy:
using: toolchain-script
script: build-clang-tidy-linux.sh
resources:
- 'build/clang-plugin/**'
- 'build/clang-plugin/**/*.cpp'
- 'build/clang-plugin/**/*.h'
- 'build/clang-plugin/*.inc'
- 'build/clang-plugin/*.py'
- 'build/clang-plugin/moz.build'
- 'build/clang-plugin/Makefile.in'
- 'build/build-clang/build-clang.py'
- 'build/build-clang/clang-tidy-linux64.json'
- 'taskcluster/scripts/misc/tooltool-download.sh'

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

@ -56,7 +56,12 @@ macosx64-clang-tidy:
script: build-clang-tidy-macosx.sh
tooltool-downloads: internal
resources:
- 'build/clang-plugin/**'
- 'build/clang-plugin/**/*.cpp'
- 'build/clang-plugin/**/*.h'
- 'build/clang-plugin/*.inc'
- 'build/clang-plugin/*.py'
- 'build/clang-plugin/moz.build'
- 'build/clang-plugin/Makefile.in'
- 'build/build-clang/build-clang.py'
- 'build/build-clang/clang-tidy-macosx64.json'
- 'taskcluster/scripts/misc/tooltool-download.sh'

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

@ -42,7 +42,12 @@ win32-clang-tidy:
using: toolchain-script
script: build-clang-tidy32-windows.sh
resources:
- 'build/clang-plugin/**'
- 'build/clang-plugin/**/*.cpp'
- 'build/clang-plugin/**/*.h'
- 'build/clang-plugin/*.inc'
- 'build/clang-plugin/*.py'
- 'build/clang-plugin/moz.build'
- 'build/clang-plugin/Makefile.in'
- 'build/build-clang/build-clang.py'
- 'build/build-clang/clang-tidy-win32.json'
- 'taskcluster/scripts/misc/build-clang-windows-helper32.sh'
@ -70,7 +75,12 @@ win64-clang-tidy:
using: toolchain-script
script: build-clang-tidy64-windows.sh
resources:
- 'build/clang-plugin/**'
- 'build/clang-plugin/**/*.cpp'
- 'build/clang-plugin/**/*.h'
- 'build/clang-plugin/*.inc'
- 'build/clang-plugin/*.py'
- 'build/clang-plugin/moz.build'
- 'build/clang-plugin/Makefile.in'
- 'build/build-clang/build-clang.py'
- 'build/build-clang/clang-tidy-win32.json'
- 'taskcluster/scripts/misc/build-clang-windows-helper64.sh'

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

@ -1400,7 +1400,14 @@ function switchToFrame(msg) {
if (typeof msg.json.element != "undefined") {
webEl = WebElement.fromUUID(msg.json.element, "content");
}
if (webEl && seenEls.has(webEl)) {
if (webEl) {
if (!seenEls.has(webEl)) {
let err = new NoSuchElementError(`Unable to locate element: ${webEl}`);
sendError(err, commandID);
return;
}
let wantedFrame;
try {
wantedFrame = seenEls.get(webEl, curContainer.frame);

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

@ -1,2 +0,0 @@
[focus-autofocus.html]
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1273247

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

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<meta http-equiv="Content-Security-Policy" content="form-action 'none'; script-src 'self' 'nonce-noncynonce'; connect-src 'self';">
</head>
<body>
<form action='/content-security-policy/support/postmessage-pass-to-opener.html'
id='form_id'
target="_blank">
<input type="submit" />
</form>
<p>
Test that "form-action 'none'" doesn't create a violation report if the event was prevented.
</p>
</body>
<script nonce='noncynonce'>
async_test(t => {
document.addEventListener('securitypolicyviolation', function(e) {
assert_unreached('Form submission was blocked.');
});
window.addEventListener('message', function(event) {
assert_unreached('Form submission was blocked.');
})
window.addEventListener("load", function() {
let form = document.getElementById("form_id");
form.addEventListener("submit", e => {
e.preventDefault();
setTimeout(() => {
t.done();
}, 0);
});
// clicking the input is used here as form.submit() will submit a form without an event and should also be blocked.
form.querySelector("input").click();
});
}, "The form submission should not be blocked by when javascript prevents the load.");
</script>
</html>

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

@ -0,0 +1,33 @@
<!doctype html>
<html class="reftest-wait">
<title>Image intrinsic size specified via sizes attribute reacts properly to media changes in Shadow DOM</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="match" href="sizes-dynamic-001-ref.html">
<link rel="help" href="https://html.spec.whatwg.org/#sizes-attributes">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1149357">
<script>
function frameLoaded(frame) {
let doc = frame.contentDocument;
let shadow = doc.getElementById("host").attachShadow({ mode: "open" });
let img = doc.createElement("img");
img.srcset = "/images/green-256x256.png 100w";
img.style.maxWidth = "100%";
img.setAttribute("sizes", "(min-width: 400px) 10px, 20px");
img.onload = function() {
img.offsetWidth; // Flush layout.
frame.width = "500";
// Trigger the viewport resize, which will trigger the image load task.
img.offsetWidth;
// Wait for the image load task to run.
setTimeout(() => document.documentElement.removeAttribute("class"), 0);
};
shadow.appendChild(img);
}
</script>
<iframe onload="frameLoaded(this)" width="200" height="500" srcdoc='<!doctype html><div id="host"></div>'></iframe>

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

@ -474,6 +474,7 @@ def setup_logging(kwargs, default_config=None):
default_config = {default_formatter: sys.stdout}
wptrunner.setup_logging(kwargs, default_config)
logger = wptrunner.logger
return logger
def setup_wptrunner(venv, prompt=True, install_browser=False, **kwargs):

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

@ -1,7 +1,11 @@
import pytest
import webdriver.protocol as protocol
from webdriver import StaleElementReferenceException
from webdriver.transport import Response
from tests.support.asserts import assert_error, assert_success
from tests.support.asserts import assert_error, assert_same_element, assert_success
from tests.support.inline import inline, iframe
@ -13,6 +17,11 @@ def switch_to_frame(session, frame):
session=session)
def frameset(*docs):
frames = map(lambda doc: "<frame src='{}'></frame>".format(inline(doc)), docs)
return "<frameset rows='{}'>\n{}</frameset>".format(len(frames) * "*,", "\n".join(frames))
def test_null_parameter_value(session, http):
path = "/session/{session_id}/frame".format(**vars(session))
with http.post(path, None) as response:
@ -21,13 +30,120 @@ def test_null_parameter_value(session, http):
def test_null_response_value(session):
session.url = inline(iframe("<p>foo"))
frame_element = session.find.css("iframe", all=False)
frame = session.find.css("iframe", all=False)
response = switch_to_frame(session, frame_element)
response = switch_to_frame(session, frame)
value = assert_success(response)
assert value is None
@pytest.mark.parametrize("value", ["foo", True, [], {}])
def test_frame_id_invalid_types(session, value):
response = switch_to_frame(session, value)
assert_error(response, "invalid argument")
@pytest.mark.parametrize("value", [-1, 2**16])
def test_frame_id_out_of_bounds(session, value):
response = switch_to_frame(session, value)
assert_error(response, "invalid argument")
def test_no_browsing_context(session, closed_window):
response = switch_to_frame(session, 1)
assert_error(response, "no such window")
def test_frame_id_null(session):
session.url = inline(iframe("{}<div>foo".format(iframe("<p>bar"))))
frame1 = session.find.css("iframe", all=False)
session.switch_frame(frame1)
frame1_element = session.find.css("div", all=False)
frame2 = session.find.css("iframe", all=False)
session.switch_frame(frame2)
frame2_element = session.find.css("p", all=False)
# Switch to top-level browsing context
response = switch_to_frame(session, None)
assert_success(response)
with pytest.raises(StaleElementReferenceException):
frame2_element.text
with pytest.raises(StaleElementReferenceException):
frame1_element.text
frame = session.find.css("iframe", all=False)
assert_same_element(session, frame, frame1)
@pytest.mark.parametrize("index, value", [[0, "foo"], [1, "bar"]])
def test_frame_id_number_index(session, index, value):
session.url = inline("{}{}".format(iframe("<p>foo"), iframe("<p>bar")))
response = switch_to_frame(session, index)
assert_success(response)
frame_element = session.find.css("p", all=False)
assert frame_element.text == value
def test_frame_id_number_index_out_of_bounds(session):
session.url = inline(iframe("<p>foo"))
response = switch_to_frame(session, 1)
assert_error(response, "no such frame")
@pytest.mark.parametrize("index, value", [[0, "foo"], [1, "bar"]])
def test_frame_id_webelement_frame(session, index, value):
session.url = inline(frameset("<p>foo", "<p>bar"))
frames = session.find.css("frame")
assert len(frames) == 2
response = switch_to_frame(session, frames[index])
assert_success(response)
frame_element = session.find.css("p", all=False)
assert frame_element.text == value
@pytest.mark.parametrize("index, value", [[0, "foo"], [1, "bar"]])
def test_frame_id_webelement_iframe(session, index, value):
session.url = inline("{}{}".format(iframe("<p>foo"), iframe("<p>bar")))
frames = session.find.css("iframe")
assert len(frames) == 2
response = switch_to_frame(session, frames[index])
assert_success(response)
frame_element = session.find.css("p", all=False)
assert frame_element.text == value
def test_frame_id_webelement_no_element_reference(session):
session.url = inline(iframe("<p>foo"))
frame = session.find.css("iframe", all=False)
frame.id = "bar"
response = switch_to_frame(session, frame)
assert_error(response, "no such element")
def test_frame_id_webelement_stale_reference(session):
session.url = inline(iframe("<p>foo"))
frame = session.find.css("iframe", all=False)
session.switch_frame(frame)
response = switch_to_frame(session, frame)
assert_error(response, "stale element reference")
def test_frame_id_webelement_no_frame_element(session):
session.url = inline("<p>foo")
no_frame = session.find.css("p", all=False)
response = switch_to_frame(session, no_frame)
assert_error(response, "no such frame")

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

@ -989,7 +989,7 @@ mod tests {
#[test]
fn test_json_switch_to_frame_parameters_with_invalid_id_field() {
let json = r#"{"id":"3""#;
let json = r#"{"id":"3"}"#;
assert!(serde_json::from_str::<SwitchToFrameParameters>(&json).is_err());
}

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

@ -614,6 +614,7 @@ function Search(searchString, searchParam, autocompleteListener,
this._disablePrivateActions = params.has("disable-private-actions");
this._inPrivateWindow = params.has("private-window");
this._prohibitAutoFill = params.has("prohibit-autofill");
this._disableTelemetry = params.has("disable-telemetry");
// Extract the max-results param.
let maxResults = searchParam.match(REGEXP_MAX_RESULTS);
@ -856,8 +857,10 @@ Search.prototype = {
}
};
TelemetryStopwatch.start(TELEMETRY_1ST_RESULT, this);
TelemetryStopwatch.start(TELEMETRY_6_FIRST_RESULTS, this);
if (!this._disableTelemetry) {
TelemetryStopwatch.start(TELEMETRY_1ST_RESULT, this);
TelemetryStopwatch.start(TELEMETRY_6_FIRST_RESULTS, this);
}
// Since we call the synchronous parseSubmissionURL function later, we must
// wait for the initialization of PlacesSearchAutocompleteProvider first.
@ -1934,10 +1937,12 @@ Search.prototype = {
this._currentMatchCount++;
this._counts[match.type]++;
if (this._currentMatchCount == 1)
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT, this);
if (this._currentMatchCount == 6)
TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS, this);
if (!this._disableTelemetry) {
if (this._currentMatchCount == 1)
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT, this);
if (this._currentMatchCount == 6)
TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS, this);
}
this.notifyResult(true, match.type == UrlbarUtils.MATCH_GROUP.HEURISTIC);
},
@ -2685,8 +2690,10 @@ UnifiedComplete.prototype = {
* results or not.
*/
finishSearch(notify = false) {
TelemetryStopwatch.cancel(TELEMETRY_1ST_RESULT, this);
TelemetryStopwatch.cancel(TELEMETRY_6_FIRST_RESULTS, this);
if (!this._disableTelemetry) {
TelemetryStopwatch.cancel(TELEMETRY_1ST_RESULT, this);
TelemetryStopwatch.cancel(TELEMETRY_6_FIRST_RESULTS, this);
}
// Clear state now to avoid race conditions, see below.
let search = this._currentSearch;
if (!search)

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

@ -17,7 +17,6 @@ var histograms = {
PLACES_DATABASE_PAGESIZE_B: val => Assert.equal(val, 32768),
PLACES_DATABASE_SIZE_PER_PAGE_B: val => Assert.ok(val > 0),
PLACES_EXPIRATION_STEPS_TO_CLEAN2: val => Assert.ok(val > 1),
// PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS: val => do_check_true(val > 1),
PLACES_IDLE_FRECENCY_DECAY_TIME_MS: val => Assert.ok(val >= 0),
PLACES_IDLE_MAINTENANCE_TIME_MS: val => Assert.ok(val > 0),
PLACES_ANNOS_BOOKMARKS_COUNT: val => Assert.equal(val, 1),
@ -121,42 +120,6 @@ add_task(async function test_execute() {
await promiseForceExpirationStep(2);
await promiseForceExpirationStep(2);
// Test autocomplete probes.
/*
// This is useful for manual testing by changing the minimum time for
// autocomplete telemetry to 0, but there is no way to artificially delay
// autocomplete by more than 50ms in a realiable way.
Services.prefs.setIntPref("browser.urlbar.search.sources", 3);
Services.prefs.setIntPref("browser.urlbar.default.behavior", 0);
function AutoCompleteInput(aSearches) {
this.searches = aSearches;
}
AutoCompleteInput.prototype = {
timeout: 10,
textValue: "",
searchParam: "",
popupOpen: false,
minResultsForPopup: 0,
invalidate: function() {},
disableAutoComplete: false,
completeDefaultIndex: false,
get popup() { return this; },
onSearchBegin: function() {},
onSearchComplete: function() {},
setSelectedIndex: function() {},
get searchCount() { return this.searches.length; },
getSearchAt: function(aIndex) { return this.searches[aIndex]; },
QueryInterface: ChromeUtils.generateQI([
Ci.nsIAutoCompleteInput,
Ci.nsIAutoCompletePopup,
])
};
let controller = Cc["@mozilla.org/autocomplete/controller;1"].
getService(Ci.nsIAutoCompleteController);
controller.input = new AutoCompleteInput(["unifiedcomplete"]);
controller.startSearch("moz");
*/
// Test idle probes.
PlacesUtils.history.QueryInterface(Ci.nsIObserver)
.observe(null, "idle-daily", null);

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

@ -80,7 +80,7 @@ toolkit.jar:
content/global/bindings/richlistbox.xml (widgets/richlistbox.xml)
content/global/bindings/scrollbox.xml (widgets/scrollbox.xml)
content/global/bindings/spinner.js (widgets/spinner.js)
* content/global/bindings/tabbox.xml (widgets/tabbox.xml)
content/global/bindings/tabbox.xml (widgets/tabbox.xml)
content/global/bindings/text.xml (widgets/text.xml)
* content/global/bindings/textbox.xml (widgets/textbox.xml)
content/global/bindings/timekeeper.js (widgets/timekeeper.js)

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

@ -138,6 +138,10 @@
this.tabbox;
]]></field>
<field name="_prefService" readonly="true"><![CDATA[
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
]]></field>
<property name="selectedIndex">
<getter>
<![CDATA[
@ -354,20 +358,20 @@
</method>
</implementation>
#ifdef MOZ_WIDGET_GTK
<handlers>
<handler event="DOMMouseScroll">
<![CDATA[
if (event.detail > 0)
this.advanceSelectedTab(1, false);
else
this.advanceSelectedTab(-1, false);
event.stopPropagation();
if (this._prefService.getBoolPref("toolkit.tabbox.switchByScrolling")) {
if (event.detail > 0) {
this.advanceSelectedTab(1, false);
} else {
this.advanceSelectedTab(-1, false);
}
event.stopPropagation();
}
]]>
</handler>
</handlers>
#endif
</binding>
<binding id="tab"

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

@ -1300,8 +1300,7 @@ NS_IMETHODIMP AsyncEncodeAndWriteIcon::Run() {
}
}
nsresult rv = gfxUtils::EncodeSourceSurface(
surface, NS_LITERAL_CSTRING("image/vnd.microsoft.icon"), EmptyString(),
gfxUtils::eBinaryEncode, file);
surface, ImageType::ICO, EmptyString(), gfxUtils::eBinaryEncode, file);
fclose(file);
NS_ENSURE_SUCCESS(rv, rv);