Implement the mechanics of fxa login on android, but don't show ui fo… (#1000)
* Implement the mechanics of fxa login on android, but don't show ui for it yet. Also, scopedKeys are not yet implemented. * Hopefully fix the package-lock conflict? * WIP on android scoped keys * Finish implementing login. * created android/user.js to handle android logins
This commit is contained in:
parent
ffac4ae5b1
commit
cab6f1bafb
17 changed files with 592 additions and 304 deletions
|
@ -1,13 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module external.linked.project.id="android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
<module external.linked.project.id="android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="java-gradle" name="Java-Gradle">
|
|
||||||
<configuration>
|
|
||||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
|
||||||
<option name="BUILDABLE" value="false" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global window */
|
/* global window, navigator */
|
||||||
|
|
||||||
window.LIMITS = {
|
window.LIMITS = {
|
||||||
ANON: {
|
ANON: {
|
||||||
|
@ -27,14 +27,18 @@ const locale = require('../common/locales');
|
||||||
const home = require('../app/ui/home');
|
const home = require('../app/ui/home');
|
||||||
const app = choo();
|
const app = choo();
|
||||||
|
|
||||||
|
if (navigator.userAgent === 'Send Android') {
|
||||||
|
assets.setPrefix('/android_asset');
|
||||||
|
}
|
||||||
|
|
||||||
function body(main) {
|
function body(main) {
|
||||||
return function(state, emit) {
|
return function(state, emit) {
|
||||||
return html`<body class="flex flex-col items-center font-sans bg-blue-lightest md:h-screen md:bg-grey-lightest">
|
return html`<body class="flex flex-col items-center font-sans bg-blue-lightest md:h-screen md:bg-grey-lightest">
|
||||||
${header(state, emit)}
|
<a id="hamburger" class="absolute pin-t pin-r z-50" href="#" onclick=${clickPreferences}>
|
||||||
<a id="hamburger" class="absolute pin-t pin-r z-50" href="#" onclick=${clickPreferences}>
|
<img src=${assets.get('preferences.png')} />
|
||||||
<img src=${assets.get('preferences.png')} />
|
</a>
|
||||||
</a>
|
${header(state, emit)}
|
||||||
${main(state, emit)}
|
${main(state, emit)}
|
||||||
</body>`;
|
</body>`;
|
||||||
|
|
||||||
function clickPreferences(event) {
|
function clickPreferences(event) {
|
||||||
|
@ -44,15 +48,22 @@ function body(main) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.use(require('./stores/state').default);
|
||||||
app.use((state, emitter) => {
|
app.use((state, emitter) => {
|
||||||
state.translate = locale.getTranslator();
|
state.translate = locale.getTranslator();
|
||||||
state.capabilities = {}; //TODO
|
state.capabilities = {
|
||||||
|
account: true
|
||||||
|
}; //TODO
|
||||||
|
|
||||||
|
window.finishLogin = async function(accountInfo) {
|
||||||
|
await state.user.finishLogin(accountInfo);
|
||||||
|
emitter.emit('render');
|
||||||
|
};
|
||||||
|
|
||||||
// for debugging
|
// for debugging
|
||||||
window.appState = state;
|
window.appState = state;
|
||||||
window.appEmit = emitter.emit.bind(emitter);
|
window.appEmit = emitter.emit.bind(emitter);
|
||||||
});
|
});
|
||||||
app.use(require('./stores/state').default);
|
|
||||||
app.use(require('../app/fileManager').default);
|
app.use(require('../app/fileManager').default);
|
||||||
app.use(require('./stores/intents').default);
|
app.use(require('./stores/intents').default);
|
||||||
app.route('/', body(home));
|
app.route('/', body(home));
|
||||||
|
|
|
@ -51,19 +51,19 @@
|
||||||
</facet>
|
</facet>
|
||||||
</component>
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
|
||||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources/debug/processDebugResources/r" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources/debugAndroidTest/processDebugAndroidTestResources/r" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||||
|
@ -112,31 +112,40 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/.DS_Store" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/apk_list" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/build-info" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/build-info" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-libraries" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/checkDebugClasspath" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/compatible_screen_manifest" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-apk" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-apk" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-main-apk-res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_main_apk_resources" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_merged_manifests" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_split_apk_resources" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint_jar" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split_list" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||||
|
@ -146,9 +155,11 @@
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
|
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Gradle: net.java.dev.jna:jna-4.5.2" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:runner-1.0.2" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:runner-1.0.2" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
|
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:27.1.1@jar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:27.1.1@jar" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.2.61@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable-27.1.1" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable-27.1.1" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:support-compat-27.1.1" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:support-compat-27.1.1" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel-1.1.0" level="project" />
|
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel-1.1.0" level="project" />
|
||||||
|
@ -162,21 +173,26 @@
|
||||||
<orderEntry type="library" name="Gradle: com.github.delight-im:Android-AdvancedWebView-v3.0.0" level="project" />
|
<orderEntry type="library" name="Gradle: com.github.delight-im:Android-AdvancedWebView-v3.0.0" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test.espresso:espresso-core-3.0.2" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test.espresso:espresso-core-3.0.2" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-coroutines-android:0.23.4@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:support-fragment-27.1.1" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:support-fragment-27.1.1" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: android.arch.core:runtime-1.1.0" level="project" />
|
<orderEntry type="library" name="Gradle: android.arch.core:runtime-1.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61@jar" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3@jar" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:monitor-1.0.2" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:monitor-1.0.2" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7-27.1.1" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7-27.1.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: org.mozilla.components:service-firefox-accounts-0.26.0" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test.espresso:espresso-idling-resource-3.0.2" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test.espresso:espresso-idling-resource-3.0.2" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: com.android.support.constraint:constraint-layout-solver:1.1.2@jar" level="project" />
|
<orderEntry type="library" name="Gradle: com.android.support.constraint:constraint-layout-solver:1.1.2@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.2.60@jar" level="project" />
|
<orderEntry type="library" name="Gradle: org.mozilla.fxa_client:fxa_client-0.5.1" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core-1.1.0" level="project" />
|
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core-1.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-coroutines-core-common:0.23.4@jar" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3@jar" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-integration:1.3@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-integration:1.3@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60@jar" level="project" />
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:atomicfu-common:0.10.3@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
|
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.60@jar" level="project" />
|
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.2.61@jar" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
|
<orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
|
||||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.1.0" level="project" />
|
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.1.0" level="project" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -31,6 +31,7 @@ dependencies {
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||||
implementation 'com.github.delight-im:Android-AdvancedWebView:v3.0.0'
|
implementation 'com.github.delight-im:Android-AdvancedWebView:v3.0.0'
|
||||||
|
implementation "org.mozilla.components:service-firefox-accounts:${rootProject.ext.android_components_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
task generateAndLinkBundle(type: Exec, description: 'Generate the android.js bundle and link it into the assets directory') {
|
task generateAndLinkBundle(type: Exec, description: 'Generate the android.js bundle and link it into the assets directory') {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.support.v7.app.AppCompatActivity
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import im.delight.android.webview.AdvancedWebView
|
import im.delight.android.webview.AdvancedWebView
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -13,7 +14,13 @@ import android.webkit.WebMessage
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.webkit.ConsoleMessage
|
import android.webkit.ConsoleMessage
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
import android.webkit.WebChromeClient
|
import android.webkit.WebChromeClient
|
||||||
|
import mozilla.components.service.fxa.Config
|
||||||
|
import mozilla.components.service.fxa.FirefoxAccount
|
||||||
|
import mozilla.components.service.fxa.OAuthInfo
|
||||||
|
import mozilla.components.service.fxa.Profile
|
||||||
|
import mozilla.components.service.fxa.FxaResult
|
||||||
|
|
||||||
internal class LoggingWebChromeClient : WebChromeClient() {
|
internal class LoggingWebChromeClient : WebChromeClient() {
|
||||||
override fun onConsoleMessage(cm: ConsoleMessage): Boolean {
|
override fun onConsoleMessage(cm: ConsoleMessage): Boolean {
|
||||||
|
@ -23,9 +30,18 @@ internal class LoggingWebChromeClient : WebChromeClient() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WebAppInterface(private val mContext: MainActivity) {
|
||||||
|
@JavascriptInterface
|
||||||
|
fun beginOAuthFlow() {
|
||||||
|
mContext.beginOAuthFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
||||||
private var mWebView: AdvancedWebView? = null
|
private var mWebView: AdvancedWebView? = null
|
||||||
private var mToShare: String? = null
|
private var mToShare: String? = null
|
||||||
|
private var mToCall: String? = null
|
||||||
|
private var mAccount: FirefoxAccount? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -34,14 +50,17 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
||||||
mWebView = findViewById<WebView>(R.id.webview) as AdvancedWebView
|
mWebView = findViewById<WebView>(R.id.webview) as AdvancedWebView
|
||||||
mWebView!!.setListener(this, this)
|
mWebView!!.setListener(this, this)
|
||||||
mWebView!!.setWebChromeClient(LoggingWebChromeClient())
|
mWebView!!.setWebChromeClient(LoggingWebChromeClient())
|
||||||
|
mWebView!!.addJavascriptInterface(WebAppInterface(this), "Android")
|
||||||
|
|
||||||
val webSettings = mWebView!!.getSettings()
|
val webSettings = mWebView!!.getSettings()
|
||||||
|
webSettings.setUserAgentString("Send Android")
|
||||||
webSettings.setAllowUniversalAccessFromFileURLs(true)
|
webSettings.setAllowUniversalAccessFromFileURLs(true)
|
||||||
webSettings.setJavaScriptEnabled(true)
|
webSettings.setJavaScriptEnabled(true)
|
||||||
|
|
||||||
val intent = getIntent()
|
val intent = getIntent()
|
||||||
val action = intent.getAction()
|
val action = intent.getAction()
|
||||||
val type = intent.getType()
|
val type = intent.getType()
|
||||||
|
|
||||||
if (Intent.ACTION_SEND.equals(action) && type != null) {
|
if (Intent.ACTION_SEND.equals(action) && type != null) {
|
||||||
if (type.equals("text/plain")) {
|
if (type.equals("text/plain")) {
|
||||||
val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT)
|
val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||||
|
@ -51,12 +70,25 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
||||||
val imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri
|
val imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri
|
||||||
Log.w("INTENT", "image/ " + imageUri)
|
Log.w("INTENT", "image/ " + imageUri)
|
||||||
mToShare = "data:text/plain;base64," + Base64.encodeToString(imageUri.path.toByteArray(), 16).trim()
|
mToShare = "data:text/plain;base64," + Base64.encodeToString(imageUri.path.toByteArray(), 16).trim()
|
||||||
|
|
||||||
// TODO Currently this causes a Permission Denied error
|
|
||||||
// val stream = contentResolver.openInputStream(imageUri)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mWebView!!.loadUrl("file:///android_asset/android.html")
|
mWebView!!.loadUrl("file:///android_asset/android.html")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun beginOAuthFlow() {
|
||||||
|
Config.custom("https://send-fxa.dev.lcip.org").then(fun (value: Config): FxaResult<Unit> {
|
||||||
|
mAccount = FirefoxAccount(value, "12cc4070a481bc73", "fxaclient://android.redirect")
|
||||||
|
mAccount?.beginOAuthFlow(arrayOf("profile", "https://identity.mozilla.com/apps/send"), true)?.then(fun (url: String): FxaResult<Unit> {
|
||||||
|
Log.w("CONFIG", "GOT A URL " + url)
|
||||||
|
this@MainActivity.runOnUiThread({
|
||||||
|
mWebView!!.loadUrl(url)
|
||||||
|
})
|
||||||
|
return FxaResult.fromValue(Unit)
|
||||||
|
})
|
||||||
|
Log.w("CONFIG", "CREATED FIREFOXACCOUNT")
|
||||||
|
return FxaResult.fromValue(Unit)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
|
@ -94,7 +126,48 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageStarted(url: String, favicon: Bitmap?) {
|
override fun onPageStarted(url: String, favicon: Bitmap?) {
|
||||||
|
if (url.startsWith("fxaclient")) {
|
||||||
|
// We load this here so the user doesn't see an ugly screen that says "can't handle fxaclient urls"...
|
||||||
|
mWebView!!.loadUrl("file:///android_asset/android.html")
|
||||||
|
|
||||||
|
val parsed = Uri.parse(url)
|
||||||
|
val code = parsed.getQueryParameter("code")
|
||||||
|
val state = parsed.getQueryParameter("state")
|
||||||
|
|
||||||
|
code?.let { code ->
|
||||||
|
state?.let { state ->
|
||||||
|
mAccount?.completeOAuthFlow(code, state)?.whenComplete { info ->
|
||||||
|
//displayAndPersistProfile(code, state)
|
||||||
|
val profile = mAccount?.getProfile(false)?.then(fun (profile: Profile): FxaResult<Unit> {
|
||||||
|
val accessToken = info.accessToken
|
||||||
|
val keys = info.keys
|
||||||
|
val avatar = profile.avatar
|
||||||
|
val displayName = profile.displayName
|
||||||
|
val email = profile.email
|
||||||
|
val uid = profile.uid
|
||||||
|
val toPass = "{\"accessToken\": \"${accessToken}}\", \"keys\": '${keys}', \"avatar\": \"${avatar}\", \"displayName\": \"${displayName}\", \"email\": \"${email}\", \"uid\": \"${uid}\"}"
|
||||||
|
mToCall = "finishLogin(${toPass})"
|
||||||
|
this@MainActivity.runOnUiThread({
|
||||||
|
// But then we also reload this here because we need to make sure onPageFinished runs after mToCall has been set.
|
||||||
|
// We can't guarantee that onPageFinished has already been called at this point.
|
||||||
|
mWebView!!.loadUrl("file:///android_asset/android.html")
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
return FxaResult.fromValue(Unit)
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO get k from it.keys
|
||||||
|
// TODO get profile from mAccount.getProfile
|
||||||
|
// TODO get access_token
|
||||||
|
|
||||||
|
//mToShare = "data:text/plain;base64," + Base64.encodeToString(toSend.toByteArray(), 16).trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Log.w("MAIN", "onPageStarted");
|
Log.w("MAIN", "onPageStarted");
|
||||||
|
// account.completeOAuthFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageFinished(url: String) {
|
override fun onPageFinished(url: String) {
|
||||||
|
@ -102,14 +175,22 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener {
|
||||||
if (mToShare != null) {
|
if (mToShare != null) {
|
||||||
Log.w("INTENT", mToShare)
|
Log.w("INTENT", mToShare)
|
||||||
|
|
||||||
val webView = findViewById<WebView>(R.id.webview) as AdvancedWebView
|
mWebView?.postWebMessage(WebMessage(mToShare), Uri.EMPTY)
|
||||||
webView.postWebMessage(WebMessage(mToShare), Uri.EMPTY)
|
mToShare = null
|
||||||
}
|
}
|
||||||
|
if (mToCall != null) {
|
||||||
|
this@MainActivity.runOnUiThread({
|
||||||
|
mWebView?.evaluateJavascript(mToCall, fun (value: String) {
|
||||||
|
// noop
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
mToCall = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageError(errorCode: Int, description: String, failingUrl: String) {
|
override fun onPageError(errorCode: Int, description: String, failingUrl: String) {
|
||||||
Log.w("MAIN", "onPageError")
|
Log.w("MAIN", "onPageError " + description)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDownloadRequested(url: String, suggestedFilename: String, mimeType: String, contentLength: Long, contentDisposition: String, userAgent: String) {
|
override fun onDownloadRequested(url: String, suggestedFilename: String, mimeType: String, contentLength: Long, contentDisposition: String, userAgent: String) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.2.60'
|
ext.kotlin_version = '1.2.60'
|
||||||
|
ext.android_components_version = '0.26.0'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.60"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.60"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
@ -18,6 +19,9 @@ buildscript {
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
maven {
|
||||||
|
url "https://maven.mozilla.org/maven2"
|
||||||
|
}
|
||||||
jcenter()
|
jcenter()
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ const path = require('path');
|
||||||
|
|
||||||
child_process.execSync('npm run build');
|
child_process.execSync('npm run build');
|
||||||
child_process.execSync(
|
child_process.execSync(
|
||||||
`cp -R ${path.resolve(__dirname, '../dist')} ${path.resolve(
|
`cp -R ${path.resolve(__dirname, '../dist/*')} ${path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
'app/src/main/assets'
|
'app/src/main/assets'
|
||||||
)}`
|
)}`
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#Wed May 23 21:14:24 EDT 2018
|
#Thu Oct 11 12:20:52 EDT 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
import User from '../../app/user';
|
import User from '../user';
|
||||||
import storage from '../../app/storage';
|
import storage from '../../app/storage';
|
||||||
|
|
||||||
export default function initialState(state, emitter) {
|
export default function initialState(state, emitter) {
|
||||||
|
|
26
android/user.js
Normal file
26
android/user.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* global Android */
|
||||||
|
import User from '../app/user';
|
||||||
|
import { deriveFileListKey } from '../app/fxa';
|
||||||
|
|
||||||
|
export default class AndroidUser extends User {
|
||||||
|
constructor(storage) {
|
||||||
|
super(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
async login() {
|
||||||
|
Android.beginOAuthFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
async finishLogin(accountInfo) {
|
||||||
|
const jwks = JSON.parse(accountInfo.keys);
|
||||||
|
const ikm = jwks['https://identity.mozilla.com/apps/send'].k;
|
||||||
|
const profile = {
|
||||||
|
displayName: accountInfo.displayName,
|
||||||
|
email: accountInfo.email,
|
||||||
|
avatar: accountInfo.avatar,
|
||||||
|
access_token: accountInfo.accessToken
|
||||||
|
};
|
||||||
|
profile.fileListKey = await deriveFileListKey(ikm);
|
||||||
|
this.info = profile;
|
||||||
|
}
|
||||||
|
}
|
12
app/fxa.js
12
app/fxa.js
|
@ -146,12 +146,10 @@ export async function preparePkce(storage) {
|
||||||
return arrayToB64(new Uint8Array(challenge));
|
return arrayToB64(new Uint8Array(challenge));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFileListKey(storage, bundle) {
|
export async function deriveFileListKey(ikm) {
|
||||||
const jwks = await decryptBundle(storage, bundle);
|
|
||||||
const jwk = jwks['https://identity.mozilla.com/apps/send'];
|
|
||||||
const baseKey = await crypto.subtle.importKey(
|
const baseKey = await crypto.subtle.importKey(
|
||||||
'raw',
|
'raw',
|
||||||
b64ToArray(jwk.k),
|
b64ToArray(ikm),
|
||||||
{ name: 'HKDF' },
|
{ name: 'HKDF' },
|
||||||
false,
|
false,
|
||||||
['deriveKey']
|
['deriveKey']
|
||||||
|
@ -174,3 +172,9 @@ export async function getFileListKey(storage, bundle) {
|
||||||
const rawFileListKey = await crypto.subtle.exportKey('raw', fileListKey);
|
const rawFileListKey = await crypto.subtle.exportKey('raw', fileListKey);
|
||||||
return arrayToB64(new Uint8Array(rawFileListKey));
|
return arrayToB64(new Uint8Array(rawFileListKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getFileListKey(storage, bundle) {
|
||||||
|
const jwks = await decryptBundle(storage, bundle);
|
||||||
|
const jwk = jwks['https://identity.mozilla.com/apps/send'];
|
||||||
|
return deriveFileListKey(jwk.k);
|
||||||
|
}
|
||||||
|
|
33
app/user.js
33
app/user.js
|
@ -16,28 +16,37 @@ export default class User {
|
||||||
this.data = storage.user || {};
|
this.data = storage.user || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get info() {
|
||||||
|
return this.data || this.storage.user || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
set info(data) {
|
||||||
|
this.data = data;
|
||||||
|
this.storage.user = data;
|
||||||
|
}
|
||||||
|
|
||||||
get avatar() {
|
get avatar() {
|
||||||
const defaultAvatar = assets.get('user.svg');
|
const defaultAvatar = assets.get('user.svg');
|
||||||
if (this.data.avatarDefault) {
|
if (this.info.avatarDefault) {
|
||||||
return assets.get('firefox_logo-only.svg');
|
return assets.get('firefox_logo-only.svg');
|
||||||
}
|
}
|
||||||
return this.data.avatar || defaultAvatar;
|
return this.info.avatar || defaultAvatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
return this.data.displayName;
|
return this.info.displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
get email() {
|
get email() {
|
||||||
return this.data.email;
|
return this.info.email;
|
||||||
}
|
}
|
||||||
|
|
||||||
get loggedIn() {
|
get loggedIn() {
|
||||||
return !!this.data.access_token;
|
return !!this.info.access_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
get bearerToken() {
|
get bearerToken() {
|
||||||
return this.data.access_token;
|
return this.info.access_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
get maxSize() {
|
get maxSize() {
|
||||||
|
@ -104,15 +113,13 @@ export default class User {
|
||||||
const userInfo = await infoResponse.json();
|
const userInfo = await infoResponse.json();
|
||||||
userInfo.access_token = auth.access_token;
|
userInfo.access_token = auth.access_token;
|
||||||
userInfo.fileListKey = await getFileListKey(this.storage, auth.keys_jwe);
|
userInfo.fileListKey = await getFileListKey(this.storage, auth.keys_jwe);
|
||||||
this.storage.user = userInfo;
|
this.info = userInfo;
|
||||||
this.data = userInfo;
|
|
||||||
this.storage.remove('pkceVerifier');
|
this.storage.remove('pkceVerifier');
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
this.storage.user = null;
|
|
||||||
this.storage.clearLocalFiles();
|
this.storage.clearLocalFiles();
|
||||||
this.data = {};
|
this.info = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
async syncFileList() {
|
async syncFileList() {
|
||||||
|
@ -124,7 +131,7 @@ export default class User {
|
||||||
try {
|
try {
|
||||||
const encrypted = await getFileList(this.bearerToken);
|
const encrypted = await getFileList(this.bearerToken);
|
||||||
const decrypted = await streamToArrayBuffer(
|
const decrypted = await streamToArrayBuffer(
|
||||||
decryptStream(encrypted, b64ToArray(this.data.fileListKey))
|
decryptStream(encrypted, b64ToArray(this.info.fileListKey))
|
||||||
);
|
);
|
||||||
list = JSON.parse(textDecoder.decode(decrypted));
|
list = JSON.parse(textDecoder.decode(decrypted));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -142,7 +149,7 @@ export default class User {
|
||||||
textEncoder.encode(JSON.stringify(this.storage.files))
|
textEncoder.encode(JSON.stringify(this.storage.files))
|
||||||
]);
|
]);
|
||||||
const encrypted = await streamToArrayBuffer(
|
const encrypted = await streamToArrayBuffer(
|
||||||
encryptStream(blobStream(blob), b64ToArray(this.data.fileListKey))
|
encryptStream(blobStream(blob), b64ToArray(this.info.fileListKey))
|
||||||
);
|
);
|
||||||
await setFileList(this.bearerToken, encrypted);
|
await setFileList(this.bearerToken, encrypted);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -152,6 +159,6 @@ export default class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON() {
|
toJSON() {
|
||||||
return this.data;
|
return this.info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const genmap = require('../build/generate_asset_map');
|
const genmap = require('../build/generate_asset_map');
|
||||||
const isServer = typeof genmap === 'function';
|
const isServer = typeof genmap === 'function';
|
||||||
const prefix = '';
|
let prefix = '';
|
||||||
let manifest = {};
|
let manifest = {};
|
||||||
try {
|
try {
|
||||||
//eslint-disable-next-line node/no-missing-require
|
//eslint-disable-next-line node/no-missing-require
|
||||||
|
@ -15,6 +15,10 @@ function getAsset(name) {
|
||||||
return prefix + assets[name];
|
return prefix + assets[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPrefix(name) {
|
||||||
|
prefix = name;
|
||||||
|
}
|
||||||
|
|
||||||
function getMatches(match) {
|
function getMatches(match) {
|
||||||
return Object.keys(assets)
|
return Object.keys(assets)
|
||||||
.filter(k => match.test(k))
|
.filter(k => match.test(k))
|
||||||
|
@ -22,6 +26,7 @@ function getMatches(match) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const instance = {
|
const instance = {
|
||||||
|
setPrefix: setPrefix,
|
||||||
get: getAsset,
|
get: getAsset,
|
||||||
match: getMatches,
|
match: getMatches,
|
||||||
setMiddleware: function(middleware) {
|
setMiddleware: function(middleware) {
|
||||||
|
|
630
package-lock.json
generated
630
package-lock.json
generated
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue