Merge autoland to mozilla-central r=merge a=merge

This commit is contained in:
Dorel Luca 2018-01-16 06:03:35 +02:00
commit 0bc344f9d6
92 changed files with 1682 additions and 1415 deletions

View File

@ -103,6 +103,9 @@
#ifdef MOZ_GTK3
@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
@BINPATH@/gtk2/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
#ifdef MOZ_WAYLAND
@BINPATH@/@DLL_PREFIX@mozwayland@DLL_SUFFIX@
#endif
#endif
; We don't have a complete view of which dlls to expect when doing an artifact

View File

@ -16,7 +16,6 @@ allprojects {
topobjdir = gradle.mozconfig.topobjdir
compileSdkVersion = tryInt(mozconfig.substs.ANDROID_COMPILE_SDK_VERSION)
buildToolsVersion = tryInt(mozconfig.substs.ANDROID_BUILD_TOOLS_VERSION)
targetSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK)
minSdkVersion = tryInt(mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION)
manifestPlaceholders = [
@ -52,7 +51,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.android.tools.build:gradle:3.0.0'
// Provided in tree.
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.7.3'
}

View File

@ -12,6 +12,7 @@
#include <direct.h>
#include <io.h>
#include <windows.h>
#include "StringOperations.h"
#else
#include <sys/file.h>
#include <sys/time.h>
@ -50,7 +51,7 @@ void ensurePath(std::string Path) {
#if defined(_WIN32) || defined(_WIN64)
AutoLockFile::AutoLockFile(const std::string &Filename) {
std::string Hash = Hash(filename);
std::string Hash = hash(Filename);
std::string MutexName = std::string("Local\\searchfox-") + Hash;
std::wstring WideMutexName;
WideMutexName.assign(MutexName.begin(), MutexName.end());
@ -85,7 +86,7 @@ bool AutoLockFile::truncateFile(size_t Length) {
}
std::string getAbsolutePath(const std::string &Filename) {
char full[_MAX_PATH];
char Full[_MAX_PATH];
if (!_fullpath(Full, Filename.c_str(), _MAX_PATH)) {
return std::string("");
}

View File

@ -70,28 +70,18 @@ redistributed publicly.)
Archiving the Gradle executable is straight-forward, but archiving a
local Maven repository is not. Therefore a special Task Cluster
Docker image and job exist for producing the required archives. The
Docker image definition is rooted in
``taskcluster/docker/android-build``. The Task Cluster job
definition is in
``testing/taskcluster/tasks/builds/android_api_16_gradle_dependencies.yml``.
The job runs in a container based on the custom Docker image and
spawns a Sonatype Nexus proxying Maven repository process in the
background. The job builds Firefox for Android using Gradle and the
in-tree Gradle configuration rooted at ``build.gradle``. The spawned
proxying Maven repository downloads external dependencies and collects
them. After the Gradle build completes, the job archives the Gradle
version used to build, and the downloaded Maven repository, and
exposes them as Task Cluster artifacts.
Here is `an example try job fetching these dependencies
<https://treeherder.mozilla.org/#/jobs?repo=try&revision=75bc98935147&selectedJob=17793653>`_.
The resulting task produced a `Gradle archive
<https://queue.taskcluster.net/v1/task/CeYMgAP3Q-KF8h37nMhJjg/runs/0/artifacts/public%2Fbuild%2Fgradle.tar.xz>`_
and a `Maven repository archive
<https://queue.taskcluster.net/v1/task/CeYMgAP3Q-KF8h37nMhJjg/runs/0/artifacts/public%2Fbuild%2Fjcentral.tar.xz>`_.
These archives were then uploaded (manually) to Mozilla automation
using tooltool for consumption in Gradle builds.
Docker image and toolchain job exist for producing the required
archives. The Docker image definition is rooted in
``taskcluster/docker/android-build``. The Task Cluster toolchain job
is named `android-gradle-dependencies`. The job runs in a container
based on the custom Docker image and spawns a Sonatype Nexus proxying
Maven repository process in the background. The job builds Firefox
for Android using Gradle and the in-tree Gradle configuration rooted
at ``build.gradle``. The spawned proxying Maven repository downloads
external dependencies and collects them. After the Gradle build
completes, the job archives the Gradle version used to build, and the
downloaded Maven repository, and exposes them as Task Cluster
artifacts.
To update the version of Gradle in the archive produced, update
``gradle/wrapper/gradle-wrapper.properties``. Be sure to also update
@ -100,12 +90,18 @@ the SHA256 checksum to prevent poisoning the build machines!
To update the versions of Gradle dependencies used, update
``dependencies`` sections in the in-tree Gradle configuration rooted
at ``build.gradle``. Once you are confident your changes build
locally, push a fresh try build with an invocation like::
locally, push a fresh build to try. The `android-gradle-dependencies`
toolchain should run automatically, fetching your new dependencies and
wiring them into the appropriate try build jobs.
$ hg push-to-try -m "try: -b o -p android-api-16-gradle-dependencies"
To update the version of Sonatype Nexus, update `NEXUS_VERSION` in the
`android-build` Docker image.
Then `upload your archives to tooltool
<https://wiki.mozilla.org/ReleaseEngineering/Applications/Tooltool#How_To_Upload_To_Tooltool>`_,
update the in-tree manifests in
``mobile/android/config/tooltool-manifests``, and push a fresh try
build.
To modify the Sonatype Nexus configuration, typically to proxy a new
remote Maven repository, modify
`taskcluster/scripts/misc/android-gradle-dependencies/nexus.xml`.
There is also a toolchain job that fetches the Android SDK and related
packages. To update the versions of packaged fetched, modify
`python/mozboot/mozboot/android-packages.txt` and update the various
in-tree versions accordingly.

View File

@ -11,6 +11,7 @@ cairo_version=1.10.2
pango_version=1.30.1
atk_version=2.2.0
gtk__version=3.4.4
pulseaudio_version=2.0
fontconfig_url=http://www.freedesktop.org/software/fontconfig/release/fontconfig-${fontconfig_version}.tar.gz
libffi_url=ftp://sourceware.org/pub/libffi/libffi-${libffi_version}.tar.gz
@ -21,12 +22,16 @@ cairo_url=http://cairographics.org/releases/cairo-${cairo_version}.tar.gz
pango_url=http://ftp.gnome.org/pub/GNOME/sources/pango/${pango_version%.*}/pango-${pango_version}.tar.xz
atk_url=http://ftp.gnome.org/pub/GNOME/sources/atk/${atk_version%.*}/atk-${atk_version}.tar.xz
gtk__url=http://ftp.gnome.org/pub/gnome/sources/gtk+/${gtk__version%.*}/gtk+-${gtk__version}.tar.xz
pulseaudio_url=https://freedesktop.org/software/pulseaudio/releases/pulseaudio-${pulseaudio_version}.tar.xz
root_dir=$(mktemp -d)
cd $root_dir
make_flags=-j$(nproc)
# Install a few packages for pulseaudio.
yum install -y libtool-ltdl-devel libtool-ltdl-devel.i686 json-c-devel json-c-devel.i686 libsndfile-devel libsndfile-devel.i686
build() {
name=$1
shift
@ -72,6 +77,7 @@ build pango
build atk
make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
build gtk+
build pulseaudio --disable-nls
done

View File

@ -278,6 +278,12 @@
margin-inline-end: 15px;
}
/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
the margin on the start of the node */
.tree-node[data-expandable="false"][aria-level="0"] {
padding-inline-start: 15px
}
.tree .tree-node[data-expandable="true"] {
cursor: default;
}

File diff suppressed because it is too large Load Diff

View File

@ -280,11 +280,7 @@ skip-if = true # Bug 1404382
[browser_webconsole_highlighter_console_helper.js]
[browser_webconsole_history_arrow_keys.js]
[browser_webconsole_hpkp_invalid-headers.js]
skip-if = true # Bug 1405340
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_hsts_invalid-headers.js]
skip-if = true # Bug 1405341
# old console skip-if = e10s # Bug 1042253 - webconsole e10s tests
[browser_webconsole_iframe_wrong_hud.js]
skip-if = true # Bug 1404378
[browser_webconsole_ineffective_iframe_sandbox_warning.js]

View File

@ -1,74 +1,68 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that errors about invalid HPKP security headers are logged to the web
// console.
// Tests that errors about invalid HPKP security headers are logged to the web console.
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,Web Console HPKP invalid " +
"header test";
const TEST_URI = "data:text/html;charset=utf-8,Web Console HPKP invalid header test";
const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" +
"test/test_hpkp-invalid-headers.sjs";
const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/HTTP/" +
"Public_Key_Pinning" + DOCS_GA_PARAMS;
const NON_BUILTIN_ROOT_PREF = "security.cert_pinning.process_headers_from_" +
"non_builtin_roots";
"new-console-output/test/mochitest/test_hpkp-invalid-headers.sjs";
const LEARN_MORE_URI =
"https://developer.mozilla.org/docs/Web/HTTP/Public_Key_Pinning" + DOCS_GA_PARAMS;
const NON_BUILTIN_ROOT_PREF =
"security.cert_pinning.process_headers_from_non_builtin_roots";
add_task(function* () {
add_task(async function () {
registerCleanupFunction(() => {
Services.prefs.clearUserPref(NON_BUILTIN_ROOT_PREF);
});
yield loadTab(TEST_URI);
let hud = await openNewTabAndConsole(TEST_URI);
let hud = yield openConsole();
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?badSyntax",
name: "Could not parse header error displayed successfully",
text: "Public-Key-Pins: The site specified a header that could not be " +
"parsed successfully."
}, hud);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?noMaxAge",
name: "No max-age error displayed successfully",
text: "Public-Key-Pins: The site specified a header that did not include " +
"a \u2018max-age\u2019 directive."
}, hud);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?invalidIncludeSubDomains",
name: "Invalid includeSubDomains error displayed successfully",
text: "Public-Key-Pins: The site specified a header that included an " +
"invalid \u2018includeSubDomains\u2019 directive."
}, hud);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?invalidMaxAge",
name: "Invalid max-age error displayed successfully",
text: "Public-Key-Pins: The site specified a header that included an " +
"invalid \u2018max-age\u2019 directive."
}, hud);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?multipleIncludeSubDomains",
name: "Multiple includeSubDomains error displayed successfully",
text: "Public-Key-Pins: The site specified a header that included " +
"multiple \u2018includeSubDomains\u2019 directives."
}, hud);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?multipleMaxAge",
name: "Multiple max-age error displayed successfully",
text: "Public-Key-Pins: The site specified a header that included " +
"multiple \u2018max-age\u2019 directives."
}, hud);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?multipleReportURIs",
name: "Multiple report-uri error displayed successfully",
text: "Public-Key-Pins: The site specified a header that included " +
@ -79,7 +73,7 @@ add_task(function* () {
// true to have the PKP implementation return more specific errors.
Services.prefs.setBoolPref(NON_BUILTIN_ROOT_PREF, true);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?pinsetDoesNotMatch",
name: "Non-matching pinset error displayed successfully",
text: "Public-Key-Pins: The site specified a header that did not include " +
@ -88,7 +82,7 @@ add_task(function* () {
Services.prefs.setBoolPref(NON_BUILTIN_ROOT_PREF, false);
yield* checkForMessage({
await navigateAndCheckForWarningMessage({
url: SJS_URL + "?pinsetDoesNotMatch",
name: "Non-built-in root error displayed successfully",
text: "Public-Key-Pins: The certificate used by the site was not issued " +
@ -97,30 +91,17 @@ add_task(function* () {
}, hud);
});
function* checkForMessage(curTest, hud) {
hud.jsterm.clearOutput();
async function navigateAndCheckForWarningMessage({name, text, url}, hud) {
hud.jsterm.clearOutput(true);
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, curTest.url);
const onMessage = waitForMessage(hud, text, ".message.warning");
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
const {node} = await onMessage;
ok(node, name);
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
name: curTest.name,
text: curTest.text,
category: CATEGORY_SECURITY,
severity: SEVERITY_WARNING,
objects: true,
},
],
});
yield testClickOpenNewTab(hud, results);
}
function testClickOpenNewTab(hud, results) {
let warningNode = results[0].clickableElements[0];
ok(warningNode, "link element");
ok(warningNode.classList.contains("learn-more-link"), "link class name");
return simulateMessageLinkClick(warningNode, LEARN_MORE_URI);
let learnMoreNode = node.querySelector(".learn-more-link");
ok(learnMoreNode, `There is a "Learn more" link`);
const navigatedLink = await simulateLinkClick(learnMoreNode);
is(navigatedLink, LEARN_MORE_URI,
"Click on the learn more link navigates the user to the expected url");
}

View File

@ -1,61 +1,55 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that errors about invalid HSTS security headers are logged
// to the web console.
// Tests that errors about invalid HSTS security headers are logged to the web console.
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,Web Console HSTS invalid " +
"header test";
const TEST_URI = "data:text/html;charset=utf-8,Web Console HSTS invalid header test";
const SJS_URL = "https://example.com/browser/devtools/client/webconsole/" +
"test/test_hsts-invalid-headers.sjs";
"/new-console-output/test/mochitest/test_hsts-invalid-headers.sjs";
const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/HTTP/Headers/" +
"Strict-Transport-Security" + DOCS_GA_PARAMS;
add_task(function* () {
yield loadTab(TEST_URI);
add_task(async function () {
const hud = await openNewTabAndConsole(TEST_URI);
let hud = yield openConsole();
yield* checkForMessage({
await navigateAndCheckWarningMessage({
url: SJS_URL + "?badSyntax",
name: "Could not parse header error displayed successfully",
text: "Strict-Transport-Security: The site specified a header that could " +
"not be parsed successfully."
}, hud);
yield* checkForMessage({
await navigateAndCheckWarningMessage({
url: SJS_URL + "?noMaxAge",
name: "No max-age error displayed successfully",
text: "Strict-Transport-Security: The site specified a header that did " +
"not include a \u2018max-age\u2019 directive."
}, hud);
yield* checkForMessage({
await navigateAndCheckWarningMessage({
url: SJS_URL + "?invalidIncludeSubDomains",
name: "Invalid includeSubDomains error displayed successfully",
text: "Strict-Transport-Security: The site specified a header that " +
"included an invalid \u2018includeSubDomains\u2019 directive."
}, hud);
yield* checkForMessage({
await navigateAndCheckWarningMessage({
url: SJS_URL + "?invalidMaxAge",
name: "Invalid max-age error displayed successfully",
text: "Strict-Transport-Security: The site specified a header that " +
"included an invalid \u2018max-age\u2019 directive."
}, hud);
yield* checkForMessage({
await navigateAndCheckWarningMessage({
url: SJS_URL + "?multipleIncludeSubDomains",
name: "Multiple includeSubDomains error displayed successfully",
text: "Strict-Transport-Security: The site specified a header that " +
"included multiple \u2018includeSubDomains\u2019 directives."
}, hud);
yield* checkForMessage({
await navigateAndCheckWarningMessage({
url: SJS_URL + "?multipleMaxAge",
name: "Multiple max-age error displayed successfully",
text: "Strict-Transport-Security: The site specified a header that " +
@ -63,30 +57,17 @@ add_task(function* () {
}, hud);
});
function* checkForMessage(curTest, hud) {
hud.jsterm.clearOutput();
async function navigateAndCheckWarningMessage({url, name, text}, hud) {
hud.jsterm.clearOutput(true);
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, curTest.url);
const onMessage = waitForMessage(hud, text, ".message.warning");
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
const {node} = await onMessage;
ok(node, name);
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
name: curTest.name,
text: curTest.text,
category: CATEGORY_SECURITY,
severity: SEVERITY_WARNING,
objects: true,
},
],
});
yield testClickOpenNewTab(hud, results);
}
function testClickOpenNewTab(hud, results) {
let warningNode = results[0].clickableElements[0];
ok(warningNode, "link element");
ok(warningNode.classList.contains("learn-more-link"), "link class name");
return simulateMessageLinkClick(warningNode, LEARN_MORE_URI);
let learnMoreNode = node.querySelector(".learn-more-link");
ok(learnMoreNode, `There is a "Learn more" link`);
const navigatedLink = await simulateLinkClick(learnMoreNode);
is(navigatedLink, LEARN_MORE_URI,
"Click on the learn more link navigates the user to the expected url");
}

View File

@ -1,3 +1,4 @@
org.gradle.parallel=true
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx2560M
android.enableAapt2=false

View File

@ -3,5 +3,5 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip
distributionSha256Sum=ed7e9c8bb41bd10d4c9339c95b2f8b122f5bf13188bd90504a26e0f00b123b0d
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionSha256Sum=5c07b3bac2209fbc98fb1fdf6fd831f72429cdf8c503807404eae03d8c8099e5

View File

@ -5,13 +5,14 @@ apply plugin: 'checkstyle'
apply plugin: 'com.getkeepsafe.dexcount'
apply plugin: 'findbugs'
apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
dexcount {
format = "tree"
}
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
targetSdkVersion project.ext.targetSdkVersion
@ -84,35 +85,13 @@ android {
// want to develop significant new user interface pieces in-tree that don't ship (even in the
// Nightly channel) while under development. A new "skin" flavour allows us to develop such
// pieces in Gradle without changing the mainline configuration.
flavorDimensions "audience", "skin"
project.configureProductFlavors.delegate = it
project.configureProductFlavors()
flavorDimensions "audience", "geckoBinaries", "minApi", "skin"
productFlavors {
// For API 21+ - with pre-dexing, this will be faster for local development.
local {
dimension "audience"
// For pre-dexing, setting `minSdkVersion 21` allows the Android gradle plugin to
// pre-DEX each module and produce an APK that can be tested on
// Android Lollipop without time consuming DEX merging processes.
minSdkVersion 21
dexOptions {
preDexLibraries true
}
}
// For API < 21 - does not support pre-dexing because local development
// is slow in that case.
localOld {
dimension "audience"
}
// Automation builds. We use "official" rather than "automation" to drive these builds down
// the list of configurations that Android Studio offers, thereby making it _not_ the
// default. This avoids a common issue with "omni.ja" not being packed into the default APK
// built and deployed by Android Studio.
official {
dimension "audience"
}
// Since Firefox 57, the mobile user interface has followed the Photon design.
// Before Firefox 57, the user interface followed the Australis design.
photon {
@ -162,13 +141,10 @@ android {
exclude 'org/mozilla/gecko/gcm/**/*.java'
exclude 'org/mozilla/gecko/push/**/*.java'
}
srcDir "${project.buildDir}/generated/source/preprocessed_code" // See syncPreprocessedCode.
}
res {
srcDir "${topsrcdir}/${mozconfig.substs.MOZ_BRANDING_DIRECTORY}/res"
srcDir "${project.buildDir}/generated/source/preprocessed_resources" // See syncPreprocessedResources.
srcDir "${topsrcdir}/mobile/android/services/src/main/res"
if (mozconfig.substs.MOZ_CRASHREPORTER) {
srcDir "${topsrcdir}/mobile/android/base/crashreporter/res"
@ -182,18 +158,6 @@ android {
}
}
// Every configuration needs the stub manifest at
// src/main/AndroidManifest.xml and the generated manifest. We can't
// use the main sourceSet without losing the stub, so we cover all the
// configurations by enumerating the buildTypes here.
debug {
manifest.srcFile "${project.buildDir}/generated/source/preprocessed_manifest/AndroidManifest.xml"
}
release {
manifest.srcFile "${project.buildDir}/generated/source/preprocessed_manifest/AndroidManifest.xml"
}
test {
java {
// Bug 1229149 tracks pushing this into a :services Gradle project.
@ -227,6 +191,9 @@ android {
}
testOptions {
// For Robolectric: see https://github.com/robolectric/robolectric/issues/3333#issuecomment-324300418.
unitTests.includeAndroidResources true
unitTests.all {
// We'd like to use (Runtime.runtime.availableProcessors()/2), but
// we have tests that start test servers and the bound ports
@ -237,72 +204,50 @@ android {
}
dependencies {
compile "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:cardview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:recyclerview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:design:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:customtabs:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:cardview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:recyclerview-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:design:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:customtabs:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:palette-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
if (mozconfig.substs.MOZ_NATIVE_DEVICES) {
compile "com.android.support:mediarouter-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-cast:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.android.support:mediarouter-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-cast:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
}
if (mozconfig.substs.MOZ_INSTALL_TRACKING) {
compile "com.google.android.gms:play-services-analytics:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-analytics:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
}
if (mozconfig.substs.MOZ_ANDROID_GCM) {
compile "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-measurement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-basement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-base:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-measurement:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
}
// Include LeakCanary in most gradle based builds. LeakCanary adds about 5k methods, so we disable
// it for the (non-proguarded, non-predex) localOld builds to allow space for other libraries.
// Gradle based tests include the no-op version. Mach based builds only include the no-op version
// of this library.
// It doesn't seem like there is a non-trivial way to be conditional on 'localOld', so instead we explicitly
// define a version of leakcanary for every flavor:
localCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
localOldCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
officialCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
officialCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
// Include LeakCanary in most gradle based builds. Gradle based tests
// include the no-op version. Mach based builds only include the no-op
// version of this library.
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
// With a simple "compile", Gradle will always build these libraries in their default configuration
// (i.e. release), so we need to explicitly forward our own build configuration here (bug 1385695).
//
// Official builds compile a hacked up app:Official..Debug, but need the
// release versions of the dependencies, in order to not have debugging
// information. It's not yet possible to specify just officialDebug, so we
// hack around it here.
if (mozconfig.substs.MOZILLA_OFFICIAL) {
debugCompile project(path: ':geckoview', configuration: "release")
} else {
debugCompile project(path: ':geckoview', configuration: "debug")
}
releaseCompile project(path: ':geckoview', configuration: "release")
implementation project(path: ':geckoview')
implementation project(path: ':thirdparty')
if (mozconfig.substs.MOZILLA_OFFICIAL) {
debugCompile project(path: ':thirdparty', configuration: "release")
} else {
debugCompile project(path: ':thirdparty', configuration: "debug")
}
releaseCompile project(path: ':thirdparty', configuration: "release")
testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.1.2'
testCompile 'org.simpleframework:simple-http:6.0.1'
testCompile 'org.mockito:mockito-core:1.10.19'
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:3.5.1'
testImplementation 'org.simpleframework:simple-http:6.0.1'
testImplementation 'org.mockito:mockito-core:1.10.19'
// Including the Robotium JAR directly can cause issues with dexing.
androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.5.4'
androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.5.4'
}
// TODO: (bug 1261486): This impl is not robust -
@ -317,11 +262,6 @@ task checkstyle(type: Checkstyle) {
classpath = files()
}
task syncPreprocessedCode(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
into("${project.buildDir}/generated/source/preprocessed_code")
from("${topobjdir}/mobile/android/base/generated/preprocessed")
}
// The localization system uses the moz.build preprocessor to interpolate a .dtd
// file of XML entity definitions into an XML file of elements referencing those
// entities. (Each locale produces its own .dtd file, backstopped by the en-US
@ -337,49 +277,80 @@ class ExpandXMLEntitiesFilter extends FilterReader {
}
}
task syncPreprocessedResources(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
into("${project.buildDir}/generated/source/preprocessed_resources")
from("${topobjdir}/mobile/android/base/res")
filesMatching('**/strings.xml') {
filter(ExpandXMLEntitiesFilter)
}
}
// It's not easy -- see the backout in Bug 1242213 -- to change the <manifest>
// package for Fennec. Gradle has grown a mechanism to achieve what we want for
// Fennec, however, with applicationId. To use the same manifest as moz.build,
// we replace the package with org.mozilla.gecko (the eventual package) here.
task rewriteManifestPackage(type: Copy, dependsOn: rootProject.generateCodeAndResources) {
into("${project.buildDir}/generated/source/preprocessed_manifest")
from("${topobjdir}/mobile/android/base/AndroidManifest.xml")
filter { it.replaceFirst(/package=".*?"/, 'package="org.mozilla.gecko"') }
}
apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
android.applicationVariants.all { variant ->
def syncPreprocessedJava = task("syncPreprocessedJavaFor${variant.name.capitalize()}", type: Sync) {
into("${project.buildDir}/moz.build/src/${variant.name}/java")
from("${topobjdir}/mobile/android/base/generated/preprocessed")
exclude('**/*.mkdir.done')
}
// This is an Android-Gradle plugin 3+-ism. Culted from reading the source,
// searching for "registerJavaGeneratingTask", and finding
// https://github.com/GoogleCloudPlatform/endpoints-framework-gradle-plugin/commit/2f2b91476fb1c6647791e2c6fe531a47615a1e85.
// The added directory doesn't appear in the paths listed by the
// `sourceSets` task, for reasons unknown.
variant.registerJavaGeneratingTask(syncPreprocessedJava, syncPreprocessedJava.destinationDir)
def syncPreprocessedRes = task("syncPreprocessedResFor${variant.name.capitalize()}", type: Sync) {
into("${project.buildDir}/moz.build/src/${variant.name}/res")
from("${topobjdir}/mobile/android/base/res")
filesMatching('**/strings.xml') {
filter(ExpandXMLEntitiesFilter)
}
exclude('**/*.mkdir.done')
}
// This is an Android-Gradle plugin 3+-ism. Determined by reading the
// source. The added directory doesn't appear in the paths listed by the
// `sourceSets` task, for reasons unknown.
variant.registerGeneratedResFolders(project.files(syncPreprocessedRes.destinationDir).builtBy(syncPreprocessedRes))
// It's not easy -- see the backout in Bug 1242213 -- to change the
// <manifest> package for Fennec. Gradle has grown a mechanism to achieve
// what we want for Fennec, however, with applicationId. To use the same
// manifest as moz.build, we replace the package with org.mozilla.gecko (the
// eventual package) here.
def rewriteManifestPackage = task("rewriteManifestPackageFor${variant.name.capitalize()}", type: Copy, dependsOn: rootProject.generateCodeAndResources) {
into("${project.buildDir}/moz.build/src/${variant.name}")
from("${topobjdir}/mobile/android/base/AndroidManifest.xml")
filter { it.replaceFirst(/package=".*?"/, 'package="org.mozilla.gecko"') }
exclude('**/*.mkdir.done')
}
// Every configuration needs the stub manifest at
// src/main/AndroidManifest.xml and the generated manifest. We can't use
// the main sourceSet without losing the stub, so we cover all the
// configurations here.
android.sourceSets."${variant.name}".manifest.srcFile "${rewriteManifestPackage.destinationDir}/AndroidManifest.xml"
variant.preBuild.dependsOn rewriteManifestPackage
variant.preBuild.dependsOn syncPreprocessedCode
variant.preBuild.dependsOn syncPreprocessedResources
// Official automation builds don't include Gecko binaries, since those binaries are not
// produced until after build time (at package time). official Therefore, automation builds
// include the Gecko binaries into the APK at package time. The "withGeckoBinaries" variant of
// the :geckoview project also does this. (It does what it says on the tin!) For notes on this
// approach, see mobile/android/gradle/with_gecko_binaries.gradle.
// Like 'local' or 'localOld'.
def audienceDimension = variant.productFlavors[0].name
// Local (read, not 'official') builds want to reflect developer changes to
// AndroidManifest.xml.in, strings.xml, and preprocessed Java code. To do
// this, the Gradle build calls out to the moz.build system, which can be
// re-entrant. Official builds are driven by the moz.build system and
// should never be re-entrant in this way.
if (!((variant.productFlavors*.name).contains('official'))) {
syncPreprocessedJava.dependsOn rootProject.generateCodeAndResources
syncPreprocessedRes.dependsOn rootProject.generateCodeAndResources
rewriteManifestPackage.dependsOn rootProject.generateCodeAndResources
}
// :app uses :geckoview:release and handles it's own Gecko binary inclusion,
// even though this would be most naturally done in the :geckoview project.
if (!audienceDimension.equals('official')) {
// When driven from moz.build via |mach build|, Gradle does not require or
// use Gecko binaries. It's only |mach package| that packs the Gecko
// binaries into the resulting APK. The "withoutGeckoBinaries" variants
// handle this. When driven from Android Studio or Gradle, the
// "withGeckoBinaries" variants handle packing the Gecko binaries into the
// resulting APK (for on-device deployment). They also update the Omnijars
// as necessary, smoothing out the edit-compile-test development cycle.
// They do what they say on the tin!
if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
configureVariantWithGeckoBinaries(variant)
}
}
android.applicationVariants.all { variant ->
configureVariantWithJNIWrappers(variant, "Fennec")
configureApplicationVariantWithJNIWrappers(variant, "Fennec")
}
if (gradle.startParameter.taskNames.any { it.endsWith('UnitTest') }) {
@ -416,7 +387,7 @@ android.applicationVariants.all { variant ->
reports {
html.enabled = true // HTML reports for humans.
html.destination = "$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.html"
html.destination = file("$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.html")
xml.enabled = false
}
}
@ -440,7 +411,7 @@ android.applicationVariants.all { variant ->
reports {
xml.enabled = true // XML reports for machines.
xml.destination = "$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.xml"
xml.destination = file("$project.buildDir/reports/findbugs/findbugs-${variant.name}-output.xml")
html.enabled = false
}
}
@ -466,8 +437,7 @@ android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.processManifest.doLast {
[output.processManifest.manifestOutputFile,
output.processManifest.instantRunManifestOutputFile,
[file("${manifestOutputDirectory}/AndroidManifest.xml"),
].each({ File manifestOutFile ->
if (manifestOutFile.exists()) {
def contents = manifestOutFile.getText('UTF-8')

View File

@ -38,7 +38,6 @@
<issue id="ResourceAsColor" severity="warning" />
<issue id="ResourceType" severity="warning" />
<issue id="ValidFragment" severity="warning" />
<issue id="WrongConstant" severity="warning" />
<!-- New Android-Gradle lint integration regressed this check. -->
<issue id="MissingRegistered" severity="warning" />
@ -51,7 +50,6 @@
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadContentTelemetry.java"/>
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java"/>
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java"/>
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/db/PerProfileDatabaseProvider.java"/>
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/PrintHelper.java"/>
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/animation/PropertyAnimator.java"/>
<ignore path="**/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java"/>

View File

@ -5,5 +5,5 @@
android:viewportHeight="12.0">
<path
android:fillColor="@color/activity_stream_icon"
android:pathData="M4.97.151l-2.819,6.5A.25.25,0,0,0,2.381,7H4.029a.25.25,0,0,1,.225.359L2,12,9.4,5.437A.25.25,0,0,0,9.234,5H6.791a.25.25,0,0,1-.19-.412L10.15.412A.25.25,0,0,0,9.959,0H5.2A.25.25,0,0,0,4.97.151Z"/>
android:pathData="M4.97,0.151l-2.819,6.5A0.25,0.25,0,0,0,2.381,7H4.029a0.25,0.25,0,0,1,0.225,0.359L2,12,9.4,5.437A0.25,0.25,0,0,0,9.234,5H6.791a0.25,0.25,0,0,1,-0.19,-0.412L10.15,0.412A0.25,0.25,0,0,0,9.959,0H5.2A0.25,0.25,0,0,0,4.97,0.151Z"/>
</vector>

View File

@ -40,7 +40,7 @@
android:id="@+id/custom_tabs_action_bar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:singleLine="true"
android:textColor="?android:textColorPrimary"
android:textSize="14sp"
tools:text="Mozilla.org"/>
@ -49,7 +49,6 @@
android:id="@+id/custom_tabs_action_bar_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:singleLine="true"
android:textColor="?android:textColorPrimary"
android:textSize="10sp"

View File

@ -15,15 +15,6 @@
<item name="windowNoTitle">true</item>
</style>
<style name="GeckoDialogBase" parent="@android:style/Theme.Holo.Light.Dialog">
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="GeckoTitleDialogBase" parent="@android:style/Theme.Holo.Light.Dialog" />
<!--
Activity based themes for API 11+. This theme completely replaces
GeckoAppBase from res/values/themes.xml on API 11+ devices.

View File

@ -1,15 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
<item name="android:windowBackground">@color/toolbar_grey</item>
<item name="android:colorBackground">@color/toolbar_grey</item>
</style>
<style name="SettingsTheme" parent="@android:style/Theme.Holo.Light"/>
</resources>

View File

@ -1,19 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
<style name="TextAppearance.EmptyView.Title" parent="@android:style/TextAppearance.Small">
<item name="android:textColor">@color/text_and_tabs_tray_grey</item>
<item name="android:textSize">20sp</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.EmptyView.Message" parent="@android:style/TextAppearance.Small">
<item name="android:textColor">@color/placeholder_grey</item>
<item name="android:textSize">16sp</item>
<item name="android:lineSpacingExtra">4sp</item>
</style>
</resources>

View File

@ -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/. -->
<resources>
<resources
xmlns:tools="http://schemas.android.com/tools">
<!--
Base application theme. This could be overridden by GeckoBaseTheme
@ -15,13 +16,6 @@
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="GeckoDialogBase" parent="@android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="GeckoTitleDialogBase" parent="@android:style/Theme.Dialog" />
<style name="Gecko.Preferences">
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
@ -73,10 +67,6 @@
<item name="actionBarTheme">@style/GeckoActionBar</item>
</style>
<style name="Gecko.Dialog" parent="GeckoDialogBase"/>
<style name="Gecko.TitleDialog" parent="GeckoTitleDialogBase"/>
<!--
Activity based themes, dependent on API level. This theme is replaced
by GeckoAppBase from res/values-vXX/themes.xml on newer devices.
@ -126,7 +116,8 @@
</style>
<!-- Bookmark full-page dialog theme -->
<style name="Bookmark" parent="Theme.AppCompat.Light.DialogWhenLarge"/>
<style name="Bookmark" parent="Theme.AppCompat.Light.DialogWhenLarge"
tools:ignore="UnusedResources" />
<style name="Bookmark.Gecko" parent="Gecko">
<item name="toolbarStyle">@style/BookmarkToolbarStyle</item>
<item name="colorAccent">@color/fennec_ui_accent</item>

View File

@ -4,7 +4,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/. -->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!--
Only overriden styles for Honeycomb/Ice cream sandwich are specified here.
@ -26,9 +27,6 @@
<style name="Widget.BaseTextView" parent="android:style/Widget.Holo.Light.TextView" />
<style name="Widget.ProgressBar.Horizontal" parent="android:style/Widget.Holo.ProgressBar.Horizontal" />
<!--
Application styles. All customizations that are not specific
to a particular API level can go here.
@ -47,18 +45,6 @@
<!-- ActionBar -->
<style name="ActionBar" parent="android:style/Widget.Holo.ActionBar" />
<!-- TabsLayout ActionBar -->
<style name="ActionBar.TabsLayout">
<item name="android:visibility">gone</item>
</style>
<!-- DropDown List View -->
<style name="DropDownListView" parent="@android:style/Widget.Holo.ListView.DropDown">
<item name="android:listSelector">@drawable/action_bar_button</item>
<item name="android:divider">@color/toolbar_divider_grey</item>
<item name="android:dividerHeight">@dimen/page_row_divider_height</item>
</style>
<!-- Spinner DropDown Item -->
<style name="Widget.DropDownItem.Spinner" parent="@android:style/Widget.Holo.Light.DropDownItem.Spinner">
<item name="android:textColor">#FF000000</item>
@ -108,7 +94,8 @@
<style name="TabInput.TabWidget" parent="android:style/Widget.Holo.Light.TabWidget" />
<style name="TabInput.Tab" parent="android:style/Widget.Holo.Light.Tab">
<style name="TabInput.Tab" parent="android:style/Widget.Holo.Light.Tab"
tools:ignore="UnusedResources">
<item name="android:minHeight">@dimen/menu_item_row_height</item>
<item name="android:textAllCaps">true</item>
</style>

View File

@ -14,14 +14,6 @@
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.FirstrunTextLight">
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.FirstrunTextRegular">
<item name="android:fontFamily">sans-serif</item>
</style>
<style name="TextAppearance.UrlBar.Title" parent="TextAppearance.Small">
<item name="android:textSize">16sp</item>
</style>

View File

@ -25,8 +25,6 @@
<style name="Widget.BaseTextView" parent="android:style/Widget.TextView"/>
<style name="Widget.ProgressBar.Horizontal" parent="android:style/Widget.ProgressBar.Horizontal"/>
<!--
Application styles. All customizations that are not specific
to a particular API level can go here.
@ -65,10 +63,6 @@
<item name="android:listSelector">@drawable/action_bar_button</item>
</style>
<style name="Widget.Home.HomeList">
<item name="android:scrollbarStyle">outsideOverlay</item>
</style>
<style name="Widget.ListItem">
<item name="android:minHeight">?android:attr/listPreferredItemHeight</item>
<item name="android:textAppearance">?android:attr/textAppearanceLargeInverse</item>
@ -216,12 +210,6 @@
<item name="android:scaleType">centerCrop</item>
</style>
<style name="Widget.TopSitesGridItemPin">
<item name="android:minWidth">30dip</item>
<item name="android:minHeight">30dip</item>
<item name="android:padding">0dip</item>
</style>
<style name="Widget.TopSitesGridItemTitle">
<item name="android:textColor">@color/top_sites_grid_item_title</item>
<item name="android:textSize">12sp</item>
@ -295,7 +283,8 @@
<!--
We are overriding the snackbar message style to guarantee a consistent style across Android versions (bug 1217416).
-->
<style name="TextAppearance.Design.Snackbar.Message" parent="android:TextAppearance" tools:override="true">
<style name="TextAppearance.Design.Snackbar.Message" parent="android:TextAppearance" tools:override="true"
tools:ignore="UnusedResources">
<item name="android:textSize">@dimen/design_snackbar_text_size</item>
<item name="android:textColor">@android:color/white</item>
</style>
@ -370,7 +359,8 @@
<item name="android:textColor">?android:attr/textColorTertiary</item>
</style>
<style name="TextAppearance.Micro.Inverse">
<style name="TextAppearance.Micro.Inverse"
tools:ignore="UnusedResources">
<item name="android:textColor">?android:attr/textColorTertiaryInverse</item>
<item name="android:textColorHint">?android:attr/textColorHintInverse</item>
<item name="android:textColorHighlight">@color/text_color_highlight_inverse</item>
@ -400,7 +390,8 @@
<item name="android:textSize">14sp</item>
</style>
<style name="TextAppearance.Widget.Home" />
<style name="TextAppearance.Widget.Home"
tools:ignore="UnusedResources" />
<style name="TextAppearance.Widget.Home.Header" parent="TextAppearance.Small">
<item name="android:textColor">@color/disabled_grey</item>
@ -436,7 +427,8 @@
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.DoorHanger.Small">
<style name="TextAppearance.DoorHanger.Small"
tools:ignore="UnusedResources">
<item name="android:textSize">14sp</item>
</style>
@ -527,30 +519,21 @@
<item name="android:layout_marginRight">6dp</item>
</style>
<style name="Widget.RemoteTabsItemView" parent="Widget.TwoLinePageRow"/>
<style name="Widget.RemoteTabsClientView" parent="Widget.TwoLinePageRow">
<item name="android:background">@color/about_page_header_grey</item>
</style>
<style name="Widget.RemoteTabsListView" parent="Widget.HomeListView">
<item name="android:childDivider">@color/toolbar_divider_grey</item>
</style>
<style name="Widget.HistoryListView" parent="Widget.HomeListView">
<item name="android:childDivider">@color/toolbar_divider_grey</item>
<item name="android:drawSelectorOnTop">true</item>
</style>
<!-- TabsLayout Row -->
<style name="TabLayoutItemTextAppearance">
<style name="TabLayoutItemTextAppearance"
tools:ignore="UnusedResources">
<item name="android:textColor">#FFFFFFFF</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">middle</item>
</style>
<!-- TabsLayout RemoteTabs Row Url -->
<style name="TabLayoutItemTextAppearance.Url">
<style name="TabLayoutItemTextAppearance.Url"
tools:ignore="UnusedResources">
<item name="android:textColor">#FFA4A7A9</item>
</style>
@ -579,8 +562,8 @@
</style>
<style name="PopupAnimation">
<item name="@android:windowEnterAnimation">@anim/popup_show</item>
<item name="@android:windowExitAnimation">@anim/popup_hide</item>
<item name="android:windowEnterAnimation">@anim/popup_show</item>
<item name="android:windowExitAnimation">@anim/popup_hide</item>
</style>
<style name="ToastBase">
@ -737,7 +720,8 @@
<item name="android:background">@drawable/tab_indicator_background</item>
</style>
<style name="TabInput.Tab">
<style name="TabInput.Tab"
tools:ignore="UnusedResources">
<item name="android:background">@drawable/tabs_strip_indicator</item>
<item name="android:gravity">center</item>
<item name="android:minHeight">@dimen/menu_item_row_height</item>
@ -798,7 +782,8 @@
<item name="android:layout_marginBottom">8dp</item>
</style>
<style name="RemoteTabsPanelItem.TextAppearance.Linkified">
<style name="RemoteTabsPanelItem.TextAppearance.Linkified"
tools:ignore="UnusedResources">
<item name="android:clickable">true</item>
<item name="android:focusable">true</item>
<item name="android:textColor">#0092DB</item>
@ -820,8 +805,6 @@
<item name="textAllCaps">false</item>
</style>
<style name="TabQueueActivity" parent="android:style/Theme.NoDisplay" />
<style name="ActivityStreamContextMenuText">
<item name="android:textSize">16sp</item>
</style>
@ -831,7 +814,8 @@
<item name="android:listDivider">@drawable/as_contextmenu_divider</item>
</style>
<style name="ActivityStreamButton" parent="Widget.AppCompat.Button.Colored">
<style name="ActivityStreamButton" parent="Widget.AppCompat.Button.Colored"
tools:ignore="UnusedResources">
<item name="colorButtonNormal">@color/link_blue</item>
<item name="android:textColor">@android:color/white</item>
</style>

View File

@ -3,6 +3,7 @@
package org.mozilla.gecko;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.database.Cursor;
@ -15,7 +16,6 @@ import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserContract.PageMetadata;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.BrowserProvider;
import org.mozilla.gecko.db.LocalBrowserDB;
import org.robolectric.shadows.ShadowContentResolver;
@ -27,11 +27,8 @@ public class GlobalPageMetadataTest {
public void testQueueing() throws Exception {
BrowserDB db = new LocalBrowserDB("default");
BrowserProvider provider = new BrowserProvider();
final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
try {
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
ShadowContentResolver cr = new ShadowContentResolver();
ContentProviderClient pageMetadataClient = cr.acquireContentProviderClient(PageMetadata.CONTENT_URI);
@ -64,11 +61,8 @@ public class GlobalPageMetadataTest {
// Start listening for events.
GlobalPageMetadata.getInstance().init();
BrowserProvider provider = new BrowserProvider();
final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
try {
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
ShadowContentResolver cr = new ShadowContentResolver();
ContentProviderClient historyClient = cr.acquireContentProviderClient(BrowserContract.History.CONTENT_URI);
ContentProviderClient pageMetadataClient = cr.acquireContentProviderClient(PageMetadata.CONTENT_URI);
@ -171,4 +165,4 @@ public class GlobalPageMetadataTest {
cursor.close();
}
}
}
}

View File

@ -3,29 +3,21 @@
package org.mozilla.gecko.icons.loader;
import android.content.ContentProvider;
import android.graphics.Bitmap;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.BrowserProvider;
import org.mozilla.gecko.icons.IconDescriptor;
import org.mozilla.gecko.icons.IconRequest;
import org.mozilla.gecko.icons.IconResponse;
import org.mozilla.gecko.icons.Icons;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowContentResolver;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ -46,9 +38,7 @@ public class TestLegacyLoader {
// We need to ensure we close our db connection properly.
// This is the only test in this class that actually accesses a database. If that changes,
// move BrowserProvider registration into a @Before method, and provider.shutdown into @After.
final BrowserProvider provider = new BrowserProvider();
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
try {
final IconRequest request = Icons.with(RuntimeEnvironment.application)
.pageUrl(TEST_PAGE_URL)
@ -61,8 +51,8 @@ public class TestLegacyLoader {
verify(loader).loadBitmapFromDatabase(request);
Assert.assertNull(response);
// Close any open db connections.
} finally {
// Close any open db connections.
provider.shutdown();
}
}

View File

@ -28,6 +28,7 @@ public class TestLookupIconUrl {
@Before
public void setUp() {
MemoryStorage.get().evictAll();
DiskStorage.get(RuntimeEnvironment.application).evictAll();
}
@Test

View File

@ -12,13 +12,17 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.util.NetworkUtils.*;
import org.mozilla.gecko.util.NetworkUtils.ConnectionSubType;
import org.mozilla.gecko.util.NetworkUtils.ConnectionType;
import org.mozilla.gecko.util.NetworkUtils.NetworkStatus;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.internal.ShadowExtractor;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowConnectivityManager;
import org.robolectric.shadows.ShadowNetworkInfo;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(TestRunner.class)
public class NetworkUtilsTest {
@ -31,7 +35,7 @@ public class NetworkUtilsTest {
// Not using Shadows.shadowOf(connectivityManager) because of Robolectric bug when using API23+
// See: https://github.com/robolectric/robolectric/issues/1862
shadowConnectivityManager = (ShadowConnectivityManager) ShadowExtractor.extract(connectivityManager);
shadowConnectivityManager = (ShadowConnectivityManager) Shadow.extract(connectivityManager);
}
@Test
@ -182,4 +186,4 @@ public class NetworkUtilsTest {
);
assertEquals(NetworkStatus.UP, NetworkUtils.getNetworkStatus(connectivityManager));
}
}
}

View File

@ -1,3 +1,3 @@
sdk=21
sdk=23
constants=org.mozilla.gecko.BuildConfig
packageName=org.mozilla.gecko

View File

@ -1,6 +1,7 @@
#filter substitution
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="@ANDROID_PACKAGE_NAME@"
android:installLocation="internalOnly"
android:versionCode="@ANDROID_VERSION_CODE@"
@ -133,7 +134,7 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.WEB_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
@ -159,7 +160,7 @@
android:resource="@integer/assist_launch_icon_res"/>
<!-- For XPI installs from websites and the download manager. -->
<intent-filter>
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
@ -169,7 +170,7 @@
</intent-filter>
<!-- For XPI installs from file: URLs. -->
<intent-filter>
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="" />

View File

@ -27,6 +27,8 @@ GARBAGE_DIRS += classes db jars res sync services generated
gradle_dir := $(topobjdir)/gradle/build/mobile/android
ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
# The bootclasspath is functionally identical to the classpath, but allows the
# classes given to redefine classes in core packages, such as java.lang.
# android.jar is here as it provides Android's definition of the Java Standard
@ -143,7 +145,6 @@ uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
java_bundled_libs := $(call uniq,$(java_bundled_libs))
java_bundled_libs := $(subst $(NULL) ,:,$(strip $(java_bundled_libs)))
ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
GECKOVIEW_JARS = \
constants.jar \
gecko-R.jar \
@ -175,16 +176,6 @@ ifdef MOZ_ANDROID_MLS_STUMBLER
FENNEC_JARS += ../stumbler/stumbler.jar
endif
else # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
GECKOVIEW_JARS := $(gradle_dir)/geckoview/intermediates/bundles/debug/classes.jar
FENNEC_JARS := $(gradle_dir)/app/intermediates/packaged/officialPhoton/debug/classes.jar
$(GECKOVIEW_JARS): .gradle.deps
$(FENNEC_JARS): .gradle.deps
endif # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
geckoview_jars_classpath := $(subst $(NULL) ,:,$(strip $(GECKOVIEW_JARS)))
# All the jars we're compiling from source. (not to be confused with
@ -232,6 +223,8 @@ endif # MOZ_INSTALL_TRACKING
library_jars := $(subst $(NULL) ,:,$(strip $(library_jars)))
endif # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
define gradle_command
$(1): $(2)
@ -244,7 +237,7 @@ $(eval $(call gradle_command,.gradle.deps,.aapt.deps FORCE))
classes.dex: .gradle.deps
$(REPORT_BUILD)
cp $(gradle_dir)/app/intermediates/transforms/dex/officialPhoton/debug/folders/1000/1f/main/classes.dex $@
cp $(gradle_dir)/app/intermediates/transforms/dexMerger/officialWithoutGeckoBinariesNoMinApiPhoton/debug/0/classes.dex classes.dex
GeneratedJNIWrappers.cpp GeneratedJNIWrappers.h GeneratedJNINatives.h : .gradle.deps
$(REPORT_BUILD)
@ -252,7 +245,7 @@ GeneratedJNIWrappers.cpp GeneratedJNIWrappers.h GeneratedJNINatives.h : .gradle.
FennecJNIWrappers.cpp FennecJNIWrappers.h FennecJNINatives.h: .gradle.deps
$(REPORT_BUILD)
else
else # MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
classes.dex: .proguard.deps
$(REPORT_BUILD)
$(DX) --dex --output=classes.dex --force-jumbo jars-proguarded
@ -273,19 +266,6 @@ endif
proguard_config_dir=$(topsrcdir)/mobile/android/config/proguard
# This stanza ensures that the set of GeckoView classes does not depend on too
# much of Fennec, where "too much" is defined as the set of potentially
# non-GeckoView classes that GeckoView already depended on at a certain point in
# time. The idea is to set a high-water mark that is not to be crossed.
classycle_jar := $(topsrcdir)/mobile/android/build/classycle/classycle-1.4.1.jar
.geckoview.deps: geckoview.ddf $(classycle_jar) $(ALL_JARS)
$(JAVA) -cp $(classycle_jar) \
classycle.dependency.DependencyChecker \
-mergeInnerClasses \
-dependencies=@$< \
$(ALL_JARS)
@$(TOUCH) $@
# First, we delete debugging information from libraries. Having line-number
# information for libraries for which we lack the source isn't useful, so this
# saves us a bit of space. Importantly, Proguard has a bug causing it to
@ -312,7 +292,7 @@ classycle_jar := $(topsrcdir)/mobile/android/build/classycle/classycle-1.4.1.jar
# outputs are fresher than the target, preventing a subsequent
# invocation from thinking Proguard's outputs are stale. This is safe
# because Make removes the target file if any recipe command fails.
.proguard.deps: .geckoview.deps .bundled.proguard.deps $(ALL_JARS) $(proguard_config_dir)/proguard.cfg $(PROGUARD_JAR)
.proguard.deps: .bundled.proguard.deps $(ALL_JARS) $(proguard_config_dir)/proguard.cfg $(PROGUARD_JAR)
$(REPORT_BUILD)
@$(TOUCH) $@
$(JAVA) \
@ -504,7 +484,7 @@ $(eval $(call gradle_command,.gradle.nodeps,AndroidManifest.xml $(constants_PP_J
.aapt.nodeps: .gradle.nodeps FORCE
@$(TOUCH) $@
cp $(GRADLE_ANDROID_APP_APK) gecko-nodeps.ap_
cp $(gradle_dir)/app/intermediates/transforms/dex/officialPhoton/debug/folders/1000/1f/main/classes.dex classes.dex
cp $(gradle_dir)/app/intermediates/transforms/dexMerger/officialWithoutGeckoBinariesNoMinApiPhoton/debug/0/classes.dex classes.dex
else
# .aapt.nodeps: AndroidManifest.xml FORCE
$(eval $(call aapt_command,.aapt.nodeps,AndroidManifest.xml FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/))

View File

@ -1,74 +0,0 @@
# This is a Classycle dependency definition file that asserts that the contents
# of the GeckoView library (Classycle set [lib]) is a dependency (but does not
# depend) on Fennec (Classycle set [main]). The additional Classycle set
# [middle] consists of classes referenced by GeckoView that probably should not
# be referenced. We want this middle set to shrink over time.
show allResults
[lib] = \
org.mozilla.gecko.gfx.* \
org.mozilla.gecko.mozglue.* \
org.mozilla.gecko.sqlite.* \
org.mozilla.gecko.util.* \
org.mozilla.gecko.AndroidGamepadManager \
org.mozilla.gecko.AppConstants \
org.mozilla.gecko.ContextGetter \
org.mozilla.gecko.CrashHandler \
org.mozilla.gecko.EventDispatcher \
org.mozilla.gecko.GeckoAccessibility \
org.mozilla.gecko.GeckoAppShell \
org.mozilla.gecko.GeckoBatteryManager \
org.mozilla.gecko.GeckoEditable \
org.mozilla.gecko.GeckoEditableClient \
org.mozilla.gecko.GeckoEditableListener \
org.mozilla.gecko.GeckoEvent \
org.mozilla.gecko.GeckoInputConnection \
org.mozilla.gecko.GeckoJavaSampler \
org.mozilla.gecko.GeckoNetworkManager \
org.mozilla.gecko.GeckoProfile \
org.mozilla.gecko.GeckoScreenOrientation \
org.mozilla.gecko.GeckoSharedPrefs \
org.mozilla.gecko.GeckoThread \
org.mozilla.gecko.GeckoView \
org.mozilla.gecko.GlobalHistory \
org.mozilla.gecko.InputMethods \
org.mozilla.gecko.NSSBridge \
org.mozilla.gecko.NotificationClient \
org.mozilla.gecko.NotificationHandler \
org.mozilla.gecko.PrefsHelper \
org.mozilla.gecko.SysInfo \
org.mozilla.gecko.TouchEventInterceptor \
org.mozilla.gecko.ZoomConstraints
[middle] = \
org.mozilla.gecko.prompts.* \
org.mozilla.gecko.FormAssistPopup \
org.mozilla.gecko.GeckoActivity \
org.mozilla.gecko.GeckoApp \
org.mozilla.gecko.GeckoProfileDirectories \
org.mozilla.gecko.GuestSession \
org.mozilla.gecko.R \
org.mozilla.gecko.Tab \
org.mozilla.gecko.Tabs \
org.mozilla.gecko.Telemetry \
org.mozilla.gecko.TelemetryContract \
org.mozilla.gecko.ThumbnailHelper \
org.mozilla.gecko.db.BrowserDB \
org.mozilla.gecko.db.LocalBrowserDB \
org.mozilla.gecko.distribution.Distribution \
org.mozilla.gecko.icons.*
[main] = org.mozilla.gecko.* excluding [lib] [middle]
check sets [lib] [middle] [main]
# Bug 1107134: it appears that Classycle can be fooled if the Java
# compiler inlines a constant from [main] into [lib]. That is, [main]
# really does depend on [lib] but Classycle only sees the dependency
# with some javac versions. For now, disable the check. Yes, this
# processing is useless without this check.
# check [lib] directlyIndependentOf [main]
# This fails; if this passed, GeckoView would be ready to extract from Fennec.
# check [lib] independentOf [middle]

View File

@ -46,7 +46,9 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
@SuppressLint("Registered") // This activity is only registered in the manifest if MOZ_CRASHREPORTER is set
// Registered: This activity is only registered in the manifest if MOZ_CRASHREPORTER is set.
// CutPasteId: This lint is not worth fixing. To fix it, cache all the findViewById results.
@SuppressLint("Registered,CutPasteId")
public class CrashReporter extends AppCompatActivity
{
private static final String LOGTAG = "GeckoCrashReporter";

View File

@ -5,6 +5,7 @@
package org.mozilla.gecko.activitystream;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
@ -216,8 +217,7 @@ public class ActivityStreamTelemetry {
break;
// While we also have a "blank" type, it is not used by Activity Stream.
case BrowserContract.TopSites.TYPE_BLANK:
default:
throw new IllegalStateException("Unknown top site type: " + topSite.getType());
throw new IllegalStateException("Unknown top site type :" + (int) topSite.getType());
}
return this;

View File

@ -226,4 +226,5 @@ public class Highlight implements WebpageRowModel {
// The Highlights cursor automatically notifies of data changes, so nothing needs to be done here.
@Override
public void onStateCommitted() {}}
public void onStateCommitted() {}
}

View File

@ -34,7 +34,6 @@ import org.mozilla.gecko.R;
import org.mozilla.gecko.SiteIdentity;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.toolbar.SecurityModeUtil;
import org.mozilla.gecko.toolbar.CustomTabsSecurityPopup;
import org.mozilla.gecko.util.ColorUtil;
/**

View File

@ -2,7 +2,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/. */
package org.mozilla.gecko.toolbar;
package org.mozilla.gecko.customtabs;
import android.content.ClipData;
import android.content.ClipboardManager;

View File

@ -42,8 +42,6 @@ import java.util.Arrays;
*
* * {@link AbstractPerProfileDatabaseProvider} provides a simple abstraction for
* querying databases that are stored in the user's profile directory.
* * {@link PerProfileDatabaseProvider} is a simple version that only allows a
* single ContentProvider to access each per-profile database.
* * {@link SharedBrowserDatabaseProvider} is an example of a per-profile provider
* that allows for multiple providers to safely work with the same databases.
*/
@ -134,7 +132,7 @@ public abstract class AbstractTransactionalProvider extends ContentProvider {
* If we're not in a batch, but we are in a write transaction,
* end it.
*
* @see PerProfileDatabaseProvider#markWriteSuccessful(SQLiteDatabase)
* @see AbstractTransactionalProvider#markWriteSuccessful(SQLiteDatabase)
*/
protected void endWrite(final SQLiteDatabase db) {
if (isInBatch()) {

View File

@ -306,7 +306,11 @@ public class LocalBrowserDB extends BrowserDB {
bookmarkValue.put(Bookmarks.FAVICON_ID, faviconID);
faviconValues.add(iconValue);
}
} catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException e) {
} catch (IllegalAccessException e) {
Log.wtf(LOGTAG, "Reflection failure.", e);
} catch (IllegalArgumentException e) {
Log.wtf(LOGTAG, "Reflection failure.", e);
} catch (NoSuchFieldException e) {
Log.wtf(LOGTAG, "Reflection failure.", e);
}
}
@ -502,7 +506,13 @@ public class LocalBrowserDB extends BrowserDB {
faviconField.setAccessible(true);
return faviconField.getInt(null);
} catch (IllegalAccessException | NoSuchFieldException e) {
} catch (IllegalAccessException e) {
// We'll end up here for any default bookmark that doesn't have a favicon in
// resources/raw/ (i.e., about:firefox). When this happens, the Favicons service will
// fall back to the default branding icon for about pages. Non-about pages should always
// specify an icon; otherwise, the placeholder globe favicon will be used.
Log.d(LOGTAG, "No raw favicon resource found for " + name);
} catch (NoSuchFieldException e) {
// We'll end up here for any default bookmark that doesn't have a favicon in
// resources/raw/ (i.e., about:firefox). When this happens, the Favicons service will
// fall back to the default branding icon for about pages. Non-about pages should always

View File

@ -1,55 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.db;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
import android.content.Context;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Abstract class containing methods needed to make a SQLite-based content
* provider with a database helper of type T, where one database helper is
* held per profile.
*/
public abstract class PerProfileDatabaseProvider<T extends SQLiteOpenHelper> extends AbstractPerProfileDatabaseProvider {
private PerProfileDatabases<T> databases;
@Override
protected PerProfileDatabases<T> getDatabases() {
return databases;
}
protected abstract String getDatabaseName();
/**
* Creates and returns an instance of the appropriate DB helper.
*
* @param context to use to create the database helper
* @param databasePath path to the DB file
* @return instance of the database helper
*/
protected abstract T createDatabaseHelper(Context context, String databasePath);
@Override
public boolean onCreate() {
synchronized (this) {
databases = new PerProfileDatabases<T>(
getContext(), getDatabaseName(), new DatabaseHelperFactory<T>() {
@Override
public T makeDatabaseHelper(Context context, String databasePath) {
final T helper = createDatabaseHelper(context, databasePath);
if (Versions.feature16Plus) {
helper.setWriteAheadLoggingEnabled(true);
}
return helper;
}
});
}
return true;
}
}

View File

@ -5,6 +5,7 @@
package org.mozilla.gecko.dlc;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.IntDef;
import android.util.Log;
@ -100,7 +101,7 @@ public abstract class BaseAction {
} else if (content.isHyphenationDictionary()) {
destinationDirectory = new File(context.getApplicationInfo().dataDir, "hyphenation");
} else {
throw new UnrecoverableDownloadContentException("Can't determine destination for kind: " + content.getKind());
throw new UnrecoverableDownloadContentException("Can't determine destination for kind: " + (String) content.getKind());
}
if (!destinationDirectory.exists() && !destinationDirectory.mkdirs()) {

View File

@ -5,6 +5,7 @@
package org.mozilla.gecko.dlc;
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@ -106,7 +107,7 @@ public class DownloadAction extends BaseAction {
}
if (!content.isAssetArchive()) {
Log.e(LOGTAG, "Downloaded content is not of type 'asset-archive': " + content.getType());
Log.e(LOGTAG, "Downloaded content is not of type 'asset-archive': " + (String) content.getType());
temporaryFile.delete();
DownloadContentTelemetry.eventDownloadFailure(content, DownloadContentTelemetry.ERROR_LOGIC);
continue;

View File

@ -1,68 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ExpandableListView;
/**
* <code>HomeExpandableListView</code> is a custom extension of
* <code>ExpandableListView<code>, that packs a <code>HomeContextMenuInfo</code>
* when any of its rows is long pressed.
* <p>
* This is the <code>ExpandableListView</code> equivalent of
* <code>HomeListView</code>.
*/
public class HomeExpandableListView extends ExpandableListView
implements OnItemLongClickListener {
// ContextMenuInfo associated with the currently long pressed list item.
private HomeContextMenuInfo mContextMenuInfo;
// ContextMenuInfo factory.
private HomeContextMenuInfo.ExpandableFactory mContextMenuInfoFactory;
public HomeExpandableListView(Context context) {
this(context, null);
}
public HomeExpandableListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HomeExpandableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setOnItemLongClickListener(this);
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (mContextMenuInfoFactory == null) {
return false;
}
// HomeExpandableListView items can correspond to groups and children.
// The factory can determine whether to add context menu for either,
// both, or none by unpacking the given position.
mContextMenuInfo = mContextMenuInfoFactory.makeInfoForAdapter(view, position, id, getExpandableListAdapter());
return showContextMenuForChild(HomeExpandableListView.this);
}
@Override
public ContextMenuInfo getContextMenuInfo() {
return mContextMenuInfo;
}
public void setContextMenuInfoFactory(final HomeContextMenuInfo.ExpandableFactory factory) {
mContextMenuInfoFactory = factory;
}
}

View File

@ -294,12 +294,14 @@ public class UpdateService extends IntentService {
public void run() {
showPermissionNotification();
sendCheckUpdateResult(CheckUpdateResult.NOT_AVAILABLE);
}})
}
})
.run(new Runnable() {
@Override
public void run() {
startDownload(info, flags);
}});
}
});
}
private void startDownload(UpdateInfo info, int flags) {

View File

@ -101,4 +101,8 @@ final class UnusedResourcesUtil {
public static final int[] USED_IN_PAGE_ACTION = {
R.drawable.add_to_homescreen
};
public static final int[] USED_IN_LEANPLUM_EXPANDABLE_LIST_ACTIVITY = {
R.style.Widget_ExpandableListView,
};
}

View File

@ -22,9 +22,6 @@ with Files('pocket-api-sandbox.token'):
with Files('android-services.mozbuild'):
BUG_COMPONENT = ('Android Background Services', 'Android Sync')
with Files('geckoview.ddf'):
BUG_COMPONENT = ('Firefox for Android', 'GeckoView')
with Files('crashreporter/**'):
BUG_COMPONENT = ('Firefox for Android', 'General')
@ -568,7 +565,6 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
'db/LocalURLMetadata.java',
'db/LoginsProvider.java',
'db/PasswordsProvider.java',
'db/PerProfileDatabaseProvider.java',
'db/PerProfileDatabases.java',
'db/RemoteClient.java',
'db/RemoteTab.java',
@ -666,7 +662,6 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
'home/HomeConfigLoader.java',
'home/HomeConfigPrefsBackend.java',
'home/HomeContextMenuInfo.java',
'home/HomeExpandableListView.java',
'home/HomeFragment.java',
'home/HomeListView.java',
'home/HomePager.java',
@ -1165,7 +1160,7 @@ gbjar.extra_jars += [CONFIG['ANDROID_DESIGN_AAR_LIB']]
gbjar.extra_jars += [CONFIG['ANDROID_RECYCLERVIEW_V7_AAR_LIB']]
gbjar.extra_jars += [CONFIG['ANDROID_CUSTOMTABS_AAR_LIB']]
gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough', '-J-Xmx512m', '-J-Xms128m']
gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough,-cast', '-J-Xmx512m', '-J-Xms128m']
# gecko-thirdparty is a good place to put small independent libraries
gtjar = add_java_jar('gecko-thirdparty')

View File

@ -1,22 +0,0 @@
Copyright (c) 2003-2008, Franz-Josef Elmer, All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,101 @@
.. -*- Mode: rst; fill-column: 80; -*-
=================================
The Fennec Gradle configuration
=================================
The Fennec Gradle configuration has three major facets:
1. separation into Gradle projects;
2. Android-Gradle build configurations using `flavorDimensions`;
3. integration into the larger `moz.build` build system.
Separation into Gradle projects
===============================
The Fennec source code is separated into multiple Gradle projects. Right now,
there are only a few: `:app`, `:geckoview`, `:thirdparty`, etc. Over time, pieces
of the Fennec source code will be extracted into separate, more-or-less
stand-alone Gradle projects (e.g., `:services`, `:stumbler`, `:media`) and use
modern techniques such as dependency injection to configure themselves at
runtime.
The `:omnijar` project is special and exists only to support integration with
Android Studio.
The details of the Gradle projects are reflected in the root `settings.gradle`
and the `**/build.gradle` files throughout the tree.
Android-Gradle build configurations
===================================
The Fennec `:app` project uses the Android-Gradle build plugin
`flavorDimensions` feature set to support many different configurations. The
Gradle integration must support many often conflicting requirements; the flavor
dimensions chosen support these requirements.
Version 3.0+ of the Android-Gradle build plugin improves support for "variant
dependencies". This makes it easier for a consuming application (for us,
`:app`) to use the appropriate configuration of consumed libraries (for us,
`:geckoview`). This allows us to simplify the logic around packaging the Gecko
libraries and Omnijar.
The details of the Android-Gradle build configurations are reflected
`**/build.gradle` files throughout the tree, in the
`mobile/android/gradle/*.gradle` files, and in the configuration baked into
`mobile/android/gradle.configure`.
The notable flavor dimensions are:
audience
--------
The `audience` flavor dimension determines who the build is for. "local"
audiences are developers: they should get extra logging and as much support for
building Fennec as possible. In particular, "local" audiences get support for
modifying the Android manifest and regenerating the pre-processed `strings.xml`
files while building with Gradle from within Android Studio.
"official" audiences are end users: they should get Mozilla's official branding
and have security-sensitive developer features disabled. The "official"
audience corresponds roughly to the `MOZILLA_OFFICIAL=1` build setting.
**Builds shipped to the Google Play Store are always for "official" audiences.**
geckoBinaries
-------------
For deep historical reasons, Mozilla's build system has multiple stages, the
most important of which are the build stage and the package stage. During the
build stage, the Gecko compiled libraries (e.g., `libxul.so`) and the Omnijar
have not yet been built. These libraries are only available during the package
stage. Gradle builds always want to include the Gecko libraries and the
Omnijar.
To accommodate the different stages, the build stage always invokes
"withoutGeckoBinaries" Gradle configurations. These configurations don't expect
or use the Gecko libraries or Omnijar. At the moment, the package stage also
invokes "withoutGeckoBinaries", but in the future, the package stage will invoke
"withGeckoBinaries" Gradle configurations to simplify the packaging of libraries
and the omnijar.
**Local developers almost always want to build "withGeckoBinaries", so that the
APK files produced can be run on device.**
minApi
------
At various times in the past, Fennec has supported APK splits, producing APKs
that support only specific Android versions. While this is not used at this
time, there are certain developer options (i.e., options that should only apply
to "local" audiences) that *also* depend on the target Android version. This
flavor dimension allows to opt in to those options, improving the speed of
development.
Integration into the larger `moz.build` build system
====================================================
The details of the Gradle integration into the larger `moz.build` system are
mostly captured in configuration baked into `mobile/android/gradle.configure`.
This configuration is reflected in the Android-specific `mach android *`
commands defined in `mobile/android/mach_commands.py`.

View File

@ -20,6 +20,7 @@ Contents:
defaultdomains
shutdown
push
gradle
Indices and tables
==================

View File

@ -2,6 +2,8 @@ buildDir "${topobjdir}/gradle/build/mobile/android/geckoview"
apply plugin: 'com.android.library'
apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
// This converts MOZ_APP_VERSION into an integer
// version code.
//
@ -38,12 +40,8 @@ def computeVersionCode() {
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
defaultPublishConfig 'release'
publishNonDefault true
targetSdkVersion project.ext.targetSdkVersion
minSdkVersion project.ext.minSdkVersion
manifestPlaceholders = project.ext.manifestPlaceholders
@ -103,14 +101,8 @@ android {
buildConfigField 'boolean', 'MOZILLA_OFFICIAL', mozconfig.substs.MOZILLA_OFFICIAL ? 'true' : 'false';
}
buildTypes {
withGeckoBinaries {
initWith release
}
withoutGeckoBinaries { // For clarity and consistency throughout the tree.
initWith release
}
}
project.configureProductFlavors.delegate = it
project.configureProductFlavors()
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
@ -154,21 +146,16 @@ android {
}
dependencies {
compile "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:palette-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:palette-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
}
apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
android.libraryVariants.all { variant ->
// Like 'debug', 'release', or 'withGeckoBinaries'.
def buildType = variant.buildType.name
// It would be most natural for :geckoview to always include the Gecko
// binaries, but that's difficult; see the notes in
// mobile/android/gradle/with_gecko_binaries.gradle. Instead :app uses
// :geckoview:release and handles it's own Gecko binary inclusion.
if (buildType.equals('withGeckoBinaries')) {
// See the notes in mobile/android/app/build.gradle for details on including
// Gecko binaries and the Omnijar.
if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
configureVariantWithGeckoBinaries(variant)
}
@ -202,12 +189,12 @@ android.libraryVariants.all { variant ->
options.addStringOption('noqualifier', 'java.lang');
}
task "javadocJar${name.capitalize()}"(type: Jar, dependsOn: javadoc) {
def javadocJar = task("javadocJar${name.capitalize()}", type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
task "sourcesJar${name.capitalize()}"(type: Jar) {
def sourcesJar = task("sourcesJar${name.capitalize()}", type: Jar) {
classifier 'sources'
description = "Generate Javadoc for build variant $name"
destinationDir = new File(destinationDir, variant.baseName)
@ -216,7 +203,7 @@ android.libraryVariants.all { variant ->
}
android.libraryVariants.all { variant ->
configureVariantWithJNIWrappers(variant, "Generated")
configureLibraryVariantWithJNIWrappers(variant, "Generated")
}
apply plugin: 'maven'
@ -245,7 +232,7 @@ afterEvaluate {
// The bundle tasks are only present when the particular configuration is
// being built, so this task might not exist. (This is due to the way the
// Android Gradle plugin defines things during configuration.)
def bundleWithGeckoBinaries = tasks.findByName('bundleWithGeckoBinaries')
def bundleWithGeckoBinaries = tasks.findByName('bundleOfficialWithGeckoBinariesNoMinApiRelease')
if (!bundleWithGeckoBinaries) {
return
}
@ -259,10 +246,10 @@ afterEvaluate {
artifacts {
// Instead of default (release) configuration, publish one with Gecko binaries.
archives bundleWithGeckoBinaries
archives bundleOfficialWithGeckoBinariesNoMinApiRelease
// Javadoc and sources for developer ergononomics.
archives javadocJarWithGeckoBinaries
archives sourcesJarWithGeckoBinaries
archives javadocJarOfficialWithGeckoBinariesNoMinApiRelease
archives sourcesJarOfficialWithGeckoBinariesNoMinApiRelease
}
}

View File

@ -64,7 +64,7 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
private final int mPlayerId;
private boolean mExoplayerSuspended = false;
private enum MediaDecoderPlayState{
private enum MediaDecoderPlayState {
PLAY_STATE_PREPARING,
PLAY_STATE_PAUSED,
PLAY_STATE_PLAYING

View File

@ -2,9 +2,10 @@ buildDir "${topobjdir}/gradle/build/mobile/android/geckoview_example"
apply plugin: 'com.android.application'
apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
targetSdkVersion project.ext.targetSdkVersion
@ -17,52 +18,27 @@ android {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
// This is extremely frustrating, but the only way to do it automation for
// now. Without this, we only get a "debugAndroidTest" configuration; we
// have no "withoutGeckoBinariesAndroidTest" configuration.
testBuildType "withoutGeckoBinaries"
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
withGeckoBinaries { // For consistency with :geckoview project in Task Cluster invocations.
initWith debug
}
withoutGeckoBinaries { // Logical negation of withGeckoBinaries.
initWith debug
}
}
project.configureProductFlavors.delegate = it
project.configureProductFlavors()
}
dependencies {
testCompile 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
compile 'com.android.support:support-annotations:23.4.0'
implementation 'com.android.support:support-annotations:23.4.0'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestImplementation 'com.android.support.test:runner:0.5'
// Not defining this library again results in test-app assuming 23.1.1, and the following errors:
// "Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app (23.4.0) and test app (23.1.1) differ."
androidTestCompile 'com.android.support:support-annotations:23.4.0'
androidTestImplementation 'com.android.support:support-annotations:23.4.0'
debugCompile project(path: ':geckoview', configuration: "debug")
releaseCompile project(path: ':geckoview', configuration: "release")
withGeckoBinariesCompile project(path: ':geckoview', configuration: "withGeckoBinaries")
withoutGeckoBinariesCompile project(path: ':geckoview', configuration: "withoutGeckoBinaries")
}
apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
android.applicationVariants.all { variant ->
// Like 'debug', 'release', or 'withoutGeckoBinaries'.
def buildType = variant.buildType.name
// It would be most natural for :geckoview to always include the Gecko
// binaries, but that's difficult; see the notes in
// mobile/android/gradle/with_gecko_binaries.gradle. Instead we handle our
// own Gecko binary inclusion.
if (!buildType.equals('withoutGeckoBinaries')) {
configureVariantWithGeckoBinaries(variant)
}
implementation project(path: ':geckoview')
}

View File

@ -46,9 +46,6 @@ def gradle_android_build_config():
else:
return s
# It's not really possible to abstract the GeckoView details just yet; post
# Android-Gradle plugin 3.0+, the configurations can be more sensible and
# we'll do this work.
def variant(productFlavors, buildType):
return namespace(
productFlavors=productFlavors,
@ -59,7 +56,13 @@ def gradle_android_build_config():
return namespace(
app=namespace(
variant=variant(('official', 'photon'), 'debug'),
variant=variant(('official', 'withoutGeckoBinaries', 'noMinApi', 'photon'), 'debug'),
),
geckoview=namespace(
variant=variant(('official', 'withGeckoBinaries', 'noMinApi'), 'release'),
),
geckoview_example=namespace(
variant=variant(('official', 'withGeckoBinaries', 'noMinApi'), 'debug'),
),
)
@ -82,7 +85,7 @@ set_config('GRADLE_ANDROID_APP_VARIANT_NAME', gradle_android_app_variant_name)
def gradle_android_app_tasks(build_config):
'''Gradle tasks run by |mach android assemble-app|.'''
return [
'geckoview:generateJNIWrappersForGeneratedRelease',
'geckoview:generateJNIWrappersForGenerated{geckoview.variant.name}'.format(geckoview=build_config.geckoview),
'app:generateJNIWrappersForFennec{app.variant.name}'.format(app=build_config.app),
'app:assemble{app.variant.name}'.format(app=build_config.app),
'app:assemble{app.variant.name}AndroidTest'.format(app=build_config.app),
@ -92,14 +95,39 @@ set_config('GRADLE_ANDROID_APP_TASKS', gradle_android_app_tasks)
@depends(gradle_android_build_config, check_build_environment)
@imports(_from='itertools', _import='imap')
def gradle_android_app_apks(build_config, build_env):
'''Paths to APK files produced by |mach android assemble-app|.'''
flavor = '-'.join(build_config.app.variant.productFlavors)
buildType = build_config.app.variant.buildType
f = '{}/gradle/build/mobile/android/app/outputs/apk/app-{}-{}.apk'
g = '{}/gradle/build/mobile/android/app/outputs/apk/app-{}-{}-androidTest.apk'
return namespace(app_apk=f.format(build_env.topobjdir, flavor, buildType),
app_androidTest_apk=g.format(build_env.topobjdir, flavor, buildType))
def capitalize(s):
# str.capitalize lower cases trailing letters.
if s:
return s[0].upper() + s[1:]
else:
return s
def uncapitalize(s):
if s:
return s[0].lower() + s[1:]
else:
return s
# Like 'officialPhoton'.
productFlavor = uncapitalize(''.join(imap(capitalize, build_config.app.variant.productFlavors)))
# Like 'official-photon'.
product_flavor = '-'.join(build_config.app.variant.productFlavors)
substs = {
'topobjdir': build_env.topobjdir,
'productFlavor': productFlavor,
'product_flavor': product_flavor,
'buildType': build_config.app.variant.buildType,
}
f = '{topobjdir}/gradle/build/mobile/android/app/outputs/apk/{productFlavor}/{buildType}/app-{product_flavor}-{buildType}.apk'
g = '{topobjdir}/gradle/build/mobile/android/app/outputs/apk/androidTest/{productFlavor}/{buildType}/app-{product_flavor}-{buildType}-androidTest.apk'
return namespace(app_apk=f.format(**substs),
app_androidTest_apk=g.format(**substs))
set_config('GRADLE_ANDROID_APP_APK', gradle_android_app_apks.app_apk)
set_config('GRADLE_ANDROID_APP_ANDROIDTEST_APK', gradle_android_app_apks.app_androidTest_apk)
@ -146,13 +174,13 @@ def gradle_android_findbugs_tasks(build_config):
set_config('GRADLE_ANDROID_FINDBUGS_TASKS', gradle_android_findbugs_tasks)
@dependable
def gradle_android_archive_geckoview_tasks():
@depends(gradle_android_build_config)
def gradle_android_archive_geckoview_tasks(build_config):
'''Gradle tasks run by |mach android archive-geckoview|.'''
return [
'geckoview:assembleWithGeckoBinaries',
'geckoview_example:assembleWithGeckoBinaries',
'geckoview_example:assembleWithGeckoBinariesAndroidTest',
'geckoview:assemble{geckoview.variant.name}'.format(geckoview=build_config.geckoview),
'geckoview_example:assemble{geckoview_example.variant.name}'.format(geckoview_example=build_config.geckoview_example),
'geckoview_example:assemble{geckoview_example.variant.name}AndroidTest'.format(geckoview_example=build_config.geckoview_example),
'geckoview:uploadArchives',
]

View File

@ -5,16 +5,13 @@
// Bug 1353055 - Strip 'vars' debugging information to agree with moz.build.
ext.configureVariantDebugLevel = { variant ->
// Like 'debug', 'release', or 'withGeckoBinaries'.
// Like 'debug' or 'release'.
def buildType = variant.buildType.name
// For :app, like 'local', 'localOld', or 'official'. For other projects, null.
def audienceDimension = variant.productFlavors[0]?.name
// The default is 'lines,source,vars', which includes debugging information
// that is quite large: roughly 500kb for Fennec. Therefore we remove
// 'vars' unless we're producing a debug build, where it is useful.
if (!'debug'.equals(buildType) || 'official'.equals(audienceDimension)) {
if (!'debug'.equals(buildType) || (variant.productFlavors*.name).contains('official')) {
variant.javaCompile.options.debugOptions.debugLevel = 'lines,source'
}
}

View File

@ -0,0 +1,48 @@
/* -*- Mode: Groovy; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* 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/. */
ext.configureProductFlavors = {
flavorDimensions "audience", "geckoBinaries", "minApi"
productFlavors {
local {
dimension "audience"
}
// Automation builds. We use "official" rather than "automation" to drive these builds down
// the list of configurations that Android Studio offers, thereby making it _not_ the
// default. This avoids a common issue with "omni.ja" not being packed into the default APK
// built and deployed by Android Studio.
official {
dimension "audience"
}
withGeckoBinaries {
dimension "geckoBinaries"
}
withoutGeckoBinaries {
dimension "geckoBinaries"
}
// For API 21+ - with pre-dexing, this will be faster for local development.
minApi21 {
dimension "minApi"
// For pre-dexing, setting `minSdkVersion 21` allows the Android gradle plugin to
// pre-DEX each module and produce an APK that can be tested on
// Android Lollipop without time consuming DEX merging processes.
minSdkVersion 21
dexOptions {
preDexLibraries true
}
}
// For API < 21 - does not support pre-dexing because local development
// is slow in that case.
noMinApi {
dimension "minApi"
}
}
}

View File

@ -1,46 +1,22 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
/* -*- Mode: Groovy; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* 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/. */
// We run fairly hard into a fundamental limitation of the Android Gradle
// plugin. There are many bugs filed about this, but
// https://code.google.com/p/android/issues/detail?id=216978#c6 is a reason one.
// The issue is that we need fine-grained control over when to include Gecko's
// binary libraries into the GeckoView AAR and the Fennec APK, and that's hard
// to achieve. In particular:
//
// * :app:official* wants :geckoview to not include Gecko binaries (official
// * automation build, before package)
//
// * :geckoview:withLibraries wants :geckoview to include Gecko binaries
// * (automation build, after package)
//
// * non-:app:official* wants :geckoview to include Gecko binaries (local
// * build, always after package)
//
// publishNonDefault (see
// http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication)
// is intended to address this, but doesn't handle our case. That option always
// builds *all* configurations, which fails when the required Gecko binaries
// don't exist (automation build, before package). So instead, we make both
// :app and :geckoview both know how to include the Gecko binaries, and use a
// non-default, non-published :geckoview:withGeckoBinaries configuration to
// handle automation's needs. Simple, right?
// The omnijar inputs are listed as resource directory inputs to a dummy JAR.
// That arrangement labels them nicely in IntelliJ. See the comment in the
// :omnijar project for more context.
evaluationDependsOn(':omnijar')
task buildOmnijar(type:Exec) {
task buildOmnijars(type:Exec) {
dependsOn rootProject.generateCodeAndResources
// See comment in :omnijar project regarding interface mismatches here.
inputs.file(project(':omnijar').sourceSets.main.resources.srcDirs).skipWhenEmpty()
// Produce a single output file.
// Produce both the Fennec and the GeckoView omnijars.
outputs.file "${topobjdir}/dist/fennec/assets/omni.ja"
outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja"
workingDir "${topobjdir}"
@ -60,97 +36,85 @@ task buildOmnijar(type:Exec) {
}
}
task syncOmnijarFromDistDir(type: Sync) {
// :app needs the full Fennec omni.ja, whereas other projects need the GeckoView-specific omni.ja.
def omnijar_dir = "app".equals(project.name) ? "fennec" : "geckoview"
into("${project.buildDir}/generated/omnijar")
from("${topobjdir}/dist/${omnijar_dir}/omni.ja",
"${topobjdir}/dist/${omnijar_dir}/assets/omni.ja") {
// Throw an exception if we find multiple, potentially conflicting omni.ja files.
duplicatesStrategy 'fail'
}
}
task checkLibsExistInDistDir {
doLast {
if (syncLibsFromDistDir.source.empty) {
throw new GradleException("Required JNI libraries not found in ${topobjdir}/dist/fennec/lib. Have you built and packaged?")
}
}
}
task syncLibsFromDistDir(type: Sync, dependsOn: checkLibsExistInDistDir) {
into("${project.buildDir}/generated/jniLibs")
from("${topobjdir}/dist/fennec/lib")
}
task checkAssetsExistInDistDir {
doLast {
if (syncAssetsFromDistDir.source.empty) {
throw new GradleException("Required assets not found in ${topobjdir}/dist/fennec/assets. Have you built and packaged?")
}
}
}
task syncAssetsFromDistDir(type: Sync, dependsOn: checkAssetsExistInDistDir) {
into("${project.buildDir}/generated/assets")
from("${topobjdir}/dist/fennec/assets") {
exclude 'omni.ja'
}
}
ext.configureVariantWithGeckoBinaries = { variant ->
// Like 'localPhoton' or 'localOldPhoton'; may be null.
def productFlavor = ""
def productFlavorNames = variant.productFlavors.collect { it.name.capitalize() }
if (!productFlavorNames.isEmpty()) {
productFlavor = productFlavorNames.join()
// Groovy's `uncapitilize` is not yet available.
def c = productFlavor.toCharArray()
c[0] = Character.toLowerCase(c[0])
productFlavor = new String(c)
// :app needs the full Fennec omni.ja, whereas other projects need the
// GeckoView-specific omni.ja.
def omnijar_dir = "app".equals(project.name) ? "fennec" : "geckoview"
def distDir = "${topobjdir}/dist/${omnijar_dir}"
def syncOmnijarFromDistDir = task("syncOmnijarFromDistDirFor${variant.name.capitalize()}", type: Sync) {
doFirst {
if (source.empty) {
throw new GradleException("Required omnijar not found in ${source.asPath}. Have you built and packaged?")
}
}
into("${project.buildDir}/moz.build/src/${variant.name}/omnijar")
from("${distDir}/omni.ja",
"${distDir}/assets/omni.ja") {
// Throw an exception if we find multiple, potentially conflicting omni.ja files.
duplicatesStrategy 'fail'
}
}
// Like 'debug' or 'release'.
def buildType = variant.buildType.name
def syncLibsFromDistDir = task("syncLibsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
doFirst {
if (source.empty) {
throw new GradleException("Required JNI libraries not found in ${source.asPath}. Have you built and packaged?")
}
}
syncOmnijarFromDistDir.dependsOn buildOmnijar
def generateAssetsTask = tasks.findByName("generate${productFlavor.capitalize()}${buildType.capitalize()}Assets")
generateAssetsTask.dependsOn syncOmnijarFromDistDir
generateAssetsTask.dependsOn syncLibsFromDistDir
generateAssetsTask.dependsOn syncAssetsFromDistDir
into("${project.buildDir}/moz.build/src/${variant.name}/jniLibs")
from("${distDir}/lib")
}
def sourceSet = productFlavor ? "${productFlavor}${buildType.capitalize()}" : buildType
android.sourceSets."${sourceSet}".assets.srcDir syncOmnijarFromDistDir.destinationDir
android.sourceSets."${sourceSet}".assets.srcDir syncAssetsFromDistDir.destinationDir
android.sourceSets."${sourceSet}".jniLibs.srcDir syncLibsFromDistDir.destinationDir
def syncAssetsFromDistDir = task("syncAssetsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
doFirst {
if (source.empty) {
throw new GradleException("Required assets not found in ${source.asPath}. Have you built and packaged?")
}
}
into("${project.buildDir}/moz.build/src/${variant.name}/assets")
from("${distDir}/assets") {
exclude 'omni.ja'
}
}
// Local (read, not 'official') builds want to reflect developer changes to
// the Omnijar sources. To do this, the Gradle build calls out to the
// moz.build system, which can be re-entrant. Official builds are driven by
// the moz.build system and should never be re-entrant in this way.
if (!((variant.productFlavors*.name).contains('official'))) {
syncOmnijarFromDistDir.dependsOn buildOmnijars
}
def assetGenTask = tasks.findByName("generate${variant.name.capitalize()}Assets")
if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
assetGenTask.dependsOn syncOmnijarFromDistDir
assetGenTask.dependsOn syncLibsFromDistDir
assetGenTask.dependsOn syncAssetsFromDistDir
android.sourceSets."${variant.name}".assets.srcDir syncOmnijarFromDistDir.destinationDir
android.sourceSets."${variant.name}".assets.srcDir syncAssetsFromDistDir.destinationDir
android.sourceSets."${variant.name}".jniLibs.srcDir syncLibsFromDistDir.destinationDir
}
}
ext.configureVariantWithJNIWrappers = { variant, module ->
def jarTask
if (module == 'Generated') {
jarTask = tasks["package${variant.name.capitalize()}JarArtifact"]
} else {
jarTask = tasks["jar${variant.name.capitalize()}Classes"]
}
if (jarTask.outputs.files.size() != 1) {
throw new GradleException("Jar task output multiple files other than one single jar")
}
// At configuration time, the classpath of dependencies with internal_impl
// JAR files may not be correct. This manifests in
ext.configureLibraryVariantWithJNIWrappers = { variant, module ->
// Library variants have two essentially independent transform* tasks:
//
// 'Exception in thread "main" java.lang.NoClassDefFoundError: android/support/v4/app/ActivityCompatApi23$RequestPermissionsRequestCodeValidator'
// - ...WithSyncLibJars... is used by assemble* and bundle*
// - ...WithPrepareIntermediateJars... is used by consuming applications.
//
// when running |mach gradle clean app:generateJNI...|. We work around this
// by configuring the classpath at evaluation-time, not configuration-time.
//
// The specific dependency on the `prepareDependencies` task may not be
// necessary, but commits like
// https://github.com/evant/gradle-retrolambda/commit/15108c65ee43be499a1359d9d4f88b0851d46769
// suggest that it is. It certainly doesn't hurt.
def prepareDependenciesTask = tasks.getByName("prepare${variant.name.capitalize()}Dependencies")
// It's not really possible to insert something immediately _after_
// ...WithPrepareIntermediateJars..., so we make the consuming moz.build
// system invoke this target directly, and force the
// ...WithPrepareIntermediateJars... dependency. The real consumer of the
// JNI wrappers is the moz.build system, which always builds geckoview to
// consume from Fennec, so that dependency likely adds less to the build time.
def jarTask = tasks["transformClassesAndResourcesWithPrepareIntermediateJarsFor${variant.name.capitalize()}"]
def output = jarTask.outputs.files.find({ it.absolutePath.contains('/classes.jar') })
def wrapperTask
if (System.env.IS_LANGUAGE_REPACK == '1') {
@ -160,7 +124,7 @@ ext.configureVariantWithJNIWrappers = { variant, module ->
} else {
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) {
classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar"
// Configure the classpath at evaluation-time, not at
// configuration-time: see above comment.
doFirst {
@ -171,12 +135,11 @@ ext.configureVariantWithJNIWrappers = { variant, module ->
main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor'
args module
args jarTask.outputs.files.iterator().next()
args output
workingDir "${topobjdir}/mobile/android/base"
dependsOn jarTask
dependsOn prepareDependenciesTask
}
}
@ -186,3 +149,36 @@ ext.configureVariantWithJNIWrappers = { variant, module ->
tasks["assemble${variant.name.capitalize()}"].dependsOn wrapperTask
}
}
ext.configureApplicationVariantWithJNIWrappers = { variant, module ->
def jarTask = tasks["bundleAppClasses${variant.name.capitalize()}"]
def output = jarTask.outputs.files.find({ it.absolutePath.contains('/classes.jar') })
def wrapperTask
if (System.env.IS_LANGUAGE_REPACK == '1') {
// Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and don't
// really have a build environment.
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}")
} else {
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) {
classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar"
// Configure the classpath at evaluation-time, not at
// configuration-time: see above comment.
doFirst {
classpath variant.javaCompile.classpath
// Include android.jar.
classpath variant.javaCompile.options.bootClasspath
}
main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor'
args module
args output
workingDir "${topobjdir}/mobile/android/base"
// This forces bundling, which isn't usually part of the assemble* process.
dependsOn jarTask
}
}
}

View File

@ -141,11 +141,9 @@
@BINPATH@/components/dom_range.xpt
@BINPATH@/components/dom_security.xpt
@BINPATH@/components/dom_sidebar.xpt
@BINPATH@/components/dom_mobilemessage.xpt
@BINPATH@/components/dom_storage.xpt
@BINPATH@/components/dom_system.xpt
@BINPATH@/components/dom_traversal.xpt
@BINPATH@/components/dom_tv.xpt
#ifdef MOZ_WEBSPEECH
@BINPATH@/components/dom_webspeechrecognition.xpt
#endif
@ -259,10 +257,6 @@
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@BINPATH@/components/ConsoleAPIStorage.js
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest
@BINPATH@/components/PhoneNumberService.js
@BINPATH@/components/PhoneNumberService.manifest
@BINPATH@/components/NotificationStorage.js
@BINPATH@/components/NotificationStorage.manifest
#ifdef MOZ_ANDROID_GCM
@ -402,9 +396,6 @@
@BINPATH@/components/PresentationDataChannelSessionTransport.manifest
@BINPATH@/components/AndroidCastDeviceProvider.manifest
@BINPATH@/components/AndroidCastDeviceProvider.js
@BINPATH@/components/TVSimulatorService.js
@BINPATH@/components/TVSimulatorService.manifest
#endif
@BINPATH@/components/mozIntl.manifest

View File

@ -414,7 +414,9 @@ class MachCommands(MachCommandBase):
# $JAVA_HOME/bin/java into $JAVA_HOME.
java_home = os.path.dirname(os.path.dirname(self.substs['JAVA']))
gradle_flags = shell_split(self.substs.get('GRADLE_FLAGS', ''))
gradle_flags = self.substs.get('GRADLE_FLAGS', '') or \
os.environ.get('GRADLE_FLAGS', '')
gradle_flags = shell_split(gradle_flags)
# We force the Gradle JVM to run with the UTF-8 encoding, since we
# filter strings.xml, which is really UTF-8; the ellipsis character is

View File

@ -11,9 +11,6 @@ with Files('**'):
with Files('branding/**'):
BUG_COMPONENT = ('Firefox for Android', 'General')
with Files('build/**'):
BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
with Files('config/**'):
BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')

View File

@ -8,13 +8,19 @@ import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserProvider;
import org.mozilla.gecko.db.TabsProvider;
import org.robolectric.android.controller.ContentProviderController;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
@ -22,17 +28,54 @@ import java.util.ArrayList;
* Wrap a ContentProvider, appending &test=1 to all queries.
*/
public class DelegatingTestContentProvider extends ContentProvider {
protected final ContentProvider mTargetProvider;
protected ContentProvider mTargetProvider;
protected static Uri appendUriParam(Uri uri, String param, String value) {
return uri.buildUpon().appendQueryParameter(param, value).build();
}
/**
* Create and register a new <tt>BrowserProvider</tt> that has test delegation.
* <p>
* Robolectric doesn't make it easy to parameterize a created
* <tt>ContentProvider</tt>, so we modify a built-in helper to do it.
* @return delegated <tt>ContentProvider</tt>.
*/
public static ContentProvider createDelegatingBrowserProvider() {
final ContentProviderController<DelegatingTestContentProvider> contentProviderController
= ContentProviderController.of(ReflectionHelpers.callConstructor(DelegatingTestContentProvider.class,
ReflectionHelpers.ClassParameter.from(ContentProvider.class, new BrowserProvider())));
return contentProviderController.create(BrowserContract.AUTHORITY).get();
}
/**
* Create and register a new <tt>TabsProvider</tt> that has test delegation.
* <p>
* Robolectric doesn't make it easy to parameterize a created
* <tt>ContentProvider</tt>, so we modify a built-in helper to do it.
* @return delegated <tt>ContentProvider</tt>.
*/
public static ContentProvider createDelegatingTabsProvider() {
final ContentProviderController<DelegatingTestContentProvider> contentProviderController
= ContentProviderController.of(ReflectionHelpers.callConstructor(DelegatingTestContentProvider.class,
ReflectionHelpers.ClassParameter.from(ContentProvider.class, new TabsProvider())));
return contentProviderController.create(BrowserContract.TABS_AUTHORITY).get();
}
public DelegatingTestContentProvider(ContentProvider targetProvider) {
super();
mTargetProvider = targetProvider;
}
public void attachInfo(Context context, ProviderInfo info) {
// With newer Robolectric versions, we must create the target provider
// before calling into super. If we don't do this, the target
// provider's onCreate() will witness a null getContext(), which the
// Android documentation guarantees never happens on device.
mTargetProvider.attachInfo(context, null);
super.attachInfo(context, info);
}
private Uri appendTestParam(Uri uri) {
return appendUriParam(uri, BrowserContract.PARAM_IS_TEST, "1");
}
@ -88,6 +131,10 @@ public class DelegatingTestContentProvider extends ContentProvider {
return mTargetProvider.call(method, arg, extras);
}
public void shutdown() {
mTargetProvider.shutdown();
}
public ContentProvider getTargetProvider() {
return mTargetProvider;
}

View File

@ -3,6 +3,7 @@
package org.mozilla.gecko.background.db;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.database.Cursor;
@ -17,7 +18,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.TabsProvider;
import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
import org.mozilla.gecko.sync.repositories.domain.TabsRecord;
@ -35,13 +35,11 @@ public class TestTabsProvider {
protected Tab testTab2;
protected Tab testTab3;
protected TabsProvider provider;
protected ContentProvider provider;
@Before
public void setUp() {
provider = new TabsProvider();
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.TABS_AUTHORITY, new DelegatingTestContentProvider(provider));
provider = DelegatingTestContentProvider.createDelegatingTabsProvider();
}
@After

View File

@ -13,6 +13,8 @@ import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
import org.mozilla.gecko.sync.stage.CompletedStage;
import org.mozilla.gecko.sync.stage.GlobalSyncStage;
import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import java.io.IOException;
import java.util.HashMap;
@ -26,7 +28,7 @@ public class MockGlobalSession extends MockPrefsGlobalSession {
public MockGlobalSession(SyncConfiguration config, GlobalSessionCallback callback)
throws SyncConfigurationException, IllegalArgumentException, IOException, NonObjectJSONException {
super(config, callback, null, null);
super(config, callback, RuntimeEnvironment.application, null);
}
@Override

View File

@ -53,9 +53,4 @@ public class MockPrefsGlobalSession extends GlobalSession {
config.syncKeyBundle = syncKeyBundle;
return new MockPrefsGlobalSession(config, callback, context, clientsDelegate);
}
@Override
public Context getContext() {
return null;
}
}

View File

@ -3,6 +3,7 @@
package org.mozilla.gecko.db;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentUris;
import android.content.ContentValues;
@ -17,12 +18,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
import org.robolectric.shadows.ShadowContentResolver;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -41,8 +41,9 @@ import static org.mozilla.gecko.db.BrowserProviderGeneralTest.INVALID_TIMESTAMP;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.assertVersionsForSelection;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.bookmarksTestSyncUri;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.bookmarksTestUri;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.getBookmarksTestSyncIncrementLocalVersionUri;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.getBookmarkIdFromGuid;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest
.getBookmarksTestSyncIncrementLocalVersionUri;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.insertBookmark;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.withDeleted;
import static org.mozilla.gecko.db.BrowserProviderGeneralTest.withSync;
@ -53,13 +54,11 @@ import static org.mozilla.gecko.db.BrowserProviderGeneralTest.withSync;
@RunWith(TestRunner.class)
public class BrowserProviderBookmarksTest {
private ContentProviderClient bookmarksClient;
private BrowserProvider provider;
private ContentProvider provider;
@Before
public void setUp() throws Exception {
provider = new BrowserProvider();
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
ShadowContentResolver contentResolver = new ShadowContentResolver();
bookmarksClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);

View File

@ -3,13 +3,13 @@
package org.mozilla.gecko.db;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.provider.Browser;
import org.junit.After;
import org.junit.Before;
@ -41,15 +41,12 @@ public class BrowserProviderGeneralTest {
private static final long INVALID_ID = -1;
private BrowserProvider provider;
private ContentProvider provider;
private ContentProviderClient browserClient;
@Before
public void setUp() throws Exception {
provider = new BrowserProvider();
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
ShadowContentResolver contentResolver = new ShadowContentResolver();
browserClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);

View File

@ -3,6 +3,7 @@
package org.mozilla.gecko.db;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.net.Uri;
@ -14,21 +15,17 @@ import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
import org.robolectric.shadows.ShadowContentResolver;
import java.util.UUID;
public class BrowserProviderHistoryVisitsTestBase {
/* package-private */ ShadowContentResolver contentResolver;
/* package-private */ ContentProviderClient historyClient;
/* package-private */ ContentProviderClient visitsClient;
/* package-private */ Uri historyTestUri;
/* package-private */ Uri visitsTestUri;
/* package-private */ BrowserProvider provider;
/* package-private */ ContentProvider provider;
@Before
public void setUp() throws Exception {
provider = new BrowserProvider();
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
contentResolver = new ShadowContentResolver();
historyClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.HISTORY_CONTENT_URI);

View File

@ -4,6 +4,7 @@
package org.mozilla.gecko.db;
import android.annotation.SuppressLint;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
@ -44,15 +45,13 @@ public class LocalBrowserDBTest {
private static final String FOLDER_NAME = "folder1";
private Context context;
private BrowserProvider provider;
private ContentProvider provider;
private ContentProviderClient bookmarkClient;
@Before
public void setUp() throws Exception {
context = RuntimeEnvironment.application;
provider = new BrowserProvider();
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
ShadowContentResolver contentResolver = new ShadowContentResolver();
bookmarkClient = contentResolver.acquireContentProviderClient(BrowserContractHelpers.BOOKMARKS_CONTENT_URI);

View File

@ -3,6 +3,7 @@
package org.mozilla.gecko.fxa.devices;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
@ -21,7 +22,6 @@ import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
import org.mozilla.gecko.background.fxa.FxAccountClient;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserProvider;
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
import org.mozilla.gecko.fxa.login.State;
import org.robolectric.shadows.ShadowContentResolver;
@ -119,12 +119,9 @@ public class TestFxAccountDeviceListUpdater {
public void testBrowserProvider() {
Uri uri = testUri(BrowserContract.RemoteDevices.CONTENT_URI);
BrowserProvider provider = new BrowserProvider();
final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
Cursor c = null;
try {
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
final ShadowContentResolver cr = new ShadowContentResolver();
ContentProviderClient remoteDevicesClient = cr.acquireContentProviderClient(BrowserContract.RemoteDevices.CONTENT_URI);

View File

@ -3,6 +3,7 @@
package org.mozilla.gecko.sync.repositories.android;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.net.Uri;
@ -16,7 +17,6 @@ import org.junit.runner.RunWith;
import org.mozilla.gecko.background.db.DelegatingTestContentProvider;
import org.mozilla.gecko.background.testhelpers.TestRunner;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserProvider;
import org.robolectric.shadows.ShadowContentResolver;
import static org.junit.Assert.assertEquals;
@ -56,11 +56,8 @@ public class VisitsHelperTest {
Uri historyTestUri = testUri(BrowserContract.History.CONTENT_URI);
Uri visitsTestUri = testUri(BrowserContract.Visits.CONTENT_URI);
BrowserProvider provider = new BrowserProvider();
final ContentProvider provider = DelegatingTestContentProvider.createDelegatingBrowserProvider();
try {
provider.onCreate();
ShadowContentResolver.registerProvider(BrowserContract.AUTHORITY, new DelegatingTestContentProvider(provider));
final ShadowContentResolver cr = new ShadowContentResolver();
ContentProviderClient historyClient = cr.acquireContentProviderClient(BrowserContractHelpers.HISTORY_CONTENT_URI);
ContentProviderClient visitsClient = cr.acquireContentProviderClient(BrowserContractHelpers.VISITS_CONTENT_URI);

View File

@ -4,12 +4,8 @@ apply plugin: 'com.android.library'
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
defaultPublishConfig 'release'
publishNonDefault true
targetSdkVersion project.ext.targetSdkVersion
minSdkVersion project.ext.minSdkVersion
manifestPlaceholders = project.ext.manifestPlaceholders
@ -47,11 +43,11 @@ android {
}
dependencies {
compile "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:support-v4:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
if (mozconfig.substs.MOZ_ANDROID_MMA) {
compile "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
compile "com.android.support:support-annotations:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
compile "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.android.support:appcompat-v7:${mozconfig.substs.ANDROID_SUPPORT_LIBRARY_VERSION}"
implementation "com.android.support:support-annotations:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
implementation "com.google.android.gms:play-services-gcm:${mozconfig.substs.ANDROID_GOOGLE_PLAY_SERVICES_VERSION}"
}
}

View File

@ -83,13 +83,6 @@ interface nsINetUtil : nsISupports
*/
nsIURI toImmutableURI(in nsIURI aURI);
/**
* Create a simple nested URI using the result of
* toImmutableURI on the passed-in aURI which may not be null.
* Note: The return URI will not have had its spec set yet.
*/
nsIURI newSimpleNestedURI(in nsIURI aURI);
/** Escape every character with its %XX-escaped equivalent */
const unsigned long ESCAPE_ALL = 0;

View File

@ -1574,19 +1574,6 @@ nsIOService::ToImmutableURI(nsIURI* uri, nsIURI** result)
return NS_OK;
}
NS_IMETHODIMP
nsIOService::NewSimpleNestedURI(nsIURI* aURI, nsIURI** aResult)
{
NS_ENSURE_ARG(aURI);
nsCOMPtr<nsIURI> safeURI;
nsresult rv = NS_EnsureSafeToReturn(aURI, getter_AddRefs(safeURI));
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(*aResult = new nsSimpleNestedURI(safeURI));
return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsIOService::SetManageOfflineStatus(bool aManage)
{

View File

@ -2133,7 +2133,7 @@ dnl ========================================================
case "$MOZ_BUILD_APP" in
mobile/android)
MOZ_ANDROID_SDK(23, 23, 25.0.3, 26.0.0 26.0.0-dev 25.3.2 25.3.1)
MOZ_ANDROID_SDK(23, 23, 26.0.2, 26.0.0 26.0.0-dev 25.3.2 25.3.1)
;;
esac

View File

@ -1,5 +1,5 @@
platform-tools
build-tools;25.0.3
build-tools;26.0.2
platforms;android-23
extras;android;m2repository
extras;google;m2repository

View File

@ -38,13 +38,10 @@ ANDROID_IDE_ADVERTISEMENT = '''
ADVERTISEMENT
You are building Firefox for Android. After your build completes, you can open
the top source directory in IntelliJ or Android Studio directly and build using
Gradle. See the documentation at
the top source directory in Android Studio directly and build using Gradle.
See the documentation at
https://developer.mozilla.org/en-US/docs/Simple_Firefox_for_Android_build
PLEASE BE AWARE THAT GRADLE AND INTELLIJ/ANDROID STUDIO SUPPORT IS EXPERIMENTAL.
You should verify any changes using |mach build|.
=============
'''.strip()

View File

@ -21,7 +21,7 @@ android-api-16/debug:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -73,7 +73,7 @@ android-x86/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -130,7 +130,7 @@ android-x86-nightly/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -178,7 +178,7 @@ android-api-16/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -230,7 +230,7 @@ android-api-16-nightly/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -283,7 +283,7 @@ android-x86-old-id/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -339,7 +339,7 @@ android-x86-old-id-nightly/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -388,7 +388,7 @@ android-api-16-old-id/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -439,7 +439,7 @@ android-api-16-old-id-nightly/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -488,7 +488,7 @@ android-api-16-gradle/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -534,7 +534,7 @@ android-aarch64/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
@ -586,7 +586,7 @@ android-aarch64-nightly/opt:
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/geckoview_example-withGeckoBinaries.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/

View File

@ -5,7 +5,7 @@ set -x -e
echo "running as" $(id)
: WORKSPACE ${WORKSPACE:=/builds/worker/workspace}
: GRADLE_VERSION ${GRADLE_VERSION:=3.4.1}
: GRADLE_VERSION ${GRADLE_VERSION:=4.1}
set -v

View File

@ -72,7 +72,8 @@
</remoteStorage>
<externalConfiguration>
<repositoryPolicy>RELEASE</repositoryPolicy>
<checksumPolicy>STRICT</checksumPolicy>
<!-- Google doesn't publish checksums. Why, Google, why? -->
<checksumPolicy>STRICT_IF_EXISTS</checksumPolicy>
<fileTypeValidation>true</fileTypeValidation>
<downloadRemoteIndex>false</downloadRemoteIndex>
<artifactMaxAge>-1</artifactMaxAge>

View File

@ -2767,13 +2767,8 @@ GeckoDriver.prototype.deleteSession = function() {
// frame scripts can be safely reused
Preferences.set(CONTENT_LISTENER_PREF, false);
// clean up state in each frame in each browser
for (let win in this.browsers) {
let browser = this.browsers[win];
browser.knownFrames.forEach(() => {
globalMessageManager.broadcastAsyncMessage("Marionette:Deregister");
});
}
globalMessageManager.broadcastAsyncMessage("Marionette:Session:Delete");
globalMessageManager.broadcastAsyncMessage("Marionette:Deregister");
for (let win of this.windows) {
if (win.messageManager) {

View File

@ -46,7 +46,6 @@ Cu.import("chrome://marionette/content/session.js");
Cu.importGlobalProperties(["URL"]);
let outerWindowID = null;
let curContainer = {frame: content, shadowRoot: null};
// Listen for click event to indicate one click has happened, so actions
@ -447,7 +446,7 @@ const loadListener = {
* an ID, we start the listeners. Otherwise, nothing happens.
*/
function registerSelf() {
outerWindowID = winUtil.outerWindowID;
let {outerWindowID} = winUtil;
logger.debug(`Register listener.js for window ${outerWindowID}`);
sandboxes.clear();
@ -459,10 +458,12 @@ function registerSelf() {
action.inputStateMap = new Map();
action.inputsToCancel = [];
// register will have the ID and a boolean describing if this is the
// main process or not
let register = sendSyncMessage("Marionette:Register", {outerWindowID});
if (register[0].outerWindowID === outerWindowID) {
let reply = sendSyncMessage("Marionette:Register", {outerWindowID});
if (reply.length == 0) {
logger.error("No reply from Marionette:Register");
}
if (reply[0].outerWindowID === outerWindowID) {
startListeners();
sendAsyncMessage("Marionette:ListenersAttached", {outerWindowID});
}
@ -557,6 +558,7 @@ function startListeners() {
addMessageListener("Marionette:reftestWait", reftestWaitFn);
addMessageListener("Marionette:releaseActions", releaseActionsFn);
addMessageListener("Marionette:sendKeysToElement", sendKeysToElementFn);
addMessageListener("Marionette:Session:Delete", deleteSession);
addMessageListener("Marionette:singleTap", singleTapFn);
addMessageListener("Marionette:switchToFrame", switchToFrame);
addMessageListener("Marionette:switchToParentFrame", switchToParentFrame);
@ -594,13 +596,16 @@ function deregister() {
removeMessageListener("Marionette:refresh", refresh);
removeMessageListener("Marionette:releaseActions", releaseActionsFn);
removeMessageListener("Marionette:sendKeysToElement", sendKeysToElementFn);
removeMessageListener("Marionette:Session:Delete", deleteSession);
removeMessageListener("Marionette:singleTap", singleTapFn);
removeMessageListener("Marionette:switchToFrame", switchToFrame);
removeMessageListener("Marionette:switchToParentFrame", switchToParentFrame);
removeMessageListener("Marionette:switchToShadowRoot", switchToShadowRootFn);
removeMessageListener("Marionette:takeScreenshot", takeScreenshotFn);
removeMessageListener("Marionette:waitForPageLoaded", waitForPageLoaded);
}
function deleteSession() {
seenEls.clear();
// reset container frame to the top-most frame
curContainer = {frame: content, shadowRoot: null};

View File

@ -57,7 +57,9 @@ toolkit.jar:
content/global/TopLevelVideoDocument.js
content/global/timepicker.xhtml
content/global/treeUtils.js
#ifndef MOZ_FENNEC
content/global/viewZoomOverlay.js
#endif
content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
content/global/bindings/browser.xml (widgets/browser.xml)
content/global/bindings/button.xml (widgets/button.xml)

View File

@ -141,6 +141,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
'mozgtk_stub',
]
if CONFIG['MOZ_WAYLAND']:
USE_LIBS += [
'mozwayland',
]
if CONFIG['MOZ_JPROF']:
USE_LIBS += [
'jprof',

View File

@ -56,7 +56,7 @@ void WindowSurfaceProvider::Initialize(
#ifdef MOZ_WAYLAND
void WindowSurfaceProvider::Initialize(nsWindow *aWidget)
{
MOZ_ASSERT(!aWidget->IsX11Display(),
MOZ_ASSERT(aWidget->GetWaylandDisplay(),
"We are supposed to have a Wayland display!");
mWidget = aWidget;

View File

@ -220,7 +220,10 @@ WaylandDisplayLoopLocked(wl_display* aDisplay,
if (gWaylandDisplays[i]->Matches(aDisplay)) {
if (gWaylandDisplays[i]->DisplayLoop()) {
MessageLoop::current()->PostDelayedTask(
NewRunnableFunction(&WaylandDisplayLoop, aDisplay), EVENT_LOOP_DELAY);
NewRunnableFunction("WaylandDisplayLoop",
&WaylandDisplayLoop,
aDisplay),
EVENT_LOOP_DELAY);
}
break;
}
@ -271,6 +274,7 @@ nsWaylandDisplay::GetShm()
wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue);
wl_display_roundtrip_queue(mDisplay, mEventQueue);
MOZ_RELEASE_ASSERT(mShm, "Wayland registry query failed!");
}
@ -305,8 +309,8 @@ nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay)
mEventQueue = nullptr;
} else {
mEventQueue = wl_display_create_queue(mDisplay);
MessageLoop::current()->PostTask(NewRunnableFunction(&WaylandDisplayLoop,
mDisplay));
MessageLoop::current()->PostTask(NewRunnableFunction(
"WaylandDisplayLoop", &WaylandDisplayLoop, mDisplay));
}
}
@ -577,7 +581,9 @@ WindowSurfaceWayland::~WindowSurfaceWayland()
// in compositor thread. We have to unref/delete WaylandDisplay in compositor
// thread then and we can't use MessageLoop::current() here.
mDisplayThreadMessageLoop->PostTask(
NewRunnableFunction(&WaylandDisplayRelease, mWaylandDisplay->GetDisplay()));
NewRunnableFunction("WaylandDisplayRelease",
&WaylandDisplayRelease,
mWaylandDisplay->GetDisplay()));
} else {
WaylandDisplayRelease(mWaylandDisplay->GetDisplay());
}

View File

@ -16,6 +16,12 @@ with Files("*WindowSurface*"):
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
DIRS += ['mozgtk']
if CONFIG['MOZ_WAYLAND']:
if CONFIG['GLIB_LIBS']:
DIRS += ['mozwayland']
else:
error('We support Wayland on glibc systems only, see Bug 1409707 for reference.')
EXPORTS += [
'mozcontainer.h',
'nsGTKToolkit.h',

View File

@ -12,6 +12,7 @@
#include <gdk/gdkwayland.h>
#endif
#include <stdio.h>
#include <dlfcn.h>
#ifdef ACCESSIBILITY
#include <atk/atk.h>
@ -208,7 +209,12 @@ moz_container_init (MozContainer *container)
{
GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
wl_display* display = gdk_wayland_display_get_wl_display(gdk_display);
// Available as of GTK 3.8+
static auto sGdkWaylandDisplayGetWlDisplay =
(wl_display *(*)(GdkDisplay *))
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display);
wl_registry* registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, container);
wl_display_dispatch(display);
@ -229,6 +235,14 @@ moz_container_init (MozContainer *container)
static gboolean
moz_container_map_surface(MozContainer *container)
{
// Available as of GTK 3.8+
static auto sGdkWaylandDisplayGetWlCompositor =
(wl_compositor *(*)(GdkDisplay *))
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor");
static auto sGdkWaylandWindowGetWlSurface =
(wl_surface *(*)(GdkWindow *))
dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface");
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
if (GDK_IS_X11_DISPLAY(display))
return false;
@ -238,13 +252,13 @@ moz_container_map_surface(MozContainer *container)
if (!container->surface) {
struct wl_compositor *compositor;
compositor = gdk_wayland_display_get_wl_compositor(display);
compositor = sGdkWaylandDisplayGetWlCompositor(display);
container->surface = wl_compositor_create_surface(compositor);
}
if (!container->subsurface) {
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
wl_surface* gtk_surface = gdk_wayland_window_get_wl_surface(window);
wl_surface* gtk_surface = sGdkWaylandWindowGetWlSurface(window);
if (!gtk_surface) {
// We requested the underlying wl_surface too early when container
// is not realized yet. We'll try again before first rendering
@ -264,7 +278,7 @@ moz_container_map_surface(MozContainer *container)
// Route input to parent wl_surface owned by Gtk+ so we get input
// events from Gtk+.
GdkDisplay* display = gtk_widget_get_display(GTK_WIDGET (container));
wl_compositor* compositor = gdk_wayland_display_get_wl_compositor(display);
wl_compositor* compositor = sGdkWaylandDisplayGetWlCompositor(display);
wl_region* region = wl_compositor_create_region(compositor);
wl_surface_set_input_region(container->surface, region);
wl_region_destroy(region);

View File

@ -0,0 +1,13 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SOURCES += [
'mozwayland.c',
]
SharedLibrary('mozwayland')
CFLAGS += CONFIG['TK_CFLAGS']

View File

@ -0,0 +1,273 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Types.h"
#include <gtk/gtk.h>
#include <gdk/gdkwayland.h>
const struct wl_interface wl_buffer_interface;
const struct wl_interface wl_callback_interface;
const struct wl_interface wl_data_device_interface;
const struct wl_interface wl_data_device_manager_interface;
const struct wl_interface wl_keyboard_interface;
const struct wl_interface wl_region_interface;
const struct wl_interface wl_registry_interface;
const struct wl_interface wl_shm_interface;
const struct wl_interface wl_shm_pool_interface;
const struct wl_interface wl_seat_interface;
const struct wl_interface wl_surface_interface;
const struct wl_interface wl_subsurface_interface;
const struct wl_interface wl_subcompositor_interface;
MOZ_EXPORT void
wl_event_queue_destroy(struct wl_event_queue *queue)
{
}
MOZ_EXPORT void
wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...)
{
}
MOZ_EXPORT void
wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode,
union wl_argument *args)
{
}
MOZ_EXPORT struct wl_proxy *
wl_proxy_create(struct wl_proxy *factory,
const struct wl_interface *interface)
{
return NULL;
}
MOZ_EXPORT void *
wl_proxy_create_wrapper(void *proxy)
{
return NULL;
}
MOZ_EXPORT void
wl_proxy_wrapper_destroy(void *proxy_wrapper)
{
}
MOZ_EXPORT struct wl_proxy *
wl_proxy_marshal_constructor(struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
...)
{
return NULL;
}
MOZ_EXPORT struct wl_proxy *
wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy,
uint32_t opcode,
const struct wl_interface *interface,
uint32_t version,
...)
{
return NULL;
}
MOZ_EXPORT struct wl_proxy *
wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
uint32_t opcode, union wl_argument *args,
const struct wl_interface *interface)
{
return NULL;
}
MOZ_EXPORT struct wl_proxy *
wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
uint32_t opcode,
union wl_argument *args,
const struct wl_interface *interface,
uint32_t version)
{
return NULL;
}
MOZ_EXPORT void
wl_proxy_destroy(struct wl_proxy *proxy)
{
}
MOZ_EXPORT int
wl_proxy_add_listener(struct wl_proxy *proxy,
void (**implementation)(void), void *data)
{
return -1;
}
MOZ_EXPORT const void *
wl_proxy_get_listener(struct wl_proxy *proxy)
{
return NULL;
}
MOZ_EXPORT int
wl_proxy_add_dispatcher(struct wl_proxy *proxy,
wl_dispatcher_func_t dispatcher_func,
const void * dispatcher_data, void *data)
{
return -1;
}
MOZ_EXPORT void
wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
{
}
MOZ_EXPORT void *
wl_proxy_get_user_data(struct wl_proxy *proxy)
{
return NULL;
}
MOZ_EXPORT uint32_t
wl_proxy_get_version(struct wl_proxy *proxy)
{
return -1;
}
MOZ_EXPORT uint32_t
wl_proxy_get_id(struct wl_proxy *proxy)
{
return -1;
}
MOZ_EXPORT const char *
wl_proxy_get_class(struct wl_proxy *proxy)
{
return NULL;
}
MOZ_EXPORT void
wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
{
}
MOZ_EXPORT struct wl_display *
wl_display_connect(const char *name)
{
return NULL;
}
MOZ_EXPORT struct wl_display *
wl_display_connect_to_fd(int fd)
{
return NULL;
}
MOZ_EXPORT void
wl_display_disconnect(struct wl_display *display)
{
}
MOZ_EXPORT int
wl_display_get_fd(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT int
wl_display_dispatch(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT int
wl_display_dispatch_queue(struct wl_display *display,
struct wl_event_queue *queue)
{
return -1;
}
MOZ_EXPORT int
wl_display_dispatch_queue_pending(struct wl_display *display,
struct wl_event_queue *queue)
{
return -1;
}
MOZ_EXPORT int
wl_display_dispatch_pending(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT int
wl_display_get_error(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT uint32_t
wl_display_get_protocol_error(struct wl_display *display,
const struct wl_interface **interface,
uint32_t *id)
{
return -1;
}
MOZ_EXPORT int
wl_display_flush(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT int
wl_display_roundtrip_queue(struct wl_display *display,
struct wl_event_queue *queue)
{
return -1;
}
MOZ_EXPORT int
wl_display_roundtrip(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT struct wl_event_queue *
wl_display_create_queue(struct wl_display *display)
{
return NULL;
}
MOZ_EXPORT int
wl_display_prepare_read_queue(struct wl_display *display,
struct wl_event_queue *queue)
{
return -1;
}
MOZ_EXPORT int
wl_display_prepare_read(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT void
wl_display_cancel_read(struct wl_display *display)
{
}
MOZ_EXPORT int
wl_display_read_events(struct wl_display *display)
{
return -1;
}
MOZ_EXPORT void
wl_log_set_handler_client(wl_log_func_t handler)
{
}

View File

@ -29,6 +29,7 @@
#include <gdk/gdkprivate.h>
#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include "gfxContext.h"
#include "gfxPlatformGtk.h"
@ -51,6 +52,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeGTK, nsNativeTheme, nsITheme,
nsIObserver)
@ -1133,7 +1135,11 @@ nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext,
gdk_rect, transparency);
if (!safeState) {
gdk_flush();
// gdk_flush() call from expose event crashes Gtk+ on Wayland
// (Gnome BZ #773307)
if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
gdk_flush();
}
gLastGdkError = gdk_error_trap_pop ();
if (gLastGdkError) {

View File

@ -4986,7 +4986,7 @@ nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen)
LOG(("nsWindow::MakeFullScreen [%p] aFullScreen %d\n",
(void *)this, aFullScreen));
if (!IsFullscreenSupported(mShell)) {
if (mIsX11Display && !IsFullscreenSupported(mShell)) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -6912,22 +6912,10 @@ nsWindow::RoundsWidgetCoordinatesTo()
void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
{
#ifdef MOZ_X11
#ifdef MOZ_WAYLAND
if (!mIsX11Display) {
*aInitData = mozilla::widget::GtkCompositorWidgetInitData(
(uintptr_t)nullptr,
nsCString(nullptr),
GetClientSize());
} else
#endif
{
*aInitData = mozilla::widget::GtkCompositorWidgetInitData(
mXWindow,
nsCString(XDisplayString(mXDisplay)),
GetClientSize());
}
#endif
*aInitData = mozilla::widget::GtkCompositorWidgetInitData(
(mXWindow != X11None) ? mXWindow : (uintptr_t)nullptr,
mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(),
GetClientSize());
}
bool
@ -6948,9 +6936,14 @@ nsWindow::IsComposited() const
wl_display*
nsWindow::GetWaylandDisplay()
{
// Available as of GTK 3.8+
static auto sGdkWaylandDisplayGetWlDisplay =
(wl_display *(*)(GdkDisplay *))
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
GdkDisplay* gdkDisplay = gdk_display_get_default();
return mIsX11Display ? nullptr :
gdk_wayland_display_get_wl_display(gdkDisplay);
sGdkWaylandDisplayGetWlDisplay(gdkDisplay);
}
wl_surface*

View File

@ -89,7 +89,7 @@ DBusRemoteClient::DoSendDBusCommandLine(const char *aProgram, const char *aProfi
// D-Bus names can contain only [a-z][A-Z][0-9]_
// characters so adjust the profile string properly.
nsAutoCString profileName;
nsresult rv = mozilla::Base64Encode(nsAutoCString(aProfileName), profileName);
nsresult rv = mozilla::Base64Encode(nsAutoCString(aProfile), profileName);
NS_ENSURE_SUCCESS(rv, rv);
profileName.ReplaceChar("+/=", '_');