Bug 1639180 - Port docs to Sphinx and reST and stop copying to GitHub. r=geckoview-reviewers,snorp

Differential Revision: https://phabricator.services.mozilla.com/D75935
This commit is contained in:
Emily Toop 2020-05-19 14:51:17 +00:00
Родитель b9ffa0fb6a
Коммит 3a5a675f9f
31 изменённых файлов: 2198 добавлений и 1863 удалений

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

@ -1,10 +0,0 @@
source "https://rubygems.org"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "just-the-docs"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
gem "github-pages", group: :jekyll_plugins

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

@ -1,18 +0,0 @@
title: GeckoView
email: etoop@mozilla.com
description:
The privacy focused WebView you've been looking for.
baseurl: "/geckoview" # the subpath of your site, e.g. /blog
url: "https://mozilla.github.io" # the base hostname & protocol for your site, e.g. http://example.com
twitter_username: geckoview
github_username: mozilla
tags: [GeckoView,Gecko,mozilla,android,WebView,web,browser,toolkit,open source,privacy,online,security,mobile]
# Build settings
markdown: kramdown
remote_theme: pmarsceill/just-the-docs@aa0d8f1d400b051c090b04b3e530c2848afb585c
plugins:
- jekyll-feed
- jekyll-seo-tag
search_enabled: true

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

@ -1,32 +0,0 @@
<head>
<!-- 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/. -->
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
{% if page.title %}
<meta name="title" content="{{ page.title }} - {{ site.title }}">
{% endif %}
{% if page.description %}
<meta name="description" content="{{ page.description }}">
{% elsif page.summary %}
<meta name="description" content="{{ page.summary }}">
{% else %}
<meta name="description" content="{{ site.description }}">
{% endif %}
{% if page.tags %}
<meta name="keywords" content="{{ page.tags | join: "," }}">
{% else %}
<meta name="keywords" content="{{ site.tags | join: "," }}">
{% endif %}
<title>{{ page.title }} - {{ site.title }}</title>
<link rel="stylesheet" href="{{ "/assets/css/just-the-docs.css" | absolute_url }}">
<link rel="stylesheet" href="{{ "/assets/css/geckoview.css" | absolute_url }}">
{% if site.search_enabled != nil %}
<script type="text/javascript" src="{{ "/assets/js/vendor/lunr.min.js" | absolute_url }}"></script>
{% endif %}
<script type="text/javascript" src="{{ "/assets/js/just-the-docs.js" | absolute_url }}"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>

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

@ -1,9 +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/. -->
<li class="navigation-list-item{% if page.url contains '/javadoc/mozilla-central/index.html' %} active{% endif %}">
<a href="{{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/index.html" class="navigation-list-link{% if page.url contains '/javadoc/mozilla-central/index.html' %} active{% endif %}">API Documentation</a>
</li>
<li class="navigation-list-item{% if page.url contains 'CHANGELOG' %} active{% endif %}">
<a href="{{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/doc-files/CHANGELOG" class="navigation-list-link{% if page.url contains 'CHANGELOG' %} active{% endif %}">API Changelog</a>
</li>

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

@ -1,49 +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/. -->
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
{% assign pages_list = site.html_pages | sort:"nav_order" %}
{% for node in pages_list %}
<!-- <div>{{node.title}} = {{node.nav_exclude}}</div> -->
{% unless node.nav_exclude %}
{% if node.parent == nil %}
<li class="navigation-list-item{% if page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
{% if page.parent == node.title or page.grand_parent == node.title %}
{% assign first_level_url = node.url | absolute_url %}
{% endif %}
<a href="{{ node.url | absolute_url }}" class="navigation-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
{% if node.has_children %}
{% assign children_list = site.html_pages | sort:"nav_order" %}
<ul class="navigation-list-child-list ">
{% for child in children_list %}
{% if child.parent == node.title %}
<li class="navigation-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
{% if page.url == child.url or page.parent == child.title %}
{% assign second_level_url = child.url | absolute_url %}
{% endif %}
<a href="{{ child.url | absolute_url }}" class="navigation-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
{% if child.has_children %}
{% assign grand_children_list = site.html_pages | sort:"nav_order" %}
<ul class="navigation-list-child-list">
{% for grand_child in grand_children_list %}
{% if grand_child.parent == child.title %}
<li class="navigation-list-item {% if page.url == grand_child.url %} active{% endif %}">
<a href="{{ grand_child.url | absolute_url }}" class="navigation-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
{% endunless %}
{% endfor %}
{% include javadoc.html %}
</ul>
</nav>

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

@ -1,83 +0,0 @@
<!DOCTYPE html>
<!-- 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/. -->
<html lang="en-us">
{% include head.html %}
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="{{ site.url }}{{ site.baseurl }}" class="site-title fs-6 lh-tight">
<img src="{{ site.url }}{{ site.baseurl }}/assets/geckoview_icon_fullcolor-green.png" title="GeckoView" alt="GeckoView" style="vertical-align:middle; width:60px; height:60px">
<span>GeckoView</span>
</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
{% include nav.html %}
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap">
<div class="page-header">
<div class="main-content">
{% if site.search_enabled != nil %}
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search {{ site.title }}" aria-label="Search {{ site.title }}" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
{% endif %}
{% if site.aux_links != nil %}
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
{% for link in site.aux_links %}
<li class="d-inline-block my-0{% unless forloop.last %} mr-2{% endunless %}"><a href="{{ link.last }}">{{ link.first }}</a></li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
<div class="main-content js-main-content" tabindex="0">
{% unless page.url == "/" %}
{% if page.parent %}
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
{% if page.grand_parent %}
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a></li>
<li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li>
{% else %}
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li>
{% endif %}
<li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li>
</ol>
</nav>
{% endif %}
{% endunless %}
<div id="main-content" class="page-content" role="main">
{{ content }}
{% if page.has_children == true and page.has_toc != false %}
<hr>
<h2 class="text-delta">Table of contents</h2>
{% assign children_list = site.pages | sort:"nav_order" %}
<ul>
{% for child in children_list %}
{% if child.parent == page.title and child.title != page.title %}
<li>
<a href="{{ child.url | absolute_url }}">{{ child.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</div>
</div>
</div>
</div>
</body>
</html>

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

@ -1,10 +0,0 @@
$sidebar-color: #ededf0;
$body-text-color: #4a4a4f;
$body-heading-color: #2a2a2e;
$nav-child-link-color: #2a2a2e;
$link-color: #0060df;
$btn-primary-color: #003eaa;
$code-background-color: #ededf0;

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

@ -0,0 +1,121 @@
.. -*- Mode: rst; fill-column: 80; -*-
Configuring GeckoView for Automation
####################################
How to set environment variables, Gecko arguments, and Gecko preferences for automation and debugging.
.. contents:: :local:
Configuring GeckoView
=====================================
GeckoView and the underlying Gecko engine have many, many options, switches, and toggles "under the hood". Automation (and to a lesser extent, debugging) can require configuring the Gecko engine to allow (or disallow) specific actions or features.
Some such actions and features are controlled by the `GeckoRuntimeSettings <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.html>`_ instance you configure in your consuming project. For example, remote debugging web content via the Firefox Developer Tools is configured by `GeckoRuntimeSettings.Builder#remoteDebuggingEnabled <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#remoteDebuggingEnabled-boolean-)>`_
Not all actions and features have GeckoView API interfaces. Generally, actions and features that do not have GeckoView API interfaces are not intended for broad usage. Configuration for these types of things is controlled by:
- environment variables in GeckoView's runtime environment
- command line arguments to the Gecko process
- internal Gecko preferences
Automation-specific configuration is generally in this category.
Running GeckoView with environment variables
------------------------------------------------
After a successful ``./mach build``, ``./mach run --setenv`` can be used to run GeckoView with
the given environment variables.
For example, to wait for attaching a debugger when starting a content tab process, use
``./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab`` and then attach to that
process within Android Studio.
Reading configuration from a file
------------------------------------------------
When GeckoView is embedded into a debugabble application (i.e., when your manifest includes ``android:debuggable="true"``), by default GeckoView reads configuration from a file named ``/data/local/tmp/$PACKAGE-geckoview-config.yaml``. For example, if your Android package name is ``com.yourcompany.yourapp``, GeckoView will read configuration from::
/data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
Configuration file format
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The configuration file format is `YAML <https://yaml.org>`_. The following keys are recognized:
- ``env`` is a map from string environment variable name to string value to set in GeckoView's runtime environment
- ``args`` is a list of string command line arguments to pass to the Gecko process
- ``prefs`` is a map from string Gecko preference name to boolean, string, or integer value to set in the Gecko profile
.. code-block:: yaml
# Contents of /data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
env:
MOZ_LOG: nsHttp:5
args:
- --marionette
- --profile
- "/path/to/gecko-profile"
prefs:
foo.bar.boolean: true
foo.bar.string: "string"
foo.bar.int: 500
Verifying configuration from a file
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When configuration from a file is read, GeckoView logs to ``adb logcat``, like: ::
GeckoRuntime I Adding debug configuration from: /data/local/tmp/org.mozilla.geckoview_example-geckoview-config.yaml
GeckoDebugConfig D Adding environment variables from debug config: {MOZ_LOG=nsHttp:5}
GeckoDebugConfig D Adding arguments from debug config: [--marionette]
GeckoDebugConfig D Adding prefs from debug config: {foo.bar.baz=true}
When a configuration file is found but cannot be parsed, an error is logged and the file is ignored entirely. When a configuration file is not found, nothing is logged.
Controlling configuration from a file
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, GeckoView provides a secure web rendering engine. Custom configuration can compromise security in many ways: by storing sensitive data in insecure locations on the device, by trusting websites with incorrect security configurations, by not validating HTTP Public Key Pinning configurations; the list goes on.
**You should only allow such configuration if your end-user opts-in to the configuration!**
GeckoView will always read configuration from a file if the consuming Android package is set as the current Android "debug app" (see ``set-debug-app`` and ``clear-debug-app`` in the `adb documentation <https://developer.android.com/studio/command-line/adb>`_). An Android package can be set as the "debug app" without regard to the ``android:debuggable`` flag. There can only be one "debug app" set at a time. To disable the "debug app" check, `disable reading configuration from a file entirely <#disabling-reading-configuration-from-a-file-entirely>`_. Setting an Android package as the "debug app" requires privileged shell access to the device (generally via ``adb shell am ...``, which is only possible on devices which have ADB debugging enabled) and therefore it is safe to act on the "debug app" flag.
To enable reading configuration from a file: ::
adb shell am set-debug-app --persistent com.yourcompany.yourapp
To disable reading configuration from a file: ::
adb shell am clear-debug-app
Enabling reading configuration from a file unconditionally
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some applications (for example, web browsers) may want to allow configuration for automation unconditionally, i.e., even when the application is not debuggable, like release builds that have ``android:debuggable="false"``. In such cases, you can use `GeckoRuntimeSettings.Builder#configFilePath <javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-)>`_ to force GeckoView to read configuration from the given file path, like:
.. code-block:: java
new GeckoRuntimeSettings.Builder()
.configFilePath("/your/app/specific/location")
.build();
Disabling reading configuration from a file entirely
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To force GeckoView to never read configuration from a file, even when the embedding application is debuggable, invoke `GeckoRuntimeSettings.Builder#configFilePath <javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-)>`_ with an empty path, like:
.. code-block:: java
new GeckoRuntimeSettings.Builder()
.configFilePath("")
.build();
The empty path is recognized and no file I/O is performed.

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

@ -1,121 +0,0 @@
---
layout: default
title: Configuring GeckoView for Automation
summary: How to set environment variables, Gecko arguments, and Gecko preferences for automation and debugging.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,debugging,automation,config,configuration,environment,variables,arguments,preferences]
nav_exclude: true
exclude: true
---
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
# Configuring GeckoView
GeckoView and the underlying Gecko engine have many, many options, switches, and toggles "under the hood". Automation (and to a lesser extent, debugging) can require configuring the Gecko engine to allow (or disallow) specific actions or features.
Some such actions and features are controlled by the [`GeckoRuntimeSettings`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.html) instance you configure in your consuming project. For example, remote debugging web content via the Firefox Developer Tools is configured by [`GeckoRuntimeSettings.Builder#remoteDebuggingEnabled`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#remoteDebuggingEnabled-boolean-)
Not all actions and features have GeckoView API interfaces. Generally, actions and features that do not have GeckoView API interfaces are not intended for broad usage. Configuration for these types of things is controlled by:
- environment variables in GeckoView's runtime environment
- command line arguments to the Gecko process
- internal Gecko preferences
Automation-specific configuration is generally in this category.
## Running GeckoView with environment variables
After a successful `./mach build`, `./mach run --setenv` can be used to run GeckoView with
the given environment variables.
For example, to wait for attaching a debugger when starting a content tab process, use
`./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab` and then attach to that
process within Android Studio.
## Reading configuration from a file
When GeckoView is embedded into a debugabble application (i.e., when your manifest includes `android:debuggable="true"`), by default GeckoView reads configuration from a file named `/data/local/tmp/$PACKAGE-geckoview-config.yaml`. For example, if your Android package name is `com.yourcompany.yourapp`, GeckoView will read configuration from
```
/data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
```
### Configuration file format
The configuration file format is [YAML](https://yaml.org). The following keys are recognized:
- `env` is a map from string environment variable name to string value to set in GeckoView's runtime environment
- `args` is a list of string command line arguments to pass to the Gecko process
- `prefs` is a map from string Gecko preference name to boolean, string, or integer value to set in the Gecko profile
```yaml
# Contents of /data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
env:
MOZ_LOG: nsHttp:5
args:
- --marionette
- --profile
- "/path/to/gecko-profile"
prefs:
foo.bar.boolean: true
foo.bar.string: "string"
foo.bar.int: 500
```
### Verifying configuration from a file
When configuration from a file is read, GeckoView logs to `adb logcat`, like:
```
GeckoRuntime I Adding debug configuration from: /data/local/tmp/org.mozilla.geckoview_example-geckoview-config.yaml
GeckoDebugConfig D Adding environment variables from debug config: {MOZ_LOG=nsHttp:5}
GeckoDebugConfig D Adding arguments from debug config: [--marionette]
GeckoDebugConfig D Adding prefs from debug config: {foo.bar.baz=true}
```
When a configuration file is found but cannot be parsed, an error is logged and the file is ignored entirely. When a configuration file is not found, nothing is logged.
### Controlling configuration from a file
By default, GeckoView provides a secure web rendering engine. Custom configuration can compromise security in many ways: by storing sensitive data in insecure locations on the device, by trusting websites with incorrect security configurations, by not validating HTTP Public Key Pinning configurations; the list goes on.
**You should only allow such configuration if your end-user opts-in to the configuration!**
GeckoView will always read configuration from a file if the consuming Android package is set as the current Android "debug app" (see `set-debug-app` and `clear-debug-app` in the [adb documentation](https://developer.android.com/studio/command-line/adb)). An Android package can be set as the "debug app" without regard to the `android:debuggable` flag. There can only be one "debug app" set at a time. To disable the "debug app" check, [disable reading configuration from a file entirely](#disabling-reading-configuration-from-a-file-entirely). Setting an Android package as the "debug app" requires privileged shell access to the device (generally via `adb shell am ...`, which is only possible on devices which have ADB debugging enabled) and therefore it is safe to act on the "debug app" flag.
To enable reading configuration from a file:
```
adb shell am set-debug-app --persistent com.yourcompany.yourapp
```
To disable reading configuration from a file:
```
adb shell am clear-debug-app
```
#### Enabling reading configuration from a file unconditionally
Some applications (for example, web browsers) may want to allow configuration for automation unconditionally, i.e., even when the application is not debuggable, like release builds that have `android:debuggable="false"`. In such cases, you can use [`GeckoRuntimeSettings.Builder#configFilePath`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-) to force GeckoView to read configuration from the given file path, like:
```java
new GeckoRuntimeSettings.Builder()
.configFilePath("/your/app/specific/location")
.build();
```
#### Disabling reading configuration from a file entirely
To force GeckoView to never read configuration from a file, even when the embedding application is debuggable, invoke [`GeckoRuntimeSettings.Builder#configFilePath`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-)` with an empty path, like:
```java
new GeckoRuntimeSettings.Builder()
.configFilePath("")
.build();
```
The empty path is recognized and no file I/O is performed.

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

@ -1,100 +0,0 @@
---
layout: default
title: Getting Started with GeckoView
nav_order: 2
summary: How to use GeckoView in your Android app.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,quick start]
---
_Building a browser? Check out [Android Components](https://mozilla-mobile.github.io/android-components/), our collection of ready-to-use support libraries!_
The following article is a brief guide to embedding GeckoView in an app. For a more in depth tutorial on getting started with GeckoView please read the article we have published on [raywenderlich.com](https://www.raywenderlich.com/1381698-android-tutorial-for-geckoview-getting-started).
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
## Configure Gradle
You need to add or edit four stanzas inside your module's `build.gradle` file.
**1. Set the GeckoView version**
_Like Firefox, GeckoView has three release channels: Stable, Beta, and Nightly. Browse the [Maven Repository](https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/) to see currently available builds._
```groovy
ext {
geckoviewChannel = "nightly"
geckoviewVersion = "70.0.20190712095934"
}
```
**2. Add Mozilla's Maven repository**
```groovy
repositories {
maven {
url "https://maven.mozilla.org/maven2/"
}
}
```
**3. Java 8 required support**
As GeckoView uses some Java 8 APIs, it requires these compatibility flags:
```groovy
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
```
**4. Add GeckoView Implementations**
```groovy
dependencies {
// ...
implementation "org.mozilla.geckoview:geckoview-${geckoviewChannel}:${geckoviewVersion}"
}
```
## Add GeckoView to a Layout
Inside a layout `.xml` file, add the following:
```xml
<org.mozilla.geckoview.GeckoView
android:id="@+id/geckoview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
```
## Initialize GeckoView in an Activity
**1. Import the GeckoView classes inside an Activity:**
```java
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.GeckoView;
```
**2. In that activity's <code>onCreate</code> function, add the following:**
```java
GeckoView view = findViewById(R.id.geckoview);
GeckoSession session = new GeckoSession();
GeckoRuntime runtime = GeckoRuntime.create(this);
session.open(runtime);
view.setSession(session);
session.loadUri("about:buildconfig"); // Or any other URL...
```
## You're done!
Your application should now load and display a webpage inside of GeckoView.
To learn more about GeckoView's capabilities, review GeckoView's [JavaDoc](https://mozilla.github.io/geckoview/javadoc/mozilla-central/) or the [reference application](https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example).

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

@ -1,20 +0,0 @@
---
layout: default
title: Using GeckoView
nav_order: 3
---
# Usage Documentation
We are working on providing detailed usage documentation for all of GeckoView's most popular features. Here is what we have so far.
- [GeckoView Quick Start Guide](geckoview-quick-start):
Get GeckoView up and running inside your application.
- [Interacting with Web Content](web-extensions):
Writing Web Extensions, running content scripts and interacting with Javascript running in a web page.
- [Working with Site Permissions](permissions):
Handling and responding to requests from websites for permissions, such as geolocation, storage, media etc.
- [Configuring GeckoView for Automation](automation):
Get GeckoView set up on your automation system.
If there is documentation that you feel is missing, or an existing document doesn't cover the aspect that you are looking for, please request it by raising an issue on our [documentation site](https://github.com/mozilla/geckoview/issues).

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

@ -1,289 +0,0 @@
---
layout: default
title: Working with Site Permissions
summary: How to receive and respond to permission requests from websites.
nav_exclude: true
exclude: true
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,permissions,site,media,grant,notifications,storage,persistent storage,app]
---
# Working with Site Permissions
When a website wants to access certain services on a user's device, it will send out a permissions request. This document will explain how to use GeckoView to receive those requests, and respond to them by granting or denying those permissions.
## The Permission Delegate
The way an app interacts with site permissions in GeckoView is through the [`PermissionDelegate`][1]. There are three broad categories of permission that the `PermissionDelegate` handles, Android Permissions, Content Permissions and Media Permissions. All site permissions handled by GeckoView fall into one of these three categories.
To get notified about permission requests, you need to implement the `PermissionDelegate` interface:
```java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
@Override
public void onAndroidPermissionsRequest(final GeckoSession session,
final String[] permissions,
final Callback callback) { }
@Override
public void onContentPermissionRequest(final GeckoSession session,
final String uri,
final int type, final Callback callback) { }
@Override
public void onMediaPermissionRequest(final GeckoSession session,
final String uri,
final MediaSource[] video,
final MediaSource[] audio,
final MediaCallback callback) { }
}
```
You will then need to register the delegate with your [`GeckoSession`][3] instance.
```java
public class GeckoViewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
final ExamplePermissionDelegate permission = new ExamplePermissionDelegate();
session.setPermissionDelegate(permission);
...
}
}
```
### Android Permissions
Android permissions are requested whenever a site wants access to a device's navigation or input capabilities.
The user will often need to grant these Android permissions to the app alongside granting the Content or Media site permissions.
When you receive an [`onAndroidPermissionsRequest`][2] call, you will also receive the `GeckoSession` the request was sent from, an array containing the permissions that are being requested, and a [`Callback`][4] to respond to the request. It is then up to the app to request those permissions from the device, which can be done using [`requestPermissions`][5].
Possible `permissions` values are; [`ACCESS_COARSE_LOCATION`][6], [`ACCESS_FINE_LOCATION`][7], [`CAMERA`][8] or [`RECORD_AUDIO`][9].
```java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
private Callback mCallback;
public void onRequestPermissionsResult(final String[] permissions,
final int[] grantResults) {
if (mCallback == null) { return; }
final Callback cb = mCallback;
mCallback = null;
for (final int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
// At least one permission was not granted.
cb.reject();
return;
}
}
cb.grant();
}
@Override
public void onAndroidPermissionsRequest(final GeckoSession session,
final String[] permissions,
final Callback callback) {
mCallback = callback;
requestPermissions(permissions, androidPermissionRequestCode);
}
}
public class GeckoViewActivity extends AppCompatActivity {
@Override
public void onRequestPermissionsResult(final int requestCode,
final String[] permissions,
final int[] grantResults) {
if (requestCode == REQUEST_PERMISSIONS ||
requestCode == REQUEST_WRITE_EXTERNAL_STORAGE) {
final ExamplePermissionDelegate permission = (ExamplePermissionDelegate)
getCurrentSession().getPermissionDelegate();
permission.onRequestPermissionsResult(permissions, grantResults);
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
```
### Content Permissions
Content permissions are requested whenever a site wants access to content that is stored on the device. The content permissions that can be requested through GeckoView are; [`Geolocation`][10], [`Site Notifications`][11] [`Persistent Storage`][12] and [`XR`][13] access.
When you receive an [`onContentPermissionRequest`][14] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the type of the content permission requested (geolocation, site notification or persistent storage), and a [`Callback`][4] to respond to the request. It is then up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `Callback`.
*Please note, in the case of `PERMISSION_DESKTOP_NOTIFICATION` and `PERMISSION_PERSISTENT_STORAGE`, GeckoView does not track accepted permissions and prevent further requests being sent for a particular site. It is therefore up to the calling app to do this if that is the desired behaviour. The code below demonstrates how to track storage permissions by site and track notification permission rejection for the whole app*
```java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
private boolean showNotificationsRejected;
private ArrayList<String> acceptedPersistentStorage = new ArrayList<String>();
@Override
public void onContentPermissionRequest(final GeckoSession session,
final String uri,
final int type,
final Callback callback) {
final int resId;
Callback contentPermissionCallback = callback;
if (PERMISSION_GEOLOCATION == type) {
resId = R.string.request_geolocation;
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
if (showNotificationsRejected) {
callback.reject();
return;
}
resId = R.string.request_notification;
} else if (PERMISSION_PERSISTENT_STORAGE == type) {
if (acceptedPersistentStorage.contains(uri)) {
callback.grant();
return;
}
resId = R.string.request_storage;
} else if (PERMISSION_XR == type) {
resId = R.string.request_xr;
} else { // unknown permission type
callback.reject();
return;
}
final String title = getString(resId, Uri.parse(uri).getAuthority());
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
if (PERMISSION_DESKTOP_NOTIFICATION == type) {
showNotificationsRejected = false;
}
callback.reject();
}
})
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
if (PERMISSION_PERSISTENT_STORAGE == type) {
acceptedPersistentStorage.add(mUri);
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
showNotificationsRejected = true;
}
callback.grant();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
}
```
### Media Permissions
Media permissions are requested whenever a site wants access to play or record media from the device's camera and microphone.
When you receive an [`onMediaPermissionRequest`][15] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the list of video devices available, if requesting video, the list of audio devices available, if requesting audio, and a [`MediaCallback`][17] to respond to the request.
It is up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `MediaCallback`.
*Please note, media permissions will still be requested if the associated device permissions have been denied if there are video or audio sources in that category that can still be accessed when listed. It is the responsibility of consumers to ensure that media permission requests are not displayed in this case.*
```java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
@Override
public void onMediaPermissionRequest(final GeckoSession session,
final String uri,
final MediaSource[] video,
final MediaSource[] audio,
final MediaCallback callback) {
// Reject permission if Android permission has been previously denied.
if ((audio != null
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
|| (video != null
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
callback.reject();
return;
}
final String host = Uri.parse(uri).getAuthority();
final String title;
if (audio == null) {
title = getString(R.string.request_video, host);
} else if (video == null) {
title = getString(R.string.request_audio, host);
} else {
title = getString(R.string.request_media, host);
}
// Get the media device name from the `MediaDevice`
String[] videoNames = normalizeMediaName(video);
String[] audioNames = normalizeMediaName(audio);
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// Create drop down boxes to allow users to select which device to grant permission to
final LinearLayout container = addStandardLayout(builder, title, null);
final Spinner videoSpinner;
if (video != null) {
videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames); // create spinner and add to alert UI
} else {
videoSpinner = null;
}
final Spinner audioSpinner;
if (audio != null) {
audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames); // create spinner and add to alert UI
} else {
audioSpinner = null;
}
builder.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
// gather selected media devices and grant access
final MediaSource video = (videoSpinner != null)
? (MediaSource) videoSpinner.getSelectedItem() : null;
final MediaSource audio = (audioSpinner != null)
? (MediaSource) audioSpinner.getSelectedItem() : null;
callback.grant(video, audio);
}
});
final AlertDialog dialog = builder.create();
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(final DialogInterface dialog) {
callback.reject();
}
});
dialog.show();
}
}
```
To see the `PermissionsDelegate` in action, you can find the full example implementation in the [GeckoView example app][16].
[1]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html
[2]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onAndroidPermissionsRequest-org.mozilla.geckoview.GeckoSession-java.lang.String:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback-
[3]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html
[4]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html
[5]: https://developer.android.com/reference/android/app/Activity#requestPermissions(java.lang.String%5B%5D,%2520int)
[6]: https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION
[7]: https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_FINE_LOCATION
[8]: https://developer.android.com/reference/android/Manifest.permission.html#CAMERA
[9]: https://developer.android.com/reference/android/Manifest.permission.html#RECORD_AUDIO
[10]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_GEOLOCATION
[11]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_DESKTOP_NOTIFICATION
[12]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_STORAGE
[13]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_XR
[14]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-int-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback-
[15]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback-
[16]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html
[17]: https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686

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

@ -1,391 +0,0 @@
---
layout: default
title: Interacting with Web content
summary: How to interact with Web content and register WebExtensions in GeckoView.
nav_exclude: true
exclude: true
---
# Interacting with Web content and WebExtensions
GeckoView allows embedder applications to register and run [WebExtensions][8]
in a GeckoView instance. Extensions are the preferred way to interact with
Web content.
## Running extensions in GeckoView
Extensions bundled with applications can be provided in a folder in the
`/assets` section of the APK. Like ordinary extensions, every extension bundled
with GeckoView requires a [`manifest.json`][23] file.
To locate files bundled with the APK, GeckoView provides a shorthand
`resource://android/` that points to the root of the APK.
E.g. `resource://android/assets/messaging/` will point to the
`/assets/messaging/` folder present in the APK.
Note: Every installed extension will need an [`id`][25] and [`version`][26]
specified in the `manifest.json` file.
To install a bundled extension in GeckoView, simply call
[`WebExtensionController.installBuilt`][3].
```java
runtime.getWebExtensionController()
.installBuiltIn("resource://android/assets/messaging/")
```
Note that the lifetime of the extension is not tied with the lifetime of the
[`GeckoRuntime`][24] instance. The extension persist even when your app is
restarted. Installing at every start up is fine, but it could be slow. To avoid
installing multiple times you can query the list of installed extensions using
`WebExtensionRuntime.list`:
```java
runtime.getWebExtensionController().list().then(extensionList -> {
for (WebExtension extension : extensionList) {
if (extension.id.equals("messaging@example.com")
&& extension.metaData.version.equals("1.0")) {
// Extension already installed, no need to install it again
return GeckoResult.fromValue(extension);
}
}
// Install if it's not already installed.
return runtime.getWebExtensionController()
.installBuiltIn("resource://android/assets/messaging/");
}).accept(
extension -> Log.i("MessageDelegate", "Extension installed: " + extension),
e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
);
```
## Communicating with Web Content
GeckoView allows bidirectional communication with Web pages through
extensions.
When using GeckoView, [native messaging][11] can be used for communicating to
and from the browser.
* [`runtime.sendNativeMessage`][12] for one-off messages.
* [`runtime.connectNative`][13] for connection-based messaging.
Note: these APIs are only available when the `geckoViewAddons` [permission][17]
is present in the `manifest.json` file of the extension.
### One-off messages
The easiest way to send messages from a [content script][9] or a [background
script][10] is using [`runtime.sendNativeMessage`][12].
Note: Ordinarily, native extensions would use a [native manifest][27] to define
what native app identifier to use. For GeckoView this is _not_ needed, the
`nativeApp` parameter in `setMessageDelegate` will be use to determine what
native app string is used.
### Messaging Example
To receive messages from the background script, call [`setMessageDelegate`][14]
on the [`WebExtension`][3] object.
```java
extension.setMessageDelegate(messageDelegate, "browser");
```
[`SessionController.setMessageDelegate`][16] allows the app to
receive messages from content scripts.
```java
session.getWebExtensionController()
.setMessageDelegate(extension, messageDelegate, "browser");
```
Note: the `"browser"` parameter in the code above determines what native app id
the extension can use to send native messages.
Note: extension can only send messages from content scripts if explicitly
authorized by the app by adding `nativeMessagingFromContent` in the
manifest.json file, e.g.
```json
"permissions": [
"nativeMessaging",
"nativeMessagingFromContent",
"geckoViewAddons"
]
```
### Example
Let's set up an activity that registers an extension located in the
`/assets/messaging/` folder of the APK. This activity will set up a
[`MessageDelegate`][18] that will be used to communicate with Web Content.
You can find the full example here: [MessagingExample][20].
##### Activity.java
```java
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
@Nullable
public GeckoResult<Object> onMessage(final @NonNull String nativeApp,
final @NonNull Object message,
final @NonNull WebExtension.MessageSender sender) {
// The sender object contains information about the session that
// originated this message and can be used to validate that the message
// has been sent from the expected location.
// Be careful when handling the type of message as it depends on what
// type of object was sent from the WebExtension script.
if (message instanceof JSONObject) {
// Do something with message
}
return null;
}
};
// Let's check if the extension is already installed first
runtime.getWebExtensionController().list().then(extensionList -> {
for (WebExtension extension : extensionList) {
if (extension.id.equals(EXTENSION_ID)
&& extension.metaData.version.equals(EXTENSION_VERSION)) {
// Extension already installed, no need to install it again
return GeckoResult.fromValue(extension);
}
}
// Install if it's not already installed.
return runtime.getWebExtensionController().installBuiltIn(EXTENSION_LOCATION);
}).accept(
// Set the delegate that will receive messages coming from this WebExtension.
extension -> session.getWebExtensionController()
.setMessageDelegate(extension, messageDelegate, "browser"),
// Something bad happened, let's log an error
e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
);
```
Now add the `geckoViewAddons`, `nativeMessaging` and
`nativeMessagingFromContent` permissions to your `manifest.json` file.
##### /assets/messaging/manifest.json
```json
{
"manifest_version": 2,
"name": "messaging",
"version": "1.0",
"description": "Example messaging web extension.",
"browser_specific_settings": {
"gecko": {
"id": "messaging@example.com"
}
},
"content_scripts": [
{
"matches": ["*://*.twitter.com/*"],
"js": ["messaging.js"]
}
],
"permissions": [
"nativeMessaging",
"nativeMessagingFromContent",
"geckoViewAddons"
]
}
```
And finally, write a content script that will send a message to the app when a
certain event occurs. For example, you could send a message whenever a [WPA
manifest][19] is found on the page. Note that our `nativeApp` identifier used
for `sendNativeMessage` is the same as the one used in the `setMessageDelegate`
call in [`Activity.java`](#activityjava).
##### /assets/messaging/messaging.js
```javascript
let manifest = document.querySelector("head > link[rel=manifest]");
if (manifest) {
fetch(manifest.href)
.then(response => response.json())
.then(json => {
let message = {type: "WPAManifest", manifest: json};
browser.runtime.sendNativeMessage("browser", message);
});
}
```
You can handle this message in the `onMessage` method in the `messageDelegate`
[above](#activityjava).
```java
@Nullable
public GeckoResult<Object> onMessage(final @NonNull String nativeApp,
final @NonNull Object message,
final @NonNull WebExtension.MessageSender sender) {
if (message instanceof JSONObject) {
JSONObject json = (JSONObject) message;
try {
if (json.has("type") && "WPAManifest".equals(json.getString("type"))) {
JSONObject manifest = json.getJSONObject("manifest");
Log.d("MessageDelegate", "Found WPA manifest: " + manifest);
}
} catch (JSONException ex) {
Log.e("MessageDelegate", "Invalid manifest", ex);
}
}
return null;
}
```
Note that, in the case of content scripts, `sender.session` will be a reference
to the `GeckoSession` instance from which the message originated. For
background scripts, `sender.session` will always be `null`.
Also note that the type of `message` will depend on what was sent from the
extension.
The type of `message` will be `JSONObject` when the extension sends a
javascript object, but could also be a primitive type if the extension sends
one, e.g. for
```javascript
runtime.browser.sendNativeMessage("browser", "Hello World!");
```
the type of `message` will be `java.util.String`.
## Connection-based messaging
For more complex scenarios or for when you want to send messages _from_ the app
to the extension, [`runtime.connectNative`][13] is the appropriate API to
use.
`connectNative` returns a [`runtime.Port`][6] that can be used to send messages
to the app. On the app side, implementing [`MessageDelegate#onConnect`][1] will
allow you to receive a [`Port`][7] object that can be used to receive and send
messages to the extension.
The following example can be found [here][21].
For this example, the extension side will do the following:
* open a port on the background script using `connectNative`
* listen on the port and log to console every message received
* send a message immediately after opening the port.
##### /assets/messaging/background.js
```javascript
// Establish connection with app
let port = browser.runtime.connectNative("browser");
port.onMessage.addListener(response => {
// Let's just echo the message back
port.postMessage(`Received: ${JSON.stringify(response)}`);
});
port.postMessage("Hello from WebExtension!");
```
On the app side, following the [above](#activityjava) example, `onConnect` will
be storing the `Port` object in a member variable and then using it when
needed.
```java
private WebExtension.Port mPort;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... initialize GeckoView
// This delegate will handle all communications from and to a specific Port
// object
WebExtension.PortDelegate portDelegate = new WebExtension.PortDelegate() {
public WebExtension.Port port = null;
public void onPortMessage(final @NonNull Object message,
final @NonNull WebExtension.Port port) {
// This method will be called every time a message is sent from the
// extension through this port. For now, let's just log a
// message.
Log.d("PortDelegate", "Received message from WebExtension: "
+ message);
}
public void onDisconnect(final @NonNull WebExtension.Port port) {
// After this method is called, this port is not usable anymore.
if (port == mPort) {
mPort = null;
}
}
};
// This delegate will handle requests to open a port coming from the
// extension
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
@Nullable
public void onConnect(final @NonNull WebExtension.Port port) {
// Let's store the Port object in a member variable so it can be
// used later to exchange messages with the WebExtension.
mPort = port;
// Registering the delegate will allow us to receive messages sent
// through this port.
mPort.setDelegate(portDelegate);
}
};
runtime.getWebExtensionController()
.installBuiltIn("resource://android/assets/messaging/")
.accept(
// Register message delegate for background script
extension -> extension.setMessageDelegate(messageDelegate, "browser"),
e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
);
// ... other
}
```
For example, let's send a message to the extension every time the user long
presses on a key on the virtual keyboard, e.g. on the back button.
```java
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (mPort == null) {
// No extension registered yet, let's ignore this message
return false;
}
JSONObject message = new JSONObject();
try {
message.put("keyCode", keyCode);
message.put("event", KeyEvent.keyCodeToString(event.getKeyCode()));
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
mPort.postMessage(message);
return true;
}
```
This allows bidirectional communication between the app and the extension.
[1]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html#onConnect-org.mozilla.geckoview.WebExtension.Port-
[3]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html
[6]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port
[7]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Port.html
[8]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions
[9]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts
[10]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts
[11]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#Exchanging_messages
[12]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage
[13]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative
[14]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String-
[15]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#WebExtension-java.lang.String-java.lang.String-long-
[16]: ../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String-
[17]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions
[18]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html
[19]: https://developer.mozilla.org/en-US/docs/Web/Manifest
[20]: https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/messaging_example/
[21]: https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/port_messaging_example/
[22]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Flags.html#ALLOW_CONTENT_MESSAGING
[23]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json
[24]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntime.html
[25]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings
[26]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/version
[27]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#App_manifest

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

@ -0,0 +1,101 @@
.. -*- Mode: rst; fill-column: 80; -*-
Getting Started with GeckoView
######################################
How to use GeckoView in your Android app.
*Building a browser? Check out* `Android Components <https://mozilla-mobile.github.io/android-components/>`_, *our collection of ready-to-use support libraries!*
The following article is a brief guide to embedding GeckoView in an app. For a more in depth tutorial on getting started with GeckoView please read the article we have published on `raywenderlich.com <https://www.raywenderlich.com/1381698-android-tutorial-for-geckoview-getting-started>`_.
.. contents:: :local:
Configure Gradle
=================
You need to add or edit four stanzas inside your module's ``build.gradle`` file.
**1. Set the GeckoView version**
*Like Firefox, GeckoView has three release channels: Stable, Beta, and Nightly. Browse the* `Maven Repository <https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/>`_ *to see currently available builds.*
.. code-block:: groovy
ext {
geckoviewChannel = "nightly"
geckoviewVersion = "70.0.20190712095934"
}
**2. Add Mozilla's Maven repository**
.. code-block:: groovy
repositories {
maven {
url "https://maven.mozilla.org/maven2/"
}
}
**3. Java 8 required support**
As GeckoView uses some Java 8 APIs, it requires these compatibility flags:
.. code-block:: groovy
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
**4. Add GeckoView Implementations**
.. code-block:: groovy
dependencies {
// ...
implementation "org.mozilla.geckoview:geckoview-${geckoviewChannel}:${geckoviewVersion}"
}
Add GeckoView to a Layout
==========================
Inside a layout ``.xml`` file, add the following:
.. code-block:: xml
<org.mozilla.geckoview.GeckoView
android:id="@+id/geckoview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
Initialize GeckoView in an Activity
====================================
**1. Import the GeckoView classes inside an Activity:**
.. code-block:: java
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoSession;
import org.mozilla.geckoview.GeckoView;
**2. In that activity's** ``onCreate`` **function, add the following:**
.. code-block:: java
GeckoView view = findViewById(R.id.geckoview);
GeckoSession session = new GeckoSession();
GeckoRuntime runtime = GeckoRuntime.create(this);
session.open(runtime);
view.setSession(session);
session.loadUri("about:buildconfig"); // Or any other URL...
You're done!
==============
Your application should now load and display a webpage inside of GeckoView.
To learn more about GeckoView's capabilities, review GeckoView's `JavaDoc <javadoc/mozilla-central/>`_ or the `reference application <https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example>`_.

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

@ -0,0 +1,35 @@
.. -*- Mode: rst; fill-column: 80; -*-
===============
Using GeckoView
===============
Usage Documentation
===================
.. toctree::
:maxdepth: 1
:hidden:
geckoview-quick-start
web-extensions
permissions
automation
We are working on providing detailed usage documentation for all of
GeckoViews most popular features. Here is what we have so far.
- `GeckoView Quick Start Guide <geckoview-quick-start.html>`__: Get
GeckoView up and running inside your application.
- `Interacting with Web Content <web-extensions.html>`__: Writing Web
Extensions, running content scripts and interacting with Javascript
running in a web page.
- `Working with Site Permissions <permissions.html>`__: Handling and
responding to requests from websites for permissions, such as
geolocation, storage, media etc.
- `Configuring GeckoView for Automation <automation.html>`__: Get GeckoView
set up on your automation system.
If there is documentation that you feel is missing, or an existing
document doesnt cover the aspect that you are looking for, please
request it by raising an issue on our `documentation
site <https://github.com/mozilla/geckoview/issues>`__.

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

@ -0,0 +1,353 @@
.. -*- Mode: rst; fill-column: 80; -*-
=============================
Working with Site Permissions
=============================
Working with Site Permissions
=============================
When a website wants to access certain services on a users device, it
will send out a permissions request. This document will explain how to
use GeckoView to receive those requests, and respond to them by granting
or denying those permissions.
.. contents:: :local:
The Permission Delegate
-----------------------
The way an app interacts with site permissions in GeckoView is through
the
`PermissionDelegate <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html>`_.
There are three broad categories of permission that the
``PermissionDelegate`` handles, Android Permissions, Content Permissions
and Media Permissions. All site permissions handled by GeckoView fall
into one of these three categories.
To get notified about permission requests, you need to implement the
``PermissionDelegate`` interface:
.. code:: java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
@Override
public void onAndroidPermissionsRequest(final GeckoSession session,
final String[] permissions,
final Callback callback) { }
@Override
public void onContentPermissionRequest(final GeckoSession session,
final String uri,
final int type, final Callback callback) { }
@Override
public void onMediaPermissionRequest(final GeckoSession session,
final String uri,
final MediaSource[] video,
final MediaSource[] audio,
final MediaCallback callback) { }
}
You will then need to register the delegate with your
`GeckoSession <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html>`_
instance.
.. code:: java
public class GeckoViewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
final ExamplePermissionDelegate permission = new ExamplePermissionDelegate();
session.setPermissionDelegate(permission);
...
}
}
Android Permissions
~~~~~~~~~~~~~~~~~~~
Android permissions are requested whenever a site wants access to a
devices navigation or input capabilities.
The user will often need to grant these Android permissions to the app
alongside granting the Content or Media site permissions.
When you receive an
`onAndroidPermissionsRequest <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onAndroidPermissionsRequest-org.mozilla.geckoview.GeckoSession-java.lang.String:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback->`_
call, you will also receive the ``GeckoSession`` the request was sent
from, an array containing the permissions that are being requested, and
a
`Callback <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html>`_
to respond to the request. It is then up to the app to request those
permissions from the device, which can be done using
`requestPermissions <https://developer.android.com/reference/android/app/Activity#requestPermissions(java.lang.String%5B%5D,%2520int)>`_.
Possible ``permissions`` values are;
`ACCESS_COARSE_LOCATION <https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION>`_,
`ACCESS_FINE_LOCATION <https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_FINE_LOCATION>`_,
`CAMERA <https://developer.android.com/reference/android/Manifest.permission.html#CAMERA>`_
or
`RECORD_AUDIO <https://developer.android.com/reference/android/Manifest.permission.html#RECORD_AUDIO>`_.
.. code:: java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
private Callback mCallback;
public void onRequestPermissionsResult(final String[] permissions,
final int[] grantResults) {
if (mCallback == null) { return; }
final Callback cb = mCallback;
mCallback = null;
for (final int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
// At least one permission was not granted.
cb.reject();
return;
}
}
cb.grant();
}
@Override
public void onAndroidPermissionsRequest(final GeckoSession session,
final String[] permissions,
final Callback callback) {
mCallback = callback;
requestPermissions(permissions, androidPermissionRequestCode);
}
}
public class GeckoViewActivity extends AppCompatActivity {
@Override
public void onRequestPermissionsResult(final int requestCode,
final String[] permissions,
final int[] grantResults) {
if (requestCode == REQUEST_PERMISSIONS ||
requestCode == REQUEST_WRITE_EXTERNAL_STORAGE) {
final ExamplePermissionDelegate permission = (ExamplePermissionDelegate)
getCurrentSession().getPermissionDelegate();
permission.onRequestPermissionsResult(permissions, grantResults);
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
Content Permissions
~~~~~~~~~~~~~~~~~~~
Content permissions are requested whenever a site wants access to
content that is stored on the device. The content permissions that can
be requested through GeckoView are;
`Geolocation <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_GEOLOCATION>`_,
`Site Notifications <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_DESKTOP_NOTIFICATION>`_
`Persistent Storage <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_STORAGE>`_
and
`XR <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_XR>`_
access.
When you receive an
`onContentPermissionRequest <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-int-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback->`_
call, you will also receive the ``GeckoSession`` the request was sent
from, the URI of the site that requested the permission, as a String,
the type of the content permission requested (geolocation, site
notification or persistent storage), and a
`Callback <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html>`_
to respond to the request. It is then up to the app to present UI to the
user asking for the permissions, and to notify GeckoView of the response
via the ``Callback``.
*Please note, in the case of ``PERMISSION_DESKTOP_NOTIFICATION`` and
``PERMISSION_PERSISTENT_STORAGE``, GeckoView does not track accepted
permissions and prevent further requests being sent for a particular
site. It is therefore up to the calling app to do this if that is the
desired behaviour. The code below demonstrates how to track storage
permissions by site and track notification permission rejection for the
whole app*
.. code:: java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
private boolean showNotificationsRejected;
private ArrayList<String> acceptedPersistentStorage = new ArrayList<String>();
@Override
public void onContentPermissionRequest(final GeckoSession session,
final String uri,
final int type,
final Callback callback) {
final int resId;
Callback contentPermissionCallback = callback;
if (PERMISSION_GEOLOCATION == type) {
resId = R.string.request_geolocation;
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
if (showNotificationsRejected) {
callback.reject();
return;
}
resId = R.string.request_notification;
} else if (PERMISSION_PERSISTENT_STORAGE == type) {
if (acceptedPersistentStorage.contains(uri)) {
callback.grant();
return;
}
resId = R.string.request_storage;
} else if (PERMISSION_XR == type) {
resId = R.string.request_xr;
} else { // unknown permission type
callback.reject();
return;
}
final String title = getString(resId, Uri.parse(uri).getAuthority());
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
if (PERMISSION_DESKTOP_NOTIFICATION == type) {
showNotificationsRejected = false;
}
callback.reject();
}
})
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
if (PERMISSION_PERSISTENT_STORAGE == type) {
acceptedPersistentStorage.add(mUri);
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
showNotificationsRejected = true;
}
callback.grant();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
}
Media Permissions
~~~~~~~~~~~~~~~~~
Media permissions are requested whenever a site wants access to play or
record media from the devices camera and microphone.
When you receive an
`onMediaPermissionRequest <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback->`_
call, you will also receive the ``GeckoSession`` the request was sent
from, the URI of the site that requested the permission, as a String,
the list of video devices available, if requesting video, the list of
audio devices available, if requesting audio, and a
`MediaCallback <https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686>`_
to respond to the request.
It is up to the app to present UI to the user asking for the
permissions, and to notify GeckoView of the response via the
``MediaCallback``.
*Please note, media permissions will still be requested if the
associated device permissions have been denied if there are video or
audio sources in that category that can still be accessed when listed.
It is the responsibility of consumers to ensure that media permission
requests are not displayed in this case.*
.. code:: java
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
@Override
public void onMediaPermissionRequest(final GeckoSession session,
final String uri,
final MediaSource[] video,
final MediaSource[] audio,
final MediaCallback callback) {
// Reject permission if Android permission has been previously denied.
if ((audio != null
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
|| (video != null
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
callback.reject();
return;
}
final String host = Uri.parse(uri).getAuthority();
final String title;
if (audio == null) {
title = getString(R.string.request_video, host);
} else if (video == null) {
title = getString(R.string.request_audio, host);
} else {
title = getString(R.string.request_media, host);
}
// Get the media device name from the `MediaDevice`
String[] videoNames = normalizeMediaName(video);
String[] audioNames = normalizeMediaName(audio);
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
// Create drop down boxes to allow users to select which device to grant permission to
final LinearLayout container = addStandardLayout(builder, title, null);
final Spinner videoSpinner;
if (video != null) {
videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames); // create spinner and add to alert UI
} else {
videoSpinner = null;
}
final Spinner audioSpinner;
if (audio != null) {
audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames); // create spinner and add to alert UI
} else {
audioSpinner = null;
}
builder.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
// gather selected media devices and grant access
final MediaSource video = (videoSpinner != null)
? (MediaSource) videoSpinner.getSelectedItem() : null;
final MediaSource audio = (audioSpinner != null)
? (MediaSource) audioSpinner.getSelectedItem() : null;
callback.grant(video, audio);
}
});
final AlertDialog dialog = builder.create();
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(final DialogInterface dialog) {
callback.reject();
}
});
dialog.show();
}
}
To see the ``PermissionsDelegate`` in action, you can find the full
example implementation in the `GeckoView example
app <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html>`_.

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

@ -0,0 +1,360 @@
.. -*- Mode: rst; fill-column: 80; -*-
============================
Interacting with Web content
============================
Interacting with Web content and WebExtensions
==============================================
GeckoView allows embedder applications to register and run
`WebExtensions <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions>`_
in a GeckoView instance. WebExtensions are the preferred way to interact
with Web content.
.. contents:: :local:
Running WebExtensions in GeckoView
----------------------------------
WebExtensions bundled with applications can be provided either in
compressed ``.xpi`` files or in regular folders. Like ordinary
WebExtensions, every WebExtension requires a
`manifest.json <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json>`_
file.
To run a WebExtension in GeckoView, simply create a
`WebExtension <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html>`_
object and register it in your
`GeckoRuntime <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntime.html>`_
instance.
.. code:: java
WebExtension extension = new WebExtension(
// The location where the web extension is installed, if the location is a
// folder make sure the path ends with a "/" character.
"resource://android/assets/messaging/",
// This is the id and must be unique for every web extension
"myextension@example.com",
// Extra flags can be specified here
WebExtension.Flags.NONE);
// Run the WebExtension
runtime.registerWebExtension(extension);
Note that the lifetime of the WebExtension is tied with the lifetime of
the
`GeckoRuntime <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntime.html>`_
instance. The WebExtension will need to be registered every time the
runtime is created and will not persist once the runtime is closed.
To locate files bundled with the APK, GeckoView provides a shorthand
``resource://android/`` that points to the root of the APK.
E.g. ``resource://android/assets/messaging/`` will point to the
``/assets/messaging/`` folder present in the APK.
Communicating with Web Content
------------------------------
GeckoView allows bidirectional communication with Web pages through
WebExtensions.
When using GeckoView, `native
messaging <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#Exchanging_messages>`_
can be used for communicating to and from the browser.
- `runtime.sendNativeMessage <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage>`_
for one-off messages.
- `runtime.connectNative <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative>`_
for connection-based messaging.
Note: these APIs are only available when the ``geckoViewAddons``
`permission <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions>`_
is present in the ``manifest.json`` file of the WebExtension.
One-off messages
~~~~~~~~~~~~~~~~
The easiest way to send messages from a `content
script <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts>`_
or a `background
script <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts>`_
is using
`runtime.sendNativeMessage <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage>`_.
The app will set up a message delegate on the same ``nativeApp`` that
the WebExtension is using to send messages. In our example we will use
the ``"browser"`` native app identifier.
To receive messages from the background script, call
`setMessageDelegate <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String->`_
on the
`WebExtension <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html>`_
object.
`GeckoSession.setMessageDelegate <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String->`_
allows the app to receive messages from content scripts.
Note: WebExtensions can only send messages from content scripts if
explicitly authorized by the app setting
`WebExtension.Flags.ALLOW_CONTENT_MESSAGING <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Flags.html#ALLOW_CONTENT_MESSAGING>`_
in the
`constructor <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#WebExtension-java.lang.String-java.lang.String-long->`_.
Example
~~~~~~~
Lets set up an activity that registers a WebExtension located in the
``/assets/messaging/`` folder of the APK. This activity will set up a
`MessageDelegate <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html>`_
that will be used to communicate with Web Content.
You can find the full example here:
`MessagingExample <https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/messaging_example/>`_.
Activity.java
^^^^^^^^^^^^^
.. code:: java
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
@Nullable
public GeckoResult<Object> onMessage(final @NonNull Object message,
final @NonNull WebExtension.MessageSender sender) {
// The sender object contains information about the session that
// originated this message and can be used to validate that the message
// has been sent from the expected location.
// Be careful when handling the type of message as it depends on what
// type of object was sent from the WebExtension script.
if (message instanceof JSONObject) {
// Do something with message
}
return null;
}
};
WebExtension extension = new WebExtension(
"resource://android/assets/messaging/",
"myextension@example.com",
WebExtension.Flags.ALLOW_CONTENT_MESSAGING);
// Run the WebExtension
runtime.registerWebExtension(extension);
// Set the delegate that will receive messages coming from this WebExtension.
session.setMessageDelegate(messageDelegate, "browser");
Now add the ``geckoViewAddons`` and ``nativeMessaging`` permissions to
your ``manifest.json`` file.
/assets/messaging/manifest.json
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: json
{
"manifest_version": 2,
"name": "messaging",
"version": "1.0",
"description": "Example messaging web extension.",
"content_scripts": [
{
"matches": ["*://*.twitter.com/*"],
"js": ["messaging.js"]
}
],
"permissions": [
"nativeMessaging",
"geckoViewAddons"
]
}
And finally, write a content script that will send a message to the app
when a certain event occurs. For example, you could send a message
whenever a `WPA
manifest <https://developer.mozilla.org/en-US/docs/Web/Manifest>`_ is
found on the page. Note that our ``nativeApp`` identifier used for
``sendNativeMessage`` is the same as the one used in the
``setMessageDelegate`` call in `Activity.java <#activityjava>`_.
/assets/messaging/messaging.js
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: javascript
let manifest = document.querySelector("head > link[rel=manifest]");
if (manifest) {
fetch(manifest.href)
.then(response => response.json())
.then(json => {
let message = {type: "WPAManifest", manifest: json};
browser.runtime.sendNativeMessage("browser", message);
});
}
You can handle this message in the ``onMessage`` method in the
``messageDelegate`` `above <#activityjava>`_.
.. code:: java
@Nullable
public GeckoResult<Object> onMessage(final @NonNull Object message,
final @NonNull WebExtension.MessageSender sender) {
if (message instanceof JSONObject) {
JSONObject json = (JSONObject) message;
try {
if (json.has("type") && "WPAManifest".equals(json.getString("type"))) {
JSONObject manifest = json.getJSONObject("manifest");
Log.d("MessageDelegate", "Found WPA manifest: " + manifest);
}
} catch (JSONException ex) {
Log.e("MessageDelegate", "Invalid manifest", ex);
}
}
return null;
}
Note that, in the case of content scripts, ``sender.session`` will be a
reference to the ``GeckoSession`` instance from which the message
originated. For background scripts, ``sender.session`` will always be
``null``.
Also note that the type of ``message`` will depend on what was sent from
the WebExtension.
The type of ``message`` will be ``JSONObject`` when the WebExtension
sends a javascript object, but could also be a primitive type if the
WebExtension sends one, e.g. for
.. code:: javascript
runtime.browser.sendNativeMessage("browser", "Hello World!");
the type of ``message`` will be ``java.util.String``.
Connection-based messaging
--------------------------
For more complex scenarios or for when you want to send messages *from*
the app to the WebExtension,
`runtime.connectNative <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative>`_
is the appropriate API to use.
``connectNative`` returns a
`runtime.Port <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port>`_
that can be used to send messages to the app. On the app side,
implementing
`MessageDelegate#onConnect <../javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html#onConnect-org.mozilla.geckoview.WebExtension.Port->`_
will allow you to receive a
`Port <../javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Port.html>`_
object that can be used to receive and send messages to the
WebExtension.
The following example can be found
`here <https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/port_messaging_example/>`_.
For this example, the WebExtension side will do the following:
- open a port on the background script using ``connectNative``
- listen on the port and log to console every message received
- send a message immediately after opening the port.
/assets/messaging/background.js
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: javascript
// Establish connection with app
let port = browser.runtime.connectNative("browser");
port.onMessage.addListener(response => {
// Let's just echo the message back
port.postMessage(`Received: ${JSON.stringify(response)}`);
});
port.postMessage("Hello from WebExtension!");
On the app side, following the `above <#activityjava>`_ example,
``onConnect`` will be storing the ``Port`` object in a member variable
and then using it when needed.
.. code:: java
private WebExtension.Port mPort;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... initialize GeckoView
// This delegate will handle all communications from and to a specific Port
// object
WebExtension.PortDelegate portDelegate = new WebExtension.PortDelegate() {
public WebExtension.Port port = null;
public void onPortMessage(final @NonNull Object message,
final @NonNull WebExtension.Port port) {
// This method will be called every time a message is sent from the
// WebExtension through this port. For now, let's just log a
// message.
Log.d("PortDelegate", "Received message from WebExtension: "
+ message);
}
public void onDisconnect(final @NonNull WebExtension.Port port) {
// After this method is called, this port is not usable anymore.
if (port == mPort) {
mPort = null;
}
}
};
// This delegate will handle requests to open a port coming from the
// WebExtension
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
@Nullable
public void onConnect(final @NonNull WebExtension.Port port) {
// Let's store the Port object in a member variable so it can be
// used later to exchange messages with the WebExtension.
mPort = port;
// Registering the delegate will allow us to receive messages sent
// through this port.
mPort.setDelegate(portDelegate);
}
};
WebExtension extension = new WebExtension(
"resource://android/assets/messaging/");
// Register message delegate for the background script
extension.setMessageDelegate(messageDelegate, "browser");
// ... other
}
For example, lets send a message to the WebExtension every time the
user long presses on a key on the virtual keyboard, e.g. on the back
button.
.. code:: java
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (mPort == null) {
// No WebExtension registered yet, let's ignore this message
return false;
}
JSONObject message = new JSONObject();
try {
message.put("keyCode", keyCode);
message.put("event", KeyEvent.keyCodeToString(event.getKeyCode()));
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
mPort.postMessage(message);
return true;
}
This allows bidirectional communication between the app and the
WebExtension.

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

@ -1,142 +0,0 @@
---
layout: default
title: Mozilla Central Contributor Guide
summary: Guide to setting up as a contributor to mozilla-central.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,bug fix,submit,patch,arcanist,arc,moz-phab,phabricator]
nav_exclude: true
exclude: true
---
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
# Submitting a patch to Firefox using Git.
This guide will take you through submitting and updating a patch to `mozilla-central` as a git user. You need to already be [set up to use git to contribute to `mozilla-central`](mc-quick-start).
## Performing a bug fix
All of the open bugs for issues in Firefox can be found in [Bugzilla](https://bugzilla.mozilla.org). If you know the component that you wish to contribute to you can use Bugzilla to search for issues in that project. If you are unsure which component you are interested in, you can search the [Good First Bugs](https://bugzilla.mozilla.org/buglist.cgi?quicksearch=good-first-bug) list to find something you want to work on.
* Once you have your bug, assign it to yourself in Bugzilla.
* Update your local copy of the firefox codebase to match the current version on the servers to ensure you are working with the most up to date code.
```bash
git remote update
```
* Create a new feature branch tracking either Central or Inbound.
```bash
git checkout -b bugxxxxxxx [inbound|central]/default
```
* Work on your bug, checking into git according to your preferred workflow. _Try to ensure that each individual commit compiles and passes all of the tests for your component. This will make it easier to land if you use `moz-phab` to submit (details later in this post)._
It may be helpful to have Mozilla commit access, at least level 1. There are three levels of commit access that give increasing levels of access to the repositories.
Level 1: Try/User access. You will need this level of access commit to the try server.
Level 2: General access. This will give you full commit access to any mercurial or SVN repository not requiring level 3 access.
Level 3: Core access. You will need this level to commit directly to any of the core repositories (Firefox/Thunderbird/Fennec).
If you wish to apply for commit access, please follow the guide found in the [Mozilla Commit Access Policy](https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/).
### Submitting a patch that touches C/C++
If your patch makes changes to any C or C++ code and your editor does not have `clang-format` support, you should run the clang-format linter before submitting your patch to ensure that your code is properly formatted.
```bash
mach clang-format -p path/to/file.cpp
```
Note that `./mach bootstrap` will offer to set up a commit hook that will automatically do this for you.
### Submitting to `try` with Level 1 commit access.
If you only have Level 1 access, you will still need to submit your patch through phabricator, but you can test it on the try server first.
* Use `./mach try fuzzy` to select jobs to run and push to try.
### Submitting a patch via Phabricator.
To commit anything to the repository, you will need to set up Arcanist and Phabricator. If you are using `git-cinnabar` then you will need to use git enabled versions of these tools.
#### Install Arcanist (Github version)
* Ensure PHP is installed
* [Install Arcanist](https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/)
#### Set up Phabricator
* In a browser, visit Mozilla's Phabricator instance at https://phabricator.services.mozilla.com/.
* Click "Log In" at the top of the page
![alt text]({{ site.url }}/assets/LogInPhab.png "Log in to Phabricator")
* Click the "Log In or Register" button on the next page. This will take you to Bugzilla to log in or register a new account.
![alt text]({{ site.url }}/assets/LogInOrRegister.png "Log in or register a Phabiricator account")
* Sign in with your Bugzilla credentials, or create a new account.
![alt text]({{ site.url }}/assets/LogInBugzilla.png "Log in with Bugzilla")
* You will be redirected back to Phabricator, where you will have to create a new Phabricator account.
<Screenshot Needed>
* Fill in/amend any fields on the form and click "Register Account".
<Screenshot Needed>
* You now have a Phabricator account and can submit and review patches.
#### Using Arcanist to submit a patch
* Ensure you are on the branch where you have commits that you want to submit.
```bash
git checkout "your-branch-with-commits"
```
* Create a differential patch containing your commits
```bash
arc diff
```
* If you have any uncommitted files, Arcanist will ask if you want to commit them.
* If you have any files in the path not added to git Arcanist will ask if you want to ignore them.
* After formatting your patch, Arcanist will open a nano/emacs file for you to enter the commit details. If you have many individual git commits in your arcanist diff then the first line of the first commit message will become the patch title, and the rest of the commit, plus the messages for the other commits in the patch will form the summary.
* Ensure you have entered the bug number against the `Bug #` field.
* If you know who you want to review your patch, put their Phabricator handle against the `reviewers` field. If in doubt, look to see who filed, or is listed as a mentor on, the bug you are addressing and choose them.
* Close the editor (Ctrl X) to save the patch.
* Arcanist now formats your patch and submits it to Phabricator. It will display the Phabricator link in the output.
* Copy that link and paste it into a browser window to view your patch.
You may have noticed when using Arcanist that it wraps all of your carefully curated Github commits into a single patch. If you have made many commits that are self contained and pass all the tests then you may wish to submit a patch for each commit. This will make it easier to review. The way to do this is via `moz-phab`. `moz-phab` required Arcanist so you do have to have that installed first.
#### Installing `moz-phab`
```bash
pip install MozPhab [--user]
```
#### Submitting a patch using `moz-phab`.
* Ensure you are on the branch where you have commits that you want to submit.
```bash
git checkout your-branch
```
* Check the revision numbers for the commits you want to submit
```bash
git log
```
* Run `moz-phab`. Specifying a start commit will submit all commits from that commit. Specifying an end commit will submit all commits up to that commit. If no positional arguments are provided, the range is determined to be starting with the first non-public, non-obsolete changeset (for Mercurial) and ending with the currently checked-out changeset.
```bash
moz-phab submit [start_rev] [end_rev]
```
* You will receive a Phabricator link for each commit in the set.
### Updating a patch
* Often you will need to make amendments to a patch after it has been submitted to address review comments. To do this, add your commits to the base branch of your fix as normal.
To submit the update using Arcanist, run `arc diff --update <PhabricatorDifferentialNumber>`.
For `moz-phab` run in the same way as the initial submission with the same arguments, that is, specifying the full original range of commits. Note that, while inserting and amending commits should work fine, reordering commits is not yet supported, and deleting commits will leave the associated revisions open, which should be abandoned manually

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

@ -0,0 +1,239 @@
=================================
Mozilla Central Contributor Guide
=================================
Table of contents
=================
.. contents:: :local:
Submitting a patch to Firefox using Git.
========================================
This guide will take you through submitting and updating a patch to
``mozilla-central`` as a git user. You need to already be `set up to use
git to contribute to mozilla-central <mc-quick-start.html>`_.
Performing a bug fix
--------------------
All of the open bugs for issues in Firefox can be found in
`Bugzilla <https://bugzilla.mozilla.org>`_. If you know the component
that you wish to contribute to you can use Bugzilla to search for issues
in that project. If you are unsure which component you are interested
in, you can search the `Good First
Bugs <https://bugzilla.mozilla.org/buglist.cgi?quicksearch=good-first-bug>`_
list to find something you want to work on.
- Once you have your bug, assign it to yourself in Bugzilla.
- Update your local copy of the firefox codebase to match the current
version on the servers to ensure you are working with the most up to
date code.
.. code:: bash
git remote update
- Create a new feature branch tracking either Central or Inbound.
.. code:: bash
git checkout -b bugxxxxxxx [inbound|central]/default
- Work on your bug, checking into git according to your preferred
workflow. *Try to ensure that each individual commit compiles and
passes all of the tests for your component. This will make it easier
to land if you use ``moz-phab`` to submit (details later in this
post).*
It may be helpful to have Mozilla commit access, at least level 1. There
are three levels of commit access that give increasing levels of access
to the repositories.
Level 1: Try/User access. You will need this level of access commit to
the try server.
Level 2: General access. This will give you full commit
access to any mercurial or SVN repository not requiring level 3 access.
Level 3: Core access. You will need this level to commit directly to any
of the core repositories (Firefox/Thunderbird/Fennec).
If you wish to apply for commit access, please follow the guide found in
the `Mozilla Commit Access
Policy <https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/>`_.
Submitting a patch that touches C/C++
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If your patch makes changes to any C or C++ code and your editor does
not have ``clang-format`` support, you should run the clang-format
linter before submitting your patch to ensure that your code is properly
formatted.
.. code:: bash
mach clang-format -p path/to/file.cpp
Note that ``./mach bootstrap`` will offer to set up a commit hook that
will automatically do this for you.
Submitting to ``try`` with Level 1 commit access.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you only have Level 1 access, you will still need to submit your
patch through phabricator, but you can test it on the try server first.
- Use ``./mach try fuzzy`` to select jobs to run and push to try.
Submitting a patch via Phabricator.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To commit anything to the repository, you will need to set up Arcanist
and Phabricator. If you are using ``git-cinnabar`` then you will need to
use git enabled versions of these tools.
Install Arcanist (Github version)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Ensure PHP is installed
- `Install
Arcanist <https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/>`_
Set up Phabricator
^^^^^^^^^^^^^^^^^^
- In a browser, visit Mozillas Phabricator instance at
https://phabricator.services.mozilla.com/.
- Click “Log In” at the top of the page
.. figure:: ../assets/LogInPhab.png
:alt: Log in to Phabricator
alt text
- Click the “Log In or Register” button on the next page. This will
take you to Bugzilla to log in or register a new account.
.. figure:: ../assets/LogInOrRegister.png
:alt: Log in or register a Phabiricator account
alt text
- Sign in with your Bugzilla credentials, or create a new account.
.. figure:: ../assets/LogInBugzilla.png
:alt: Log in with Bugzilla
alt text
- You will be redirected back to Phabricator, where you will have to
create a new Phabricator account.
.. raw:: html
<Screenshot Needed>
- Fill in/amend any fields on the form and click “Register Account”.
.. raw:: html
<Screenshot Needed>
- You now have a Phabricator account and can submit and review patches.
Using Arcanist to submit a patch
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Ensure you are on the branch where you have commits that you want to
submit.
.. code:: bash
git checkout "your-branch-with-commits"
- Create a differential patch containing your commits
.. code:: bash
arc diff
- If you have any uncommitted files, Arcanist will ask if you want to
commit them.
- If you have any files in the path not added to git Arcanist will ask
if you want to ignore them.
- After formatting your patch, Arcanist will open a nano/emacs file for
you to enter the commit details. If you have many individual git
commits in your arcanist diff then the first line of the first commit
message will become the patch title, and the rest of the commit, plus
the messages for the other commits in the patch will form the
summary.
- Ensure you have entered the bug number against the ``Bug #`` field.
- If you know who you want to review your patch, put their Phabricator
handle against the ``reviewers`` field. If in doubt, look to see who
filed, or is listed as a mentor on, the bug you are addressing and
choose them.
- Close the editor (Ctrl X) to save the patch.
- Arcanist now formats your patch and submits it to Phabricator. It
will display the Phabricator link in the output.
- Copy that link and paste it into a browser window to view your patch.
You may have noticed when using Arcanist that it wraps all of your
carefully curated Github commits into a single patch. If you have made
many commits that are self contained and pass all the tests then you may
wish to submit a patch for each commit. This will make it easier to
review. The way to do this is via ``moz-phab``. ``moz-phab`` required
Arcanist so you do have to have that installed first.
Installing ``moz-phab``
^^^^^^^^^^^^^^^^^^^^^^^
.. code:: bash
pip install MozPhab [--user]
Submitting a patch using ``moz-phab``.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Ensure you are on the branch where you have commits that you want to
submit.
.. code:: bash
git checkout your-branch
- Check the revision numbers for the commits you want to submit
.. code:: bash
git log
- Run ``moz-phab``. Specifying a start commit will submit all commits
from that commit. Specifying an end commit will submit all commits up
to that commit. If no positional arguments are provided, the range is
determined to be starting with the first non-public, non-obsolete
changeset (for Mercurial) and ending with the currently checked-out
changeset.
.. code:: bash
moz-phab submit [start_rev] [end_rev]
- You will receive a Phabricator link for each commit in the set.
Updating a patch
~~~~~~~~~~~~~~~~
- Often you will need to make amendments to a patch after it has been
submitted to address review comments. To do this, add your commits to
the base branch of your fix as normal.
To submit the update using Arcanist, run
``arc diff --update <PhabricatorDifferentialNumber>``.
For ``moz-phab`` run in the same way as the initial submission with the
same arguments, that is, specifying the full original range of commits.
Note that, while inserting and amending commits should work fine,
reordering commits is not yet supported, and deleting commits will leave
the associated revisions open, which should be abandoned manually

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

@ -1,70 +0,0 @@
---
layout: default
title: GeckoView For Gecko Engineers
summary: Guide to contributing to GeckoView for Gecko Engineers
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,get started,compile,build,deploy,bug fix,submit,patch,arcanist,arc,moz-phab,phabricator]
nav_exclude: true
exclude: true
---
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
# GeckoView for Gecko Engineers
## Introduction
Who this guide is for: As the title suggests, the target audience of this guide is existing Gecko engineers who need to be able to build and (locally) test GeckoView. If you arent already familiar with building Firefox on a desktop platform, youll likely be better served by reading [our general introduction](geckoview-quick-start). This guide may also be helpful if you find youve written a patch that requires changing GeckoViews public API, see [Landing a Patch](#landing-a-patch).
Who this guide is not for: As mentioned above, if you are not already familiar with building Firefox for desktop, youd likely be better served by our general bootstrapping guide. If you are looking to contribute to front-end development of one of Mozillas Android browsers, youre likely better off starting with their codebase and returning here only if actual GeckoView changes are needed. See, for example, [Fenixs GitHub](https://github.com/mozilla-mobile/fenix).
What to do if this guide contains bugs or leads you astray: The quickest way to get a response is to ask generally on #gv on Mozilla Slack; #mobile on Mozilla IRC may also work for the time being, albeit likely with slower response times. If you believe the guide needs updating, it would also be good to file a ticket to request that.
## Configuring the build system
First, a quick note: This guide was written on MacOS 10.14; it should translate quite closely to other supported versions of MacOS and to Linux. Building GeckoView on Windows is not officially supported at the moment.
To begin with, re-run `./mach bootstrap`; it will present you with options for the version of Firefox/GV that you want to build. Currently, option `3` is `GeckoView/Firefox for Android Artifact Mode` and `4` is `GeckoView/Firefox for Android`; if youre here, you want one of these. The brief and approximately correct breakdown of `Artifact` vs regular builds for GeckoView is that `Artifact` builds will not allow you to work on native code, only on JS or Java.
Once youve selected your build type, `bootstrap` should do its usual thing and grab whatever dependencies are necessary. You may need to agree to some licenses along the way. Once `bootstrap` has successfully completed, it will spit out a recommended `mozconfig`.
## Mozconfig and Building
If youve followed from the previous section, `./mach bootstrap` printed out a recommended `mozconfig` that looks something like this:
```
# Build GeckoView/Firefox for Android:
ac_add_options --enable-application=mobile/android
# Targeting the following architecture.
# For regular phones, no --target is needed.
# For x86 emulators (and x86 devices, which are uncommon):
# ac_add_options --target=i686
# For newer phones.
# ac_add_options --target=aarch64
# For x86_64 emulators (and x86_64 devices, which are even less common):
# ac_add_options --target=x86_64
```
As written, this defaults to building for a 32-bit ARM architecture, which is probably not what you want. If you intend to work on an actual device, you almost certainly want a 64-bit ARM build, as it is supported by virtually all modern ARM phones/tablets and is the only ARM build we ship on the Google Play Store. To go this route, uncomment the `ac_add_options --target=aarch64` line in the `mozconfig`. On the other hand, x86-64 emulated devices are widely used by the GeckoView team and are used extensively on `try`; if you intend to use an emulator, uncomment the `ac_add_options --target=x86_64` line in the `mozconfig`. Dont worry about installing an emulator at the moment, that will be covered shortly.
Its worth noting here that other `mozconfig` options will generally work as youd expect. Additionally, if you plan on debugging native code on Android, you should include the `mozconfig` changes mentioned [here](native-debugging).
Now, using that `mozconfig` with any modifications youve made, simply `./mach build`. If all goes well, you will have successfully built GeckoView.
## Installing, Running, and Using in Fenix/AC
An (x86-64) emulator is the most common and developer-friendly way of contributing to GeckoView in most cases. If you're going to go this route, simply run `./mach android-emulator` — by default, this will install and launch an x86-64 Android emulator running the same Android 7.0 image that is used on `try`. If you need a different emulator image you can run `./mach android-emulator --help` for information on what Android images are available via `mach`. You can also install an emulator image via Android Studio.
In cases where an emulator may not suffice (eg graphics or performance testing), or if you'd simply prefer not to use an emulator, you can opt to use an actual phone instead. To do so, youll need to enable `USB Debugging` on your phone if you havent already. On most modern Android devices, you can do this by opening `Settings`, going to `About phone`, and tapping `Build number` seven times. You should get a notification informing you that youve unlocked developer options. Now return to `Settings`, go to `Developer options`, and enable USB debugging.
### GeckoView Example App
Now that youve connected a phone or setup an emulator, the simplest way to test GeckoView is to launch the GeckoView Example app by running `./mach run` (or install it with `./mach install` and run it yourself). This is a simplistic GV-based browser that lives in the tree; in many cases, it is sufficient to test and debug Gecko changes, and is by far the simplest way of doing so. It supports remote debugging by default — simply open Remote Debugging on your desktop browser and the connected device/emulator should show up when the example app is open. You can also use the example app for native debugging, follow instructions [here](native-debugging).
### GeckoView JUnit Tests
Once youve successfully built GV, you can run tests from the GeckoView JUnit test suite with `./mach geckoview-junit`. For further examples (eg running individual tests, repeating tests, etc.), consult the [quick start guide](geckoview-quick-start#running-tests-locally).
### Fenix and other GV-based Apps
If you are working on something for which the GeckoView Example app is not sufficient for some reason, you may need to use your local build of GeckoView in one of Mozillas GV-based apps like Fenix. For instructions on that, see [here](geckoview-quick-start#include-geckoview-as-a-dependency).
## Debugging
### Remote Debugging
To recap a bit of the above, in the GeckoView Example app, remote debugging is enabled by default, and your device should show up in your desktop browsers Remote Debugging window with no special effort. For Fenix, you can enable remote debugging by opening the three-dot menu and toggling `Remote debugging via USB` under `Developer tools`; other Mozilla GV-based browsers have similar options.
### Native Debugging
To perform native debugging on any GV app will require you to install Android Studio and follow instructions [here](native-debugging).
## Landing a Patch
In most cases, there shouldnt be anything out of the ordinary to deal with when landing a patch that affects GeckoView; make sure you include Android in your `try` runs and you should be good. However, if you need to alter the GeckoView public API in any way — essentially anything thats exposed as `public` in GeckoView Java files — then youll find that you need to run the API linter and update the change log. To do this, first run `./mach lint --linter android-api-lint` — if you have indeed changed the public API, this will give you a `gradle` command to run that will give further instructions. GeckoView API changes require two reviews from GeckoView team members; you can open it up to the team in general by adding `#geckoview-reviewers` as a reviewer on Phabricator.

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

@ -0,0 +1,179 @@
.. -*- Mode: rst; fill-column: 80; -*-
=============================
GeckoView For Gecko Engineers
=============================
Table of contents
=================
.. contents:: :local:
GeckoView for Gecko Engineers
=============================
Introduction
------------
Who this guide is for: As the title suggests, the target audience of
this guide is existing Gecko engineers who need to be able to build and
(locally) test GeckoView. If you arent already familiar with building
Firefox on a desktop platform, youll likely be better served by reading
`our general introduction <geckoview-quick-start>`_. This guide may
also be helpful if you find youve written a patch that requires
changing GeckoViews public API, see `Landing a
Patch <#landing-a-patch>`_.
Who this guide is not for: As mentioned above, if you are not already
familiar with building Firefox for desktop, youd likely be better
served by our general bootstrapping guide. If you are looking to
contribute to front-end development of one of Mozillas Android
browsers, youre likely better off starting with their codebase and
returning here only if actual GeckoView changes are needed. See, for
example, `Fenixs GitHub <https://github.com/mozilla-mobile/fenix>`_.
What to do if this guide contains bugs or leads you astray: The quickest
way to get a response is to ask generally on #gv on Mozilla Slack;
#mobile on Mozilla IRC may also work for the time being, albeit likely
with slower response times. If you believe the guide needs updating, it
would also be good to file a ticket to request that.
Configuring the build system
----------------------------
First, a quick note: This guide was written on MacOS 10.14; it should
translate quite closely to other supported versions of MacOS and to
Linux. Building GeckoView on Windows is not officially supported at the
moment. To begin with, re-run ``./mach bootstrap``; it will present you
with options for the version of Firefox/GV that you want to build.
Currently, option ``3`` is
``GeckoView/Firefox for Android Artifact Mode`` and ``4`` is
``GeckoView/Firefox for Android``; if youre here, you want one of
these. The brief and approximately correct breakdown of ``Artifact`` vs
regular builds for GeckoView is that ``Artifact`` builds will not allow
you to work on native code, only on JS or Java. Once youve selected
your build type, ``bootstrap`` should do its usual thing and grab
whatever dependencies are necessary. You may need to agree to some
licenses along the way. Once ``bootstrap`` has successfully completed,
it will spit out a recommended ``mozconfig``.
Mozconfig and Building
----------------------
If youve followed from the previous section, ``./mach bootstrap``
printed out a recommended ``mozconfig`` that looks something like this:
::
# Build GeckoView/Firefox for Android:
ac_add_options --enable-application=mobile/android
# Targeting the following architecture.
# For regular phones, no --target is needed.
# For x86 emulators (and x86 devices, which are uncommon):
# ac_add_options --target=i686
# For newer phones.
# ac_add_options --target=aarch64
# For x86_64 emulators (and x86_64 devices, which are even less common):
# ac_add_options --target=x86_64
As written, this defaults to building for a 32-bit ARM architecture,
which is probably not what you want. If you intend to work on an actual
device, you almost certainly want a 64-bit ARM build, as it is supported
by virtually all modern ARM phones/tablets and is the only ARM build we
ship on the Google Play Store. To go this route, uncomment the
``ac_add_options --target=aarch64`` line in the ``mozconfig``. On the
other hand, x86-64 emulated devices are widely used by the GeckoView
team and are used extensively on ``try``; if you intend to use an
emulator, uncomment the ``ac_add_options --target=x86_64`` line in the
``mozconfig``. Dont worry about installing an emulator at the moment,
that will be covered shortly. Its worth noting here that other
``mozconfig`` options will generally work as youd expect. Additionally,
if you plan on debugging native code on Android, you should include the
``mozconfig`` changes mentioned `in our native debugging guide <native-debugging.html>`_. Now, using
that ``mozconfig`` with any modifications youve made, simply
``./mach build``. If all goes well, you will have successfully built
GeckoView.
Installing, Running, and Using in Fenix/AC
------------------------------------------
An (x86-64) emulator is the most common and developer-friendly way of
contributing to GeckoView in most cases. If youre going to go this
route, simply run ``./mach android-emulator`` — by default, this will
install and launch an x86-64 Android emulator running the same Android
7.0 image that is used on ``try``. If you need a different emulator
image you can run ``./mach android-emulator --help`` for information on
what Android images are available via ``mach``. You can also install an
emulator image via Android Studio. In cases where an emulator may not
suffice (eg graphics or performance testing), or if youd simply prefer
not to use an emulator, you can opt to use an actual phone instead. To
do so, youll need to enable ``USB Debugging`` on your phone if you
havent already. On most modern Android devices, you can do this by
opening ``Settings``, going to ``About phone``, and tapping
``Build number`` seven times. You should get a notification informing
you that youve unlocked developer options. Now return to ``Settings``,
go to ``Developer options``, and enable USB debugging.
GeckoView Example App
~~~~~~~~~~~~~~~~~~~~~
Now that youve connected a phone or setup an emulator, the simplest way
to test GeckoView is to launch the GeckoView Example app by running
``./mach run`` (or install it with ``./mach install`` and run it
yourself). This is a simplistic GV-based browser that lives in the tree;
in many cases, it is sufficient to test and debug Gecko changes, and is
by far the simplest way of doing so. It supports remote debugging by
default — simply open Remote Debugging on your desktop browser and the
connected device/emulator should show up when the example app is open.
You can also use the example app for native debugging, follow
instructions `here <native-debugging.html>`_.
GeckoView JUnit Tests
~~~~~~~~~~~~~~~~~~~~~
Once youve successfully built GV, you can run tests from the GeckoView
JUnit test suite with ``./mach geckoview-junit``. For further examples
(eg running individual tests, repeating tests, etc.), consult the `quick
start guide <geckoview-quick-start.html#running-tests-locally>`_.
Fenix and other GV-based Apps
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are working on something for which the GeckoView Example app is
not sufficient for some reason, you may need to `use your local build of
GeckoView in one of Mozillas GV-based apps like Fenix <geckoview-quick-start.html#include-geckoview-as-a-dependency>`_.
Debugging
---------
Remote Debugging
~~~~~~~~~~~~~~~~
To recap a bit of the above, in the GeckoView Example app, remote
debugging is enabled by default, and your device should show up in your
desktop browsers Remote Debugging window with no special effort. For
Fenix, you can enable remote debugging by opening the three-dot menu and
toggling ``Remote debugging via USB`` under ``Developer tools``; other
Mozilla GV-based browsers have similar options.
Native Debugging
~~~~~~~~~~~~~~~~
To perform native debugging on any GV app will require you to install
Android Studio and follow instructions `here <native-debugging.html>`_.
Landing a Patch
---------------
In most cases, there shouldnt be anything out of the ordinary to deal
with when landing a patch that affects GeckoView; make sure you include
Android in your ``try`` runs and you should be good. However, if you
need to alter the GeckoView public API in any way — essentially anything
thats exposed as ``public`` in GeckoView Java files — then youll find
that you need to run the API linter and update the change log. To do
this, first run ``./mach lint --linter android-api-lint`` — if you have
indeed changed the public API, this will give you a ``gradle`` command
to run that will give further instructions. GeckoView API changes
require two reviews from GeckoView team members; you can open it up to
the team in general by adding ``#geckoview-reviewers`` as a reviewer on
Phabricator.

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

@ -1,198 +0,0 @@
---
layout: default
title: GeckoView Contributor Guide
summary: Guide to setting up as a contributor to GeckoView.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,get started,compile,build,deploy,bug fix,submit,patch,arcanist,arc,moz-phab,phabricator]
nav_exclude: true
exclude: true
---
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
# GeckoView Contributor Quick Start Guide
This is a guide for developers who want to contribute to the GeckoView project. If you want to get started using GeckoView in your app then you should refer to the [wiki](https://wiki.mozilla.org/Mobile/GeckoView#Get_Started).
You may also be interested in how to get up and running with [Firefox For Android](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build).
## Get set up with Mozilla Central
The GeckoView codebase is part of the main Firefox tree and can be found in `mozilla-central`. You will need to get set up as a contributor to Firefox in order to contribute to GeckoView. To get set up with `mozilla-central`, follow the [Quick Start Guide for Git Users](mc-quick-start), or the [Contributing to the Mozilla code base](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction) guide on [MDN](https://developer.mozilla.org/) for Mercurial users.
Once you have a copy of `mozilla-central`, you will need to build GeckoView.
## Bootstrap Gecko
Bootstrap configures everything for GeckoView and Fennec development.
* Ensure you have `mozilla-central` checked out. If this is the first time you are doing this, it may take some time.
```bash
git checkout central/default
```
If you are on a mac, you will need to have the Xcode build tools installed. You can do this by either [installing Xcode](https://developer.apple.com/xcode/) or installing only the tools from the command line by running `xcode-select --install` and following the on screen instructions. Use the ` --no-interactive` argument to automatically accept any license agreements.
```bash
./mach bootstrap [ --no-interactive]
```
* Choose option `4. Firefox for Android` for GeckoView development. This will give you a version of Gecko configured for Android that has not bundled the native code into embedded libraries so you can amend the code.
* Say Y to all configuration options
* Once `mach bootstrap` is complete it will tell you to copy and paste some configuration into your `mozconfig` file. The `mozconfig` file can be found in the root of your `gecko` repo - or create a file called `mozconfig` if it does not exist. Check that the correct value is associated with the `--target` argument as this may not correctly match your setup. Copy the file contents from the `mach bootstrap` output into your file and save in the root directory of your project.
## Build from the command line
In order to pick up the configuration changes we just made we need to build from the command line. This will update generated sources, compile native code, and produce GeckoView AARs and example and test APKs.
```bash
./mach build
```
## Build Using Android Studio
* Install [Android Studio](https://developer.android.com/studio/install).
* Disable Instant Run. This is because Fennec and the Geckoview Example app cannot deploy with Instant Run on.
* Select Android Studio > Preferences from the menu bar
* Navigate to Build, Execution, Deployment > Instant Run.
* Uncheck the box that reads `Enable Instant Run to hot swap code/resource changes on deploy`.
![alt text]({{ site.url }}/assets/DisableInstantRun.png "Disable Instant Run")
* Choose File->Open from the toolbar
* Navigate to the root of your `mozilla-central` source directory and click "Open"
* Click yes if it asks if you want to use the gradle wrapper.
* If the gradle sync does not automatically start, select File > Sync Project with Gradle Files.
* Wait for the project to index and gradle to sync. Once synced, the workspace will reconfigure to display the different projects.
* annotations contains custom annotations used inside GeckoView and Fennec.
* app is Fennec - Firefox for Android. Here is where you will find code specific to that app.
* geckoview is the GeckoView project. Here is all the Java files related to GeckoView
* geckoview_example is an example browser built using GeckoView.
* omnijar contains the parts of Gecko and GeckoView that are not written in Java or Kotlin
* thirdparty contains third party code that Fennec and GeckoView use.
![alt text]({{ site.url }}/assets/GeckoViewStructure.png "GeckoView Structure")
Now you're set up and ready to go.
**Important: at this time, building from Android Studio or directly from Gradle does not (re-)compile native code, including C++ and Rust.** This means you will need to run `mach build` yourself to pick up changes to native code. [Bug 1509539](https://bugzilla.mozilla.org/show_bug.cgi?id=1509539) tracks making Android Studio and Gradle do this automatically.
## Performing a bug fix
One you have got GeckoView building and running, you will want to start contributing. There is a general guide to [Performing a Bug Fix for Git Developers](contributing-to-mc) for you to follow. To contribute to GeckoView specifically, you will need the following additional information.
### Running tests and linter locally
To ensure that your patch does not break existing functionality in GeckoView, you can run the junit test suite with the following command
```
./mach geckoview-junit
```
This command also allows you to run individual tests or test classes, e.g.
```
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
```
If your patch makes a GeckoView JavaScript module, you should run ESLint as well:
```
./mach lint -l eslint mobile/android/modules/geckoview/
```
To see information on other options, simply run `./mach geckoview-junit --help`; of particular note for dealing with intermittent test failures are `--repeat N` and `--run-until-failure`, both of which do exactly what youd expect.
If you use Android Studio, and the emulator had been started by Android Studio, you will find the logcat output for the test in Android Studio (Logcat tab at the bottom), even if you start the test from your terminal.
To see logcat output in terminal, run the test in one terminal window, and `adb logcat` in another terminal window. Make sure that output of `which adb` includes .mozbuild. If it doesn't, add path to mozbuild tools to your PATH: `export PATH=$HOME/.mozbuild/android-sdk-<your OS - e.g. macos or linux>/platform-tools:$PATH`. Make sure to start the emulator from the terminal (if it had not been started, ``./mach geckoview-junit` will ask you if you want to start the emulator - say YES. Alternatively, you can run `./mach android-emulator` before `./mach geckoview-junit`).
### Updating the changelog and API documentation
If the patch that you want to submit changes the public API for GeckoView, you must ensure that the API documentation is kept up to date. To check whether your patch has altered the API, run the following command.
```bash
./mach lint --linter android-api-lint
```
The output of this command will inform you if any changes you have made break the existing API. Review the changes and follow the instructions it provides.
If the linter asks you to update the changelog, please ensure that you follow the correct format for changelog entries. Under the heading for the next release version, add a new entry for the changes that you are making to the API, along with links to any relevant files, and bug number e.g.
{% raw %}
```
- Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
not `about:config` should be available.
([bug 1540065]({{bugzilla}}1540065))
[71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled-boolean-
```
{% endraw %}
### Submitting to the `try` server
It is advisable to run your tests before submitting your patch. You can do this using Mozilla's `try` server. To submit a GeckoView patch to `try` before submitting it for review, type:
```bash
./mach try fuzzy -q "android"
```
This will run all of the Android test suite. If your patch passes on `try` you can be (fairly) confident that it will land successfully after review.
### Tagging a reviewer
When submitting a patch to Phabricator, if you know who you want to review your patch, put their Phabricator handle against the `reviewers` field.
If you don't know who to tag for a review in the Phabricator submission message, leave the field blank and, after submission, follow the link to the patch in Phabricator and scroll to the bottom of the screen until you see the comment box.
* Select the `Add Action` drop down and pick the `Change Reviewers` option.
* In the presented box, add `geckoview-reviewers`. Selecting this group as the reviewer will notify all the members of the GeckoView team there is a patch to review.
* Click `Submit` to submit the reviewer change request.
## Include GeckoView as a dependency
If you want to include a development version of GeckoView as a dependency inside another app, you must link to a local copy. There are several ways to achieve this, but the preferred way is to use Gradle's *dependency substitution* mechanism, for which there is first-class support in `mozilla-central` and a pattern throughout Mozilla's GeckoView-consuming ecosystem.
The good news is that `mach build` produces everything you need, so that after the configuration below, you should find that the following commands rebuild your local GeckoView and then consume your local version in the downstream project.
```sh
cd /path/to/mozilla-central && ./mach build
cd /path/to/project && ./gradlew assembleDebug
```
**Be sure that your `mozconfig` specifies the correct `--target` argument for your target device.** Many projects use "ABI splitting" to include only the target device's native code libraries in APKs deployed to the device. On x86-64 and aarch64 devices, this can result in GeckoView failing to find any libraries, because valid x86 and ARM libraries were not included in a deployed APK. Avoid this by setting `--target` to the exact ABI that your device supports.
### Dependency substiting your local GeckoView into a Mozilla project
Most GeckoView-consuming projects produced by Mozilla support dependency substitution via `local.properties`. These projects include:
* [Fenix](https://github.com/mozilla-mobile/fenix)
* [reference-browser](https://github.com/mozilla-mobile/reference-browser)
* [android-components](https://github.com/mozilla-mobile/android-components)
* [Firefox Reality](https://github.com/MozillaReality/FirefoxReality)
Simply edit (or create) the file `local.properties` in the project root and include a line like:
```properties
dependencySubstitutions.geckoviewTopsrcdir=/path/to/mozilla-central
```
The default object directory -- the one that a plain `mach build` discovers -- will be used. You can optionally specify a particular object directory with an additional line like:
```properties
dependencySubstitutions.geckoviewTopobjdir=/path/to/object-directory
```
With these lines, the GeckoView-consuming project should use the GeckoView AAR produced by `mach build` in your local `mozilla-central`.
**Remember to remove the lines in `local.properties` when you want to return to using the published GeckoView builds!**
### Dependency substituting your local GeckoView into a non-Mozilla project
In projects that don't have first-class support for dependency substitution already, you can do the substitution yourself. See the documentation in [substitue-local-geckoview.gradle](https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle), but roughly: in each Gradle project that consumes GeckoView, i.e., in each `build.gradle` with a `dependencies { ... 'org.mozilla.geckoview:geckoview-...' }` block, include lines like:
```groovy
ext.topsrcdir = "/path/to/mozilla-central"
ext.topobjdir = "/path/to/object-directory" // Optional.
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
```
**Remember to remove the lines from all `build.gradle` files when you want to return to using the published GeckoView builds!**
## Next Steps
- Get started with [Native Debugging](native-debugging)

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

@ -0,0 +1,324 @@
.. -*- Mode: rst; fill-column: 80; -*-
===========================
GeckoView Contributor Guide
===========================
Table of contents
=================
.. contents:: :local:
GeckoView Contributor Quick Start Guide
=======================================
This is a guide for developers who want to contribute to the GeckoView
project. If you want to get started using GeckoView in your app then you
should refer to the
`wiki <https://wiki.mozilla.org/Mobile/GeckoView#Get_Started>`_.
You may also be interested in how to get up and running with `Firefox
For
Android <https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build>`_.
Get set up with Mozilla Central
-------------------------------
The GeckoView codebase is part of the main Firefox tree and can be found
in ``mozilla-central``. You will need to get set up as a contributor to
Firefox in order to contribute to GeckoView. To get set up with
``mozilla-central``, follow the `Quick Start Guide for Git
Users <mc-quick-start.html>`_, or the `Contributing to the Mozilla code
base <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction>`_
guide on `MDN <https://developer.mozilla.org/>`_ for Mercurial users.
Once you have a copy of ``mozilla-central``, you will need to build
GeckoView.
Bootstrap Gecko
---------------
Bootstrap configures everything for GeckoView and Fennec (Firefox for Android) development.
- Ensure you have ``mozilla-central`` checked out. If this is the first
time you are doing this, it may take some time.
.. code:: bash
git checkout central/default
If you are on a mac, you will need to have the Xcode build tools
installed. You can do this by either `installing
Xcode <https://developer.apple.com/xcode/>`__ or installing only the
tools from the command line by running ``xcode-select --install`` and
following the on screen instructions. Use the ``--no-interactive``
argument to automatically accept any license agreements.
.. code:: bash
./mach bootstrap [ --no-interactive]
- Choose option \`4. Firefox for Android\` for GeckoView development.
This will give you a version of Gecko configured for Android that has
not bundled the native code into embedded libraries so you can amend
the code.
- Say Y to all configuration options
- Once ``mach bootstrap`` is complete it will tell you to copy and
paste some configuration into your ``mozconfig`` file. The
``mozconfig`` file can be found in the root of your ``gecko`` repo -
or create a file called ``mozconfig`` if it does not exist. Check
that the correct value is associated with the ``--target`` argument
as this may not correctly match your setup. Copy the file contents
from the ``mach bootstrap`` output into your file and save in the
root directory of your project.
Build from the command line
---------------------------
In order to pick up the configuration changes we just made we need to
build from the command line. This will update generated sources, compile
native code, and produce GeckoView AARs and example and test APKs.
.. code:: bash
./mach build
Build Using Android Studio
--------------------------
- Install `Android
Studio <https://developer.android.com/studio/install>`_.
- Disable Instant Run. This is because Fennec and the Geckoview Example
app cannot deploy with Instant Run on.
- Select Android Studio > Preferences from the menu bar
- Navigate to Build, Execution, Deployment > Instant Run.
- Uncheck the box that reads
``Enable Instant Run to hot swap code/resource changes on deploy``.
|alt text|
- Choose File->Open from the toolbar
- Navigate to the root of your ``mozilla-central`` source directory and
click “Open”
- Click yes if it asks if you want to use the gradle wrapper.
- If the gradle sync does not automatically start, select File >
Sync Project with Gradle Files.
- Wait for the project to index and gradle to sync. Once synced, the
workspace will reconfigure to display the different projects.
- annotations contains custom annotations used inside GeckoView and
Fennec.
- app is Fennec - Firefox for Android. Here is where you will find
code specific to that app.
- geckoview is the GeckoView project. Here is all the Java files
related to GeckoView
- geckoview_example is an example browser built using GeckoView.
- omnijar contains the parts of Gecko and GeckoView that are not
written in Java or Kotlin
- thirdparty contains third party code that Fennec and GeckoView
use.
|alt text|
Now youre set up and ready to go.
**Important: at this time, building from Android Studio or directly from
Gradle does not (re-)compile native code, including C++ and Rust.** This
means you will need to run ``mach build`` yourself to pick up changes to
native code. `Bug
1509539 <https://bugzilla.mozilla.org/show_bug.cgi?id=1509539>`_ tracks
making Android Studio and Gradle do this automatically.
Performing a bug fix
--------------------
One you have got GeckoView building and running, you will want to start
contributing. There is a general guide to `Performing a Bug Fix for Git
Developers <contributing-to-mc.html>`_ for you to follow. To contribute to
GeckoView specifically, you will need the following additional
information.
Running tests and linter locally
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To ensure that your patch does not break existing functionality in
GeckoView, you can run the junit test suite with the following command
::
./mach geckoview-junit
This command also allows you to run individual tests or test classes,
e.g.
::
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
If your patch makes a GeckoView JavaScript module, you should run ESLint
as well:
::
./mach lint -l eslint mobile/android/modules/geckoview/
To see information on other options, simply run
``./mach geckoview-junit --help``; of particular note for dealing with
intermittent test failures are ``--repeat N`` and
``--run-until-failure``, both of which do exactly what youd expect.
Updating the changelog and API documentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the patch that you want to submit changes the public API for
GeckoView, you must ensure that the API documentation is kept up to
date. To check whether your patch has altered the API, run the following
command.
.. code:: bash
./mach lint --linter android-api-lint
The output of this command will inform you if any changes you have made
break the existing API. Review the changes and follow the instructions
it provides.
If the linter asks you to update the changelog, please ensure that you
follow the correct format for changelog entries. Under the heading for
the next release version, add a new entry for the changes that you are
making to the API, along with links to any relevant files, and bug
number e.g.
::
- Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
not `about:config` should be available.
([bug 1540065]({{bugzilla}}1540065))
[71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled-boolean-
Submitting to the ``try`` server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is advisable to run your tests before submitting your patch. You can
do this using Mozillas ``try`` server. To submit a GeckoView patch to
``try`` before submitting it for review, type:
.. code:: bash
./mach try fuzzy -q "android"
This will run all of the Android test suite. If your patch passes on
``try`` you can be (fairly) confident that it will land successfully
after review.
Tagging a reviewer
~~~~~~~~~~~~~~~~~~
When submitting a patch to Phabricator, if you know who you want to
review your patch, put their Phabricator handle against the
``reviewers`` field.
If you dont know who to tag for a review in the Phabricator submission
message, leave the field blank and, after submission, follow the link to
the patch in Phabricator and scroll to the bottom of the screen until
you see the comment box.
- Select the ``Add Action`` drop down and pick
the ``Change Reviewers`` option.
- In the presented box, add
``geckoview-reviewers``. Selecting this group as the reviewer will
notify all the members of the GeckoView team there is a patch to review.
- Click ``Submit`` to submit the reviewer change request.
Include GeckoView as a dependency
---------------------------------
If you want to include a development version of GeckoView as a
dependency inside another app, you must link to a local copy. There are
several ways to achieve this, but the preferred way is to use Gradles
*dependency substitution* mechanism, for which there is first-class
support in ``mozilla-central`` and a pattern throughout Mozillas
GeckoView-consuming ecosystem.
The good news is that ``mach build`` produces everything you need, so
that after the configuration below, you should find that the following
commands rebuild your local GeckoView and then consume your local
version in the downstream project.
.. code:: sh
cd /path/to/mozilla-central && ./mach build
cd /path/to/project && ./gradlew assembleDebug
**Be sure that your ``mozconfig`` specifies the correct ``--target``
argument for your target device.** Many projects use “ABI splitting” to
include only the target devices native code libraries in APKs deployed
to the device. On x86-64 and aarch64 devices, this can result in
GeckoView failing to find any libraries, because valid x86 and ARM
libraries were not included in a deployed APK. Avoid this by setting
``--target`` to the exact ABI that your device supports.
Dependency substiting your local GeckoView into a Mozilla project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Most GeckoView-consuming projects produced by Mozilla support dependency
substitution via ``local.properties``. These projects include:
- `Fenix <https://github.com/mozilla-mobile/fenix>`_
- `reference-browser <https://github.com/mozilla-mobile/reference-browser>`_
- `android-components <https://github.com/mozilla-mobile/android-components>`_
- `Firefox Reality <https://github.com/MozillaReality/FirefoxReality>`_
Simply edit (or create) the file ``local.properties`` in the project
root and include a line like:
.. code:: properties
dependencySubstitutions.geckoviewTopsrcdir=/path/to/mozilla-central
The default object directory – the one that a plain ``mach build``
discovers – will be used. You can optionally specify a particular object
directory with an additional line like:
.. code:: properties
dependencySubstitutions.geckoviewTopobjdir=/path/to/object-directory
With these lines, the GeckoView-consuming project should use the
GeckoView AAR produced by ``mach build`` in your local
``mozilla-central``.
**Remember to remove the lines in ``local.properties`` when you want to
return to using the published GeckoView builds!**
Dependency substituting your local GeckoView into a non-Mozilla project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In projects that dont have first-class support for dependency
substitution already, you can do the substitution yourself. See the
documentation in
`substitue-local-geckoview.gradle <https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle>`_,
but roughly: in each Gradle project that consumes GeckoView, i.e., in
each ``build.gradle`` with a
``dependencies { ... 'org.mozilla.geckoview:geckoview-...' }`` block,
include lines like:
.. code:: groovy
ext.topsrcdir = "/path/to/mozilla-central"
ext.topobjdir = "/path/to/object-directory" // Optional.
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
**Remember to remove the lines from all ``build.gradle`` files when you
want to return to using the published GeckoView builds!**
Next Steps
----------
- Get started with `Native Debugging <native-debugging.html>`_
.. |alt text| image:: ../assets/DisableInstantRun.png
.. |alt text| image:: ../assets/GeckoViewStructure.png

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

@ -1,20 +0,0 @@
---
layout: default
title: Contributing to GeckoView
nav_order: 4
---
# Contributor Site
If you want to run GeckoView from code, or start contributing back to the project, here you will find resources to help you do that.
- [GeckoView Contributor Quick Start Guide](geckoview-quick-start): Get GeckoView set up for development.
- [GeckoView for Gecko Engineers](for-gecko-engineers): A quick-start guide for those already familiar with contributing to Firefox development.
- [Mozilla Central Quick Start Guide](mc-quick-start):
Get Mozilla Central set up for development.
- [Mozilla Central Contributor Guide](contributing-to-mc):
Get started as a contributor to Mozilla Central.
- [Guide to Native Debugging in Android Studio](native-debugging):
Set up Android Studio for debugging native code.
If there is documentation that you feel is missing, or an existing document doesn't cover the aspect that you are looking for, please request it by raising an issue on our [documentation site](https://github.com/mozilla/geckoview/issues).

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

@ -0,0 +1,37 @@
.. -*- Mode: rst; fill-column: 80; -*-
=========================
Contributing to GeckoView
=========================
Contributor Site
================
.. toctree::
:maxdepth: 1
:hidden:
geckoview-quick-start
for-gecko-engineers
mc-quick-start
contributing-to-mc
native-debugging
If you want to run GeckoView from code, or start contributing back to
the project, here you will find resources to help you do that.
- `GeckoView Contributor Quick Start Guide <geckoview-quick-start.html>`_:
Get GeckoView set up for development.
- `GeckoView for Gecko Engineers <for-gecko-engineers.html>`_: A
quick-start guide for those already familiar with contributing to
Firefox development.
- `Mozilla Central Quick Start Guide <mc-quick-start.html>`_: Get Mozilla
Central set up for development.
- `Mozilla Central Contributor Guide <contributing-to-mc.html>`_: Get
started as a contributor to Mozilla Central.
- `Guide to Native Debugging in Android Studio <native-debugging.html>`_:
Set up Android Studio for debugging native code.
If there is documentation that you feel is missing, or an existing
document doesnt cover the aspect that you are looking for, please
request it by raising an issue on our `documentation
site <https://github.com/mozilla/geckoview/issues>`_.

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

@ -1,128 +0,0 @@
---
layout: default
title: Mozilla Central Quick Start
summary: Guide to setting up as a Git contributor to mozilla-central.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,compiling,mercurial,git-cinnabar]
nav_exclude: true
exclude: true
---
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
# Firefox Developer Git Quick Start Guide
Getting setup to as a first time Mozilla contributor is hard. There are plenty of guides out there to help you get started as a contributor, but many of the new contributor guides out of date often more current ones are aimed at more experienced contributors. If you want to review these guides, you can find several linked to from [Contributing to the Mozilla code base](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction) on [MDN](https://developer.mozilla.org/).
This guide will take you through setting up as a contributor to `mozilla-central`, the Firefox main repository, as a git user.
## Setup
The first thing you will need is to install Mercurial as this is the VCS that `mozilla-central` uses.
### Mac
#### Homebrew
```bash
brew install mercurial
```
#### macports
```bash
sudo port install mercurial
```
### Linux
#### apt
```bash
sudo apt-get install mercurial
```
Alternatively you can install [Mercurial directly](https://www.mercurial-scm.org/wiki/Download).
Check that you have successfully installed Mercurial by running:
```bash
hg --version
```
If you are an experienced git user and are unfamiliar with Mercurial, you may want to install `git-cinnabar`. Cinnabar is a git remote helper that allows you to interact with Mercurial repos using git semantics.
## git-cinnabar
There is a Homebrew install option for `git-cinnabar`, but this did not work for me, nor did the installer option. Using these tools, when I tried to clone the Mercurial repo it hung and did not complete. I had to do a manual install before I could use `git-cinnabar` successfully to download a Mercurial repo. If you would like to try either of these option, however, here they are:
### Mac
#### Homebrew
```bash
brew install git-cinnabar
```
### All Platforms
#### Installer
```bash
git cinnabar download
```
#### Manual installation
```bash
git clone https://github.com/glandium/git-cinnabar.git && cd git-cinnabar
make
export PATH="$PATH:/somewhere/git-cinnabar"
echo 'export PATH="$PATH:/somewhere/git-cinnabar"' >> ~/.bash_profile
git cinnabar download
```
`git-cinnabar`'s creator, [glandium](https://glandium.org/), has written a number of posts about setting up for Firefox Development with git. This [post](https://glandium.org/blog/?page_id=3438) is the one that has formed the basis for this walkthrough.
In synopsis:
* initialize an empty git repository
```bash
git init gecko && cd gecko
```
* Configure git:
```bash
git config fetch.prune true
git config push.default upstream
```
* Add remotes for your repositories. There are several to choose from, `central`, `inbound`, `beta`, `release` etc. but in reality, if you plan on using Phabricator, which is Firefox's preferred patch submission system, you only need to set up `central`. It might be advisable to have access to `inbound` however, if you want to work on a version of Firefox that is queued for release. This guide will be focused on Phabricator.
```bash
git remote add central hg::https://hg.mozilla.org/mozilla-central -t branches/default/tip
git remote add inbound hg::https://hg.mozilla.org/integration/mozilla-inbound -t branches/default/tip
git remote set-url --push central hg::ssh://hg.mozilla.org/mozilla-central
git remote set-url --push inbound hg::ssh://hg.mozilla.org/integration/mozilla-inbound
```
* Expose the branch tip to get quick access with some easy names.
```bash
git config remote.central.fetch +refs/heads/branches/default/tip:refs/remotes/central/default
git config remote.inbound.fetch +refs/heads/branches/default/tip:refs/remotes/inbound/default
```
* Setup a remote for the try server. The try server is an easy way to test a patch without actually checking the patch into the core repository. Your code will go through the same tests as a `mozilla-central` push, and you'll be able to download builds if you wish.
```bash
git remote add try hg::https://hg.mozilla.org/try
git config remote.try.skipDefaultUpdate true
git remote set-url --push try hg::ssh://hg.mozilla.org/try
git config remote.try.push +HEAD:refs/heads/branches/default/tip
```
* Now update all the remotes. This performs a `git fetch` on all the remotes. Mozilla Central is a _large_ repository. Be prepared for this to take a very long time.
```bash
git remote update
```
All that's left to do now is pick a bug to fix and [submit a patch](contributing-to-mc).

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

@ -0,0 +1,179 @@
.. -*- Mode: rst; fill-column: 80; -*-
===========================
Mozilla Central Quick Start
===========================
Table of contents
=================
.. contents:: :local:
Firefox Developer Git Quick Start Guide
=======================================
Getting setup to as a first time Mozilla contributor is hard. There are
plenty of guides out there to help you get started as a contributor, but
many of the new contributor guides out of date often more current ones
are aimed at more experienced contributors. If you want to review these
guides, you can find several linked to from `Contributing to the Mozilla code base <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction>`_
on `MDN <https://developer.mozilla.org/>`_.
This guide will take you through setting up as a contributor to
``mozilla-central``, the Firefox main repository, as a git user.
Setup
-----
The first thing you will need is to install Mercurial as this is the VCS
that ``mozilla-central`` uses.
Mac
~~~
Homebrew
^^^^^^^^
.. code:: bash
brew install mercurial
macports
^^^^^^^^
.. code:: bash
sudo port install mercurial
Linux
~~~~~
apt
^^^
.. code:: bash
sudo apt-get install mercurial
Alternatively you can install `Mercurial directly <https://www.mercurial-scm.org/wiki/Download>`_.
Check that you have successfully installed Mercurial by running:
.. code:: bash
hg --version
If you are an experienced git user and are unfamiliar with Mercurial,
you may want to install ``git-cinnabar``. Cinnabar is a git remote
helper that allows you to interact with Mercurial repos using git
semantics.
git-cinnabar
------------
There is a Homebrew install option for ``git-cinnabar``, but this did
not work for me, nor did the installer option. Using these tools, when I
tried to clone the Mercurial repo it hung and did not complete. I had to
do a manual install before I could use ``git-cinnabar`` successfully to
download a Mercurial repo. If you would like to try either of these
option, however, here they are:
.. _mac-1:
Mac
~~~
.. _homebrew-1:
Homebrew
^^^^^^^^
.. code:: bash
brew install git-cinnabar
All Platforms
~~~~~~~~~~~~~
Installer
^^^^^^^^^
.. code:: bash
git cinnabar download
Manual installation
^^^^^^^^^^^^^^^^^^^
.. code:: bash
git clone https://github.com/glandium/git-cinnabar.git && cd git-cinnabar
make
export PATH="$PATH:/somewhere/git-cinnabar"
echo 'export PATH="$PATH:/somewhere/git-cinnabar"' >> ~/.bash_profile
git cinnabar download
``git-cinnabar``\ s creator, `glandium <https://glandium.org/>`_, has
written a number of posts about setting up for Firefox Development with
git. This `post <https://glandium.org/blog/?page_id=3438>`_ is the one
that has formed the basis for this walkthrough.
In synopsis:
- initialize an empty git repository
.. code:: bash
git init gecko && cd gecko
- Configure git:
.. code:: bash
git config fetch.prune true
git config push.default upstream
- Add remotes for your repositories. There are several to choose from,
``central``, ``inbound``, ``beta``, ``release`` etc. but in reality,
if you plan on using Phabricator, which is Firefoxs preferred patch
submission system, you only need to set up ``central``. It might be
advisable to have access to ``inbound`` however, if you want to work
on a version of Firefox that is queued for release. This guide will
be focused on Phabricator.
.. code:: bash
git remote add central hg::https://hg.mozilla.org/mozilla-central -t branches/default/tip
git remote add inbound hg::https://hg.mozilla.org/integration/mozilla-inbound -t branches/default/tip
git remote set-url --push central hg::ssh://hg.mozilla.org/mozilla-central
git remote set-url --push inbound hg::ssh://hg.mozilla.org/integration/mozilla-inbound
- Expose the branch tip to get quick access with some easy names.
.. code:: bash
git config remote.central.fetch +refs/heads/branches/default/tip:refs/remotes/central/default
git config remote.inbound.fetch +refs/heads/branches/default/tip:refs/remotes/inbound/default
- Setup a remote for the try server. The try server is an easy way to
test a patch without actually checking the patch into the core
repository. Your code will go through the same tests as a
``mozilla-central`` push, and youll be able to download builds if
you wish.
.. code:: bash
git remote add try hg::https://hg.mozilla.org/try
git config remote.try.skipDefaultUpdate true
git remote set-url --push try hg::ssh://hg.mozilla.org/try
git config remote.try.push +HEAD:refs/heads/branches/default/tip
- Now update all the remotes. This performs a ``git fetch`` on all the
remotes. Mozilla Central is a *large* repository. Be prepared for
this to take a very long time.
.. code:: bash
git remote update
All thats left to do now is pick a bug to fix and `submit a
patch <contributing-to-mc>`__.

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

@ -1,139 +0,0 @@
---
layout: default
title: Debugging Native Code
summary: How to set up native debugging for GeckoView using Android Studio.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,debugging,native,android studio]
nav_exclude: true
exclude: true
---
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
# Debugging Native Code in Android Studio.
If you want to work on the C++ code that powers GeckoView, you will need to be able to perform native debugging inside Android Studio. This article will guide you through how to do that.
If you need to get set up with GeckoView for the first time, follow the [Quick Start Guide](geckoview-quick-start).
## Perform a debug build of Gecko.
1. Edit your `mozconfig` file and add the following lines. These will ensure that the build includes debug checks and symbols.
```
ac_add_options --enable-debug
ac_add_options --with-android-ndk="<path>/.mozbuild/android-ndk-r17b"
```
2. Ensure that the following lines are commented out in your `mozconfig` if present. `./mach configure` will not allow artifact builds to be enabled when generating a debug build.
```
# ac_add_options --enable-artifact-builds
```
3. To be absolutely sure that Android Studio will pick up your debug symbols, the first time you perform a debug build it is best to clobber your `MOZ_OBJDIR`. Subsequent builds should not need this step.
```bash
./mach clobber
```
4. Build as usual. Because this is a debug build, and because you have clobbered your `MOZ_OBJDIR`, this will take a long time. Subsequent builds will be incremental and take less time, so go make yourself a cup of your favourite beverage.
```bash
./mach build
```
## Set up lldb to find your symbols
Edit your `~/.lldbinit` file (or create one if one does not already exist) and add the following lines.
The first line tells LLDB to enable inline breakpoints - Android Studio will need this if you want to use visual breakpoints.
The remaining lines tell LLDB where to go to find the symbols for debugging.
```bash
settings set target.inline-breakpoint-strategy always
settings append target.exec-search-paths <PATH>/objdir-android-opt/toolkit/library/build
settings append target.exec-search-paths <PATH>/objdir-android-opt/mozglue/build
```
# Set up Android Studio to perform native debugging.
1. Edit the configuration that you want to debug by clicking `Run -> Edit Configurations...` and selecting the correct configuration from the options on the left hand side of the resulting window.
2. Select the `Debugger` tab.
3. Select `Dual` from the `Debug type` select box. Dual will allow debugging of both native and Java code in the same session. It is possible to use `Native`, but it will only allow for debugging native code, and it's frequently necessary to break in the Java code that configures Gecko and child processes in order to attach debuggers at the correct times.
4. Under `Symbol Directories`, add a new path pointing to `<PATH>/objdir-android-opt/toolkit/library/build`, the same path that you entered into your `.lldbinit` file.
5. Select `Apply` and `OK` to close the window.
# Debug Native code in Android Studio
1. The first time you are running a debug session for your app, it's best to start from a completely clean build. Click `Build -> Rebuild Project` to clean and rebuild. You can also choose to remove any existing builds from your emulator to be completely sure, but this may not be necessary.
2. If using Android Studio visual breakpoints, set your breakpoints in your native code.
3. Run the app in debug mode as usual.
4. When debugging Fennec or geckoview_example, you will almost immediately hit a breakpoint in `ElfLoader.cpp`. This is expected. If you are not using Android Studio visual breakpoints, you can set your breakpoints here using the lldb console that is available now this breakpoint has been hit. To set a breakpoint, select the app tab (if running Dual, there will also be an `<app> java` tab) from the debug window, and then select the `lldb` console tab. Type the following into the console:
```lldb
b <file>.cpp:<line number>
```
5. Once your breakpoints have been set, click the continue execution button to move beyond the `ElfLoader` breakpoint and your newly set native breakpoints should be hit. Debug as usual.
## Attaching debuggers to content and other child processes
Internally, GeckoView has a multi-process architecture. The main Gecko process lives in the main Android process, but content rendering and some other functions live in child processes. This balances load, ensures certain critical security properties, and allows GeckoView to recover if content processes become unresponsive or crash. However, it's generally delicate to debug child processes because they come and go.
The general approach is to make the Java code in the child process that you want to debug wait for a Java debugger at startup, and then to connect such a Java debugger manually from the Android Studio UI.
[Bug 1522318](https://bugzilla.mozilla.org/show_bug.cgi?id=1522318) added environment variables that makes GeckoView wait for Java debuggers to attach, making this debug process more developer-friendly. See [Configuring GeckoView for Automation](../consumer/docs/automation) for instructions on how to set environment variables that configure GeckoView's runtime environment.
### Making processes wait for a Java debugger
The following environment variable makes the main (Gecko) process wait for a Java debugger to connect:
```shell
MOZ_DEBUG_WAIT_FOR_JAVA_DEBUGGER=1
```
This is a superset of Android Studio's built-in debugging support so it's not particularly useful (unless you want to attach a different jdwp debugger).
The following environment variable makes every child process wait for a Java debugger to connect:
```shell
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=
```
Set `MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=suffix` in the environment to make child processes with an Android process name ending with `suffix` wait for a Java debugger to connect. For example, the following environment variable makes every child content process wait for a Java debugger to connect:
```shell
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
```
An easy way to set this is with `./mach run`:
```shell
./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
```
### Attaching a Java debugger to a waiting child process
This is standard: follow the [Android Studio instructions](https://developer.android.com/studio/debug/index.html#attach-debugger). You must attach a Java debugger, so you almost certainly want to attach a `Dual` debugger and you definitely can't attach only a `Native` debugger.
Determining the correct process to attach to is a little tricky because the mapping from process ID (pid) to process name is not always clear. Gecko content child processes are suffixed `:tab` at this time.
If you attach `Dual` debuggers to both the main process and a content child process, you will have four (4!) debug tabs to manage in Android Studio, which is awkward. Android Studio doesn't appear to configure attached debuggers in the same way that it configures debuggers connecting to launched Run Configurations, so you may need to manually configure search paths -- i.e., you may need to invoke the contents of your `lldbinit` file in the appropriate `lldb` console by hand, using an invocation like `command source /absolute/path/to/topobjdir/lldbinit`.
Android Studio also doesn't appear to support targeting breakpoints from the UI (say, from clicking in a gutter) to specific debug tabs, so you may also need to set breakpoints in the appropriate `lldb` console by hand.
Managing more debug tabs may require different approaches.
### Using Android Studio on Windows
You can now use [artifact builds](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Build_Instructions/Artifact_builds) mode on [MozillaBuild environment](https://wiki.mozilla.org/MozillaBuild) even if you are not using WSL. If you want to debug GeckoView using Android Studio on Windows, you have to set an additional environment variable via the Control Panel to run the gradle script. The `mach` command sets these variables automatically, but Android Studio cannot.
If you install MozillaBuild tools to `C:\mozilla-build` (default installation path), you have to set the `MOZILLABUILD` environment variable to recognize MozillaBuild installation path.
To set environment variable on Windows 10, open the `Control Panel` from `Windows System`, then select `System and Security` - `System` - `Advanced system settings` - `Environment Variables ...`.
To set the `MOZILLABUILD` variable, click `New...` in `User variables for`, then `Variable name:` is `MOZILLABUILD` and `Variable value:` is `C:\mozilla-build`.
You also have to append some tool paths to the `Path` environment variable.
To append the variables to PATH, double click `Path` in `User Variables for`, then click `New`. And append the following variables to `Path`.
* `%MOZILLABUILD%\msys\bin`
* `%MOZILLABUILD%\bin`

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

@ -0,0 +1,241 @@
.. -*- Mode: rst; fill-column: 80; -*-
=====================
Debugging Native Code
=====================
Table of contents
=================
.. contents:: :local:
Debugging Native Code in Android Studio.
========================================
If you want to work on the C++ code that powers GeckoView, you will need
to be able to perform native debugging inside Android Studio. This
article will guide you through how to do that.
If you need to get set up with GeckoView for the first time, follow the
`Quick Start Guide <geckoview-quick-start.html>`_.
Perform a debug build of Gecko.
-------------------------------
1. Edit your ``mozconfig`` file and add the following lines. These will
ensure that the build includes debug checks and symbols.
.. code:: txt
ac_add_options --enable-debug
ac_add_options --with-android-ndk="<path>/.mozbuild/android-ndk-r17b"
2. Ensure that the following lines are commented out in your
``mozconfig`` if present. ``./mach configure`` will not allow
artifact builds to be enabled when generating a debug build.
.. code:: txt
# ac_add_options --enable-artifact-builds
3. To be absolutely sure that Android Studio will pick up your debug
symbols, the first time you perform a debug build it is best to
clobber your ``MOZ_OBJDIR``. Subsequent builds should not need this
step.
.. code:: bash
./mach clobber
4. Build as usual. Because this is a debug build, and because you have
clobbered your ``MOZ_OBJDIR``, this will take a long time. Subsequent
builds will be incremental and take less time, so go make yourself a
cup of your favourite beverage.
.. code:: bash
./mach build
Set up lldb to find your symbols
--------------------------------
Edit your ``~/.lldbinit`` file (or create one if one does not already
exist) and add the following lines.
The first line tells LLDB to enable inline breakpoints - Android Studio
will need this if you want to use visual breakpoints.
The remaining lines tell LLDB where to go to find the symbols for
debugging.
.. code:: bash
settings set target.inline-breakpoint-strategy always
settings append target.exec-search-paths <PATH>/objdir-android-opt/toolkit/library/build
settings append target.exec-search-paths <PATH>/objdir-android-opt/mozglue/build
Set up Android Studio to perform native debugging.
==================================================
1. Edit the configuration that you want to debug by clicking
``Run -> Edit Configurations...`` and selecting the correct
configuration from the options on the left hand side of the resulting
window.
2. Select the ``Debugger`` tab.
3. Select ``Dual`` from the ``Debug type`` select box. Dual will allow
debugging of both native and Java code in the same session. It is
possible to use ``Native``, but it will only allow for debugging
native code, and its frequently necessary to break in the Java code
that configures Gecko and child processes in order to attach
debuggers at the correct times.
4. Under ``Symbol Directories``, add a new path pointing to
``<PATH>/objdir-android-opt/toolkit/library/build``, the same path
that you entered into your ``.lldbinit`` file.
5. Select ``Apply`` and ``OK`` to close the window.
Debug Native code in Android Studio
===================================
1. The first time you are running a debug session for your app, its
best to start from a completely clean build. Click
``Build -> Rebuild Project`` to clean and rebuild. You can also
choose to remove any existing builds from your emulator to be
completely sure, but this may not be necessary.
2. If using Android Studio visual breakpoints, set your breakpoints in
your native code.
3. Run the app in debug mode as usual.
4. When debugging Fennec or geckoview_example, you will almost
immediately hit a breakpoint in ``ElfLoader.cpp``. This is expected.
If you are not using Android Studio visual breakpoints, you can set
your breakpoints here using the lldb console that is available now
this breakpoint has been hit. To set a breakpoint, select the app tab
(if running Dual, there will also be an ``<app> java`` tab) from the
debug window, and then select the ``lldb`` console tab. Type the
following into the console:
.. code:: lldb
b <file>.cpp:<line number>
5. Once your breakpoints have been set, click the continue execution
button to move beyond the ``ElfLoader`` breakpoint and your newly set
native breakpoints should be hit. Debug as usual.
Attaching debuggers to content and other child processes
--------------------------------------------------------
Internally, GeckoView has a multi-process architecture. The main Gecko
process lives in the main Android process, but content rendering and
some other functions live in child processes. This balances load,
ensures certain critical security properties, and allows GeckoView to
recover if content processes become unresponsive or crash. However, its
generally delicate to debug child processes because they come and go.
The general approach is to make the Java code in the child process that
you want to debug wait for a Java debugger at startup, and then to
connect such a Java debugger manually from the Android Studio UI.
`Bug 1522318 <https://bugzilla.mozilla.org/show_bug.cgi?id=1522318>`__
added environment variables that makes GeckoView wait for Java debuggers
to attach, making this debug process more developer-friendly. See
`Configuring GeckoView for Automation <../consumer/automation.html>`__
for instructions on how to set environment variables that configure
GeckoViews runtime environment.
Making processes wait for a Java debugger
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following environment variable makes the main (Gecko) process wait
for a Java debugger to connect:
.. code:: shell
MOZ_DEBUG_WAIT_FOR_JAVA_DEBUGGER=1
This is a superset of Android Studios built-in debugging support so
its not particularly useful (unless you want to attach a different jdwp
debugger).
The following environment variable makes every child process wait for a
Java debugger to connect:
.. code:: shell
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=
Set ``MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=suffix`` in the environment
to make child processes with an Android process name ending with
``suffix`` wait for a Java debugger to connect. For example, the
following environment variable makes every child content process wait
for a Java debugger to connect:
.. code:: shell
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
An easy way to set this is with ``./mach run``:
.. code:: shell
./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
Attaching a Java debugger to a waiting child process
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is standard: follow the `Android Studio instructions <https://developer.android.com/studio/debug/index.html#attach-debugger>`_.
You must attach a Java debugger, so you almost certainly want to attach
a ``Dual`` debugger and you definitely cant attach only a ``Native``
debugger.
Determining the correct process to attach to is a little tricky because
the mapping from process ID (pid) to process name is not always clear.
Gecko content child processes are suffixed ``:tab`` at this time.
If you attach ``Dual`` debuggers to both the main process and a content
child process, you will have four (4!) debug tabs to manage in Android
Studio, which is awkward. Android Studio doesnt appear to configure
attached debuggers in the same way that it configures debuggers
connecting to launched Run Configurations, so you may need to manually
configure search paths – i.e., you may need to invoke the contents of
your ``lldbinit`` file in the appropriate ``lldb`` console by hand,
using an invocation like
``command source /absolute/path/to/topobjdir/lldbinit``.
Android Studio also doesnt appear to support targeting breakpoints from
the UI (say, from clicking in a gutter) to specific debug tabs, so you
may also need to set breakpoints in the appropriate ``lldb`` console by
hand.
Managing more debug tabs may require different approaches.
Using Android Studio on Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can now use `artifact builds <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Build_Instructions/Artifact_builds>`_
mode on `MozillaBuild environment <https://wiki.mozilla.org/MozillaBuild>`_ even if you are
not using WSL. If you want to debug GeckoView using Android Studio on
Windows, you have to set an additional environment variable via the
Control Panel to run the gradle script. The ``mach`` command sets these
variables automatically, but Android Studio cannot.
If you install MozillaBuild tools to ``C:\mozilla-build`` (default
installation path), you have to set the ``MOZILLABUILD`` environment
variable to recognize MozillaBuild installation path.
To set environment variable on Windows 10, open the ``Control Panel``
from ``Windows System``, then select ``System and Security`` -
``System`` - ``Advanced system settings`` -
``Environment Variables ...``.
To set the ``MOZILLABUILD`` variable, click ``New...`` in
``User variables for``, then ``Variable name:`` is ``MOZILLABUILD`` and
``Variable value:`` is ``C:\mozilla-build``.
You also have to append some tool paths to the ``Path`` environment
variable.
To append the variables to PATH, double click ``Path`` in
``User Variables for``, then click ``New``. And append the following
variables to ``Path``.
- ``%MOZILLABUILD%\msys\bin``
- ``%MOZILLABUILD%\bin``

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

@ -1,10 +1,14 @@
---
layout: default
title: Geckoview
nav_order: 1
summary: GeckoView, a WebView-like component from Mozilla specifically designed for building Android browsers.
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central]
---
.. -*- Mode: rst; fill-column: 80; -*-
Welcome to GeckoView's documentation!
=====================================
.. toctree::
:maxdepth: 1
:hidden:
consumer/index
contributor/index
Android offers a built-in WebView, which applications can hook into in order to display web pages within the context of their app. However, Android's WebView is not really intended for building browsers, and hence, many advanced Web APIs are disabled. Furthermore, it is also a moving target: different phones might have different versions of WebView, all of which your app has to support.
@ -15,23 +19,26 @@ That is where GeckoView comes in. GeckoView is:
- **Self-Contained**: Because GeckoView is a standalone library that you bundle with your application, you can be confident that the code you test is the code that will actually run.
- **Standards Compliant**: Like Firefox, GeckoView offers excellent support for modern Web standards.
## Using GeckoView
=================
Using GeckoView
=================
* [Quick Start Guide](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/consumer/docs/geckoview-quick-start.html)
* [Usage Documentation](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/consumer/docs/index.html)
* `Quick Start Guide <consumer/geckoview-quick-start.html>`_
* `Usage Documentation <consumer/index.html>`_
## API Documentation
=================
API Documentation
=================
* [Changelog](https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/doc-files/CHANGELOG)
* [API](https://firefox-source-docs.mozilla.org/index.html)
* `Changelog <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/doc-files/CHANGELOG>`_
* `API <https://firefox-source-docs.mozilla.org/index.html>`_
## More information
* [GeckoView Wiki][1]
* [GeckoView Source Code][2]
* [Raise a bug on GeckoView code][3]
* [Raise a documentation bug][4]
=================
More information
=================
[1]:https://wiki.mozilla.org/Mobile/GeckoView
[2]:https://searchfox.org/mozilla-central/source/mobile/android/geckoview
[3]:https://bugzilla.mozilla.org/enter_bug.cgi?product=GeckoView
[4]:https://github.com/mozilla/geckoview/issues
* Talk to us on `Riot <https://chat.mozilla.org/#/room/#geckoview:mozilla.org>`_
* `GeckoView Wiki <https://wiki.mozilla.org/Mobile/GeckoView>`_
* `GeckoView Source Code <https://searchfox.org/mozilla-central/source/mobile/android/geckoview>`_
* `Raise a bug on GeckoView code <https://bugzilla.mozilla.org/enter_bug.cgi?product=GeckoView>`_
* `Raise a documentation bug <https://github.com/mozilla/geckoview/issues>`_

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

@ -253,18 +253,6 @@ REMOVED/DEPRECATED: Use 'mach lint --linter android-checkstyle'.""")
# Copy over user documentation.
import mozfile
# Remove existing geckoview docs and replace with the local copy.
# Keep all the files that are git specific and not part of the GV documentation.
keep_files = [".git", ".gitignore", "_site", "CODE_OF_CONDUCT.md",
"Gemfile.lock", "README.md"]
for filename in os.listdir(repo_path):
if filename not in keep_files:
filepath = mozpath.join(repo_path, filename)
mozfile.remove(filepath)
src_path = mozpath.join(self.topsrcdir, 'mobile', 'android', 'docs', 'geckoview')
os.system("rsync -aruz {}/ {}/".format(src_path, repo_path))
# Extract new javadoc to specified directory inside repo.
src_tar = mozpath.join(self.topobjdir, 'gradle', 'build', 'mobile', 'android',
'geckoview', 'libs', 'geckoview-javadoc.jar')