[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf"
  },
  {
    "path": ".gitattributes",
    "content": "# We'll let Git's auto-detection algorithm infer if a file is text. If it is,\n# enforce LF line endings regardless of OS or git configurations.\n* text=auto eol=lf\n\n# Isolate binary files in case the auto-detection algorithm fails and\n# marks them as text files (which could brick them).\n*.{png,jpg,jpeg,gif,webp,woff,woff2} binary"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "*\t@auth0/project-dx-sdks-engineer-codeowner\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Bug Report.yml",
    "content": "name: 🐞 Report a bug\ndescription: Have you found a bug or issue? Create a bug report for this library\nlabels: [\"bug\"]\n\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        **Please do not report security vulnerabilities here**. The [Responsible Disclosure Program](https://auth0.com/responsible-disclosure-policy) details the procedure for disclosing security issues.\n\n  - type: checkboxes\n    id: checklist\n    attributes:\n      label: Checklist\n      options:\n        - label: I have looked into the [Readme](https://github.com/auth0/Lock.Android#readme) and [Examples](https://github.com/auth0/Lock.Android/blob/main/EXAMPLES.md), and have not found a suitable solution or answer.\n          required: true\n        - label: I have looked into the [API documentation](https://javadoc.io/doc/com.auth0.android/lock/latest/index.html) and have not found a suitable solution or answer.\n          required: true\n        - label: I have searched the [issues](https://github.com/auth0/Lock.Android/issues) and have not found a suitable solution or answer.\n          required: true\n        - label: I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer.\n          required: true\n        - label: I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).\n          required: true\n\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      description: Provide a clear and concise description of the issue, including what you expected to happen.\n    validations:\n      required: true\n\n  - type: textarea\n    id: reproduction\n    attributes:\n      label: Reproduction\n      description: Detail the steps taken to reproduce this error, and whether this issue can be reproduced consistently or if it is intermittent.\n      placeholder: |\n        1. Step 1...\n        2. Step 2...\n        3. ...\n    validations:\n      required: true\n\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      description: Other libraries that might be involved, or any other relevant information you think would be useful.\n    validations:\n      required: false\n\n  - type: input\n    id: environment-version\n    attributes:\n      label: Lock.Android version\n    validations:\n      required: true\n\n  - type: input\n    id: environment-platform-version\n    attributes:\n      label: Android version(s)\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Feature Request.yml",
    "content": "name: 🧩 Feature request\ndescription: Suggest an idea or a feature for this library\nlabels: [\"feature request\"]\n\nbody:\n  - type: checkboxes\n    id: checklist\n    attributes:\n      label: Checklist\n      options:\n        - label: I have looked into the [Readme](https://github.com/auth0/Lock.Android#readme) and [Examples](https://github.com/auth0/Lock.Android/blob/main/EXAMPLES.md), and have not found a suitable solution or answer.\n          required: true\n        - label: I have looked into the [API documentation](https://javadoc.io/doc/com.auth0.android/lock/latest/index.html) and have not found a suitable solution or answer.\n          required: true\n        - label: I have searched the [issues](https://github.com/auth0/Lock.Android/issues) and have not found a suitable solution or answer.\n          required: true\n        - label: I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer.\n          required: true\n        - label: I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).\n          required: true\n\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the problem you'd like to have solved\n      description: A clear and concise description of what the problem is.\n      placeholder: I'm always frustrated when...\n    validations:\n      required: true\n\n  - type: textarea\n    id: ideal-solution\n    attributes:\n      label: Describe the ideal solution\n      description: A clear and concise description of what you want to happen.\n    validations:\n      required: true\n\n  - type: textarea\n    id: alternatives-and-workarounds\n    attributes:\n      label: Alternatives and current workarounds\n      description: A clear and concise description of any alternatives you've considered or any workarounds that are currently in place.\n    validations:\n      required: false\n\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      description: Add any other context or screenshots about the feature request here.\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Auth0 Community\n    url: https://community.auth0.com\n    about: Discuss this SDK in the Auth0 Community forums\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "### Changes\n\nPlease describe both what is changing and why this is important. Include:\n\n- Classes and methods added, deleted, deprecated, or changed\n- Screenshots of new or changed UI, if applicable\n- A summary of usage if this is a new feature or change to a public API (this should also be added to relevant documentation once released)\n\n### References\n\nPlease include relevant links supporting this change such as a:\n\n- support ticket\n- community post\n- StackOverflow post\n- support forum thread\n\nPlease note any links that are not publicly accessible.\n\n### Testing\n\nPlease describe how this can be tested by reviewers. Be specific about anything not tested and reasons why. This library has unit testing, tests should be added for new logic and functionality and existing tests should complete without errors.\n\n- [ ] This change adds unit test coverage\n\n- [ ] This change adds integration/UI test coverage\n\n- [ ] This change has been tested on the latest version of the platform/language or why not\n\n### Checklist\n\n- [ ] I have read the [Auth0 general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md)\n\n- [ ] I have read the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md)\n\n- [ ] All existing and new tests complete without errors\n\n- [ ] The correct base branch is being used\n"
  },
  {
    "path": ".github/actions/get-prerelease/action.yml",
    "content": "name: Return a boolean indicating if the version contains prerelease identifiers\n\n#\n# Returns a simple true/false boolean indicating whether the version indicates it's a prerelease or not.\n#\n# TODO: Remove once the common repo is public.\n#\n\ninputs:\n  version:\n    required: true\n\noutputs:\n  prerelease:\n    value: ${{ steps.get_prerelease.outputs.PRERELEASE }}\n\nruns:\n  using: composite\n\n  steps:\n    - id: get_prerelease\n      shell: bash\n      run: |\n        if [[ \"${VERSION}\" == *\"beta\"* || \"${VERSION}\" == *\"alpha\"* ]]; then\n          echo \"PRERELEASE=true\" >> $GITHUB_OUTPUT\n        else\n          echo \"PRERELEASE=false\" >> $GITHUB_OUTPUT\n        fi\n      env:\n        VERSION: ${{ inputs.version }}\n"
  },
  {
    "path": ".github/actions/get-release-notes/action.yml",
    "content": "name: Return the release notes extracted from the body of the PR associated with the release.\n\n#\n# Returns the release notes from the content of a pull request linked to a release branch. It expects the branch name to be in the format release/vX.Y.Z, release/X.Y.Z, release/vX.Y.Z-beta.N. etc.\n#\n# TODO: Remove once the common repo is public.\n#\ninputs:\n  version:\n    required: true\n  repo_name:\n    required: false\n  repo_owner:\n    required: true\n  token:\n    required: true\n\noutputs:\n  release-notes:\n    value: ${{ steps.get_release_notes.outputs.RELEASE_NOTES }}\n\nruns:\n  using: composite\n\n  steps:\n    - uses: actions/github-script@v7\n      id: get_release_notes\n      with:\n        result-encoding: string\n        script: |\n          const { data: pulls } = await github.rest.pulls.list({\n            owner: process.env.REPO_OWNER,\n            repo: process.env.REPO_NAME,\n            state: 'all',\n            head: `${process.env.REPO_OWNER}:release/${process.env.VERSION}`,\n          });\n          core.setOutput('RELEASE_NOTES', pulls[0].body);\n      env:\n        GITHUB_TOKEN: ${{ inputs.token }}\n        REPO_OWNER: ${{ inputs.repo_owner }}\n        REPO_NAME: ${{ inputs.repo_name }}\n        VERSION: ${{ inputs.version }}\n"
  },
  {
    "path": ".github/actions/get-version/action.yml",
    "content": "name: Return the version extracted from the branch name\n\n#\n# Returns the version from the .version file.\n#\n# TODO: Remove once the common repo is public.\n#\n\noutputs:\n  version:\n    value: ${{ steps.get_version.outputs.VERSION }}\n\nruns:\n  using: composite\n\n  steps:\n    - id: get_version\n      shell: bash\n      run: |\n        VERSION=$(head -1 .version)\n        echo \"VERSION=${VERSION}\" >> $GITHUB_OUTPUT\n"
  },
  {
    "path": ".github/actions/maven-publish/action.yml",
    "content": "name: Publish release to Java\n\ninputs:\n  ossr-username:\n    required: true\n  ossr-password:\n    required: true\n  signing-key:\n    required: true\n  signing-password:\n    required: true\n  java-version:\n    required: true\n  is-android:\n    required: true\n  version:\n    required: true\n\nruns:\n  using: composite\n\n  steps:\n    - name: Checkout code\n      uses: actions/checkout@v4\n\n    - name: Setup Java\n      shell: bash\n      run: |\n        curl -s \"https://get.sdkman.io\" | bash\n        source \"/home/runner/.sdkman/bin/sdkman-init.sh\"\n        sdk list java\n        sdk install java \"$JAVA_VERSION\" && sdk default java \"$JAVA_VERSION\"\n      env:\n        JAVA_VERSION: ${{ inputs.java-version }}\n\n    - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # pin@1.1.0\n\n    - name: Publish Java\n      shell: bash\n      if: inputs.is-android == 'false'\n      run: ./gradlew clean assemble sign publishMavenJavaPublicationToMavenRepository -PisSnapshot=false -Pversion=\"$VERSION\" -PossrhUsername=\"$OSSR_USERNAME\" -PossrhPassword=\"$OSSR_PASSWORD\" -PsigningKey=\"$SIGNING_KEY\" -PsigningPassword=\"$SIGNING_PASSWORD\"\n      env:\n        VERSION: ${{ inputs.version }}\n        OSSR_USERNAME: ${{ inputs.ossr-username }}\n        OSSR_PASSWORD: ${{ inputs.ossr-password }}\n        SIGNING_KEY: ${{ inputs.signing-key }}\n        SIGNING_PASSWORD: ${{ inputs.signing-password }}\n\n    - name: Publish Android\n      shell: bash\n      if: inputs.is-android == 'true'\n      run: ./gradlew clean assemble sign publishAndroidLibraryPublicationToMavenRepository -PisSnapshot=false -Pversion=\"$VERSION\" -PossrhUsername=\"$OSSR_USERNAME\" -PossrhPassword=\"$OSSR_PASSWORD\" -PsigningKey=\"$SIGNING_KEY\" -PsigningPassword=\"$SIGNING_PASSWORD\"\n      env:\n        VERSION: ${{ inputs.version }}\n        OSSR_USERNAME: ${{ inputs.ossr-username }}\n        OSSR_PASSWORD: ${{ inputs.ossr-password }}\n        SIGNING_KEY: ${{ inputs.signing-key }}\n        SIGNING_PASSWORD: ${{ inputs.signing-password }}\n"
  },
  {
    "path": ".github/actions/release-create/action.yml",
    "content": "name: Create a GitHub release\n\n#\n# Creates a GitHub release with the given version.\n#\n# TODO: Remove once the common repo is public.\n#\n\ninputs:\n  token:\n    required: true\n  files:\n    required: false\n  name:\n    required: true\n  body:\n    required: true\n  tag:\n    required: true\n  commit:\n    required: true\n  draft:\n    default: false\n    required: false\n  prerelease:\n    default: false\n    required: false\n  fail_on_unmatched_files:\n    default: true\n    required: false\n\nruns:\n  using: composite\n\n  steps:\n    - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844\n      with:\n        body: ${{ inputs.body }}\n        name: ${{ inputs.name }}\n        tag_name: ${{ inputs.tag }}\n        target_commitish: ${{ inputs.commit }}\n        draft: ${{ inputs.draft }}\n        prerelease: ${{ inputs.prerelease }}\n        fail_on_unmatched_files: ${{ inputs.fail_on_unmatched_files }}\n        files: ${{ inputs.files }}\n      env:\n        GITHUB_TOKEN: ${{ inputs.token }}\n"
  },
  {
    "path": ".github/actions/setup/action.yml",
    "content": "name: Configure CI\ndescription: Performs the initial configuration of the CI environment\n\ninputs:\n  java:\n    description: The Java version to use\n    required: false\n    default: '11'\n\nruns:\n  using: composite\n\n  steps:\n    - name: Set up JDK\n      uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # pin@4.8.0\n      env:\n        JAVA_VERSION : ${{ inputs.java }}\n      with:\n        java-version: ${{ env.JAVA_VERSION }}\n        distribution: 'temurin'\n\n    - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # pin@1.1.0\n\n    - name: Setup Gradle\n      uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # pin@4.4.4\n\n    - run: ./gradlew androidDependencies\n      shell: bash\n"
  },
  {
    "path": ".github/actions/tag-exists/action.yml",
    "content": "name: Return a boolean indicating if a tag already exists for the repository\n\n#\n# Returns a simple true/false boolean indicating whether the tag exists or not.\n#\n# TODO: Remove once the common repo is public.\n#\n\ninputs:\n  token:\n    required: true\n  tag:\n    required: true\n\noutputs:\n  exists:\n    description: 'Whether the tag exists or not'\n    value: ${{ steps.tag-exists.outputs.EXISTS }}\n\nruns:\n  using: composite\n\n  steps:\n    - id: tag-exists\n      shell: bash\n      run: |\n        GET_API_URL=\"https://api.github.com/repos/${GITHUB_REPOSITORY}/git/ref/tags/${TAG_NAME}\"\n        http_status_code=$(curl -LI $GET_API_URL -o /dev/null -w '%{http_code}\\n' -s -H \"Authorization: token ${GITHUB_TOKEN}\")\n        if [ \"$http_status_code\" -ne \"404\" ] ; then\n          echo \"EXISTS=true\" >> $GITHUB_OUTPUT\n        else\n          echo \"EXISTS=false\" >> $GITHUB_OUTPUT\n        fi\n      env:\n        TAG_NAME: ${{ inputs.tag }}\n        GITHUB_TOKEN: ${{ inputs.token }}\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: 'github-actions'\n    directory: '/'\n    schedule:\n      interval: 'weekly'\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Configuration for probot-stale - https://github.com/probot/stale\n\n# Number of days of inactivity before an Issue or Pull Request becomes stale\ndaysUntilStale: 90\n\n# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.\ndaysUntilClose: 7\n\n# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable\nexemptLabels: []\n\n# Set to true to ignore issues with an assignee (defaults to false)\nexemptAssignees: true\n\n# Label to use when marking as stale\nstaleLabel: closed:stale\n\n# Comment to post when marking as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you have not received a response for our team (apologies for the delay) and this is still a blocker, please reply with additional information or just a ping. Thank you for your contribution! 🙇‍♂️"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "content": "name: CodeQL\n\non:\n  merge_group:\n  pull_request:\n    types:\n      - opened\n      - synchronize\n  push:\n    branches:\n      - main\n  schedule:\n    - cron: \"37 10 * * 2\"\n\npermissions:\n  actions: read\n  contents: read\n  security-events: write\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}\n\njobs:\n  analyze:\n    name: Check for Vulnerabilities\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [java]\n\n    steps:\n      - if: github.actor == 'dependabot[bot]' || github.event_name == 'merge_group'\n        run: exit 0 # Skip unnecessary test runs for dependabot and merge queues. Artifically flag as successful, as this is a required check for branch protection.\n\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v4\n        with:\n          languages: ${{ matrix.language }}\n          queries: +security-and-quality\n\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v4\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v4\n        with:\n          category: \"/language:${{ matrix.language }}\"\n"
  },
  {
    "path": ".github/workflows/java-release.yml",
    "content": "name: Create Java and GitHub Release\n\non:\n  workflow_call:\n    inputs:\n      java-version:\n        required: true\n        type: string\n      is-android:\n        required: true\n        type: string\n    secrets:\n      ossr-username:\n        required: true\n      ossr-password:\n        required: true\n      signing-key:\n        required: true\n      signing-password:\n        required: true\n      github-token:\n        required: true\n\n### TODO: Replace instances of './.github/actions/' w/ `auth0/dx-sdk-actions/` and append `@latest` after the common `dx-sdk-actions` repo is made public.\n### TODO: Also remove `get-prerelease`, `get-version`, `release-create`, `tag-create` and `tag-exists` actions from this repo's .github/actions folder once the repo is public.\n\njobs:\n  release:\n    if: github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged && startsWith(github.event.pull_request.head.ref, 'release/'))\n    runs-on: ubuntu-latest\n    environment: release\n\n    steps:\n      # Checkout the code\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      # Get the version from the branch name\n      - id: get_version\n        uses: ./.github/actions/get-version\n\n      # Get the prerelease flag from the branch name\n      - id: get_prerelease\n        uses: ./.github/actions/get-prerelease\n        with:\n          version: ${{ steps.get_version.outputs.version }}\n\n      # Get the release notes\n      - id: get_release_notes\n        uses: ./.github/actions/get-release-notes\n        with:\n          token: ${{ secrets.github-token }}\n          version: ${{ steps.get_version.outputs.version }}\n          repo_owner: ${{ github.repository_owner }}\n          repo_name: ${{ github.event.repository.name }}\n\n      # Check if the tag already exists\n      - id: tag_exists\n        uses: ./.github/actions/tag-exists\n        with:\n          tag: ${{ steps.get_version.outputs.version }}\n          token: ${{ secrets.github-token }}\n\n      # If the tag already exists, exit with an error\n      - if: steps.tag_exists.outputs.exists == 'true'\n        run: exit 1\n\n      # Publish the release to Maven\n      - uses: ./.github/actions/maven-publish\n        with:\n          java-version: ${{ inputs.java-version }}\n          is-android: ${{ inputs.is-android }}\n          version: ${{ steps.get_version.outputs.version }}\n          ossr-username: ${{ secrets.ossr-username }}\n          ossr-password: ${{ secrets.ossr-password }}\n          signing-key: ${{ secrets.signing-key }}\n          signing-password: ${{ secrets.signing-password }}\n\n      # Create a release for the tag\n      - uses: ./.github/actions/release-create\n        with:\n          token: ${{ secrets.github-token }}\n          name: ${{ steps.get_version.outputs.version }}\n          body: ${{ steps.get_release_notes.outputs.release-notes }}\n          tag: ${{ steps.get_version.outputs.version }}\n          commit: ${{ github.sha }}\n          prerelease: ${{ steps.get_prerelease.outputs.prerelease }}\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Create GitHub Release\n\non:\n  pull_request:\n    types:\n      - closed\n  workflow_dispatch:\n\npermissions:\n  contents: write\n\n### TODO: Replace instances of './.github/workflows/' w/ `auth0/dx-sdk-actions/workflows/` and append `@latest` after the common `dx-sdk-actions` repo is made public.\n### TODO: Also remove `get-prerelease`, `get-release-notes`, `get-version`, `maven-publish`, `release-create`, and `tag-exists` actions from this repo's .github/actions folder once the repo is public.\n### TODO: Also remove `java-release` workflow from this repo's .github/workflows folder once the repo is public.\n\njobs:\n  release:\n    uses: ./.github/workflows/java-release.yml\n    with:\n      java-version: 8.0.382-tem\n      is-android: true\n    secrets:\n      ossr-username: ${{ secrets.OSSR_USERNAME }}\n      ossr-password: ${{ secrets.OSSR_PASSWORD }}\n      signing-key: ${{ secrets.SIGNING_KEY }}\n      signing-password: ${{ secrets.SIGNING_PASSWORD }}\n      github-token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/sca_scan.yml",
    "content": "name: SCA\n\non:\n  push:\n    branches: [\"master\", \"main\"]\n\njobs:\n  snyk-cli:\n    uses: auth0/devsecops-tooling/.github/workflows/sca-scan.yml@main\n    secrets: inherit"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Build and Test\n\non:\n  merge_group:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - main\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}\n\njobs:\n  unit:\n    name: Run Unit Tests\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: ./.github/actions/setup\n\n      - run: ./gradlew clean test lint --continue --console=plain --max-workers=3\n\n      - uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # pin@5.5.3\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by https://www.gitignore.io/api/intellij,android,osx,windows\n\n### Intellij ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n# .idea/shelf\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n\n### Android ###\n# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n### Android Patch ###\ngen-external-apklibs\n\n\n### OSX ###\n.DS_Store\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n"
  },
  {
    "path": ".shiprc",
    "content": "{\n  \"files\": {\n    \"auth0/build.gradle\": [],\n    \".version\": [],\n    \"README.md\": []\n  },\n  \"prefixVersion\": false\n}\n"
  },
  {
    "path": ".version",
    "content": "3.2.2"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\n## [3.2.1](https://github.com/auth0/Lock.Android/tree/3.2.2) (2023-01-11)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/3.2.1...3.2.2)\n\nThis patch release does not contain any functional changes, but is being released using an updated signing key for verification as part of our commitment to best security practices.\nPlease review [the README note for additional details.](https://github.com/auth0/Lock.Android/blob/main/README.md)\n\n**Security**\n- Bump Auth0.Android dependency to 2.8.1 [\\#652](https://github.com/auth0/Lock.Android/pull/652) ([poovamraj](https://github.com/poovamraj))\n\n## [3.2.1](https://github.com/auth0/Lock.Android/tree/3.2.1) (2022-06-24)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/3.2.0...3.2.1)\n\n**Fixed**\n- Fixing bug where custom audience was not being set in [\\#645](https://github.com/auth0/Lock.Android/pull/645) ([Blake-Carrier](https://github.com/Blake-Carrier))\n\n**Security**\n- Bump GSON dependency to 2.8.9 [\\#639](https://github.com/auth0/Lock.Android/pull/639) ([evansims](https://github.com/evansims))\n\n## [3.2.0](https://github.com/auth0/Lock.Android/tree/3.2.0) (2021-10-11)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/3.1.0...3.2.0)\n\n**Changed**\n- update dependencies and sdk [\\#636](https://github.com/auth0/Lock.Android/pull/636) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [3.1.0](https://github.com/auth0/Lock.Android/tree/3.1.0) (2021-07-20)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/3.0.0...3.1.0)\n\n**Added**\n- Add support for OOB multi-factor authentication [\\#632](https://github.com/auth0/Lock.Android/pull/632) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n- Update AndroidManifest.xml for Android 12 support [\\#631](https://github.com/auth0/Lock.Android/pull/631) ([VincentJoshuaET](https://github.com/VincentJoshuaET))\n\n## [3.0.1](https://github.com/auth0/Lock.Android/tree/3.0.1) (2021-05-27)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/3.0.0...3.0.1)\n\n**Fixed**\n- Trim username and email input to avoid NPE [\\#628](https://github.com/auth0/Lock.Android/pull/628) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [3.0.0](https://github.com/auth0/Lock.Android/tree/3.0.0) (2021-05-04)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.23.0...3.0.0)\n**Closed issues**\n- AuthenticationCallback methods are only called the first time I login [\\#607](https://github.com/auth0/Lock.Android/issues/607)\n- UnauthorizedErrors are not received in lock widget callbacks [\\#606](https://github.com/auth0/Lock.Android/issues/606)\n\n**Added**\n- Add migration guide [SDK-2430] [\\#615](https://github.com/auth0/Lock.Android/pull/615) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n- Drop Jetifier plugin usage [\\#624](https://github.com/auth0/Lock.Android/pull/624) ([lbalmaceda](https://github.com/lbalmaceda))\n- Enable AppLinks in the declared intent filters [\\#622](https://github.com/auth0/Lock.Android/pull/622) ([lbalmaceda](https://github.com/lbalmaceda))\n- Simplify library set up by declaring activities internally [\\#620](https://github.com/auth0/Lock.Android/pull/620) ([lbalmaceda](https://github.com/lbalmaceda))\n- Refactor broadcast receiver usage [\\#619](https://github.com/auth0/Lock.Android/pull/619) ([lbalmaceda](https://github.com/lbalmaceda))\n- Raise Unauthorized and Access Denied errors through callback [SDK-2480] [\\#618](https://github.com/auth0/Lock.Android/pull/618) ([lbalmaceda](https://github.com/lbalmaceda))\n- Update readme [\\#617](https://github.com/auth0/Lock.Android/pull/617) ([lbalmaceda](https://github.com/lbalmaceda))\n- Migrate sample app to use Kotlin [SDK-2431] [\\#616](https://github.com/auth0/Lock.Android/pull/616) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Removed**\n- Remove support for changing the Social Button style  [SDK-2430] [\\#614](https://github.com/auth0/Lock.Android/pull/614) ([lbalmaceda](https://github.com/lbalmaceda))\n- Remove support for Implicit Authentication flow [SDK-2430] [\\#613](https://github.com/auth0/Lock.Android/pull/613) ([lbalmaceda](https://github.com/lbalmaceda))\n- Remove WebView component support [SDK-2430] [\\#612](https://github.com/auth0/Lock.Android/pull/612) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n- Fix filtering by Country name [SDK-2546] [\\#623](https://github.com/auth0/Lock.Android/pull/623) ([lbalmaceda](https://github.com/lbalmaceda))\n- Run lint and fix inspection results [\\#611](https://github.com/auth0/Lock.Android/pull/611) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Breaking changes**\n- Update LockCallback and AuthenticationCallback [SDK-2480] [\\#621](https://github.com/auth0/Lock.Android/pull/621) ([lbalmaceda](https://github.com/lbalmaceda))\n- Use Auth0.Android v2 [SDK-2429] [\\#610](https://github.com/auth0/Lock.Android/pull/610) ([lbalmaceda](https://github.com/lbalmaceda))\n- Migrate to AndroidX [\\#609](https://github.com/auth0/Lock.Android/pull/609) ([lbalmaceda](https://github.com/lbalmaceda))\n- Bump the minimum required android version [SDK-2427] [\\#608](https://github.com/auth0/Lock.Android/pull/608) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.23.0](https://github.com/auth0/Lock.Android/tree/2.23.0) (2020-09-14)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.22.0...2.23.0)\n\n**Having project sync issues after upgrading?**\nThis release updates the core SDK to make it compatible with Android 11 new privacy changes. If you run into a build compile issue when importing this version, make sure that you are using the latest patch version of the Android Gradle Plugin. Check the table in the [announcement blogpost](https://android-developers.googleblog.com/2020/07/preparing-your-build-for-package-visibility-in-android-11.html) to learn to what version you should update.\n\n**Changed**\n- Improve compatibility with Kotlin and run Lint on CI [\\#596](https://github.com/auth0/Lock.Android/pull/596) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add compatibility with Android 11: Bump SDK version [\\#595](https://github.com/auth0/Lock.Android/pull/595) ([lbalmaceda](https://github.com/lbalmaceda))\n- Update \"37 Signals\" auth style to \"Basecamp\" [SDK-1944] [\\#593](https://github.com/auth0/Lock.Android/pull/593) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.22.0](https://github.com/auth0/Lock.Android/tree/2.22.0) (2020-08-25)\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.21.1...2.22.0)\n\n**Added**\n- Support bot protection [\\#589](https://github.com/auth0/Lock.Android/pull/589) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.21.1](https://github.com/auth0/Lock.Android/tree/2.21.1) (2020-08-05)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.21.0...2.21.1)\n\n**Fixed**\n\n- Use latest SDK patch [\\#587](https://github.com/auth0/Lock.Android/pull/587) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.21.0](https://github.com/auth0/Lock.Android/tree/2.21.0) (2020-07-20)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.20.0...2.21.0)\n\n### Read if using the SecureCredentialsManager\nStarting from this version, the alias used to store the key pair in the Android Keystore is prefixed to avoid collisions between other Auth0 enabled apps. Your users will be facing a \"credentials not found\" scenario, requiring them to log in again **once**. Double check that you are not ignoring the errors being returned in the callback and documented [here](https://github.com/auth0/Auth0.Android#handling-exceptions).\n\n**Changed**\n\n- Bump SDK to version 1.24.0 [\\#583](https://github.com/auth0/Lock.Android/pull/583) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Bugfix #581 | Fix social login buttons with white backgrounds [\\#582](https://github.com/auth0/Lock.Android/pull/582) ([morganlutz](https://github.com/morganlutz))\n\n## [2.20.0](https://github.com/auth0/Lock.Android/tree/2.20.0) (2020-05-26)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.19.0...2.20.0)\n\n**Added**\n\n- Allow to change the visible sign-up fields threshold [\\#578](https://github.com/auth0/Lock.Android/pull/578) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add social button style for Sign In with Apple [\\#575](https://github.com/auth0/Lock.Android/pull/575) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fix ModeSelectionView sync issue [\\#577](https://github.com/auth0/Lock.Android/pull/577) ([lbalmaceda](https://github.com/lbalmaceda))\n- Center Custom Fields additional form vertically [\\#576](https://github.com/auth0/Lock.Android/pull/576) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.19.0](https://github.com/auth0/Lock.Android/tree/2.19.0) (2020-04-29)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.18.0...2.19.0)\n\n**Changed**\n\n- Bump the SDK version to 1.23.0 [\\#570](https://github.com/auth0/Lock.Android/pull/570) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fixed material library 1.1.0 tab layout height issue [\\#568](https://github.com/auth0/Lock.Android/pull/568) ([ivabra](https://github.com/ivabra))\n\n## [2.18.0](https://github.com/auth0/Lock.Android/tree/2.18.0) (2020-03-04)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.17.1...2.18.0)\n\n**Changed**\n\n- Update Social Button style [\\#563](https://github.com/auth0/Lock.Android/pull/563) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.17.1](https://github.com/auth0/Lock.Android/tree/2.17.1) (2020-01-10)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.17.0...2.17.1)\n\n**Fixed**\n\n- Bump SDK version and OSS plugin version [\\#560](https://github.com/auth0/Lock.Android/pull/560) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.17.0](https://github.com/auth0/Lock.Android/tree/2.17.0) (2019-12-26)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.16.0...2.17.0)\n\n**Added**\n\n- Improve OIDC Compliance and support new Passwordless [\\#558](https://github.com/auth0/Lock.Android/pull/558) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Security**\n\n- Improve OIDC Compliance and support new Passwordless [\\#558](https://github.com/auth0/Lock.Android/pull/558) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.16.0](https://github.com/auth0/Lock.Android/tree/2.16.0) (2019-10-24)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.15.0...2.16.0)\n\n**Added**\n\n- Add hidden extra sign up fields [\\#552](https://github.com/auth0/Lock.Android/pull/552) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.15.0](https://github.com/auth0/Lock.Android/tree/2.15.0) (2019-07-26)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.14.1...2.15.0)\n\n**Added**\n\n- Add Root Attributes on sign up or user creation [\\#543](https://github.com/auth0/Lock.Android/pull/543) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Update username regex to allow special chars [\\#544](https://github.com/auth0/Lock.Android/pull/544) ([lbalmaceda](https://github.com/lbalmaceda))\n- Use latest Android Gradle plugin version [\\#542](https://github.com/auth0/Lock.Android/pull/542) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fix typo in password reset string [\\#541](https://github.com/auth0/Lock.Android/pull/541) ([horsejockey](https://github.com/horsejockey))\n- Avoid registering multiple broadcast receiver instances [\\#539](https://github.com/auth0/Lock.Android/pull/539) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.14.1](https://github.com/auth0/Lock.Android/tree/2.14.1) (2019-06-06)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.14.0...2.14.1)\n\n**Fixed**\n\n- Remove entirely the small social button style [\\#537](https://github.com/auth0/Lock.Android/pull/537) ([lbalmaceda](https://github.com/lbalmaceda))\n- Define custom email regex to validate emails [\\#534](https://github.com/auth0/Lock.Android/pull/534) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.14.0](https://github.com/auth0/Lock.Android/tree/2.14.0) (2019-04-30)\n\nFrom this release on, the option to display social connections in small styled buttons is no longer available due to branding compliance reasons. All the social connections will now be displayed as large styled buttons.\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.13.0...2.14.0)\n\n**Changed**\n\n- Remove \"Small\" social button style [\\#529](https://github.com/auth0/Lock.Android/pull/529) ([lbalmaceda](https://github.com/lbalmaceda))\n- Update google-oauth2 strategy logo [\\#528](https://github.com/auth0/Lock.Android/pull/528) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.13.0](https://github.com/auth0/Lock.Android/tree/2.13.0) (2019-04-17)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.12.1...2.13.0)\n\n**Changed**\n\n- Use auth0.android 1.15.2 [\\#526](https://github.com/auth0/Lock.Android/pull/526) ([lbalmaceda](https://github.com/lbalmaceda))\n- Update facebook icon to comply with new branding [\\#525](https://github.com/auth0/Lock.Android/pull/525) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.12.1](https://github.com/auth0/Lock.Android/tree/2.12.1) (2019-02-22)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.12.0...2.12.1)\n\n**Fixed**\n\n- Parse 'password_leaked' error message [\\#522](https://github.com/auth0/Lock.Android/pull/522) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.12.0](https://github.com/auth0/Lock.Android/tree/2.12.0) (2019-01-30)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.11.0...2.12.0)\n\n**Changed**\n\n- Use latest Auth0.Android SDK [\\#520](https://github.com/auth0/Lock.Android/pull/520) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.11.1](https://github.com/auth0/Lock.Android/tree/2.11.1) (2018-10-16)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.11.0...2.11.1)\n\n**Fixed**\n\n- Handle Tab change manually on ModeSelectionView [\\#499](https://github.com/auth0/Lock.Android/pull/499) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.11.0](https://github.com/auth0/Lock.Android/tree/2.11.0) (2018-10-05)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.10.0...2.11.0)\n\n**Added**\n\n- Added showTerms feature flag [\\#487](https://github.com/auth0/Lock.Android/pull/487) ([cocojoe](https://github.com/cocojoe))\n\n**Fixed**\n\n- Use target SDK 28 and latest Auth0 SDK version [\\#484](https://github.com/auth0/Lock.Android/pull/484) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.10.0](https://github.com/auth0/Lock.Android/tree/2.10.0) (2018-09-14)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.9.0...2.10.0)\n\n**Added**\n\n- Allow to override the password minimum length [\\#474](https://github.com/auth0/Lock.Android/pull/474) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.9.0](https://github.com/auth0/Lock.Android/tree/2.9.0) (2018-07-25)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.6...2.9.0)\n\n**Added**\n\n- Allow to disable 'ActiveAuth' on enterprise Connections [\\#471](https://github.com/auth0/Lock.Android/pull/471) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.6](https://github.com/auth0/Lock.Android/tree/2.8.6) (2018-07-20)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.5...2.8.6)\n\n**Fixed**\n\n- Fix CustomTabsController issues [\\#469](https://github.com/auth0/Lock.Android/pull/469) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.5](https://github.com/auth0/Lock.Android/tree/2.8.5) (2018-07-19)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.4...2.8.5)\n\n**Fixed**\n\n- Enable MFA support for OIDC conformant clients [\\#451](https://github.com/auth0/Lock.Android/pull/451) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.4](https://github.com/auth0/Lock.Android/tree/2.8.4) (2018-07-13)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.3...2.8.4)\n\n**Fixed**\n\n- Fix WebAuth issues by updating SDK to 1.13.1 [\\#465](https://github.com/auth0/Lock.Android/pull/465) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.3](https://github.com/auth0/Lock.Android/tree/2.8.3) (2018-03-19)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.2...2.8.3)\n\n**Fixed**\n\n- Disable HTTP 2 protocol [\\#458](https://github.com/auth0/Lock.Android/pull/458) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.2](https://github.com/auth0/Lock.Android/tree/2.8.2) (2018-02-26)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.1...2.8.2)\n\n**Fixed**\n\n- Draw background and borders on programmatically created fields [\\#455](https://github.com/auth0/Lock.Android/pull/455) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.1](https://github.com/auth0/Lock.Android/tree/2.8.1) (2018-02-21)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.8.0...2.8.1)\n\n**Changed**\n\n- Bump SDK version to 1.12.1 [\\#452](https://github.com/auth0/Lock.Android/pull/452) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.8.0](https://github.com/auth0/Lock.Android/tree/2.8.0) (2017-10-19)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.7.0...2.8.0)\n**Closed issues**\n\n- Cannot navigate social login buttons using gamepad on Android TV [\\#443](https://github.com/auth0/Lock.Android/issues/443)\n\n**Added**\n\n- Add RTL support [\\#445](https://github.com/auth0/Lock.Android/pull/445) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fix ValidatedInputView border color on focus change [\\#446](https://github.com/auth0/Lock.Android/pull/446) ([lbalmaceda](https://github.com/lbalmaceda))\n- Fix non touchscreen navigation [\\#444](https://github.com/auth0/Lock.Android/pull/444) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.7.0](https://github.com/auth0/Lock.Android/tree/2.7.0) (2017-07-19)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.6.0...2.7.0)\n\n**Changed**\n\n- Update lib version to use auth0Scheme placeholder [\\#431](https://github.com/auth0/Lock.Android/pull/431) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.6.0](https://github.com/auth0/Lock.Android/tree/2.6.0) (2017-07-12)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.5.0...2.6.0)\n**Closed issues**\n\n- NullPointerException in onResume for certain devices [\\#415](https://github.com/auth0/Lock.Android/issues/415)\n\n**Added**\n\n- Add Password Toggle enabler/disabler [\\#423](https://github.com/auth0/Lock.Android/pull/423) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add Hosted Login Page button to the demo. [\\#422](https://github.com/auth0/Lock.Android/pull/422) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add \"show password\" button for Password fields. [\\#421](https://github.com/auth0/Lock.Android/pull/421) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Change activity to context in Lock initialization [\\#416](https://github.com/auth0/Lock.Android/pull/416) ([skrabacz-michal](https://github.com/skrabacz-michal))\n\n**Fixed**\n\n- Fix NPE when enabling or disabling Lock interaction [\\#420](https://github.com/auth0/Lock.Android/pull/420) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.5.0](https://github.com/auth0/Lock.Android/tree/2.5.0) (2017-04-27)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.4.0...2.5.0)\n\n**Added**\n\n- Add paypal-sandbox support [\\#412](https://github.com/auth0/Lock.Android/pull/412) ([ziluvatar](https://github.com/ziluvatar))\n- Send login_hint on enterprise web auth when username/email is available [\\#410](https://github.com/auth0/Lock.Android/pull/410) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add screens for Lock loading errors [\\#407](https://github.com/auth0/Lock.Android/pull/407) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Allow to customize the capitalization of messages [\\#408](https://github.com/auth0/Lock.Android/pull/408) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.4.0](https://github.com/auth0/Lock.Android/tree/2.4.0) (2017-03-06)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.3.0...2.4.0)\n**Closed issues**\n\n- LockBuilder withScope method not working. [\\#397](https://github.com/auth0/Lock.Android/issues/397)\n\n**Added**\n\n- Add Passwordless auto login [\\#392](https://github.com/auth0/Lock.Android/pull/392) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Update auth0.android library to version 1.6.0 [\\#400](https://github.com/auth0/Lock.Android/pull/400) ([lbalmaceda](https://github.com/lbalmaceda))\n- Remove \"invalid client type\" user message [\\#391](https://github.com/auth0/Lock.Android/pull/391) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fix setScope to properly send the scope attribute on Auth [\\#399](https://github.com/auth0/Lock.Android/pull/399) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add loggingEnabled flag to the Auth0 parcel [\\#398](https://github.com/auth0/Lock.Android/pull/398) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.3.0](https://github.com/auth0/Lock.Android/tree/2.3.0) (2017-01-02)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.2.1...2.3.0)\n\n**Added**\n\n- Send custom audience on login/signIn if is OIDC conformant [\\#387](https://github.com/auth0/Lock.Android/pull/387) ([lbalmaceda](https://github.com/lbalmaceda))\n- Include updated Proguard rules in the packaged aar [\\#385](https://github.com/auth0/Lock.Android/pull/385) ([lbalmaceda](https://github.com/lbalmaceda))\n- Support custom audience for Web Authentication [\\#383](https://github.com/auth0/Lock.Android/pull/383) ([lbalmaceda](https://github.com/lbalmaceda))\n- Support custom schemes for Web Authentication [\\#382](https://github.com/auth0/Lock.Android/pull/382) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add option to hide Header Title on the Main screen [\\#381](https://github.com/auth0/Lock.Android/pull/381) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Update gradle plugins and google dependencies [\\#389](https://github.com/auth0/Lock.Android/pull/389) ([hzalaz](https://github.com/hzalaz))\n- Use Header style and fix Submit button height when label is displayed [\\#388](https://github.com/auth0/Lock.Android/pull/388) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Deprecated**\n\n- Deprecate useImplicitGrant method [\\#372](https://github.com/auth0/Lock.Android/pull/372) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fix Auth0 parcel that was losing telemetry and OIDC flag [\\#384](https://github.com/auth0/Lock.Android/pull/384) ([lbalmaceda](https://github.com/lbalmaceda))\n- Fix wrong label setting if login was disabled and pwd reset was first screen [\\#380](https://github.com/auth0/Lock.Android/pull/380) ([lbalmaceda](https://github.com/lbalmaceda))\n- Don't return to login/signup screen after pwd reset if those screens are disabled [\\#379](https://github.com/auth0/Lock.Android/pull/379) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add authentication parameters to custom AuthProvider [\\#375](https://github.com/auth0/Lock.Android/pull/375) ([lbalmaceda](https://github.com/lbalmaceda))\n- Avoid sending authentication parameters on password-reset [\\#373](https://github.com/auth0/Lock.Android/pull/373) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Breaking changes**\n\n- Use labeled submit button by default and separate signUp/logIn strings [\\#386](https://github.com/auth0/Lock.Android/pull/386) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.2.1](https://github.com/auth0/Lock.Android/tree/2.2.1) (2016-11-22)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.2.0...2.2.1)\n\n**Changed**\n\n- Update auth0.android to fix scope issue [\\#370](https://github.com/auth0/Lock.Android/pull/370) ([hzalaz](https://github.com/hzalaz))\n\n## [2.2.0](https://github.com/auth0/Lock.Android/tree/2.2.0) (2016-11-21)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.1.1...2.2.0)\n\n**Added**\n\n- Allow to set a custom scope. [\\#368](https://github.com/auth0/Lock.Android/pull/368) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Update to auth0.android 1.1.1 [\\#369](https://github.com/auth0/Lock.Android/pull/369) ([hzalaz](https://github.com/hzalaz))\n\n## [2.1.1](https://github.com/auth0/Lock.Android/tree/2.1.1) (2016-11-02)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.1.0...2.1.1)\n\n**Fixed**\n\n- Fix NPE when connection scope is missing [\\#365](https://github.com/auth0/Lock.Android/pull/365) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.1.0](https://github.com/auth0/Lock.Android/tree/2.1.0) (2016-10-24)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.0.0...2.1.0)\n\n**Added**\n\n- Support connection_scope for OAuth Connections [\\#361](https://github.com/auth0/Lock.Android/pull/361) ([lbalmaceda](https://github.com/lbalmaceda))\n- Send LockException if the Theme is invalid [\\#358](https://github.com/auth0/Lock.Android/pull/358) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add labeled submit button option [\\#352](https://github.com/auth0/Lock.Android/pull/352) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Non-empty username validation for custom/imported connections [\\#360](https://github.com/auth0/Lock.Android/pull/360) ([lbalmaceda](https://github.com/lbalmaceda))\n- Fix Theme load from styles.xml [\\#357](https://github.com/auth0/Lock.Android/pull/357) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Breaking changes**\n\n- Use browser by default when using WebAuthProvider. [\\#355](https://github.com/auth0/Lock.Android/pull/355) ([lbalmaceda](https://github.com/lbalmaceda))\n\nSince Google will be [blocking webview OAuth request](https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html) we switched the default authentication flow for all social connections from WebView to Browser.\nBrowser authentication requires a little more configuration in your `AndroidManifest.xml` file.\nFirst make sure `LockActivity` has `singleTask` in `android:launchMode` and then add to it an `intent-filter`:\n\n```xml\n<intent-filter>\n  <action android:name=\"android.intent.action.VIEW\" />\n\n  <category android:name=\"android.intent.category.DEFAULT\" />\n  <category android:name=\"android.intent.category.BROWSABLE\" />\n\n  <data\n    android:host=\"{YOUR_AUTH0_DOMAIN}\"\n    android:pathPrefix=\"/android/{YOUR_APP_PACKAGE_NAME}/callback\"\n    android:scheme=\"https\" />\n</intent-filter>\n```\n\n## [2.0.0](https://github.com/auth0/Lock.Android/tree/2.0.0) (2016-09-21)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.0.0-beta.4...2.0.0)\n\n**Changed**\n\n- Merge Enterprise and Social login events [\\#347](https://github.com/auth0/Lock.Android/pull/347) ([lbalmaceda](https://github.com/lbalmaceda))\n- Show button when only one enterprise connection is available [\\#341](https://github.com/auth0/Lock.Android/pull/341) ([lbalmaceda](https://github.com/lbalmaceda))\n- Filter social strategies by connection name [\\#340](https://github.com/auth0/Lock.Android/pull/340) ([lbalmaceda](https://github.com/lbalmaceda))\n- Flatten Strategies into Connections [\\#335](https://github.com/auth0/Lock.Android/pull/335) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Fixed**\n\n- Fix OAuth connection callback for PasswordlessActivity [\\#346](https://github.com/auth0/Lock.Android/pull/346) ([lbalmaceda](https://github.com/lbalmaceda))\n- Fix non ro-enabled enterprise connections flow. [\\#344](https://github.com/auth0/Lock.Android/pull/344) ([lbalmaceda](https://github.com/lbalmaceda))\n- Fix wrong telemetry version [\\#342](https://github.com/auth0/Lock.Android/pull/342) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Breaking changes**\n\n- [Breaking Change] Rename builder methods [\\#350](https://github.com/auth0/Lock.Android/pull/350) ([lbalmaceda](https://github.com/lbalmaceda))\n- Refactor AuthProviderResolver [Breaking Change][\\#333](https://github.com/auth0/Lock.Android/pull/333) ([lbalmaceda](https://github.com/lbalmaceda))\n\n## [2.0.0-beta.4](https://github.com/auth0/Lock.Android/tree/2.0.0-beta.4) (2016-08-24)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.0.0-beta.3...2.0.0-beta.4)\n\n**Closed issues**\n\n- Lock SSO Username Fails Validation [\\#332](https://github.com/auth0/Lock.Android/issues/332)\n\n**Fixed**\n\n- Change username validation for SSO connections [\\#334](https://github.com/auth0/Lock.Android/pull/334) ([lbalmaceda](https://github.com/lbalmaceda))\n- Check that requested tokens are present on the result. [\\#330](https://github.com/auth0/Lock.Android/pull/330) ([lbalmaceda](https://github.com/lbalmaceda))\n- Use first available connection name when authenticating with OAuth [\\#320](https://github.com/auth0/Lock.Android/pull/320) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Added**\n\n- Custom Style for Social Buttons [\\#325](https://github.com/auth0/Lock.Android/pull/325) ([lbalmaceda](https://github.com/lbalmaceda))\n- Request the user to accept Terms&Policy before Sign Up [\\#319](https://github.com/auth0/Lock.Android/pull/319) ([lbalmaceda](https://github.com/lbalmaceda))\n- Handle too_many_attempts API error [\\#308](https://github.com/auth0/Lock.Android/pull/308) ([lbalmaceda](https://github.com/lbalmaceda))\n- Add Service Terms and Privacy Policy dialog [\\#307](https://github.com/auth0/Lock.Android/pull/307) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Changed**\n\n- Force init lock [Breaking Change][\\#329](https://github.com/auth0/Lock.Android/pull/329) ([lbalmaceda](https://github.com/lbalmaceda))\n- Update Auth0 lib version to latest [\\#327](https://github.com/auth0/Lock.Android/pull/327) ([lbalmaceda](https://github.com/lbalmaceda))\n- Hide Theme configuration on the Builder [Breaking Change][\\#326](https://github.com/auth0/Lock.Android/pull/326) ([lbalmaceda](https://github.com/lbalmaceda))\n- Use AuthMode constants when notifying tab change [\\#323](https://github.com/auth0/Lock.Android/pull/323) ([lbalmaceda](https://github.com/lbalmaceda))\n- Handle wrong Client Type error [\\#321](https://github.com/auth0/Lock.Android/pull/321) ([lbalmaceda](https://github.com/lbalmaceda))\n- Change SocialButton title when changing the Form mode [\\#317](https://github.com/auth0/Lock.Android/pull/317) ([lbalmaceda](https://github.com/lbalmaceda))\n- UI Improvements: Bigger buttons/fields [\\#314](https://github.com/auth0/Lock.Android/pull/314) ([lbalmaceda](https://github.com/lbalmaceda))\n- New Tab design. [\\#313](https://github.com/auth0/Lock.Android/pull/313) ([lbalmaceda](https://github.com/lbalmaceda))\n- Use pngs instead of vectorial xml files [\\#311](https://github.com/auth0/Lock.Android/pull/311) ([lbalmaceda](https://github.com/lbalmaceda))\n- Make PKCE enabled by default [\\#310](https://github.com/auth0/Lock.Android/pull/310) ([lbalmaceda](https://github.com/lbalmaceda))\n- Always pick defaultDbConnection if available [\\#309](https://github.com/auth0/Lock.Android/pull/309) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Breaking changes**\n\n`Lock` & `PassworlessLock` no longer has the method `onCreate(Activity)` and it's logic is now part of the method `Lock.Builder.build(Activity)`. So to create a Lock instance you will have\n\n```java\nLock lock = Lock.newBuilder(auth0, callback)\n      //Customize Lock\n      .build(this);\n```\n\nAlso now you can create `Lock` by reading your Auth0 account credentials from a strings file\n\n```java\nLock lock = Lock.newBuilder(callback)\n      //Customize Lock\n      .build(this);\n```\n\nand he string file should have\n\n```xml\n <resources>\n    <string name=\"com_auth0_client_id\">{CLIENT_ID}</string>\n    <string name=\"com_auth0_domain\">{DOMAIN}</string>\n</resources>\n```\n\n`Lock.Builder` no longers allow to customize Lock's theme using the method `withTheme(Theme)` since using Android themes is preferable.\n\nAlso for all non-database authentication will use **Proof Key for Code Exchange** by default so your client type in Auth0 dashboard **must** be `Native`.\n\n## [2.0.0-beta.3](https://github.com/auth0/Lock.Android/tree/2.0.0-beta.3) (2016-07-22)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.0.0-beta.2...2.0.0-beta.3)\n\n**Added**\n\n- Locally Configurable Lock sample app [\\#298](https://github.com/auth0/Lock.Android/pull/298) ([lbalmaceda](https://github.com/lbalmaceda)\n- Password Strength Widget [\\#297](https://github.com/auth0/Lock.Android/pull/297) ([lbalmaceda](https://github.com/lbalmaceda)\n\n**Changed**\n\n- Update Proguard rules [\\#305](https://github.com/auth0/Lock.Android/pull/305) ([lbalmaceda](https://github.com/lbalmaceda)\n- Remove Fullscreen feature [\\#302](https://github.com/auth0/Lock.Android/pull/302) ([lbalmaceda](https://github.com/lbalmaceda)\n- Add callback setup on dashboard [\\#300](https://github.com/auth0/Lock.Android/pull/300) ([lbalmaceda](https://github.com/lbalmaceda)\n- Allow to customize Lock's theme programmatically [\\#294](https://github.com/auth0/Lock.Android/pull/294) ([lbalmaceda](https://github.com/lbalmaceda)\n- Remove unused User Profile calls. [\\#293](https://github.com/auth0/Lock.Android/pull/293) ([lbalmaceda](https://github.com/lbalmaceda)\n- Take email input across the forms [\\#292](https://github.com/auth0/Lock.Android/pull/292) ([lbalmaceda](https://github.com/lbalmaceda)\n- Allow up to 3 Social Big Buttons on Passwordless mode [\\#291](https://github.com/auth0/Lock.Android/pull/291) ([lbalmaceda](https://github.com/lbalmaceda)\n- Improve Custom Fields flow and layout [\\#290](https://github.com/auth0/Lock.Android/pull/290) ([lbalmaceda](https://github.com/lbalmaceda)\n- Handle Application without Connections [\\#289](https://github.com/auth0/Lock.Android/pull/289) ([lbalmaceda](https://github.com/lbalmaceda)\n- Draw the header behind the statusBar in Lollipop or greater [\\#288](https://github.com/auth0/Lock.Android/pull/288) ([lbalmaceda](https://github.com/lbalmaceda)\n\n**Fixed**\n\n- Fix sign up request not sending the user metadata [\\#303](https://github.com/auth0/Lock.Android/pull/303) ([lbalmaceda](https://github.com/lbalmaceda)\n- Fix TextView extra padding. [\\#296](https://github.com/auth0/Lock.Android/pull/296) ([lbalmaceda](https://github.com/lbalmaceda)\n- Country code selection widget fixes [\\#295](https://github.com/auth0/Lock.Android/pull/295) ([lbalmaceda](https://github.com/lbalmaceda)\n\n**Breaking changes**\n\n**Lock** `Builder` method\n\n```java\npublic Builder allowSignIn(boolean allow) {...}\n```\n\nwas renamed to\n\n```java\npublic Builder allowLogIn(boolean allow) {...}\n```\n\nAlso this method (and feature) is no longer supported in **Lock**\n\n```java\npublic Builder fullscreen(boolean fullscreen) {...}\n```\n\n## [2.0.0-beta.2](https://github.com/auth0/Lock.Android/tree/2.0.0-beta.2) (2016-06-06)\n\n[Full Changelog](https://github.com/auth0/Lock.Android/compare/2.0.0-beta.1...2.0.0-beta.2)\n\n**Changed**\n\n- Use new version of auth0-java to fix issue with json parsing [\\#286](https://github.com/auth0/Lock.Android/pull/286) ([lbalmaceda](https://github.com/lbalmaceda))\n- Fix issues with default values of `allow****` and `initialScreen` options [\\#286](https://github.com/auth0/Lock.Android/pull/286) ([lbalmaceda](https://github.com/lbalmaceda))\n\n**Breaking changes**\n\n`AuthenticationCallback` no longer returns `UserProfile`, it only returns `Credentials` object with the tokens of the authenticated user:\n\n```java\nprivate LockCallback callback = new AuthenticationCallback() {\n     @Override\n     public void onAuthentication(Credentials credentials) {\n        //Authenticated\n     }\n\n     @Override\n     public void onCanceled() {\n        //User pressed back\n     }\n\n     @Override\n     public void onError(LockException error)\n        //Exception occurred\n     }\n };\n```\n\nTo request the `UserProfile`, just use `AuthenticationAPIClient` from [auth0-java](https://github.com/auth0/auth0-java)\n\n```java\n@Override\npublic void onAuthentication(Credentials credentials) {\n    AuthenticationAPIClient client = new AuthenticationAPIClient(new Auth0(\"YOUR_CLIENT_ID\", \"YOUR_DOMAIN\"));\n\n    client.tokenInfo(credentials.idToken)\n        .start(new BaseCallback<UserProfile>() {\n            @Override\n            public void onSuccess(UserProfile payload) { }\n\n            @Override\n            public void onFailure(Auth0Exception error) { }\n        });\n}\n```\n\n## [2.0.0-beta.1](https://github.com/auth0/Lock.Android/tree/2.0.0-beta.1) (2016-06-03)\n\nFirst beta release of Lock for Android v2\n\n### Declaration in AndroidManifest.xml\n\nNow Lock for Android requires these permisssions\n\n```xml\n<uses-permission android:name=\"android.permission.INTERNET\" />\n<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n```\n\nand this is how `LockActivity` should be declared in your Android Manifest\n\n```xml\n<activity\n  android:name=\"com.auth0.android.lock.LockActivity\"\n  android:label=\"@string/app_name\"\n  android:launchMode=\"singleTask\"\n  android:screenOrientation=\"portrait\"\n  android:theme=\"@style/Lock.Theme\">\n    <intent-filter>\n      <action android:name=\"android.intent.action.VIEW\" />\n\n      <category android:name=\"android.intent.category.DEFAULT\" />\n      <category android:name=\"android.intent.category.BROWSABLE\" />\n\n      <data\n        android:host=\"YOUR_AUTH0_DOMAIN\"\n        android:pathPrefix=\"/android/YOUR_APP_PACKAGE_NAME/callback\"\n        android:scheme=\"https\" />\n    </intent-filter>\n</activity>\n```\n\n### Lock instance\n\nIn the previous version of **Lock**, you were asked to create a custom `Application` class and initialize the `Lock.Context` there. Now this is no longer needed. To create a new `Lock` instance and configure it, use the `Lock.Builder` class.\n\n#### Auth0\n\nCreate an `Auth0` instance to hold your account details, which are the `AUTH0_CLIENT_ID` and the `AUTH0_DOMAIN`.\n\n```java\nAuth0 auth0 = new Auth0(\"YOUR_AUTH0_CLIENT_ID\", \"YOUR_AUTH0_DOMAIN\");\n```\n\n### Authentication Callback\n\nYou'll also need a `LockCallback` implementation, we provide `AuthenticationCallback` that reports the following events:\n\n- onAuthentication: User successfuly authenticated\n- onError: An unrecoverable error ocurred during authentication\n- onCanceled: User pressed back (if closable is true)\n\n> If you need a more fine grained control you can implement `LockCallback` full interface.\n\n```java\nprivate LockCallback callback = new AuthenticationCallback() {\n     @Override\n     public void onAuthentication(Authentication authentication) {\n        //Authenticated\n     }\n\n     @Override\n     public void onCanceled() {\n        //User pressed back\n     }\n\n     @Override\n     public void onError(LockException error)\n        //Exception occurred\n     }\n };\n```\n\n### Lock.Builder\n\nCall the static method `Lock.newBuilder(Auth0, AuthenticationCallback)` passing the account details and the callback implementation, and start configuring the [Options](#options). After you're done, build the `Lock` instance and use it to start the `LockActivity`.\n\nThis is how your activity should look like.\n\n```java\npublic class MainActivity extends Activity {\n  private Lock lock;\n\n  @Override\n  protected void onCreate(@Nullable Bundle savedInstanceState) {\n    Auth0 auth0 = new Auth0(AUTH0_CLIENT_ID, AUTH0_DOMAIN);\n    lock = Lock.newBuilder(auth0, callback)\n      // ... Options\n      .build();\n    lock.onCreate(this);\n  }\n\n  @Override\n  public void onDestroy() {\n    lock.onDestroy(this);\n    super.onDestroy();\n  }\n\n  private void performLogin(boolean useBrowser) {\n    startActivity(lock.newIntent(this));\n  }\n\n  private LockCallback callback = new AuthenticationCallback() {\n       @Override\n       public void onAuthentication(Authentication authentication) {\n          //Authenticated\n       }\n\n       @Override\n       public void onCanceled() {\n          //User pressed back\n       }\n\n       @Override\n       public void onError(LockException error) {\n          //Exception occurred\n       }\n   };\n}\n```\n\n> Remember to notify the `LockActivity` on every `OnCreate` and `OnDestroy` call on your Activity, as it helps to keep the Lock state.\n\n### Options\n\nAs in the previous version, `Lock` can be configured with extra options. Check below if the behavior changed or if they only got renamed.\n\n#### Renamed options from v1\n\n- shouldUseEmail: Renamed to `withUsernameStyle`. Defines if it should ask for email only, username only, or both of them. By default, it'll respect the Dashboard configuration of the parameter `requires_username`.\n- isClosable: Renamed to `closable`. Defines if the LockActivity can be closed. By default, it's not closable.\n- setFullscreen: Renamed to `fullscreen`. Defines if the LockActivity it's displayed in fullscreen. By default, it's not fullscreen.\n- shouldLoginAfterSignUp: Renamed to `loginAfterSignUp`. Whether after a SignUp the user should be logged in automatically.\n- disableSignupAction: Renamed to `allowSignUp`. Shows the Sign Up form if a Database connection is configured.\n- disableResetAction: Renamed to `allowForgotPassword`. Shows a link to the Forgot Password form if a Database connection is configured and it's allowed from the Dashboard.\n- defaultUserPasswordConnection: Renamed to `setDefaultDatabaseConnection`. Defines which will be the default Database connection. This is useful if your application has many Database connections configured.\n- setConnections: Renamed to `onlyUseConnections`. Filters the allowed connections from the list configured in the Dashboard..\n- setAuthenticationParameters: Renamed to `withAuthenticationParameters`. Defines extra authentication parameters, sent on sign up and log in/sign in.\n\n#### New options in v2\n\n- `initialScreen(int)` allows to customize which form will show first when launching **Lock**. The possibles values are LOG_IN, SIGN_UP, and FORGOT_PASSWORD. By default LOG_IN is the initial screen.\n- `allowLogIn(boolean)` shows the Log In form if a Database connection is configured. By default, this screen it's enabled.\n- `allowSignUp(boolean)` shows the Sign Up form if a Database connection is configured. By default, this screen it's enabled.\n- `allowForgotPassword(boolean)` shows the Forgot Password form if a Database connection is configured. By default, this screen it's enabled.\n- `withSignUpFields(List<CustomFields>)` shows a second screen with extra fields after completing the sign up fields.\n- `withProviderResolver(AuthProviderResolver)` pass your own AuthProviderResolver instance to query for AuthProviders.\n- `withSocialButtonStyle(int)` allows to customize the Style of the Social buttons. Possible values are SMALL and BIG. If this is not specified, it will default to SMALL when many Social and Db/Enterprise connections are configured; and BIG on the rest of the cases.\n- `usePKCE(boolean)` whether to use the new PKCE flow or the old Token exchange one when authenticating. By default, it won't use PKCE.\n"
  },
  {
    "path": "EXAMPLES.md",
    "content": "# Examples using Lock.Android\n\n- [Examples using Lock.Android](#examples-using-lockandroid)\n  - [Passwordless & Social authentication](#passwordless--social-authentication)\n  - [Android App Links - Custom Scheme](#android-app-links---custom-scheme)\n  - [Using Proguard](#using-proguard)\n\n\n## Passwordless & Social authentication\n\nThe Passwordless feature requires your Application to have the *Passwordless OTP* Grant Type enabled first. Check [this article](https://auth0.com/docs/clients/client-grant-types) to learn how to enable it. \n\n`PasswordlessLockActivity` authenticates users by sending them an Email or SMS (similar to how WhatsApp authenticates you). In order to be able to authenticate the user, your application must have the SMS/Email connection enabled and configured in your [dashboard](https://manage.auth0.com/#/connections/passwordless).\n\nInitialize **PasswordlessLock** and handle the release of its resources appropriately after you're doing using it. \n\n```kotlin\n// This activity will show PasswordlessLock\nclass MyActivity : AppCompatActivity() {\n    \n    private lateinit var lock: PasswordlessLock\n    \n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n    \n        val account = Auth0(this)\n        // Instantiate Lock once\n        lock = PasswordlessLock.newBuilder(account, callback)\n            // Customize Lock\n            .build(this)\n    }\n    \n    override fun onDestroy() {\n        super.onDestroy()\n        // Important! Release Lock and its resources\n        lock.onDestroy(this)\n    }\n    \n    private val callback = object : AuthenticationCallback() {\n        override fun onAuthentication(credentials: Credentials) {\n            // Authenticated\n        }\n        \n        override fun onError(error: AuthenticationException) {\n            // An exception occurred\n        }\n    }\n}\n```\n\nStart `PasswordlessLockActivity` from inside your `Activity`. For this, create a new intent and launch it.\n\n```kotlin\nstartActivity(lock.newIntent(this))\n```\n\n## Android App Links - Custom Scheme\n\nThe default scheme used by the library to generate the Callback URL for Web Authentication is `https`. This works best for Android Marshmallow (API 23) or newer if you're using [Android App Links](https://developer.android.com/training/app-links/index.html). However, in previous Android versions, this may show the disambiguation dialog prompting the user to choose either your application or the browser to resolve the intent. You can change this behavior by using a unique custom scheme so that the OS opens the link directly with your app.\n\n1. Update the `auth0Scheme` Manifest Placeholder value in the `app/build.gradle` file or directly in the Intent Filter definition in the `AndroidManifest.xml` file by changing the existing scheme to the new one.\n2. Update the \"Allowed Callback URLs\" in your [Auth0 Dashboard](https://manage.auth0.com/#/clients) Application's settings to match URLs that begin with the new scheme.\n3. Call `withScheme()` in the Lock.Builder/PasswordlessLock.Builder passing the scheme you want to use.\n\n> The scheme value **must** be all lowercase. A warning message will be logged if this is not the case and authentication will never complete.\n\n## Using Proguard\n\nThe rules should be applied automatically if your application is using `minifyEnabled = true`. If you want to include them manually check the [proguard directory](proguard).\nBy default you should at least use the following files:\n* `proguard-gson.pro`\n* `proguard-otto.pro`\n* `proguard-lock-2.pro`\n\nAs this library depends on `Auth0.Android`, you should keep the files up to date with the proguard rules defined in the SDK [repository](https://github.com/auth0/Auth0.Android)."
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Auth0, Inc. <support@auth0.com> (http://auth0.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "MIGRATION_GUIDE.md",
    "content": "# Migration Guide\nThis guide will help you migrate Lock.Android from version v2.x.x to version v3.x.x. \n\n## About this release\nThe new version makes use of the latest Auth0.Android SDK, bringing improvements such as:\n - Open ID Connect compliant practices.\n - ID token verification for Web Authentication flows.\n - A new customizable networking stack.\n - Simpler Android app set up.\n \n Some of these features were previously available, but only enforced when the \"OIDC\" flag was explicitly enabled.  \n\n## New requirements\nUsing the latest core SDK comes with new constraints. Your Android application will need to:\n- Require a minimum Android version of 21 and above.\n- Target Java version 8 and above.\n\nHere’s what you need in build.gradle to target Java 8 byte code for the Android and Kotlin plugins respectively.\n\n```groovy\nandroid {\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n}\n```\n\n## Changes to the AndroidManifest file\nIn the previous version you had to declare the Lock activities you planned to use. These activities are now declared internally by the library with intent filters configured using the Manifest Placeholders that you provide for the Domain and Scheme. The Manifest Merger tool will process these and include them as part of your Android application. \n\nIf your `AndroidManifest.xml` file includes declarations for `LockActivity`, `PasswordlessLockActivity` or `CountryCodeActivity`, you should remove them to avoid duplicated intent filter declarations.\n\nIf you are using a custom style for the theme or need to override the intent-filter declarations in any of these activities, you will have to declare an activity with the same component name and annotate it with `tools:node=\"replace\"`.\n\nFind details about the merging rules that will be used in the [Android Manifest Merger article](https://developer.android.com/studio/build/manifest-merge).\n\n## Changes to the Public API\nAs part of removing legacy APIs or authentication flows no longer recommended for mobile clients, the following features are no longer available:\n\n- Web Authentication flow using a WebView component instead of an external Browser. Please refer to [this blog post](https://auth0.com/blog/google-blocks-oauth-requests-from-embedded-browsers/) for additional information.\n- Web Authentication flow using a response type other than \"code\".\n- Authentication API methods categorized as Legacy in the [API docs](https://auth0.com/docs/api/authentication).\n\nContinue reading for the detail of classes and methods that were impacted.\n\n### Updated Callbacks\nThe widget requires a callback to receive the results in. The interface for this is `LockCallback`, which takes either an event or an error. The `onError` method got updated to receive an `AuthenticationException` instead of `LockException`. This change will help developers extract the *code* and *description* of the error and understand better what went wrong and how to recover from it.\n\nThe change impacts the abstract subclass `AuthenticationCallback`. Additionally, this class no longer has an `onCanceled` method. If you need to handle this scenario you have two options:\n- Implement `LockCallback` and handle the different event types, checking for `LockEvent.CANCELED`.\n- Implement `AuthenticationCallback` and check the received exception using the `AuthenticationException#isCanceled()` method.\n\n```kotlin\n// Before\nval callback: LockCallback = object : AuthenticationCallback() {\n    override fun onAuthentication(credentials: Credentials) {\n        // Authenticated\n    }\n\n    override fun onCanceled() {\n        // Canceled\n    }\n\n    override fun onError(error: LockException) {\n        // Another error. Check code & description.\n    }\n}\n\n// After\nval callback: LockCallback = object : AuthenticationCallback() {\n    override fun onAuthentication(credentials: Credentials) {\n        // Authenticated\n    }\n\n    override fun onError(error: AuthenticationException) {\n        if (error.isCanceled) {\n            // Canceled\n        } else {\n            // Another error. Check code & description.\n        }\n    }\n}\n```\n\n### Removed classes\n- `VoidCallback` is no longer available. Please, use `Callback<Void, AuthenticationException>` instead.\n- `LockException` is no longer available. This impacts the `LockCallback` and `AuthenticationCallback` classes. Please, use `AuthenticationException` instead.\n\n### Removed methods\n\n#### From class `AuthenticationCallback`\n- Removed `public void onCanceled()`. Instead, an exception will be raised through the `public void onError(AuthenticationException)` method. Check for this scenario using the `AuthenticationException#isCanceled()` method.\n\n#### From class `Lock.Builder`\n- Removed `public Builder useBrowser(boolean)`. The library will always use a third party browser app instead of a Web View to authenticate. No replacement is available.\n- Removed `public Builder useImplicitGrant(boolean)`. The library will always use the \"Proof Key for Code Exchange\" (PKCE) flow. Your application must be configured with the type \"Native\" and the \"OIDC Conformant\" switch ON. No replacement is available.\n- Removed `public Builder withAuthButtonSize(int)`. Social buttons will always have a \"large button\" style. No replacement is available. \n\n#### From class `PasswordlessLock.Builder`\n- Removed `public Builder useBrowser(boolean)`. The library will always use a third party browser app instead of a Web View to authenticate. No replacement is available.\n- Removed `public Builder useImplicitGrant(boolean)`. The library will always use the \"Proof Key for Code Exchange\" (PKCE) flow. Your application must be configured with the type \"Native\" and the \"OIDC Conformant\" switch ON. No replacement is available.\n- Removed `public Builder withAuthButtonSize(int)`. Social buttons will always have a \"large button\" style. No replacement is available. \n\n#### From `Auth0` class\n- Removed `setOIDCConformant(boolean)`. The library will only use Open ID Connect compliant flows from now on, this cannot be turned off.\n- Removed `setLoggingEnabled(boolean)`. The ability to turn on the networking logs has been removed. If you need to inspect the traffic, take a look at the [Network Profiler](https://developer.android.com/studio/profile/network-profiler) tool. \n\n### Changed methods\n\n#### From cass `Lock.Builder`\n- Changed `public Builder withAuthenticationParameters(@NonNull Map<String, Object> authenticationParameters)` to `public Builder withAuthenticationParameters(@NonNull Map<String, String> authenticationParameters)`. Request parameters must be specified as String key/values.\n\n#### From cass `PasswordlessLock.Builder`\n- Changed `public Builder withAuthenticationParameters(@NonNull Map<String, Object> authenticationParameters)` to `public Builder withAuthenticationParameters(@NonNull Map<String, String> authenticationParameters)`. Request parameters must be specified as String key/values.\n\n### Changes to the underlying SDK\n\nThe core SDK has been updated to the version 2+. Since this is exposed as an API scoped dependency, if you were using any of the classes or methods that changed in the new major release (e.g. the `WebAuthProvider` class), you might need to update your code. Follow the [Auth0.Android Migration Guide](https://github.com/auth0/Auth0.Android/blob/main/V2_MIGRATION_GUIDE.md) to assess the impact. \n\n## Changes in behavior\n\n### Lock lifecycle\n\nThe widget registers a Broadcast Listener to expect and handle the different lifecycle events. The listener is registered as soon as a new instance of `Lock` or `PasswordlessLock` is created with the corresponding Builder class, and the listener is unregistered when the `onDestroy` method is invoked. Forgetting to call this method would retain unnecessary resources after the authentication is complete and the widget is no longer required, or cause the callback to receive duplicated calls. \n\nIn case you are not currently calling it, make sure to update your code adding the `lock?.onDestroy(this)` call.\n\n```kotlin\nclass MyActivity : AppCompatActivity() {\n\n  private lateinit var lock: Lock\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    \n    val account = Auth0(this)\n    // Create a reusable Lock instance\n    lock = Lock.newBuilder(account, callback)\n      // Customize Lock\n      // .withScheme(\"myapp\")\n      .build(this)\n  }\n\n  private fun launchLock() {\n    // Invoke as many times as needed\n    val intent = lock.newIntent(this)\n    startActivity(intent)\n  }\n \n  override fun onDestroy() {\n      super.onDestroy()\n      // Release Lock resources\n      lock.onDestroy(this)\n  }\n}\n```\n\n### Non-recoverable errors\n\nThe `LockCallback` will get its `onError` method invoked when an [Auth0 Rule](https://auth0.com/docs/rules) returns an `Error` or `UnauthorizedError`. This was previously handled internally by Lock, causing it to display an orange toast with a generic failure message. From this release on, if you are using Auth0 Rules and throwing custom errors, you should obtain the _cause_ of the exception and read the code or description values to understand what went wrong.  "
  },
  {
    "path": "README.md",
    "content": "> **Note**\n> As part of our ongoing commitment to best security practices, we have rotated the signing keys used to sign previous releases of this SDK. As a result, new patch builds have been released using the new signing key. Please upgrade at your earliest convenience.\n>\n> While this change won't affect most developers, if you have implemented a dependency signature validation step in your build process, you may notice a warning that past releases can't be verified. This is expected, and a result of the key rotation process. Updating to the latest version will resolve this for you.\n\n![Lock for Android](https://cdn.auth0.com/website/sdks/banners/lock-android-banner.png)\n\n[![CircleCI](https://circleci.com/gh/auth0/Lock.Android.svg?style=shield)](https://circleci.com/gh/auth0/Lock.Android)\n[![License](https://img.shields.io/dub/l/vibe-d.svg?style=flat)](https://opensource.org/licenses/MIT)\n[![Maven Central](https://img.shields.io/maven-central/v/com.auth0.android/lock.svg)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.auth0.android%22%20AND%20a%3A%22lock%22)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/auth0/Lock.Android)\n\n📚 [Documentation](#documentation) • 🚀 [Getting Started](#getting-started) • ⏭️ [Next Steps](#next-steps) • 💬 [Feedback](#feedback)\n\n## Documentation\n\n- [Examples](https://github.com/auth0/Lock.android/blob/main/EXAMPLES.md)\n- [Docs Site](https://auth0.com/docs/libraries/lock-android)\n- [API Reference](https://javadoc.io/doc/com.auth0.android/lock/latest/index.html)\n\n## Getting Started\n\n### Requirements\n\nAndroid API Level 21+ & Java version 8 or above is required in order to use Lock's UI.\n\nHere’s what you need in build.gradle to target Java 8 byte code for the Android and Kotlin plugins respectively.\n\n```groovy\nandroid {\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = '1.8'\n    }\n}\n```\n\n### Installation\n\nLock is available in [Maven Central](http://search.maven.org). To start using *Lock* add this line to the dependencies of your `build.gradle` file:\n\n```groovy\nimplementation 'com.auth0.android:lock:3.2.2'\n```\n\n## Next Steps\n\nIf you haven't done yet, go to [Auth0](https://auth0.com) and create an Account, it's free! Then create a new [Application](https://manage.auth0.com/#/applications) of type *Native* and add a URL in *Allowed Callback URLs* with the following format:\n\n```\nhttps://{YOUR_AUTH0_DOMAIN}/android/{YOUR_APP_PACKAGE_NAME}/callback\n```\n\nThe *package name* value required in the Callback URL can be found in your app's `build.gradle` file in the `applicationId` property. Both the *domain* and *client id* values can be found at the top of your Auth0 Application's settings. You're going to use them to setup the SDK. It's good practice to add them to the `strings.xml` file as string resources that you can reference later from the code. This guide will follow that practice.\n\n```xml\n<resources>\n    <string name=\"com_auth0_client_id\">YOUR_AUTH0_CLIENT_ID</string>\n    <string name=\"com_auth0_domain\">YOUR_AUTH0_DOMAIN</string>\n</resources>\n```\n\nIn your `app/build.gradle` file add the **Manifest Placeholders** for the Auth0 Domain and Auth0 Scheme properties, which are going to be used internally by the library to declare the Lock activities and register **intent-filters** that will capture the authentication result.\n\n```groovy\napply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 30\n    defaultConfig {\n        applicationId \"com.auth0.samples\"\n        minSdkVersion 21\n        targetSdkVersion 30\n        //...\n\n        //---> Add the next line\n        manifestPlaceholders = [auth0Domain: \"@string/com_auth0_domain\", auth0Scheme: \"https\"]\n        //<---\n    }\n    //...\n}\n```\n\nThe next step is to create an instance of `Auth0` with your application's information. The easiest way to create it is by using the values defined previously in the `strings.xml` file and passing an Android Context. For this to work, you must have defined the string resources using the same keys as listed above.\n\n```kotlin\nval account = Auth0(context)\n```\n\nAlternatively, you can directly pass the values.\n\n```kotlin\nval account = Auth0(\"{YOUR_AUTH0_CLIENT_ID}\", \"{YOUR_AUTH0_DOMAIN}\")\n```\n\nOr, if you are using _custom domains_ and are required to specify a different URL to fetch the Lock widget configuration from, you can use the constructor that takes 3 parameters:\n\n```kotlin\nval account = Auth0(\"{YOUR_AUTH0_CLIENT_ID}\", \"{YOUR_AUTH0_DOMAIN}\", \"{THE_CONFIGURATION_DOMAIN}\")\n```\n\n\n### Email/Password, Enterprise & Social authentication\n\nInitialize **Lock** and handle the release of its resources appropriately after you're done using it. \n\n```kotlin\n// This activity will show Lock\nclass MyActivity : AppCompatActivity() {\n\n    private lateinit var lock: Lock\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n    \n        val account = Auth0(this)\n        // Instantiate Lock once\n        lock = Lock.newBuilder(account, callback)\n            // Customize Lock\n            .build(this)\n    }\n    \n    override fun onDestroy() {\n        super.onDestroy()\n        // Important! Release Lock and its resources\n        lock.onDestroy(this)\n    }\n    \n    private val callback = object : AuthenticationCallback() {\n        override fun onAuthentication(credentials: Credentials) {\n            // Authenticated\n        }\n        \n        override fun onError(error: AuthenticationException) {\n            // An exception occurred\n        }\n    }\n}\n```\n\nStart `LockActivity` from inside your `Activity`. For this, create a new intent from the Lock instance and launch it.\n\n```kotlin\nstartActivity(lock.newIntent(this))\n```\n\n### Customizing the widget\n\nWhen using the `Builder` to instantiate the widget, you can pass different options to customize how it will behave. Some options are only available for **Lock** or **PasswordlessLock**. Below you will find a few of them. You can always explore all the available options with your IDE's auto-complete shortcut. Check the Javadocs to understand the default values.\n\n\n```kotlin\n// Create a new builder from Lock or LockPasswordless classes\nnewBuilder(account, callback)\n    // Shared options\n    .closable(true) // Allows the widget to be closed with the back button\n    .withScope('new-scope') // Changes the scope to be requested on authentication\n    .withAudience('my-api') // Changes the audience to be requested on authentication\n    .withScheme('myapp') // Changes the scheme part used to generate the Callback URL (more below)\n    \n    // Lock specific options\n    .initialScreen(InitialScreen.SIGN_UP) // Allows to choose the screen to be displayed first \n    .allowLogIn(false) // Disables the Log In screen\n    .allowSignUp(false) // Disables the Sign Up screen\n    .allowForgotPassword(false) // Disables the Change Password screen\n    .setDefaultDatabaseConnection('my-connection') // When multiple are available, select one\n    \n    // PasswordlessLock specific options\n    .useCode(true)  // Requests to receive a OTP that will need to be filled in your android app to authenticate the user\n    .useLink(false) // Requests to receive a link that will open your android app to authenticate the user\n    .rememberLastLogin(true) // Saves the email or phone number to avoid re-typing it in the future\n    \n    // Build the instance\n    .build(this)\n```\n\n## Feedback\n\n### Contributing\n\nWe appreciate feedback and contribution to this repo! Before you get started, please see the following:\n\n- [Auth0's general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md)\n- [Auth0's code of conduct guidelines](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md)\n\n### Raise an issue\nTo provide feedback or report a bug, [please raise an issue on our issue tracker](https://github.com/auth0/Lock.Android/issues).\n\n### Vulnerability Reporting\nPlease do not report security vulnerabilities on the public Github issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.\n\n---\n\n<p align=\"center\">\n  <picture\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png\" width=\"150\">\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://cdn.auth0.com/website/sdks/logos/auth0_dark_mode.png\" width=\"150\">\n    <img alt=\"Auth0 Logo\" src=\"https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png\" width=\"150\">\n  </picture>\n</p>\n<p align=\"center\">Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout <a href=\"https://auth0.com/why-auth0\">Why Auth0?</a></p>\n<p align=\"center\">\nThis project is licensed under the MIT license. See the <a href=\"https://github.com/auth0/lock.android/blob/main/LICENSE.md\"> LICENSE</a> file for more info.</p>"
  },
  {
    "path": "app/.gitignore",
    "content": "# Created by https://www.gitignore.io/api/intellij,android,osx,windows\n\n### Intellij ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n# .idea/shelf\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n\n### Android ###\n# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n### Android Patch ###\ngen-external-apklibs\n\n\n### OSX ###\n.DS_Store\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n"
  },
  {
    "path": "app/build.gradle",
    "content": "plugins {\n    id \"com.android.application\"\n}\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 33\n\n    defaultConfig {\n        applicationId \"com.auth0.android.lock.app\"\n        minSdkVersion 21\n        targetSdkVersion 33\n        versionCode 1\n        versionName \"1.0\"\n        manifestPlaceholders = [auth0Domain: \"@string/com_auth0_domain\", auth0Scheme: \"demo\"]\n    }\n\n    signingConfigs {\n        release {\n            storeFile file(\"release-test.jks\")\n            storePassword \"android\"\n            keyAlias \"android\"\n            keyPassword \"android\"\n        }\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            signingConfig signingConfigs.release\n        }\n    }\n\n    packagingOptions {\n        exclude 'META-INF/LICENSE'\n        exclude 'META-INF/NOTICE'\n    }\n\n    compileOptions {\n        sourceCompatibility 1.8\n        targetCompatibility 1.8\n    }\n}\n\ndependencies {\n    testImplementation 'junit:junit:4.13.2'\n    implementation project(':lock')\n    implementation 'androidx.appcompat:appcompat:1.3.0'\n    implementation 'com.google.android.material:material:1.4.0'\n    implementation \"androidx.core:core-ktx:1.9.0\"\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Library/Android/sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n## Debugging\n-renamesourcefileattribute SourceFile\n-keepattributes SourceFile, LineNumberTable\n-verbose"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.auth0.android.lock.app\">\n\n    <application\n        android:allowBackup=\"false\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        tools:ignore=\"GoogleAppIndexingWarning\">\n\n        <activity\n            android:name=\".DemoActivity\"\n            android:exported=\"true\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/auth0/android/lock/app/DemoActivity.kt",
    "content": "/*\n * DemoActivity.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.auth0.android.lock.app\n\nimport android.os.Bundle\nimport android.view.View\nimport android.widget.Button\nimport android.widget.CheckBox\nimport android.widget.LinearLayout\nimport android.widget.RadioGroup\nimport androidx.appcompat.app.AppCompatActivity\nimport com.auth0.android.Auth0\nimport com.auth0.android.authentication.AuthenticationException\nimport com.auth0.android.callback.Callback\nimport com.auth0.android.lock.*\nimport com.auth0.android.provider.WebAuthProvider.login\nimport com.auth0.android.provider.WebAuthProvider.logout\nimport com.auth0.android.result.Credentials\nimport com.google.android.material.snackbar.Snackbar\n\nclass DemoActivity : AppCompatActivity() {\n\n    // Configured instances\n    private var lock: Lock? = null\n    private var passwordlessLock: PasswordlessLock? = null\n\n    // Views\n    private lateinit var rootLayout: View\n    private lateinit var groupSubmitMode: RadioGroup\n    private lateinit var checkboxClosable: CheckBox\n    private lateinit var groupPasswordlessChannel: RadioGroup\n    private lateinit var groupPasswordlessMode: RadioGroup\n    private lateinit var checkboxConnectionsDB: CheckBox\n    private lateinit var checkboxConnectionsEnterprise: CheckBox\n    private lateinit var checkboxConnectionsSocial: CheckBox\n    private lateinit var checkboxConnectionsPasswordless: CheckBox\n    private lateinit var checkboxHideMainScreenTitle: CheckBox\n    private lateinit var groupDefaultDB: RadioGroup\n    private lateinit var groupUsernameStyle: RadioGroup\n    private lateinit var checkboxLoginAfterSignUp: CheckBox\n    private lateinit var checkboxScreenLogIn: CheckBox\n    private lateinit var checkboxScreenSignUp: CheckBox\n    private lateinit var checkboxScreenReset: CheckBox\n    private lateinit var groupInitialScreen: RadioGroup\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.demo_activity)\n        rootLayout = findViewById(R.id.scrollView)\n\n        //Basic\n        groupSubmitMode = findViewById(R.id.group_submitmode)\n        checkboxClosable = findViewById(R.id.checkbox_closable)\n        checkboxHideMainScreenTitle = findViewById(R.id.checkbox_hide_title)\n        checkboxConnectionsDB = findViewById(R.id.checkbox_connections_db)\n        checkboxConnectionsEnterprise = findViewById(R.id.checkbox_connections_enterprise)\n        checkboxConnectionsSocial = findViewById(R.id.checkbox_connections_social)\n        checkboxConnectionsPasswordless = findViewById(R.id.checkbox_connections_Passwordless)\n        groupPasswordlessChannel = findViewById(R.id.group_passwordless_channel)\n        groupPasswordlessMode = findViewById(R.id.group_passwordless_mode)\n\n        //Advanced\n        groupDefaultDB = findViewById(R.id.group_default_db)\n        groupUsernameStyle = findViewById(R.id.group_username_style)\n        checkboxLoginAfterSignUp = findViewById(R.id.checkbox_login_after_signup)\n        checkboxScreenLogIn = findViewById(R.id.checkbox_enable_login)\n        checkboxScreenSignUp = findViewById(R.id.checkbox_enable_signup)\n        checkboxScreenReset = findViewById(R.id.checkbox_enable_reset)\n        groupInitialScreen = findViewById(R.id.group_initial_screen)\n\n        //Buttons\n        val advancedContainer = findViewById<LinearLayout>(R.id.advanced_container)\n        val checkboxShowAdvanced = findViewById<CheckBox>(R.id.checkbox_show_advanced)\n        checkboxShowAdvanced.setOnCheckedChangeListener { _, b -> advancedContainer.visibility = if (b) View.VISIBLE else View.GONE }\n        val btnShowLockClassic = findViewById<Button>(R.id.btn_show_lock_classic)\n        btnShowLockClassic.setOnClickListener { showClassicLock() }\n        val btnShowLockPasswordless = findViewById<Button>(R.id.btn_show_lock_passwordless)\n        btnShowLockPasswordless.setOnClickListener { showPasswordlessLock() }\n        val btnShowUniversalLogin = findViewById<Button>(R.id.btn_show_universal_login)\n        btnShowUniversalLogin.setOnClickListener { showWebAuth() }\n        val btnClearSession = findViewById<Button>(R.id.btn_clear_session)\n        btnClearSession.setOnClickListener { clearSession() }\n    }\n\n    private fun showWebAuth() {\n        login(account)\n                .withScheme(\"demo\")\n                .withAudience(String.format(\"https://%s/userinfo\", getString(R.string.com_auth0_domain)))\n                .start(this, loginCallback)\n    }\n\n    private fun clearSession() {\n        logout(account)\n                .withScheme(\"demo\")\n                .start(this, logoutCallback)\n    }\n\n    private fun showClassicLock() {\n        val builder = Lock.newBuilder(account, callback)\n                .withScheme(\"demo\")\n                .closable(checkboxClosable.isChecked)\n                .useLabeledSubmitButton(groupSubmitMode.checkedRadioButtonId == R.id.radio_use_label)\n                .loginAfterSignUp(checkboxLoginAfterSignUp.isChecked)\n                .allowLogIn(checkboxScreenLogIn.isChecked)\n                .allowSignUp(checkboxScreenSignUp.isChecked)\n                .allowForgotPassword(checkboxScreenReset.isChecked)\n                .allowedConnections(generateConnections())\n                .hideMainScreenTitle(checkboxHideMainScreenTitle.isChecked)\n\n        when (groupUsernameStyle.checkedRadioButtonId) {\n            R.id.radio_username_style_email -> {\n                builder.withUsernameStyle(UsernameStyle.EMAIL)\n            }\n            R.id.radio_username_style_username -> {\n                builder.withUsernameStyle(UsernameStyle.USERNAME)\n            }\n        }\n        when (groupInitialScreen.checkedRadioButtonId) {\n            R.id.radio_initial_reset -> {\n                builder.initialScreen(InitialScreen.FORGOT_PASSWORD)\n            }\n            R.id.radio_initial_signup -> {\n                builder.initialScreen(InitialScreen.SIGN_UP)\n            }\n            else -> {\n                builder.initialScreen(InitialScreen.LOG_IN)\n            }\n        }\n        if (checkboxConnectionsDB.isChecked) {\n            when (groupDefaultDB.checkedRadioButtonId) {\n                R.id.radio_default_db_policy -> {\n                    builder.setDefaultDatabaseConnection(\"with-strength\")\n                }\n                R.id.radio_default_db_mfa -> {\n                    builder.setDefaultDatabaseConnection(\"mfa-connection\")\n                }\n                else -> {\n                    builder.setDefaultDatabaseConnection(\"Username-Password-Authentication\")\n                }\n            }\n        }\n\n        // For demo purposes because options change dynamically, we release the resources of Lock here.\n        // In a real app, you will have a single instance and release its resources in Activity#OnDestroy.\n        lock?.onDestroy(this)\n        // Create a new instance with the updated configuration\n        lock = builder.build(this)\n        startActivity(lock!!.newIntent(this))\n    }\n\n    private fun showPasswordlessLock() {\n        val builder = PasswordlessLock.newBuilder(account, callback)\n                .withScheme(\"demo\")\n                .closable(checkboxClosable.isChecked)\n                .allowedConnections(generateConnections())\n                .hideMainScreenTitle(checkboxHideMainScreenTitle.isChecked)\n\n        if (groupPasswordlessMode.checkedRadioButtonId == R.id.radio_use_link) {\n            builder.useLink()\n        } else {\n            builder.useCode()\n        }\n\n        // For demo purposes because options change dynamically, we release the resources of Lock here.\n        // In a real app, you will have a single instance and release its resources in Activity#OnDestroy.\n        passwordlessLock?.onDestroy(this)\n        // Create a new instance with the updated configuration\n        passwordlessLock = builder.build(this)\n        startActivity(passwordlessLock!!.newIntent(this))\n    }\n\n    private val account: Auth0 by lazy {\n        Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain))\n    }\n\n    private fun generateConnections(): List<String> {\n        val connections: MutableList<String> = ArrayList()\n        if (checkboxConnectionsDB.isChecked) {\n            connections.add(\"Username-Password-Authentication\")\n            connections.add(\"mfa-connection\")\n            connections.add(\"with-strength\")\n        }\n        if (checkboxConnectionsEnterprise.isChecked) {\n            connections.add(\"ad\")\n            connections.add(\"another\")\n            connections.add(\"fake-saml\")\n            connections.add(\"contoso-ad\")\n        }\n        if (checkboxConnectionsSocial.isChecked) {\n            connections.add(\"google-oauth2\")\n            connections.add(\"twitter\")\n            connections.add(\"facebook\")\n            connections.add(\"paypal-sandbox\")\n        }\n        if (checkboxConnectionsPasswordless.isChecked) {\n            connections.add(if (groupPasswordlessChannel.checkedRadioButtonId == R.id.radio_use_sms) \"sms\" else \"email\")\n        }\n        if (connections.isEmpty()) {\n            connections.add(\"no-connection\")\n        }\n        return connections\n    }\n\n    public override fun onDestroy() {\n        super.onDestroy()\n        lock?.onDestroy(this)\n        passwordlessLock?.onDestroy(this)\n    }\n\n    internal fun showResult(message: String) {\n        Snackbar.make(rootLayout, message, Snackbar.LENGTH_LONG).show()\n    }\n\n    private val callback: LockCallback = object : AuthenticationCallback() {\n        override fun onAuthentication(credentials: Credentials) {\n            showResult(\"OK > \" + credentials.accessToken)\n        }\n\n        override fun onError(error: AuthenticationException) {\n            if (error.isCanceled) {\n                showResult(\"User pressed back.\")\n            } else {\n                showResult(error.getDescription())\n            }\n        }\n    }\n    private val loginCallback: Callback<Credentials, AuthenticationException> = object : Callback<Credentials, AuthenticationException> {\n        override fun onFailure(error: AuthenticationException) {\n            showResult(\"Failed > \" + error.getDescription())\n        }\n\n        override fun onSuccess(result: Credentials) {\n            showResult(\"OK > \" + result.accessToken)\n        }\n    }\n    private val logoutCallback: Callback<Void?, AuthenticationException> = object : Callback<Void?, AuthenticationException> {\n        override fun onFailure(error: AuthenticationException) {\n            showResult(\"Log out cancelled\")\n        }\n\n        override fun onSuccess(result: Void?) {\n            showResult(\"Logged out!\")\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/res/layout/demo_activity.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/scrollView\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:ignore=\"HardcodedText\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"10dp\"\n        android:orientation=\"vertical\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"5dp\"\n                android:layout_weight=\"1\"\n                android:text=\"Embedded Login\"\n                android:textSize=\"20sp\" />\n\n            <CheckBox\n                android:id=\"@+id/checkbox_show_advanced\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:checked=\"false\"\n                android:text=\"+Advanced\" />\n        </LinearLayout>\n\n        <RadioGroup\n            android:id=\"@+id/group_submitmode\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <RadioButton\n                android:id=\"@+id/radio_use_label\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:checked=\"true\"\n                android:text=\"Submit with Label\" />\n\n            <RadioButton\n                android:id=\"@+id/radio_use_icon\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:text=\"Submit with Icon\" />\n\n        </RadioGroup>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <CheckBox\n                android:id=\"@+id/checkbox_closable\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:text=\"Can be Closed\" />\n\n            <CheckBox\n                android:id=\"@+id/checkbox_hide_title\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"false\"\n                android:text=\"Hide Main Title\" />\n        </LinearLayout>\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginBottom=\"5dp\"\n            android:text=\"Passwordless\" />\n\n        <RadioGroup\n            android:id=\"@+id/group_passwordless_channel\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <RadioButton\n                android:id=\"@+id/radio_use_email\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:checked=\"true\"\n                android:text=\"Use Email\" />\n\n            <RadioButton\n                android:id=\"@+id/radio_use_sms\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:text=\"Use SMS\" />\n        </RadioGroup>\n\n        <RadioGroup\n            android:id=\"@+id/group_passwordless_mode\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"horizontal\">\n\n            <RadioButton\n                android:id=\"@+id/radio_use_link\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:checked=\"true\"\n                android:text=\"Use Link\" />\n\n            <RadioButton\n                android:id=\"@+id/radio_use_code\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:text=\"Use Code\" />\n        </RadioGroup>\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginBottom=\"5dp\"\n            android:text=\"Allowed Connections\" />\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_connections_db\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"DB\" />\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_connections_enterprise\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Enterprise\" />\n\n            </LinearLayout>\n\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_connections_social\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Social\" />\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_connections_Passwordless\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Passwordless\" />\n            </LinearLayout>\n\n        </LinearLayout>\n\n        <!-- Begin Advanced -->\n\n        <LinearLayout\n            android:id=\"@+id/advanced_container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\"\n            tools:visibility=\"visible\">\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"10dp\"\n                android:layout_marginBottom=\"5dp\"\n                android:text=\"Advanced\"\n                android:textSize=\"18sp\" />\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"5dp\"\n                android:text=\"Default DB Connection\" />\n\n            <RadioGroup\n                android:id=\"@+id/group_default_db\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <RadioButton\n                    android:id=\"@+id/radio_default_db_userpassword\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Usr-Pwd\" />\n\n                <RadioButton\n                    android:id=\"@+id/radio_default_db_mfa\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"MFA\" />\n\n                <RadioButton\n                    android:id=\"@+id/radio_default_db_policy\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"Pwd Policy\" />\n            </RadioGroup>\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginBottom=\"5dp\"\n                android:text=\"Username Style\" />\n\n            <RadioGroup\n                android:id=\"@+id/group_username_style\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <RadioButton\n                    android:id=\"@+id/radio_username_style_default\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Default\" />\n\n                <RadioButton\n                    android:id=\"@+id/radio_username_style_username\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"User\" />\n\n                <RadioButton\n                    android:id=\"@+id/radio_username_style_email\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"Email\" />\n            </RadioGroup>\n\n            <CheckBox\n                android:id=\"@+id/checkbox_login_after_signup\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:checked=\"true\"\n                android:text=\"Log In after Sign Up\" />\n\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"5dp\"\n                android:text=\"Enabled Screens\" />\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_enable_login\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Log In\" />\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_enable_signup\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Sign Up\" />\n\n                <CheckBox\n                    android:id=\"@+id/checkbox_enable_reset\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Reset Pwd\" />\n\n            </LinearLayout>\n\n\n            <TextView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"5dp\"\n                android:text=\"Initial Screen\" />\n\n            <RadioGroup\n                android:id=\"@+id/group_initial_screen\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"horizontal\">\n\n                <RadioButton\n                    android:id=\"@+id/radio_initial_login\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:checked=\"true\"\n                    android:text=\"Log In\" />\n\n                <RadioButton\n                    android:id=\"@+id/radio_initial_signup\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"Sign Up\" />\n\n                <RadioButton\n                    android:id=\"@+id/radio_initial_reset\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"Reset Pwd\" />\n            </RadioGroup>\n\n\n        </LinearLayout>\n\n        <!-- End Advanced -->\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"20dp\"\n            android:orientation=\"horizontal\">\n\n            <Button\n                android:id=\"@+id/btn_show_lock_classic\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_weight=\"1\"\n                android:text=\"Show Classic\" />\n\n            <Button\n                android:id=\"@+id/btn_show_lock_passwordless\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"match_parent\"\n                android:layout_weight=\"1\"\n                android:text=\"Show Passwordless\" />\n\n        </LinearLayout>\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginBottom=\"5dp\"\n            android:text=\"Universal Login\"\n            android:textSize=\"20sp\" />\n\n        <TextView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"5dp\"\n            android:text=\"Above settings don't apply\" />\n\n        <Button\n            android:id=\"@+id/btn_show_universal_login\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Show Login Page\" />\n\n        <Button\n            android:id=\"@+id/btn_clear_session\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            android:text=\"Show Logout Page\" />\n\n\n    </LinearLayout>\n</ScrollView>\n"
  },
  {
    "path": "app/src/main/res/values/auth0.xml",
    "content": "<!--\n  ~ auth0.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources>\n    <string name=\"com_auth0_client_id\">Owu62gnGsRYhk1v9SfB3c6IUbIJcRIze</string>\n    <string name=\"com_auth0_domain\">lbalmaceda.auth0.com</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Lock Demo</string>\n    <string name=\"native_provider_message_invalid_authorize_url\">The authorize URL is invalid.</string>\n    <string name=\"native_provider_message_canceled\">Canceled</string>\n    <string name=\"native_provider_title\">Native Identity Provider</string>\n    <string name=\"native_provider_message_start\">About to start the authentication with a Native Identity Provider. Click next to continue or cancel to go back.</string>\n    <string name=\"native_provider_action_cancel\">Cancel</string>\n    <string name=\"native_provider_action_continue\">Continue</string>\n    <string name=\"native_provider_message_failed\">Native authentication failed!</string>\n    <string name=\"native_provider_message_succeeded\">Native authentication succeeded!</string>\n    <string name=\"hint_name\">First Name</string>\n    <string name=\"hint_surname\">Last Name</string>\n    <string name=\"hint_work\">Work Place</string>\n    <string name=\"hint_country\">Country name</string>\n    <string name=\"hint_phone\">Phone Number</string>\n    <string name=\"hint_date\">Your birthday</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    ext.kotlin_version = '1.9.0'\n    repositories {\n        mavenCentral()\n        maven {\n            url \"https://plugins.gradle.org/m2/\"\n        }\n        google()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:4.2.2'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\nallprojects {\n    group = 'com.auth0.android'\n    \n    repositories {\n        mavenCentral()\n        google()\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.9.3-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\nandroid.enableJetifier=false\nandroid.useAndroidX=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "lib/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "lib/build.gradle",
    "content": "plugins {\n    id \"com.auth0.gradle.oss-library.android\" version \"0.18.0\"\n}\n\nlogger.lifecycle(\"Using version ${version} for ${name}\")\n\ndef signingKey = findProperty('signingKey')\ndef signingKeyPwd = findProperty('signingPassword')\n\noss {\n    name 'Lock.Android'\n    repository 'Lock.Android'\n    organization 'auth0'\n    description 'The easiest way of securing your Android mobile apps with Auth0 & Lock'\n    skipAssertSigningConfiguration true\n\n    developers {\n        auth0 {\n            displayName = 'Auth0'\n            email = 'oss@auth0.com'\n        }\n        lbalmaceda {\n            displayName = 'Luciano Balmaceda'\n            email = 'luciano.balmaceda@auth0.com'\n        }\n    }\n}\n\nsigning {\n    useInMemoryPgpKeys(signingKey, signingKeyPwd)\n}\n\nandroid {\n    compileSdkVersion 31\n\n    defaultConfig {\n        minSdkVersion 21\n        targetSdkVersion 31\n        versionCode 1\n        versionName project.version\n        consumerProguardFiles '../proguard/proguard-gson.pro', '../proguard/proguard-otto.pro', '../proguard/proguard-lock-2.pro'\n        // Required since Android Gradle Plugin 4.1 - https://issuetracker.google.com/issues/154275579\n        buildConfigField \"String\", \"VERSION_NAME\", \"\\\"$versionName\\\"\"\n    }\n\n    lintOptions {\n        disable 'ContentDescription', 'SyntheticAccessor'\n        abortOnError true\n    }\n\n    testOptions {\n        unitTests {\n            includeAndroidResources = true\n            // https://github.com/robolectric/robolectric/issues/5115\n            all {\n                systemProperty(\"javax.net.ssl.trustStoreType\", \"JKS\")\n                maxHeapSize = \"1024m\"\n            }\n        }\n    }\n\n    compileOptions {\n        sourceCompatibility 1.8\n        targetCompatibility 1.8\n    }\n}\n\ndependencies {\n    implementation 'androidx.appcompat:appcompat:1.3.1'\n    implementation 'androidx.recyclerview:recyclerview:1.2.1'\n    implementation 'androidx.legacy:legacy-support-v4:1.0.0'\n    implementation 'com.google.android.material:material:1.4.0'\n    implementation 'com.google.code.gson:gson:2.8.9'\n    implementation 'com.squareup:otto:1.3.8'\n    api 'com.auth0.android:auth0:2.10.2'\n    testImplementation 'junit:junit:4.13.2'\n    testImplementation 'org.hamcrest:hamcrest-library:2.2'\n    testImplementation 'org.robolectric:robolectric:4.4'\n    testImplementation 'org.mockito:mockito-core:3.7.7'\n    testImplementation 'com.squareup.okhttp3:okhttp:4.12.0'\n    testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'\n    testImplementation 'com.squareup.okhttp3:okhttp-tls:4.12.0'\n    testImplementation 'com.jayway.awaitility:awaitility:1.7.0'\n    testImplementation 'androidx.test.espresso:espresso-intents:3.4.0'\n}\n"
  },
  {
    "path": "lib/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"IconDuplicates\">\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_evernote.png\" />\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_evernote_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_salesforce.png\" />\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_salesforce_community.png\" />\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_salesforce_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_thecity.png\" />\n        <ignore path=\"src/main/res/drawable-hdpi/com_auth0_lock_ic_social_thecity_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_evernote.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_evernote_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_salesforce.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_salesforce_community.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_salesforce_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_thecity.png\" />\n        <ignore path=\"src/main/res/drawable-mdpi/com_auth0_lock_ic_social_thecity_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_evernote.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_evernote_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_salesforce.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_salesforce_community.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_salesforce_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_thecity.png\" />\n        <ignore path=\"src/main/res/drawable-xhdpi/com_auth0_lock_ic_social_thecity_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_evernote.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_evernote_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_salesforce.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_salesforce_community.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_salesforce_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_thecity.png\" />\n        <ignore path=\"src/main/res/drawable-xxhdpi/com_auth0_lock_ic_social_thecity_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_evernote.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_evernote_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_salesforce.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_salesforce_community.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_salesforce_sandbox.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_thecity.png\" />\n        <ignore path=\"src/main/res/drawable-xxxhdpi/com_auth0_lock_ic_social_thecity_sandbox.png\" />\n    </issue>\n</lint>\n"
  },
  {
    "path": "lib/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/nikolaseu/android-sdk-macosx/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "lib/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.auth0.android.lock\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application>\n        <!--Auth0 WebAuthProvider-->\n        <activity\n            android:name=\"com.auth0.android.provider.RedirectActivity\"\n            android:exported=\"true\"\n            tools:node=\"replace\">\n            <intent-filter android:autoVerify=\"true\">\n            <action android:name=\"android.intent.action.VIEW\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n                <category android:name=\"android.intent.category.BROWSABLE\" />\n\n                <data\n                    android:host=\"${auth0Domain}\"\n                    android:pathPrefix=\"/android/${applicationId}/callback\"\n                    android:scheme=\"${auth0Scheme}\" />\n            </intent-filter>\n        </activity>\n        <!--Auth0 WebAuthProvider End-->\n\n        <!--Auth0 Lock-->\n        <activity\n            android:name=\"com.auth0.android.lock.LockActivity\"\n            android:exported=\"false\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/Lock.Theme\"/>\n        <!--Auth0 Lock End-->\n\n        <!--Auth0 PasswordlessLock-->\n        <activity\n            android:name=\"com.auth0.android.lock.PasswordlessLockActivity\"\n            android:exported=\"true\"\n            android:launchMode=\"singleTask\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/Lock.Theme\">\n            <intent-filter android:autoVerify=\"true\">\n            <action android:name=\"android.intent.action.VIEW\" />\n\n                <category android:name=\"android.intent.category.DEFAULT\" />\n                <category android:name=\"android.intent.category.BROWSABLE\" />\n\n                <data\n                    android:host=\"${auth0Domain}\"\n                    android:pathPrefix=\"/android/${applicationId}/email\"\n                    android:scheme=\"https\" />\n\n                <data\n                    android:host=\"${auth0Domain}\"\n                    android:pathPrefix=\"/android/${applicationId}/sms\"\n                    android:scheme=\"https\" />\n            </intent-filter>\n        </activity>\n        <!--Auth0 PasswordlessLock End-->\n\n        <!--Auth0 Lock Passwordless SMS Country Code Selection-->\n        <activity\n            android:name=\"com.auth0.android.lock.CountryCodeActivity\"\n            android:exported=\"false\"\n            android:theme=\"@style/Lock.Theme.ActionBar\" />\n        <!--Auth0 Lock Passwordless SMS Country Code Selection-->\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "lib/src/main/assets/com_auth0_lock_passwordless_countries.json",
    "content": "{\"BY\":\"+375\",\"SG\":\"+65\",\"TJ\":\"+992\",\"BB\":\"+1 246\",\"ER\":\"+291\",\"IM\":\"+44\",\"ID\":\"+62\",\"LS\":\"+266\",\"PW\":\"+680\",\"MF\":\"+590\",\"MM\":\"+95\",\"MZ\":\"+258\",\"BA\":\"+387\",\"BR\":\"+55\",\"CM\":\"+237\",\"TL\":\"+670\",\"AT\":\"+43\",\"MG\":\"+261\",\"MH\":\"+692\",\"AR\":\"+54\",\"NP\":\"+977\",\"KI\":\"+686\",\"NO\":\"+47\",\"MO\":\"+853\",\"SB\":\"+677\",\"SC\":\"+248\",\"KY\":\"+ 345\",\"UZ\":\"+998\",\"SR\":\"+597\",\"KP\":\"+850\",\"AI\":\"+1 264\",\"AG\":\"+1268\",\"MU\":\"+230\",\"MN\":\"+976\",\"LY\":\"+218\",\"IT\":\"+39\",\"SL\":\"+232\",\"TM\":\"+993\",\"GF\":\"+594\",\"GG\":\"+44\",\"SN\":\"+221\",\"LA\":\"+856\",\"HN\":\"+504\",\"AD\":\"+376\",\"UG\":\"+256\",\"SK\":\"+421\",\"UA\":\"+380\",\"BM\":\"+1 441\",\"SI\":\"+386\",\"CH\":\"+41\",\"AX\":\"+358\",\"DO\":\"+1 849\",\"GW\":\"+245\",\"RS\":\"+381\",\"TC\":\"+1 649\",\"VU\":\"+678\",\"LV\":\"+371\",\"IE\":\"+353\",\"CG\":\"+242\",\"DJ\":\"+253\",\"GY\":\"+595\",\"PH\":\"+63\",\"GM\":\"+220\",\"NU\":\"+683\",\"ES\":\"+34\",\"MP\":\"+1 670\",\"BJ\":\"+229\",\"CA\":\"+1\",\"CO\":\"+57\",\"GR\":\"+30\",\"SD\":\"+249\",\"PM\":\"+508\",\"CF\":\"+236\",\"HR\":\"+385\",\"MA\":\"+212\",\"DM\":\"+1 767\",\"NF\":\"+672\",\"MK\":\"+389\",\"PT\":\"+351\",\"TR\":\"+90\",\"SV\":\"+503\",\"LI\":\"+423\",\"GT\":\"+502\",\"TT\":\"+1 868\",\"BN\":\"+673\",\"ST\":\"+239\",\"KZ\":\"+7 7\",\"PE\":\"+51\",\"KE\":\"+254\",\"BS\":\"+1 242\",\"AF\":\"+93\",\"TD\":\"+235\",\"AW\":\"+297\",\"LU\":\"+352\",\"TZ\":\"+255\",\"PS\":\"+970\",\"ZA\":\"+27\",\"GD\":\"+1 473\",\"NI\":\"+505\",\"BZ\":\"+501\",\"GL\":\"+299\",\"HT\":\"+509\",\"CC\":\"+61\",\"VI\":\"+1 340\",\"TG\":\"+228\",\"GA\":\"+241\",\"ZM\":\"+260\",\"TK\":\"+690\",\"KR\":\"+82\",\"ML\":\"+223\",\"RE\":\"+262\",\"NR\":\"+674\",\"GH\":\"+233\",\"IS\":\"+354\",\"CU\":\"+53\",\"AS\":\"+1 684\",\"TN\":\"+216\",\"IN\":\"+91\",\"PA\":\"+507\",\"IQ\":\"+964\",\"KW\":\"+965\",\"MY\":\"+60\",\"NL\":\"+31\",\"EG\":\"+20\",\"PG\":\"+675\",\"HK\":\"+852\",\"SJ\":\"+47\",\"VE\":\"+58\",\"OM\":\"+968\",\"YT\":\"+262\",\"BL\":\"+590\",\"DZ\":\"+213\",\"BE\":\"+32\",\"TW\":\"+886\",\"PF\":\"+689\",\"GI\":\"+350\",\"ME\":\"+382\",\"CZ\":\"+420\",\"BT\":\"+975\",\"MQ\":\"+596\",\"SZ\":\"+268\",\"VA\":\"+379\",\"RO\":\"+40\",\"MW\":\"+265\",\"JE\":\"+44\",\"AZ\":\"+994\",\"DE\":\"+49\",\"MD\":\"+373\",\"AO\":\"+244\",\"JM\":\"+1 876\",\"CX\":\"+61\",\"JO\":\"+962\",\"MS\":\"+1664\",\"KG\":\"+996\",\"SM\":\"+378\",\"LK\":\"+94\",\"IR\":\"+98\",\"SO\":\"+252\",\"FI\":\"+358\",\"TO\":\"+676\",\"SA\":\"+966\",\"MR\":\"+222\",\"LB\":\"+961\",\"MV\":\"+960\",\"NG\":\"+234\",\"AM\":\"+374\",\"AU\":\"+61\",\"DK\":\"+45\",\"VG\":\"+1 284\",\"NC\":\"+687\",\"GU\":\"+1 671\",\"BI\":\"+257\",\"MX\":\"+52\",\"JP\":\"+81\",\"UY\":\"+598\",\"CY\":\"+357\",\"LR\":\"+231\",\"US\":\"+1\",\"KM\":\"+269\",\"VC\":\"+1 784\",\"CN\":\"+86\",\"KH\":\"+855\",\"PN\":\"+872\",\"LT\":\"+370\",\"TH\":\"+66\",\"TV\":\"+688\",\"YE\":\"+967\",\"BO\":\"+591\",\"BD\":\"+880\",\"NZ\":\"+64\",\"ET\":\"+251\",\"BG\":\"+359\",\"CV\":\"+238\",\"IO\":\"+246\",\"NE\":\"+227\",\"EE\":\"+372\",\"GE\":\"+995\",\"LC\":\"+1 758\",\"AN\":\"+599\",\"GB\":\"+44\",\"BH\":\"+973\",\"GN\":\"+224\",\"GP\":\"+590\",\"MT\":\"+356\",\"AL\":\"+355\",\"WS\":\"+685\",\"CI\":\"+225\",\"VN\":\"+84\",\"SY\":\"+963\",\"CR\":\"+506\",\"IL\":\"+972\",\"RW\":\"+250\",\"FJ\":\"+679\",\"RU\":\"+7\",\"MC\":\"+377\",\"HU\":\"+36\",\"NA\":\"+264\",\"ZW\":\"+263\",\"PY\":\"+595\",\"CL\":\"+56\",\"BW\":\"+267\",\"PL\":\"+48\",\"FR\":\"+33\",\"PK\":\"+92\",\"PR\":\"+1 939\",\"SE\":\"+46\",\"FK\":\"+500\",\"KN\":\"+1 869\",\"AE\":\"+971\",\"QA\":\"+974\",\"BF\":\"+226\",\"WF\":\"+681\",\"CK\":\"+682\",\"CD\":\"+243\",\"SH\":\"+290\",\"EC\":\"+593\",\"GQ\":\"+240\",\"GS\":\"+500\",\"FM\":\"+691\",\"FO\":\"+298\"}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/Auth0Parcelable.java",
    "content": "/*\n * Auth0Parcelable.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.util.Auth0UserAgent;\n\n\n/**\n * This class wraps a {@link Auth0} to make it Parcelable\n */\npublic class Auth0Parcelable implements Parcelable {\n\n    private static final double WITHOUT_DATA = 0x00;\n    private static final double WITH_DATA = 0x01;\n    private final Auth0 auth0;\n\n    public Auth0Parcelable(@NonNull Auth0 auth0) {\n        this.auth0 = auth0;\n    }\n\n    @NonNull\n    public Auth0 getAuth0() {\n        return auth0;\n    }\n\n    // PARCELABLE\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(@NonNull Parcel dest, int flags) {\n        dest.writeString(auth0.getClientId());\n        dest.writeString(auth0.getDomainUrl());\n        dest.writeString(auth0.getConfigurationUrl());\n        //FIXME: Find a way to pass the NetworkingClient implementation\n        dest.writeString(auth0.getAuth0UserAgent().getName());\n        dest.writeString(auth0.getAuth0UserAgent().getVersion());\n        dest.writeString(auth0.getAuth0UserAgent().getLibraryVersion());\n    }\n\n    public static final Parcelable.Creator<Auth0Parcelable> CREATOR\n            = new Parcelable.Creator<Auth0Parcelable>() {\n        public Auth0Parcelable createFromParcel(Parcel in) {\n            return new Auth0Parcelable(in);\n        }\n\n        public Auth0Parcelable[] newArray(int size) {\n            return new Auth0Parcelable[size];\n        }\n    };\n\n    private Auth0Parcelable(@NonNull Parcel in) {\n        String clientId = in.readString();\n        String domain = in.readString();\n        String configurationDomain = in.readString();\n        String telemetryName = in.readString();\n        String telemetryVersion = in.readString();\n        String telemetryLibraryVersion = in.readString();\n\n        auth0 = new Auth0(clientId, domain, configurationDomain);\n        Auth0UserAgent userAgent = new Auth0UserAgent(telemetryName, telemetryVersion, telemetryLibraryVersion);\n        auth0.setAuth0UserAgent(userAgent);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/AuthButtonSize.java",
    "content": "/*\n * SocialButtonStyle.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.AuthButtonSize.BIG;\nimport static com.auth0.android.lock.AuthButtonSize.SMALL;\nimport static com.auth0.android.lock.AuthButtonSize.UNSPECIFIED;\n\n@IntDef({UNSPECIFIED, BIG, SMALL})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface AuthButtonSize {\n    int UNSPECIFIED = 0;\n    int BIG = 1;\n    int SMALL = 2;\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/AuthenticationCallback.java",
    "content": "/*\n * LockAuthenticationCallback.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport android.content.Intent;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.result.Credentials;\n\nimport java.util.Date;\n\n\n/**\n * Simple implementation of the Callback used by Lock to notify the user of execution results.\n * It can handle and notify of Authentication and Canceled events.\n */\npublic abstract class AuthenticationCallback implements LockCallback {\n\n    /**\n     * Called when the authentication flow finished successfully.\n     *\n     * @param credentials with the tokens.\n     */\n    public abstract void onAuthentication(@NonNull Credentials credentials);\n\n    @Override\n    public void onEvent(@LockEvent int event, @NonNull Intent data) {\n        if (data.hasExtra(Constants.EXCEPTION_EXTRA)) {\n            onError((AuthenticationException) data.getSerializableExtra(Constants.EXCEPTION_EXTRA));\n            return;\n        }\n        if (event == LockEvent.AUTHENTICATION) {\n            Credentials credentials = extractCredentials(data);\n            onAuthentication(credentials);\n        } else if (event == LockEvent.CANCELED) {\n            onError(new AuthenticationException(\"a0.authentication_canceled\", \"The user pressed back\"));\n        }\n    }\n\n    /**\n     * Extracts the Authentication data from the intent data.\n     *\n     * @param data the intent received at the end of the login process.\n     */\n    private Credentials extractCredentials(Intent data) {\n        String idToken = data.getStringExtra(Constants.ID_TOKEN_EXTRA);\n        String accessToken = data.getStringExtra(Constants.ACCESS_TOKEN_EXTRA);\n        String tokenType = data.getStringExtra(Constants.TOKEN_TYPE_EXTRA);\n        String refreshToken = data.getStringExtra(Constants.REFRESH_TOKEN_EXTRA);\n        Date expiresAt = (Date) data.getSerializableExtra(Constants.EXPIRES_AT_EXTRA);\n        String scope = data.getStringExtra(Constants.SCOPE_EXTRA);\n        return new Credentials(idToken, accessToken, tokenType, refreshToken, expiresAt, scope);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/Constants.java",
    "content": "/*\n * Constants.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nabstract class Constants {\n    static final String LIBRARY_NAME = \"Lock.Android\";\n\n    static final String OPTIONS_EXTRA = \"com.auth0.android.lock.key.Options\";\n\n    static final String CONNECTION_SCOPE_KEY = \"connection_scope\";\n\n    static final String AUTHENTICATION_ACTION = \"com.auth0.android.lock.action.Authentication\";\n    static final String SIGN_UP_ACTION = \"com.auth0.android.lock.action.SignUp\";\n    static final String CANCELED_ACTION = \"com.auth0.android.lock.action.Canceled\";\n    static final String INVALID_CONFIGURATION_ACTION = \"com.auth0.android.lock.action.InvalidConfiguration\";\n\n    static final String EXCEPTION_EXTRA = \"com.auth0.android.lock.extra.Exception\";\n    static final String ERROR_EXTRA = \"com.auth0.android.lock.extra.Error\";\n    static final String ID_TOKEN_EXTRA = \"com.auth0.android.lock.extra.IdToken\";\n    static final String ACCESS_TOKEN_EXTRA = \"com.auth0.android.lock.extra.AccessToken\";\n    static final String TOKEN_TYPE_EXTRA = \"com.auth0.android.lock.extra.TokenType\";\n    static final String REFRESH_TOKEN_EXTRA = \"com.auth0.android.lock.extra.RefreshToken\";\n    static final String EXPIRES_AT_EXTRA = \"com.auth0.android.lock.extra.ExpiresAt\";\n    static final String SCOPE_EXTRA = \"com.auth0.android.lock.extra.Scope\";\n    static final String EMAIL_EXTRA = \"com.auth0.android.lock.extra.Email\";\n    static final String USERNAME_EXTRA = \"com.auth0.android.lock.extra.Username\";\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/CountryCodeActivity.java",
    "content": "/*\n * CountryCodeActivity.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n/*\n * CountryCodeActivity.java\n *\n * Copyright (c) 2015 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android.util.Log;\nimport android.widget.EditText;\nimport android.widget.ListView;\n\nimport androidx.annotation.Nullable;\nimport androidx.appcompat.app.ActionBar;\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.adapters.CountryAdapter;\nimport com.auth0.android.lock.utils.LoadCountriesTask;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CountryCodeActivity extends AppCompatActivity {\n\n    public static final String COUNTRY_CODE_EXTRA = \"COUNTRY_CODE\";\n    public static final String COUNTRY_DIAL_CODE_EXTRA = \"COUNTRY_DIAL_CODE\";\n\n    private static final String TAG = CountryCodeActivity.class.getName();\n\n    private static LoadCountriesTask task;\n\n    @Override\n    public void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.com_auth0_lock_passwordless_activity_country_code);\n\n        final ActionBar bar = getSupportActionBar();\n        if (bar != null) {\n            //If actionBar is present, remove it as the custom search view is already in the layout\n            bar.hide();\n        }\n\n        final EditText searchText = findViewById(R.id.com_auth0_lock_passwordless_sms_search_country);\n        final ListView listView = findViewById(R.id.com_auth0_lock_passwordless_sms_country_code_list);\n        List<Country> countryList = new ArrayList<>();\n        CountryAdapter countryAdapter = new CountryAdapter(this, countryList);\n        listView.setAdapter(countryAdapter);\n\n        searchText.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n                Log.v(TAG, String.format(\"Filtering with string (%s)\", s));\n                countryAdapter.getFilter().filter(s);\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n            }\n        });\n        listView.setOnItemClickListener((parent, view, position, id) -> {\n            Country country = countryAdapter.getItem(position);\n            Intent data = new Intent();\n            data.putExtra(COUNTRY_CODE_EXTRA, country.getIsoCode());\n            data.putExtra(COUNTRY_DIAL_CODE_EXTRA, country.getDialCode());\n            setResult(RESULT_OK, data);\n            finish();\n        });\n\n        task = new LoadCountriesTask() {\n            @Override\n            protected void onPostExecute(List<Country> result) {\n                task = null;\n                countryList.addAll(result);\n                countryAdapter.notifyDataSetChanged();\n            }\n        };\n        task.execute(this);\n    }\n\n    @Override\n    public void onStop() {\n        super.onStop();\n        if (task != null) {\n            Log.v(TAG, \"Task was cancelled\");\n            task.cancel(true);\n        }\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/InitialScreen.java",
    "content": "/*\n * InitialScreen.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.InitialScreen.FORGOT_PASSWORD;\nimport static com.auth0.android.lock.InitialScreen.LOG_IN;\nimport static com.auth0.android.lock.InitialScreen.SIGN_UP;\n\n@IntDef({LOG_IN, SIGN_UP, FORGOT_PASSWORD})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface InitialScreen {\n    int LOG_IN = 0;\n    int SIGN_UP = 1;\n    int FORGOT_PASSWORD = 2;\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/Lock.java",
    "content": "/*\n * Lock.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.util.Log;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.LockCallback.LockEvent;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.lock.internal.configuration.Theme;\nimport com.auth0.android.lock.provider.AuthResolver;\nimport com.auth0.android.lock.utils.SignUpField;\nimport com.auth0.android.provider.AuthHandler;\nimport com.auth0.android.provider.CustomTabsOptions;\nimport com.auth0.android.util.Auth0UserAgent;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class Lock {\n\n    private static final String TAG = Lock.class.getSimpleName();\n    private final LockCallback callback;\n    private final Options options;\n\n    /**\n     * Listens to LockActivity broadcasts and fires the correct action on the LockCallback.\n     */\n    private final BroadcastReceiver receiver = new BroadcastReceiver() {\n\n        @Override\n        public void onReceive(Context context, Intent data) {\n            processEvent(data);\n        }\n    };\n\n    private Lock(@NonNull Options options, @NonNull LockCallback callback) {\n        this.options = options;\n        this.callback = callback;\n    }\n\n    /**\n     * Lock.Options holds the configuration used in the Auth0 Authentication API.\n     *\n     * @return the Lock.Options for this Lock instance.\n     */\n    @NonNull\n    public Options getOptions() {\n        return options;\n    }\n\n    /**\n     * Creates a new Lock.Builder instance with the given account and callback.\n     *\n     * @param account  details to use against the Auth0 Authentication API.\n     * @param callback that will receive the authentication results.\n     * @return a new Lock.Builder instance.\n     */\n    @NonNull\n    public static Builder newBuilder(@Nullable Auth0 account, @NonNull LockCallback callback) {\n        return new Lock.Builder(account, callback);\n    }\n\n    /**\n     * Creates a new Lock.Builder instance with the given callback. The account information\n     * will be retrieved from the String resources file (strings.xml) using\n     * the keys 'com_auth0_client_id' and 'com_auth0_domain'.\n     *\n     * @param callback that will receive the authentication results.\n     * @return a new Lock.Builder instance.\n     */\n    @NonNull\n    public static Builder newBuilder(@NonNull LockCallback callback) {\n        return newBuilder(null, callback);\n    }\n\n    /**\n     * Builds a new intent to launch LockActivity with the previously configured options\n     *\n     * @param context a valid Context\n     * @return the intent to which the user has to call startActivity or startActivityForResult\n     */\n    @NonNull\n    public Intent newIntent(@NonNull Context context) {\n        Intent lockIntent = new Intent(context, LockActivity.class);\n        lockIntent.putExtra(Constants.OPTIONS_EXTRA, options);\n        lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n        return lockIntent;\n    }\n\n    /**\n     * This method ensures proper Lock's lifecycle handling. Must be called from the class\n     * holding the Lock instance whenever you're done using it. i.e. in the Activity's onDestroy method.\n     *\n     * @param context a valid Context\n     */\n    public void onDestroy(@NonNull Context context) {\n        LocalBroadcastManager.getInstance(context).unregisterReceiver(this.receiver);\n    }\n\n    private void initialize(@NonNull Context context) {\n        LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);\n        lbm.unregisterReceiver(this.receiver);\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(Constants.AUTHENTICATION_ACTION);\n        filter.addAction(Constants.SIGN_UP_ACTION);\n        filter.addAction(Constants.CANCELED_ACTION);\n        filter.addAction(Constants.INVALID_CONFIGURATION_ACTION);\n        lbm.registerReceiver(this.receiver, filter);\n    }\n\n    private void processEvent(@NonNull Intent data) {\n        if (data.hasExtra(Constants.EXCEPTION_EXTRA)) {\n            callback.onError((AuthenticationException) data.getSerializableExtra(Constants.EXCEPTION_EXTRA));\n            return;\n        }\n        String action = data.getAction();\n        switch (action) {\n            case Constants.AUTHENTICATION_ACTION:\n                Log.v(TAG, \"AUTHENTICATION action received in our BroadcastReceiver\");\n                callback.onEvent(LockEvent.AUTHENTICATION, data);\n                break;\n            case Constants.SIGN_UP_ACTION:\n                Log.v(TAG, \"SIGN_UP action received in our BroadcastReceiver\");\n                callback.onEvent(LockEvent.SIGN_UP, data);\n                break;\n            case Constants.CANCELED_ACTION:\n                Log.v(TAG, \"CANCELED action received in our BroadcastReceiver\");\n                callback.onEvent(LockEvent.CANCELED, new Intent());\n                break;\n            case Constants.INVALID_CONFIGURATION_ACTION:\n                Log.v(TAG, \"INVALID_CONFIGURATION_ACTION action received in our BroadcastReceiver\");\n                callback.onError(new AuthenticationException(\"a0.invalid_configuration\", data.getStringExtra(Constants.ERROR_EXTRA)));\n                break;\n        }\n    }\n\n    /**\n     * Helper Builder to generate the Lock.Options to use on the Auth0 Authentication.\n     */\n    @SuppressWarnings({\"UnusedReturnValue\"})\n    public static class Builder {\n        private static final String TAG = Builder.class.getSimpleName();\n        private final Options options;\n        private final LockCallback callback;\n\n        /**\n         * Creates a new Lock.Builder instance with the given account and callback.\n         *\n         * @param account  details to use against the Auth0 Authentication API.\n         * @param callback that will receive the authentication results.\n         */\n        public Builder(@Nullable Auth0 account, @NonNull LockCallback callback) {\n            this.callback = callback;\n            options = new Options();\n            options.setAccount(account);\n        }\n\n        /**\n         * Finishes the construction of the Lock.Options and generates a new Lock instance\n         * with those Lock.Options.\n         *\n         * @param context a valid Context\n         * @return a new Lock instance configured as in the Builder.\n         */\n        @NonNull\n        public Lock build(@NonNull Context context) {\n            if (options.getAccount() == null) {\n                Log.w(TAG, \"com.auth0.android.Auth0 account details not defined. Trying to create it from the String resources.\");\n                try {\n                    options.setAccount(new Auth0(context));\n                } catch (IllegalArgumentException e) {\n                    throw new IllegalStateException(\"Missing Auth0 account information.\", e);\n                }\n            }\n            if (callback == null) {\n                Log.e(TAG, \"You need to specify the callback object to receive the Authentication result.\");\n                throw new IllegalStateException(\"Missing callback.\");\n            }\n            if (!options.allowForgotPassword() && !options.allowLogIn() && !options.allowSignUp()) {\n                throw new IllegalStateException(\"You disabled all the Lock screens (LogIn/SignUp/ForgotPassword). Please enable at least one.\");\n            }\n            if (options.initialScreen() == InitialScreen.LOG_IN && !options.allowLogIn()) {\n                throw new IllegalStateException(\"You chose LOG_IN as the initial screen but you have also disabled that screen.\");\n            }\n            if (options.initialScreen() == InitialScreen.SIGN_UP && !options.allowSignUp()) {\n                throw new IllegalStateException(\"You chose SIGN_UP as the initial screen but you have also disabled that screen.\");\n            }\n            if (options.initialScreen() == InitialScreen.FORGOT_PASSWORD && !options.allowForgotPassword()) {\n                throw new IllegalStateException(\"You chose FORGOT_PASSWORD as the initial screen but you have also disabled that screen.\");\n            }\n\n            Log.v(TAG, \"Lock instance created\");\n\n            Auth0UserAgent lockUserAgent = new Auth0UserAgent(Constants.LIBRARY_NAME, BuildConfig.VERSION_NAME, com.auth0.android.auth0.BuildConfig.VERSION_NAME);\n            options.getAccount().setAuth0UserAgent(lockUserAgent);\n\n            final Lock lock = new Lock(options, callback);\n            lock.initialize(context);\n            return lock;\n        }\n\n        /**\n         * Whether the LockActivity can be closed when pressing the Back key or not.\n         *\n         * @param closable or not. By default, the LockActivity is not closable.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder closable(boolean closable) {\n            options.setClosable(closable);\n            return this;\n        }\n\n        /**\n         * Customize Lock's appearance.\n         *\n         * @param theme to use.\n         * @return the current Builder instance\n         */\n        private Builder withTheme(@NonNull Theme theme) {\n            options.withTheme(theme);\n            return this;\n        }\n\n        /**\n         * Additional Authentication parameters can be set to use with different Identity Providers.\n         *\n         * @param authenticationParameters a non-null Map containing the parameters as Key-Values\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAuthenticationParameters(@NonNull Map<String, String> authenticationParameters) {\n            options.setAuthenticationParameters(new HashMap<>(authenticationParameters));\n            return this;\n        }\n\n        /**\n         * Locally filters the Auth0 Connections that are shown in the login widgets.\n         *\n         * @param connections a non-null List containing the allowed Auth0 Connections.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder allowedConnections(@NonNull List<String> connections) {\n            options.setConnections(connections);\n            return this;\n        }\n\n        /**\n         * Username style to use in the Login and Sign Up text fields. Defaults to the Dashboard\n         * configuration of \"requires_username\".\n         *\n         * @param style a valid UsernameStyle.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withUsernameStyle(@UsernameStyle int style) {\n            options.setUsernameStyle(style);\n            return this;\n        }\n\n        /**\n         * Authentication Style to use with the given strategy or connection name. It will override any lock defaults.\n         *\n         * @param connectionName to use this style with\n         * @param style          a valid Style with the Auth0.BackgroundColor, Auth0.Logo and Auth0.Name values defined.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAuthStyle(@NonNull String connectionName, @StyleRes int style) {\n            options.withAuthStyle(connectionName, style);\n            return this;\n        }\n\n        /**\n         * Decide which screen is going to show first when launching the Lock Activity.\n         *\n         * @param screen a valid InitialScreen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder initialScreen(@InitialScreen int screen) {\n            options.setInitialScreen(screen);\n            return this;\n        }\n\n        /**\n         * Whether to show the Log In screen or not. It can be enabled/disabled locally, regardless the Dashboard configuration.\n         *\n         * @param allow whether to allow or not the login screen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder allowLogIn(boolean allow) {\n            options.setAllowLogIn(allow);\n            return this;\n        }\n\n        /**\n         * Whether to show the Sign Up screen or not. It can be enabled/disabled locally, regardless the Dashboard configuration.\n         *\n         * @param allow whether to allow or not the sign up screen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder allowSignUp(boolean allow) {\n            options.setAllowSignUp(allow);\n            return this;\n        }\n\n        /**\n         * Whether to show the Forgot Password screen or not. It can be enabled/disabled locally, regardless the Dashboard configuration.\n         *\n         * @param allow whether to allow or not the forgot password screen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder allowForgotPassword(boolean allow) {\n            options.setAllowForgotPassword(allow);\n            return this;\n        }\n\n        /**\n         * Whether to show the password visibility toggle or not. Defaults to true\n         *\n         * @param allow whether to allow the user to toggle between showing or hiding the password or not.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder allowShowPassword(boolean allow) {\n            options.setAllowShowPassword(allow);\n            return this;\n        }\n\n        /**\n         * Whether if the submit button will display a label or just an icon. By default it will use the label.\n         * If {@link #hideMainScreenTitle(boolean)} is set to true this setting is ignored and the submit button will use label.\n         *\n         * @param useLabeledSubmitButton or icon.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder useLabeledSubmitButton(boolean useLabeledSubmitButton) {\n            options.setUseLabeledSubmitButton(useLabeledSubmitButton);\n            return this;\n        }\n\n        /**\n         * Control the visibility of the header's Title on the main screen, this is for Log In and Sign Up. By default it will show the header's Title on the main screen.\n         *\n         * @param hideMainScreenTitle if it should show or hide the header's Title on the main screen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder hideMainScreenTitle(boolean hideMainScreenTitle) {\n            options.setHideMainScreenTitle(hideMainScreenTitle);\n            return this;\n        }\n\n        /**\n         * Change the connection name to use on the Database authentication flow.\n         * Defaults to the first Database connection found.\n         *\n         * @param connectionName Must exist in the Application configuration on the Dashboard.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setDefaultDatabaseConnection(@NonNull String connectionName) {\n            options.useDatabaseConnection(connectionName);\n            return this;\n        }\n\n        /**\n         * Enterprise connections based on 'ad', 'adfs' and 'waad' strategies can log their\n         * users in from within the Lock widget using their email and password. This is known as\n         * Active Authentication.\n         * By whitelisting the connections here, the Universal Login Page is used instead and the\n         * login is delegated to the browser application.\n         * Enterprise connections allowed for this client will use Active Authentication by default.\n         *\n         * @param connections the list of 'ad', 'adfs', or 'waad' enterprise connections that will use Web Authentication instead.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder enableEnterpriseWebAuthenticationFor(@NonNull List<String> connections) {\n            options.setEnterpriseConnectionsUsingWebForm(connections);\n            return this;\n        }\n\n        /**\n         * Whether to login after a successful sign up callback. Defaults to true.\n         *\n         * @param login after sign up or not\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder loginAfterSignUp(boolean login) {\n            options.setLoginAfterSignUp(login);\n            return this;\n        }\n\n        /**\n         * Uses the given AuthHandlers to query for AuthProviders on a new authentication request.\n         *\n         * @param handlers that Lock will query for AuthProviders.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAuthHandlers(@NonNull AuthHandler... handlers) {\n            AuthResolver.setAuthHandlers(Arrays.asList(handlers));\n            return this;\n        }\n\n        /**\n         * Displays the specified custom fields during sign up. If the amount of visible fields\n         * is greater than the value set in {@link #withVisibleSignUpFieldsThreshold(int)}, all\n         * of them will be shown on a separate screen after the user clicks the sign up button.\n         * Each field must have a unique key. Fields with repeated keys will be removed.\n         *\n         * @param customFields the custom fields to display in the sign up flow.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withSignUpFields(@NonNull List<? extends SignUpField> customFields) {\n            final List<SignUpField> withoutDuplicates = removeDuplicatedKeys(customFields);\n            options.setSignUpFields(withoutDuplicates);\n            return this;\n        }\n\n        /**\n         * Defines the threshold at which all of the visible sign-up fields would be shown on\n         * a secondary screen instead of the initial one after clicking the sign-up button.\n         * Has a default value of 2 visible sign-up fields.\n         *\n         * @param threshold the threshold at which all the visible sign-up fields would be\n         *                  shown on a separate screen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withVisibleSignUpFieldsThreshold(int threshold) {\n            options.setVisibleSignUpFieldsThreshold(threshold);\n            return this;\n        }\n\n        /**\n         * Sets the Scope to request when performing the Authentication.\n         *\n         * @param scope to use in the Authentication.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withScope(@NonNull String scope) {\n            options.withScope(scope);\n            return this;\n        }\n\n        /**\n         * Sets the Audience or API Identifier to request access to when performing the Authentication.\n         *\n         * @param audience to use in the Authentication.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAudience(@NonNull String audience) {\n            options.withAudience(audience);\n            return this;\n        }\n\n        /**\n         * Specify style and other additional configuration for when the Web Auth flow is used with Custom Tabs.\n         *\n         * @param customTabsOptions to use in the Web Auth flow.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withCustomTabsOptions(@NonNull CustomTabsOptions customTabsOptions) {\n            options.withCustomTabsOptions(customTabsOptions);\n            return this;\n        }\n\n        /**\n         * Specify a custom Scheme for the redirect URL used when executing a Web Authentication flow\n         * via the Universal Login page.\n         * Default redirect url scheme is 'https'.\n         *\n         * @param scheme to use in the Web Auth redirect uri.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withScheme(@NonNull String scheme) {\n            options.withScheme(scheme);\n            return this;\n        }\n\n        /**\n         * Choose a custom Privacy Policy URL to access when the user clicks the link on the Sign Up form.\n         * The default value is 'https://auth0.com/privacy'\n         *\n         * @param url a valid url to use.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setPrivacyURL(@NonNull String url) {\n            options.setPrivacyURL(url);\n            return this;\n        }\n\n        /**\n         * Choose a custom Terms of Service URL to access when the user clicks the link on the Sign Up form.\n         * The default value is 'https://auth0.com/terms'\n         *\n         * @param url a valid url to use.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setTermsURL(@NonNull String url) {\n            options.setTermsURL(url);\n            return this;\n        }\n\n        /**\n         * Sets the url of your support page for your application that will be used when an error occurs and Lock is unable to handle it. In this case it will show an error screen and if there is a support url will also show a button to open that page in the browser.\n         *\n         * @param url to your support page or where your customers can request assistance. By default no page is set.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setSupportURL(@NonNull String url) {\n            options.setSupportURL(url);\n            return this;\n        }\n\n        /**\n         * Prompts the user to accept the Privacy Policy and Terms of Service before signing up.\n         * The default value is false.\n         *\n         * @param mustAcceptTerms whether the user needs to accept the terms before sign up or not.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setMustAcceptTerms(boolean mustAcceptTerms) {\n            options.setMustAcceptTerms(mustAcceptTerms);\n            return this;\n        }\n\n        /**\n         * Displays the Privacy Policy and Terms of Service footer on the Sign Up screen.\n         * Note: The footer will always be shown if the mustAcceptTerms flag has been enabled.\n         * The default value is true.\n         *\n         * @param showTerms whether the Terms of Service are displayed.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setShowTerms(boolean showTerms) {\n            options.setShowTerms(showTerms);\n            return this;\n        }\n\n        /**\n         * Sets the Connection Scope to request when performing an Authentication with the given Connection.\n         *\n         * @param connectionName to which specify the scopes.\n         * @param scope          recognized by this specific authentication provider.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withConnectionScope(@NonNull String connectionName, @NonNull String... scope) {\n            StringBuilder sb = new StringBuilder();\n            for (String s : scope) {\n                sb.append(s.trim()).append(\",\");\n            }\n            if (sb.length() > 0) {\n                sb.deleteCharAt(sb.length() - 1);\n                options.withConnectionScope(connectionName, sb.toString());\n            }\n            return this;\n        }\n\n        private List<SignUpField> removeDuplicatedKeys(List<? extends SignUpField> customFields) {\n            int originalSize = customFields.size();\n            final List<SignUpField> withoutDuplicates = new ArrayList<>();\n\n            Set<String> keySet = new HashSet<>();\n            for (SignUpField field : customFields) {\n                if (!keySet.contains(field.getKey())) {\n                    withoutDuplicates.add(field);\n                }\n                keySet.add(field.getKey());\n            }\n\n            if (originalSize != withoutDuplicates.size()) {\n                Log.w(TAG, \"Some of the Custom Fields had a duplicate key and have been removed.\");\n            }\n            return withoutDuplicates;\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/LockActivity.java",
    "content": "/*\n * LockActivity.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\n\nimport android.annotation.SuppressLint;\nimport android.app.Dialog;\nimport android.content.Intent;\nimport android.content.res.TypedArray;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.WindowManager;\nimport android.widget.RelativeLayout;\nimport android.widget.ScrollView;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.VisibleForTesting;\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.core.app.ActivityCompat;\nimport androidx.core.content.ContextCompat;\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.Auth0Exception;\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.authentication.ParameterBuilder;\nimport com.auth0.android.callback.AuthenticationCallback;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.lock.errors.AuthenticationError;\nimport com.auth0.android.lock.errors.LoginErrorMessageBuilder;\nimport com.auth0.android.lock.errors.SignUpErrorMessageBuilder;\nimport com.auth0.android.lock.events.DatabaseChangePasswordEvent;\nimport com.auth0.android.lock.events.DatabaseLoginEvent;\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.events.FetchApplicationEvent;\nimport com.auth0.android.lock.events.LockMessageEvent;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.internal.configuration.ApplicationFetcher;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.Connection;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.lock.provider.AuthResolver;\nimport com.auth0.android.lock.views.ClassicLockView;\nimport com.auth0.android.provider.AuthCallback;\nimport com.auth0.android.provider.AuthProvider;\nimport com.auth0.android.provider.WebAuthProvider;\nimport com.auth0.android.request.AuthenticationRequest;\nimport com.auth0.android.request.SignUpRequest;\nimport com.auth0.android.result.Challenge;\nimport com.auth0.android.result.Credentials;\nimport com.auth0.android.result.DatabaseUser;\nimport com.squareup.otto.Bus;\nimport com.squareup.otto.Subscribe;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@SuppressLint(\"GoogleAppIndexingApiWarning\")\npublic class LockActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback {\n\n    private static final String TAG = LockActivity.class.getSimpleName();\n    private static final String KEY_LOGIN_HINT = \"login_hint\";\n    private static final String KEY_SCREEN_HINT = \"screen_hint\";\n    private static final String KEY_MFA_TOKEN = \"mfa_token\";\n    private static final String MFA_CHALLENGE_TYPE_OOB = \"oob\";\n    private static final long RESULT_MESSAGE_DURATION = 3000;\n    private static final int WEB_AUTH_REQUEST_CODE = 200;\n    private static final int CUSTOM_AUTH_REQUEST_CODE = 201;\n    private static final int PERMISSION_REQUEST_CODE = 202;\n\n    private ApplicationFetcher applicationFetcher;\n    private Configuration configuration;\n    private Options options;\n    private Handler handler;\n\n    private ClassicLockView lockView;\n    private TextView resultMessage;\n\n    private AuthProvider currentProvider;\n    private WebProvider webProvider;\n\n    private LoginErrorMessageBuilder loginErrorBuilder;\n    private SignUpErrorMessageBuilder signUpErrorBuilder;\n    private DatabaseLoginEvent lastDatabaseLogin;\n    private DatabaseSignUpEvent lastDatabaseSignUp;\n\n    public LockActivity() {\n    }\n\n    @VisibleForTesting\n    LockActivity(Configuration configuration, Options options, ClassicLockView lockView, WebProvider webProvider) {\n        this.configuration = configuration;\n        this.options = options;\n        this.lockView = lockView;\n        this.webProvider = webProvider;\n        this.handler = new Handler();\n        this.loginErrorBuilder = new LoginErrorMessageBuilder();\n        this.signUpErrorBuilder = new SignUpErrorMessageBuilder();\n    }\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (!hasValidLaunchConfig()) {\n            return;\n        }\n\n        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);\n        Bus lockBus = new Bus();\n        lockBus.register(this);\n        handler = new Handler(getMainLooper());\n        webProvider = new WebProvider(options);\n\n        setContentView(R.layout.com_auth0_lock_activity_lock);\n        resultMessage = findViewById(R.id.com_auth0_lock_result_message);\n        ScrollView rootView = findViewById(R.id.com_auth0_lock_content);\n        lockView = new ClassicLockView(this, lockBus, options.getTheme());\n        RelativeLayout.LayoutParams lockViewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n        lockView.setLayoutParams(lockViewParams);\n        rootView.addView(lockView);\n\n        loginErrorBuilder = new LoginErrorMessageBuilder(R.string.com_auth0_lock_db_login_error_message, R.string.com_auth0_lock_db_login_error_invalid_credentials_message);\n        signUpErrorBuilder = new SignUpErrorMessageBuilder();\n\n        lockBus.post(new FetchApplicationEvent());\n    }\n\n    private boolean hasValidLaunchConfig() {\n        String errorDescription = null;\n        if (!hasValidOptions()) {\n            errorDescription = \"Configuration is not valid and the Activity will finish.\";\n        }\n        if (!hasValidTheme()) {\n            errorDescription = \"You need to use a Lock.Theme theme (or descendant) with this Activity.\";\n        }\n        if (errorDescription == null) {\n            return true;\n        }\n        Intent intent = new Intent(Constants.INVALID_CONFIGURATION_ACTION);\n        intent.putExtra(Constants.ERROR_EXTRA, errorDescription);\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n        return false;\n    }\n\n    private boolean hasValidTheme() {\n        TypedArray a = getTheme().obtainStyledAttributes(R.styleable.Lock_Theme);\n        boolean validTheme = a.hasValue(R.styleable.Lock_Theme_Auth0_HeaderLogo);\n        a.recycle();\n        return validTheme;\n    }\n\n    private boolean hasValidOptions() {\n        options = getIntent().getParcelableExtra(Constants.OPTIONS_EXTRA);\n        if (options == null) {\n            Log.e(TAG, \"Lock Options are missing in the received Intent and LockActivity will not launch. \" +\n                    \"Use the PasswordlessLock.Builder to generate a valid Intent.\");\n            return false;\n        }\n\n        boolean launchedForResult = getCallingActivity() != null;\n        if (launchedForResult) {\n            Log.e(TAG, \"You're not allowed to start Lock with startActivityForResult.\");\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void onBackPressed() {\n        if (lockView.onBackPressed() || !options.isClosable()) {\n            return;\n        }\n\n        Log.v(TAG, \"User had just closed the activity.\");\n        Intent intent = new Intent(Constants.CANCELED_ACTION);\n        LocalBroadcastManager.getInstance(LockActivity.this).sendBroadcast(intent);\n        super.onBackPressed();\n    }\n\n    private void deliverAuthenticationResult(Credentials credentials) {\n        Intent intent = new Intent(Constants.AUTHENTICATION_ACTION);\n        intent.putExtra(Constants.ID_TOKEN_EXTRA, credentials.getIdToken());\n        intent.putExtra(Constants.ACCESS_TOKEN_EXTRA, credentials.getAccessToken());\n        intent.putExtra(Constants.REFRESH_TOKEN_EXTRA, credentials.getRefreshToken());\n        intent.putExtra(Constants.TOKEN_TYPE_EXTRA, credentials.getType());\n        intent.putExtra(Constants.EXPIRES_AT_EXTRA, credentials.getExpiresAt());\n\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n    }\n\n    private void deliverAuthenticationError(AuthenticationException exception) {\n        Intent intent = new Intent(Constants.AUTHENTICATION_ACTION);\n        intent.putExtra(Constants.EXCEPTION_EXTRA, exception);\n\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n    }\n\n    private void deliverSignUpResult(DatabaseUser result) {\n        Intent intent = new Intent(Constants.SIGN_UP_ACTION);\n        intent.putExtra(Constants.EMAIL_EXTRA, result.getEmail());\n        intent.putExtra(Constants.USERNAME_EXTRA, result.getEmail());\n\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n    }\n\n    private void requestMFAChallenge(String mfaToken) {\n        lastDatabaseLogin.setMultifactorToken(mfaToken);\n        AuthenticationAPIClient apiClient = options.getAuthenticationAPIClient();\n        apiClient.multifactorChallenge(mfaToken, null, null)\n                .start(new Callback<Challenge, AuthenticationException>() {\n                    @Override\n                    public void onSuccess(@NonNull Challenge challenge) {\n                        lastDatabaseLogin.setMultifactorChallengeType(challenge.getChallengeType());\n                        lastDatabaseLogin.setMultifactorOOBCode(challenge.getOobCode());\n                        handler.post(() -> {\n                            lockView.showProgress(false);\n                            lockView.showMFACodeForm(lastDatabaseLogin);\n                        });\n                    }\n\n                    @Override\n                    public void onFailure(@NonNull AuthenticationException ignored) {\n                        // Ignore error:\n                        // Lock will fallback to completing the authentication using OTP MFA.\n                        handler.post(() -> {\n                            lockView.showProgress(false);\n                            lockView.showMFACodeForm(lastDatabaseLogin);\n                        });\n                    }\n                });\n    }\n\n    private void showSuccessMessage(String message) {\n        resultMessage.setBackgroundColor(ContextCompat.getColor(this, R.color.com_auth0_lock_result_message_success_background));\n        resultMessage.setVisibility(View.VISIBLE);\n        resultMessage.setText(message);\n        lockView.showProgress(false);\n        handler.removeCallbacks(resultMessageHider);\n        handler.postDelayed(resultMessageHider, RESULT_MESSAGE_DURATION);\n    }\n\n    private void showErrorMessage(String message) {\n        resultMessage.setBackgroundColor(ContextCompat.getColor(this, R.color.com_auth0_lock_result_message_error_background));\n        resultMessage.setVisibility(View.VISIBLE);\n        resultMessage.setText(message);\n        lockView.showProgress(false);\n        handler.removeCallbacks(resultMessageHider);\n        handler.postDelayed(resultMessageHider, RESULT_MESSAGE_DURATION);\n    }\n\n    private final Runnable resultMessageHider = new Runnable() {\n        @Override\n        public void run() {\n            resultMessage.setVisibility(View.GONE);\n        }\n    };\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n        if (currentProvider != null) {\n            currentProvider.onRequestPermissionsResult(this, requestCode, permissions, grantResults);\n        }\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\n        switch (requestCode) {\n            case WEB_AUTH_REQUEST_CODE:\n                lockView.showProgress(false);\n                webProvider.resume(data);\n                break;\n            case CUSTOM_AUTH_REQUEST_CODE:\n                lockView.showProgress(false);\n                if (currentProvider != null) {\n                    currentProvider.authorize(requestCode, resultCode, data);\n                    currentProvider = null;\n                }\n                break;\n            default:\n                super.onActivityResult(requestCode, resultCode, data);\n        }\n    }\n\n    @Override\n    protected void onNewIntent(@Nullable Intent intent) {\n        lockView.showProgress(false);\n        if (webProvider.resume(intent)) {\n            return;\n        } else if (currentProvider != null) {\n            currentProvider.authorize(intent);\n            currentProvider = null;\n            return;\n        }\n        super.onNewIntent(intent);\n    }\n\n    @Subscribe\n    public void onFetchApplicationRequest(@NonNull FetchApplicationEvent event) {\n        if (applicationFetcher == null) {\n            Auth0 account = options.getAccount();\n            applicationFetcher = new ApplicationFetcher(account);\n            applicationFetcher.fetch(applicationCallback);\n        }\n    }\n\n    @Subscribe\n    public void onLockMessage(@NonNull final LockMessageEvent event) {\n        handler.post(() -> showErrorMessage(getString(event.getMessageRes())));\n    }\n\n    @Subscribe\n    public void onOAuthAuthenticationRequest(@NonNull OAuthLoginEvent event) {\n        final String connection = event.getConnection();\n\n        if (event.useActiveFlow()) {\n            lockView.showProgress(true);\n            Log.d(TAG, \"Using the /ro endpoint for this OAuth Login Request\");\n            AuthenticationRequest request = options.getAuthenticationAPIClient()\n                    .login(event.getUsername(), event.getPassword(), connection);\n            request.addParameters(options.getAuthenticationParameters());\n            if (options.getScope() != null) {\n                request.setScope(options.getScope());\n            }\n            if (options.getAudience() != null) {\n                request.setAudience(options.getAudience());\n            }\n            request.start(authCallback);\n            return;\n        }\n\n        Log.v(TAG, \"Looking for a provider to use /authorize with the connection \" + connection);\n        currentProvider = AuthResolver.providerFor(event.getStrategy(), connection);\n        if (currentProvider != null) {\n            Map<String, Object> authParameters = new HashMap<>();\n            for (Map.Entry<String, String> e : options.getAuthenticationParameters().entrySet()) {\n                authParameters.put(e.getKey(), e.getValue());\n            }\n            final String connectionScope = options.getConnectionsScope().get(connection);\n            if (connectionScope != null) {\n                authParameters.put(Constants.CONNECTION_SCOPE_KEY, connectionScope);\n            }\n            final String scope = options.getScope();\n            if (scope != null) {\n                authParameters.put(ParameterBuilder.SCOPE_KEY, scope);\n            }\n            final String audience = options.getAudience();\n            if (audience != null) {\n                authParameters.put(ParameterBuilder.AUDIENCE_KEY, audience);\n            }\n            if (!TextUtils.isEmpty(event.getUsername())) {\n                authParameters.put(KEY_LOGIN_HINT, event.getUsername());\n            }\n            currentProvider.setParameters(authParameters);\n            currentProvider.start(this, authProviderCallback, PERMISSION_REQUEST_CODE, CUSTOM_AUTH_REQUEST_CODE);\n            return;\n        }\n\n        Map<String, String> extraAuthParameters = null;\n        if (!TextUtils.isEmpty(event.getUsername())) {\n            extraAuthParameters = Collections.singletonMap(KEY_LOGIN_HINT, event.getUsername());\n        }\n        Log.d(TAG, \"Couldn't find an specific provider, using the default: \" + WebAuthProvider.class.getSimpleName());\n        webProvider.start(this, connection, extraAuthParameters, new WebCallbackWrapper(authProviderCallback));\n    }\n\n    private void completeDatabaseAuthenticationOnBrowser() {\n        //DBConnection checked for nullability before the API call\n        String connection = configuration.getDatabaseConnection().getName();\n\n        String loginHint = null;\n        String screenHint = null;\n        if (lastDatabaseSignUp != null) {\n            loginHint = lastDatabaseSignUp.getEmail();\n            screenHint = \"signup\";\n        } else if (lastDatabaseLogin != null) {\n            loginHint = lastDatabaseLogin.getUsernameOrEmail();\n            screenHint = \"login\";\n        }\n        HashMap<String, String> params = new HashMap<>();\n        params.put(KEY_LOGIN_HINT, loginHint);\n        params.put(KEY_SCREEN_HINT, screenHint);\n\n        webProvider.start(this, connection, params, new WebCallbackWrapper(authProviderCallback));\n    }\n\n    @Subscribe\n    public void onDatabaseAuthenticationRequest(@NonNull DatabaseLoginEvent event) {\n        if (configuration.getDatabaseConnection() == null) {\n            Log.w(TAG, \"There is no default Database connection to authenticate with\");\n            return;\n        }\n\n        lockView.showProgress(true);\n        lastDatabaseLogin = event;\n        AuthenticationAPIClient apiClient = options.getAuthenticationAPIClient();\n        AuthenticationRequest request;\n        Map<String, String> parameters = new HashMap<>(options.getAuthenticationParameters());\n        if (TextUtils.isEmpty(event.getMultifactorToken())) {\n            // regular database authentication\n            String connection = configuration.getDatabaseConnection().getName();\n            request = apiClient.login(event.getUsernameOrEmail(), event.getPassword(), connection);\n        } else if (MFA_CHALLENGE_TYPE_OOB.equals(lastDatabaseLogin.getMultifactorChallengeType())) {\n            // oob multi-factor authentication\n            request = apiClient.loginWithOOB(event.getMultifactorToken(), event.getMultifactorOOBCode(), event.getMultifactorOTP());\n        } else {\n            // otp multi-factor authentication\n            request = apiClient.loginWithOTP(event.getMultifactorToken(), event.getMultifactorOTP());\n        }\n\n        request.addParameters(parameters);\n        if (options.getScope() != null) {\n            request.setScope(options.getScope());\n        }\n        if (options.getAudience() != null) {\n            request.setAudience(options.getAudience());\n        }\n        request.start(authCallback);\n    }\n\n    @Subscribe\n    public void onDatabaseAuthenticationRequest(@NonNull DatabaseSignUpEvent event) {\n        if (configuration.getDatabaseConnection() == null) {\n            Log.w(TAG, \"There is no default Database connection to authenticate with\");\n            return;\n        }\n\n        AuthenticationAPIClient apiClient = options.getAuthenticationAPIClient();\n        final String connection = configuration.getDatabaseConnection().getName();\n        lockView.showProgress(true);\n        lastDatabaseSignUp = event;\n\n        if (configuration.loginAfterSignUp()) {\n            SignUpRequest request = event.getSignUpRequest(apiClient, connection)\n                    .addParameters(options.getAuthenticationParameters());\n            if (options.getScope() != null) {\n                request.setScope(options.getScope());\n            }\n            if (options.getAudience() != null) {\n                request.setAudience(options.getAudience());\n            }\n            request.start(authCallback);\n        } else {\n            event.getCreateUserRequest(apiClient, connection)\n                    .start(createCallback);\n        }\n    }\n\n    @Subscribe\n    public void onDatabaseAuthenticationRequest(@NonNull DatabaseChangePasswordEvent event) {\n        if (configuration.getDatabaseConnection() == null) {\n            Log.w(TAG, \"There is no default Database connection to authenticate with\");\n            return;\n        }\n\n        lockView.showProgress(true);\n        AuthenticationAPIClient apiClient = options.getAuthenticationAPIClient();\n        final String connection = configuration.getDatabaseConnection().getName();\n        apiClient.resetPassword(event.getEmail(), connection)\n                .start(changePwdCallback);\n    }\n\n    //Callbacks\n    private final Callback<List<Connection>, Auth0Exception> applicationCallback = new Callback<List<Connection>, Auth0Exception>() {\n        @Override\n        public void onSuccess(@Nullable final List<Connection> connections) {\n            configuration = new Configuration(connections, options);\n            handler.post(() -> lockView.configure(configuration));\n            applicationFetcher = null;\n        }\n\n        @Override\n        public void onFailure(@NonNull final Auth0Exception error) {\n            Log.e(TAG, \"Failed to fetch the application: \" + error.getMessage(), error);\n            applicationFetcher = null;\n            handler.post(() -> lockView.configure(null));\n        }\n    };\n\n    private final AuthCallback authProviderCallback = new AuthCallback() {\n        @Override\n        public void onFailure(@NonNull final Dialog dialog) {\n            Log.e(TAG, \"Failed to authenticate the user. A dialog is going to be shown with more information.\");\n            dialog.show();\n            handler.post(dialog::show);\n        }\n\n        @Override\n        public void onFailure(@NonNull final AuthenticationException exception) {\n            Log.e(TAG, \"Failed to authenticate the user: \" + exception.getCode(), exception);\n            if (exception.isRuleError() || exception.isAccessDenied()) {\n                deliverAuthenticationError(exception);\n                return;\n            }\n            final AuthenticationError authError = loginErrorBuilder.buildFrom(exception);\n            final String message = authError.getMessage(LockActivity.this);\n            handler.post(() -> showErrorMessage(message));\n        }\n\n        @Override\n        public void onSuccess(@NonNull final Credentials credentials) {\n            deliverAuthenticationResult(credentials);\n        }\n    };\n\n    private final AuthenticationCallback<Credentials> authCallback = new AuthenticationCallback<Credentials>() {\n        @Override\n        public void onSuccess(@Nullable Credentials credentials) {\n            deliverAuthenticationResult(credentials);\n            lastDatabaseLogin = null;\n            lastDatabaseSignUp = null;\n        }\n\n        @Override\n        public void onFailure(@NonNull final AuthenticationException error) {\n            Log.e(TAG, \"Failed to authenticate the user: \" + error.getCode(), error);\n            if (error.isRuleError() || error.isAccessDenied()) {\n                deliverAuthenticationError(error);\n                return;\n            }\n            if (error.isVerificationRequired()) {\n                completeDatabaseAuthenticationOnBrowser();\n                return;\n            }\n\n            if (error.isMultifactorRequired()) {\n                String mfaToken = (String) error.getValue(KEY_MFA_TOKEN);\n                requestMFAChallenge(mfaToken);\n                return;\n            }\n\n            if (error.isMultifactorTokenInvalid()) {\n                //The MFA Token has expired. The user needs to log in again. Show the username/password form\n                onBackPressed();\n            }\n\n            final AuthenticationError authError = loginErrorBuilder.buildFrom(error);\n            String message = authError.getMessage(LockActivity.this);\n            handler.post(() -> showErrorMessage(message));\n        }\n    };\n\n    private final AuthenticationCallback<DatabaseUser> createCallback = new AuthenticationCallback<DatabaseUser>() {\n        @Override\n        public void onSuccess(@Nullable final DatabaseUser user) {\n            handler.post(() -> deliverSignUpResult(user));\n            lastDatabaseSignUp = null;\n        }\n\n        @Override\n        public void onFailure(@NonNull final AuthenticationException error) {\n            Log.e(TAG, \"Failed to create the user: \" + error.getCode(), error);\n            if (error.isVerificationRequired()) {\n                completeDatabaseAuthenticationOnBrowser();\n                return;\n            }\n            handler.post(() -> {\n                String message = signUpErrorBuilder.buildFrom(error).getMessage(LockActivity.this);\n                showErrorMessage(message);\n            });\n        }\n    };\n\n    private final AuthenticationCallback<Void> changePwdCallback = new AuthenticationCallback<Void>() {\n        @Override\n        public void onSuccess(@Nullable Void payload) {\n            handler.post(() -> {\n                showSuccessMessage(getString(R.string.com_auth0_lock_db_change_password_message_success));\n                if (options.allowLogIn() || options.allowSignUp()) {\n                    lockView.showChangePasswordForm(false);\n                }\n            });\n\n        }\n\n        @Override\n        public void onFailure(@NonNull AuthenticationException error) {\n            Log.e(TAG, \"Failed to reset the user password: \" + error.getCode(), error);\n            handler.post(() -> {\n                String message = new AuthenticationError(R.string.com_auth0_lock_db_message_change_password_error).getMessage(LockActivity.this);\n                showErrorMessage(message);\n            });\n        }\n    };\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/LockCallback.java",
    "content": "/*\n * AuthenticationCallback.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport android.content.Intent;\n\nimport androidx.annotation.IntDef;\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.authentication.AuthenticationException;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.LockCallback.LockEvent.AUTHENTICATION;\nimport static com.auth0.android.lock.LockCallback.LockEvent.CANCELED;\nimport static com.auth0.android.lock.LockCallback.LockEvent.RESET_PASSWORD;\nimport static com.auth0.android.lock.LockCallback.LockEvent.SIGN_UP;\n\n/**\n * Callback used by Lock to notify the user of execution results.\n */\npublic interface LockCallback {\n    /**\n     * Type of Events that Lock can notified of.\n     */\n    @SuppressWarnings(\"UnnecessaryInterfaceModifier\")\n    @IntDef({CANCELED, AUTHENTICATION, SIGN_UP, RESET_PASSWORD})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface LockEvent {\n        int CANCELED = 0;\n        int AUTHENTICATION = 1;\n        int SIGN_UP = 2;\n        int RESET_PASSWORD = 3;\n    }\n\n    /**\n     * Called when a known event is fired by Lock.\n     *\n     * @param event to notify of\n     * @param data  related to the event.\n     */\n    void onEvent(@LockEvent int event, @NonNull Intent data);\n\n    /**\n     * Called when an error is raised by Lock.\n     *\n     * @param error describing what happened.\n     */\n    void onError(@NonNull AuthenticationException error);\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/PasswordlessIdentityHelper.java",
    "content": "package com.auth0.android.lock;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\n\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.DISABLED;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_LINK;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_LINK;\n\nclass PasswordlessIdentityHelper {\n    private static final String LAST_PASSWORDLESS_IDENTITY_KEY = \"last_passwordless_identity\";\n    private static final String LAST_PASSWORDLESS_COUNTRY_KEY = \"last_passwordless_country\";\n    private static final String LAST_PASSWORDLESS_MODE_KEY = \"last_passwordless_mode\";\n    private static final String LOCK_PREFERENCES_NAME = \"Lock\";\n    private static final String COUNTRY_DATA_DIV = \"@\";\n\n    private final SharedPreferences sp;\n    @PasswordlessMode\n    private final int mode;\n\n    PasswordlessIdentityHelper(@NonNull Context context, @PasswordlessMode int mode) {\n        sp = context.getSharedPreferences(LOCK_PREFERENCES_NAME, Context.MODE_PRIVATE);\n        this.mode = mode;\n    }\n\n    public void saveIdentity(@NonNull String identity, @Nullable Country country) {\n        String countryData = country != null ? country.getIsoCode() + COUNTRY_DATA_DIV + country.getDialCode() : null;\n        sp.edit()\n                .putString(LAST_PASSWORDLESS_IDENTITY_KEY, identity)\n                .putString(LAST_PASSWORDLESS_COUNTRY_KEY, countryData)\n                .putInt(LAST_PASSWORDLESS_MODE_KEY, mode)\n                .apply();\n    }\n\n    @Nullable\n    public Country getLastCountry() {\n        Country country = null;\n        String countryInfo = sp.getString(LAST_PASSWORDLESS_COUNTRY_KEY, null);\n        if (countryInfo != null) {\n            String isoCode = countryInfo.split(COUNTRY_DATA_DIV)[0];\n            String dialCode = countryInfo.split(COUNTRY_DATA_DIV)[1];\n            country = new Country(isoCode, dialCode);\n        }\n        return country;\n    }\n\n    @NonNull\n    public String getLastIdentity() {\n        String identity = sp.getString(LAST_PASSWORDLESS_IDENTITY_KEY, \"\");\n        Country country = getLastCountry();\n        if (country != null && identity.startsWith(country.getDialCode())) {\n            identity = identity.substring(country.getDialCode().length());\n        }\n        return identity;\n    }\n\n    public boolean hasLoggedInBefore() {\n        @PasswordlessMode\n        int lastMode = sp.getInt(LAST_PASSWORDLESS_MODE_KEY, DISABLED);\n        return lastMode != DISABLED && hasSameConnection(lastMode);\n    }\n\n    private boolean hasSameConnection(@PasswordlessMode int lastMode) {\n        if (lastMode == mode) {\n            return true;\n        }\n        boolean sms = (lastMode == SMS_CODE || lastMode == SMS_LINK) && (mode == SMS_CODE || mode == SMS_LINK);\n        boolean email = (lastMode == EMAIL_CODE || lastMode == EMAIL_LINK) && (mode == EMAIL_CODE || mode == EMAIL_LINK);\n        return sms || email;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/PasswordlessLock.java",
    "content": "/*\n * PasswordlessLock.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.util.Log;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.LockCallback.LockEvent;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.lock.internal.configuration.Theme;\nimport com.auth0.android.lock.provider.AuthResolver;\nimport com.auth0.android.provider.AuthHandler;\nimport com.auth0.android.provider.CustomTabsOptions;\nimport com.auth0.android.util.Auth0UserAgent;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class PasswordlessLock {\n\n    private static final String TAG = PasswordlessLock.class.getSimpleName();\n    private final LockCallback callback;\n    private final Options options;\n\n    /**\n     * Listens to PasswordlessLockActivity broadcasts and fires the correct action on the LockCallback.\n     */\n    private final BroadcastReceiver receiver = new BroadcastReceiver() {\n\n        @Override\n        public void onReceive(@NonNull Context context, @NonNull Intent data) {\n            processEvent(data);\n        }\n    };\n\n    private PasswordlessLock(@NonNull Options options, @NonNull LockCallback callback) {\n        this.options = options;\n        this.callback = callback;\n    }\n\n    /**\n     * Lock.Options holds the configuration used in the Auth0 Passwordless Authentication API.\n     *\n     * @return the Lock.Options for this Lock instance.\n     */\n    @NonNull\n    public Options getOptions() {\n        return options;\n    }\n\n    /**\n     * Creates a new Lock.Builder instance with the given account and callback.\n     * Use of Passwordless connections requires your Application to have the <b>Resource Owner</b> Legacy Grant Type enabled.\n     * See <a href=\"https://auth0.com/docs/clients/client-grant-types\">Client Grant Types</a> to learn how to enable it.\n     *\n     * @param account  details to use against the Auth0 Authentication API.\n     * @param callback that will receive the authentication results.\n     * @return a new Lock.Builder instance.\n     */\n    @NonNull\n    public static Builder newBuilder(@Nullable Auth0 account, @NonNull LockCallback callback) {\n        return new PasswordlessLock.Builder(account, callback);\n    }\n\n    /**\n     * Creates a new Lock.Builder instance with the given callback. The account information\n     * will be retrieved from the String resources file (strings.xml) using\n     * the keys 'com_auth0_client_id' and 'com_auth0_domain'.\n     * Use of Passwordless connections requires your Application to have the <b>Resource Owner</b> Legacy Grant Type enabled.\n     * See <a href=\"https://auth0.com/docs/clients/client-grant-types\">Client Grant Types</a> to learn how to enable it.\n     *\n     * @param callback that will receive the authentication results.\n     * @return a new Lock.Builder instance.\n     */\n    @NonNull\n    public static Builder newBuilder(@NonNull LockCallback callback) {\n        return newBuilder(null, callback);\n    }\n\n    /**\n     * Builds a new intent to launch LockActivity with the previously configured options\n     *\n     * @param context a valid Context\n     * @return the intent to which the user has to call startActivity or startActivityForResult\n     */\n    @NonNull\n    public Intent newIntent(@NonNull Context context) {\n        Intent lockIntent = new Intent(context, PasswordlessLockActivity.class);\n        lockIntent.putExtra(Constants.OPTIONS_EXTRA, options);\n        lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n        return lockIntent;\n    }\n\n    /**\n     * This method ensures proper Lock's lifecycle handling. Must be called from the class\n     * holding the Lock instance whenever you're done using it. i.e. in the Activity's onDestroy method.\n     *\n     * @param context a valid Context\n     */\n    public void onDestroy(@NonNull Context context) {\n        LocalBroadcastManager.getInstance(context).unregisterReceiver(this.receiver);\n    }\n\n    private void initialize(Context context) {\n        LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);\n        lbm.unregisterReceiver(this.receiver);\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(Constants.AUTHENTICATION_ACTION);\n        filter.addAction(Constants.CANCELED_ACTION);\n        filter.addAction(Constants.INVALID_CONFIGURATION_ACTION);\n        lbm.registerReceiver(this.receiver, filter);\n    }\n\n    private void processEvent(@NonNull Intent data) {\n        if (data.hasExtra(Constants.EXCEPTION_EXTRA)) {\n            callback.onError((AuthenticationException) data.getSerializableExtra(Constants.EXCEPTION_EXTRA));\n            return;\n        }\n        String action = data.getAction();\n        switch (action) {\n            case Constants.AUTHENTICATION_ACTION:\n                Log.v(TAG, \"AUTHENTICATION action received in our BroadcastReceiver\");\n                callback.onEvent(LockEvent.AUTHENTICATION, data);\n                break;\n            case Constants.CANCELED_ACTION:\n                Log.v(TAG, \"CANCELED action received in our BroadcastReceiver\");\n                callback.onEvent(LockEvent.CANCELED, new Intent());\n                break;\n            case Constants.INVALID_CONFIGURATION_ACTION:\n                Log.v(TAG, \"INVALID_CONFIGURATION_ACTION action received in our BroadcastReceiver\");\n                callback.onError(new AuthenticationException(\"a0.invalid_configuration\", data.getStringExtra(Constants.ERROR_EXTRA)));\n                break;\n        }\n    }\n\n    /**\n     * Helper Builder to generate the Lock.Options to use on the Auth0 Passwordless Authentication.\n     */\n    @SuppressWarnings({\"UnusedReturnValue\"})\n    public static class Builder {\n        private static final String TAG = Builder.class.getSimpleName();\n        private final Options options;\n        private final LockCallback callback;\n\n        /**\n         * Creates a new Lock.Builder instance with the given account and callback.\n         *\n         * @param account  details to use against the Auth0 Authentication API.\n         * @param callback that will receive the authentication results.\n         */\n        public Builder(@Nullable Auth0 account, @NonNull LockCallback callback) {\n            this.callback = callback;\n            options = new Options();\n            options.setAccount(account);\n        }\n\n        /**\n         * Finishes the construction of the Lock.Options and generates a new Lock instance\n         * with those Lock.Options.\n         *\n         * @param context a valid Context\n         * @return a new Lock instance configured as in the Builder.\n         */\n        @NonNull\n        public PasswordlessLock build(@NonNull Context context) {\n            if (options.getAccount() == null) {\n                Log.w(TAG, \"com.auth0.android.Auth0 account details not defined. Trying to create it from the String resources.\");\n                try {\n                    options.setAccount(new Auth0(context));\n                } catch (IllegalArgumentException e) {\n                    throw new IllegalStateException(\"Missing Auth0 account information.\", e);\n                }\n            }\n            if (callback == null) {\n                Log.e(TAG, \"You need to specify the callback object to receive the Authentication result.\");\n                throw new IllegalStateException(\"Missing callback.\");\n            }\n            Log.v(TAG, \"PasswordlessLock instance created\");\n\n            Auth0UserAgent lockUserAgent = new Auth0UserAgent(Constants.LIBRARY_NAME, BuildConfig.VERSION_NAME, com.auth0.android.auth0.BuildConfig.VERSION_NAME);\n            options.getAccount().setAuth0UserAgent(lockUserAgent);\n\n            final PasswordlessLock lock = new PasswordlessLock(options, callback);\n            lock.initialize(context);\n            return lock;\n        }\n\n        /**\n         * Control the visibility of the header's Title on the main screen. By default it will show the header's Title on the main screen.\n         *\n         * @param hideMainScreenTitle if it should show or hide the header's Title on the main screen.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder hideMainScreenTitle(boolean hideMainScreenTitle) {\n            options.setHideMainScreenTitle(hideMainScreenTitle);\n            return this;\n        }\n\n        /**\n         * Defines the Passwordless type to use in the Authentication as Code. Default value is to use Code\n         *\n         * @return the current Builder instance\n         */\n        @NonNull\n        public Builder useCode() {\n            options.setUseCodePasswordless(true);\n            return this;\n        }\n\n        /**\n         * Defines the Passwordless type to use in the Authentication as Link. Default value is to use Code\n         *\n         * @return the current Builder instance\n         */\n        @NonNull\n        public Builder useLink() {\n            options.setUseCodePasswordless(false);\n            return this;\n        }\n\n        /**\n         * Whether Lock should remember the last used passwordless identity and auto request a sign or not. By default, lock will not remember the last login.\n         *\n         * @return the current Builder instance\n         */\n        @NonNull\n        public Builder rememberLastLogin(boolean remember) {\n            options.setRememberLastPasswordlessLogin(remember);\n            return this;\n        }\n\n        /**\n         * Whether the PasswordlessLockActivity can be closed when pressing the Back key or not.\n         *\n         * @param closable or not. By default, the LockActivity is not closable.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder closable(boolean closable) {\n            options.setClosable(closable);\n            return this;\n        }\n\n        /**\n         * Customize Lock's appearance.\n         *\n         * @param theme to use.\n         * @return the current Builder instance\n         */\n        private Builder withTheme(@NonNull Theme theme) {\n            options.withTheme(theme);\n            return this;\n        }\n\n        /**\n         * Authentication Style to use with the given strategy or connection name. It will override any lock defaults.\n         *\n         * @param connectionName to use this style with\n         * @param style          a valid Style with the Auth0.BackgroundColor, Auth0.Logo and Auth0.Name values defined.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAuthStyle(@NonNull String connectionName, @StyleRes int style) {\n            options.withAuthStyle(connectionName, style);\n            return this;\n        }\n\n        /**\n         * Additional Authentication parameters can be set to use with different Identity Providers.\n         *\n         * @param authenticationParameters a non-null Map containing the parameters as Key-Values\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAuthenticationParameters(@NonNull Map<String, String> authenticationParameters) {\n            options.setAuthenticationParameters(new HashMap<>(authenticationParameters));\n            return this;\n        }\n\n        /**\n         * Locally filters the Auth0 Connections that are shown in the login widgets.\n         *\n         * @param connections a non-null List containing the allowed Auth0 Connections.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder allowedConnections(@NonNull List<String> connections) {\n            options.setConnections(connections);\n            return this;\n        }\n\n        /**\n         * Uses the given AuthHandlers to query for AuthProviders on a new authentication request.\n         *\n         * @param handlers that Lock will query for AuthProviders.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAuthHandlers(@NonNull AuthHandler... handlers) {\n            AuthResolver.setAuthHandlers(Arrays.asList(handlers));\n            return this;\n        }\n\n        /**\n         * Sets the Scope to request when performing the Authentication.\n         *\n         * @param scope to use in the Authentication.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withScope(@NonNull String scope) {\n            options.withScope(scope);\n            return this;\n        }\n\n        /**\n         * Sets the Audience or API Identifier to request access to when performing the Authentication.\n         *\n         * @param audience to use in the Authentication.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withAudience(@NonNull String audience) {\n            options.withAudience(audience);\n            return this;\n        }\n\n        /**\n         * Specify a custom Scheme for the redirect URL used when executing a Web Authentication flow\n         * via the Universal Login page. This has no effect on the Passwordless with Link mode.\n         * Default redirect url scheme is 'https'.\n         *\n         * @param scheme to use in the Web Auth redirect uri.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withScheme(@NonNull String scheme) {\n            options.withScheme(scheme);\n            return this;\n        }\n\n        /**\n         * Specify style and other additional configuration for when the Web Auth flow is used with Custom Tabs.\n         *\n         * @param customTabsOptions to use in the Web Auth flow.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withCustomTabsOptions(@NonNull CustomTabsOptions customTabsOptions) {\n            options.withCustomTabsOptions(customTabsOptions);\n            return this;\n        }\n\n        /**\n         * Sets the url of your support page for your application that will be used when an error occurs and Lock is unable to handle it. In this case it will show an error screen and if there is a support url will also show a button to open that page in the browser.\n         *\n         * @param url to your support page or where your customers can request assistance. By default no page is set.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder setSupportURL(@NonNull String url) {\n            options.setSupportURL(url);\n            return this;\n        }\n\n        /**\n         * Sets the Connection Scope to request when performing an Authentication with the given Connection.\n         *\n         * @param connectionName to which specify the scopes.\n         * @param scope          recognized by this specific authentication provider.\n         * @return the current builder instance\n         */\n        @NonNull\n        public Builder withConnectionScope(@NonNull String connectionName, @NonNull String... scope) {\n            StringBuilder sb = new StringBuilder();\n            for (String s : scope) {\n                sb.append(s.trim()).append(\",\");\n            }\n            if (sb.length() > 0) {\n                sb.deleteCharAt(sb.length() - 1);\n                options.withConnectionScope(connectionName, sb.toString());\n            }\n            return this;\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/PasswordlessLockActivity.java",
    "content": "/*\n * LockPasswordlessActivity.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\n\nimport android.annotation.SuppressLint;\nimport android.app.Dialog;\nimport android.content.Intent;\nimport android.content.res.TypedArray;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.WindowManager;\nimport android.widget.LinearLayout;\nimport android.widget.RelativeLayout;\nimport android.widget.ScrollView;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.VisibleForTesting;\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.core.app.ActivityCompat;\nimport androidx.core.content.ContextCompat;\nimport androidx.localbroadcastmanager.content.LocalBroadcastManager;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.Auth0Exception;\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.authentication.ParameterBuilder;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.errors.AuthenticationError;\nimport com.auth0.android.lock.errors.LoginErrorMessageBuilder;\nimport com.auth0.android.lock.events.CountryCodeChangeEvent;\nimport com.auth0.android.lock.events.FetchApplicationEvent;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.events.PasswordlessLoginEvent;\nimport com.auth0.android.lock.internal.configuration.ApplicationFetcher;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.Connection;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.lock.provider.AuthResolver;\nimport com.auth0.android.lock.views.PasswordlessLockView;\nimport com.auth0.android.provider.AuthCallback;\nimport com.auth0.android.provider.AuthProvider;\nimport com.auth0.android.provider.WebAuthProvider;\nimport com.auth0.android.request.AuthenticationRequest;\nimport com.auth0.android.result.Credentials;\nimport com.squareup.otto.Bus;\nimport com.squareup.otto.Subscribe;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@SuppressLint(\"GoogleAppIndexingApiWarning\")\npublic class PasswordlessLockActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback {\n\n    private static final String TAG = PasswordlessLockActivity.class.getSimpleName();\n    private static final int WEB_AUTH_REQUEST_CODE = 200;\n    private static final int CUSTOM_AUTH_REQUEST_CODE = 201;\n    private static final int PERMISSION_REQUEST_CODE = 202;\n    private static final int COUNTRY_CODE_REQUEST_CODE = 120;\n    private static final long RESULT_MESSAGE_DURATION = 3000;\n    private static final long RESEND_TIMEOUT = 20 * 1000;\n\n    private ApplicationFetcher applicationFetcher;\n    private Configuration configuration;\n    private Options options;\n    private Handler handler;\n\n    private PasswordlessLockView lockView;\n    private LinearLayout passwordlessSuccessCover;\n    private TextView resultMessage;\n\n    private String lastPasswordlessIdentity;\n    private Country lastPasswordlessCountry;\n    private Bus lockBus;\n    private ScrollView rootView;\n    private TextView resendButton;\n\n    private AuthProvider currentProvider;\n    private WebProvider webProvider;\n\n    private LoginErrorMessageBuilder loginErrorBuilder;\n    private PasswordlessIdentityHelper identityHelper;\n\n    public PasswordlessLockActivity() {\n    }\n\n    @VisibleForTesting\n    PasswordlessLockActivity(Configuration configuration, Options options, PasswordlessLockView lockView, WebProvider webProvider, String lastEmailOrNumber) {\n        this.configuration = configuration;\n        this.options = options;\n        this.lockView = lockView;\n        this.webProvider = webProvider;\n        this.lastPasswordlessIdentity = lastEmailOrNumber;\n    }\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (!hasValidLaunchConfig()) {\n            return;\n        }\n\n        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);\n        lockBus = new Bus();\n        lockBus.register(this);\n        handler = new Handler(getMainLooper());\n        webProvider = new WebProvider(options);\n\n        setContentView(R.layout.com_auth0_lock_activity_lock_passwordless);\n        passwordlessSuccessCover = findViewById(R.id.com_auth0_lock_link_sent_cover);\n        rootView = findViewById(R.id.com_auth0_lock_content);\n        resultMessage = findViewById(R.id.com_auth0_lock_result_message);\n        lockView = new PasswordlessLockView(this, lockBus, options.getTheme());\n        RelativeLayout.LayoutParams lockViewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n        lockView.setLayoutParams(lockViewParams);\n        rootView.addView(lockView);\n\n        if (options.useCodePasswordless()) {\n            loginErrorBuilder = new LoginErrorMessageBuilder(R.string.com_auth0_lock_passwordless_code_request_error_message, R.string.com_auth0_lock_passwordless_login_error_invalid_credentials_message);\n        } else {\n            loginErrorBuilder = new LoginErrorMessageBuilder(R.string.com_auth0_lock_passwordless_link_request_error_message, R.string.com_auth0_lock_passwordless_login_error_invalid_credentials_message);\n        }\n        lockBus.post(new FetchApplicationEvent());\n    }\n\n    private boolean hasValidLaunchConfig() {\n        String errorDescription = null;\n        if (!hasValidOptions()) {\n            errorDescription = \"Configuration is not valid and the Activity will finish.\";\n        }\n        if (!hasValidTheme()) {\n            errorDescription = \"You need to use a Lock.Theme theme (or descendant) with this Activity.\";\n        }\n        if (errorDescription == null) {\n            return true;\n        }\n        Intent intent = new Intent(Constants.INVALID_CONFIGURATION_ACTION);\n        intent.putExtra(Constants.ERROR_EXTRA, errorDescription);\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n        return false;\n    }\n\n    private boolean hasValidTheme() {\n        TypedArray a = getTheme().obtainStyledAttributes(R.styleable.Lock_Theme);\n        boolean validTheme = a.hasValue(R.styleable.Lock_Theme_Auth0_HeaderLogo);\n        a.recycle();\n        return validTheme;\n    }\n\n    private boolean hasValidOptions() {\n        options = getIntent().getParcelableExtra(Constants.OPTIONS_EXTRA);\n        if (options == null) {\n            Log.e(TAG, \"Lock Options are missing in the received Intent and PasswordlessLockActivity will not launch. \" +\n                    \"Use the PasswordlessLock.Builder to generate a valid Intent.\");\n            return false;\n        }\n\n        boolean launchedForResult = getCallingActivity() != null;\n        if (launchedForResult) {\n            Log.e(TAG, \"You're not allowed to start Lock with startActivityForResult.\");\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void onBackPressed() {\n        boolean showingSuccessLayout = passwordlessSuccessCover.getVisibility() == View.VISIBLE;\n        if (!showingSuccessLayout && lockView.onBackPressed()) {\n            reloadRecentPasswordlessData(false);\n            return;\n        }\n        if (!options.isClosable()) {\n            return;\n        }\n\n        Log.v(TAG, \"User has just closed the activity.\");\n        Intent intent = new Intent(Constants.CANCELED_ACTION);\n        LocalBroadcastManager.getInstance(PasswordlessLockActivity.this).sendBroadcast(intent);\n        super.onBackPressed();\n    }\n\n    private void deliverAuthenticationResult(Credentials credentials) {\n        Intent intent = new Intent(Constants.AUTHENTICATION_ACTION);\n        intent.putExtra(Constants.ID_TOKEN_EXTRA, credentials.getIdToken());\n        intent.putExtra(Constants.ACCESS_TOKEN_EXTRA, credentials.getAccessToken());\n        intent.putExtra(Constants.REFRESH_TOKEN_EXTRA, credentials.getRefreshToken());\n        intent.putExtra(Constants.TOKEN_TYPE_EXTRA, credentials.getType());\n        intent.putExtra(Constants.EXPIRES_AT_EXTRA, credentials.getExpiresAt());\n\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n    }\n\n    private void deliverAuthenticationError(AuthenticationException exception) {\n        Intent intent = new Intent(Constants.AUTHENTICATION_ACTION);\n        intent.putExtra(Constants.EXCEPTION_EXTRA, exception);\n\n        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);\n        finish();\n    }\n\n    private void showErrorMessage(String message) {\n        resultMessage.setBackgroundColor(ContextCompat.getColor(this, R.color.com_auth0_lock_result_message_error_background));\n        resultMessage.setVisibility(View.VISIBLE);\n        resultMessage.setText(message);\n        lockView.showProgress(false);\n        handler.removeCallbacks(resultMessageHider);\n        handler.postDelayed(resultMessageHider, RESULT_MESSAGE_DURATION);\n    }\n\n    private final Runnable resultMessageHider = new Runnable() {\n        @Override\n        public void run() {\n            resultMessage.setVisibility(View.GONE);\n        }\n    };\n\n    private void showLinkSentLayout() {\n        //Next 2 lines required to avoid focus on the form behind\n        rootView.setFocusable(false);\n        rootView.setFocusableInTouchMode(false);\n        TextView successMessage = passwordlessSuccessCover.findViewById(R.id.com_auth0_lock_passwordless_message);\n        successMessage.setText(String.format(getString(R.string.com_auth0_lock_title_passwordless_link_sent), lastPasswordlessIdentity));\n        TextView gotCodeButton = passwordlessSuccessCover.findViewById(R.id.com_auth0_lock_got_code);\n        gotCodeButton.setOnClickListener(v -> {\n            lockView.setVisibility(View.VISIBLE);\n            passwordlessSuccessCover.setVisibility(View.GONE);\n        });\n        resendButton = passwordlessSuccessCover.findViewById(R.id.com_auth0_lock_resend);\n        resendButton.setOnClickListener(v -> {\n            resendButton.setVisibility(View.GONE);\n            rootView.removeView(lockView);\n            lockView = new PasswordlessLockView(PasswordlessLockActivity.this, lockBus, options.getTheme());\n            if (configuration != null) {\n                lockView.configure(configuration);\n                reloadRecentPasswordlessData(false);\n            } else {\n                lockBus.post(new FetchApplicationEvent());\n            }\n            rootView.addView(lockView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n            passwordlessSuccessCover.setVisibility(View.GONE);\n        });\n        lockView.setVisibility(View.GONE);\n        passwordlessSuccessCover.setVisibility(View.VISIBLE);\n        handler.removeCallbacks(resendTimeoutShower);\n        handler.postDelayed(resendTimeoutShower, RESEND_TIMEOUT);\n    }\n\n    final Runnable resendTimeoutShower = new Runnable() {\n        @Override\n        public void run() {\n            if (resendButton != null) {\n                resendButton.setVisibility(View.VISIBLE);\n            }\n        }\n    };\n\n    private void reloadRecentPasswordlessData(boolean submitForm) {\n        if (!configuration.usePasswordlessAutoSubmit() || !identityHelper.hasLoggedInBefore()) {\n            return;\n        }\n\n        Log.d(TAG, \"Reloading passwordless identity from a previous successful log in.\");\n        lockView.loadPasswordlessData(identityHelper.getLastIdentity(), identityHelper.getLastCountry());\n        if (submitForm) {\n            lockView.onFormSubmit();\n        }\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {\n        switch (requestCode) {\n            case COUNTRY_CODE_REQUEST_CODE:\n                if (resultCode == RESULT_OK && data != null) {\n                    String country = data.getStringExtra(CountryCodeActivity.COUNTRY_CODE_EXTRA);\n                    String dialCode = data.getStringExtra(CountryCodeActivity.COUNTRY_DIAL_CODE_EXTRA);\n                    lockView.onCountryCodeSelected(country, dialCode);\n                }\n                break;\n            case WEB_AUTH_REQUEST_CODE:\n                lockView.showProgress(false);\n                webProvider.resume(data);\n                break;\n            case CUSTOM_AUTH_REQUEST_CODE:\n                lockView.showProgress(false);\n                if (currentProvider != null) {\n                    currentProvider.authorize(requestCode, resultCode, data);\n                    currentProvider = null;\n                }\n                break;\n            default:\n                super.onActivityResult(requestCode, resultCode, data);\n        }\n    }\n\n    @Override\n    protected void onNewIntent(@Nullable Intent intent) {\n        lockView.showProgress(false);\n        if (webProvider.resume(intent)) {\n            return;\n        } else if (currentProvider != null) {\n            currentProvider.authorize(intent);\n            currentProvider = null;\n            return;\n        }\n\n        //Passwordless result\n        if (intent == null) {\n            return;\n        }\n        if (configuration == null) {\n            Log.w(TAG, String.format(\"Intent arrived with data %s but is going to be discarded as the Activity lacks of Configuration\", intent.getData()));\n            return;\n        }\n\n        boolean useMagicLink = configuration.getPasswordlessMode() == PasswordlessMode.EMAIL_LINK || configuration.getPasswordlessMode() == PasswordlessMode.SMS_LINK;\n        if (lastPasswordlessIdentity != null && useMagicLink) {\n            String code = intent.getData().getQueryParameter(\"code\");\n            if (code == null || code.isEmpty()) {\n                Log.w(TAG, \"Passwordless Code is missing or could not be parsed\");\n                showErrorMessage(getString(R.string.com_auth0_lock_db_login_error_message));\n                return;\n            }\n            PasswordlessLoginEvent event = PasswordlessLoginEvent.submitCode(configuration.getPasswordlessMode(), code);\n            onPasswordlessAuthenticationRequest(event);\n        } else {\n            Log.w(TAG, \"Invalid Activity state\");\n        }\n\n        super.onNewIntent(intent);\n    }\n\n    @Override\n    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n        if (currentProvider != null) {\n            currentProvider.onRequestPermissionsResult(this, requestCode, permissions, grantResults);\n        }\n    }\n\n    @Subscribe\n    public void onFetchApplicationRequest(@NonNull FetchApplicationEvent event) {\n        if (applicationFetcher == null) {\n            Auth0 account = options.getAccount();\n            applicationFetcher = new ApplicationFetcher(account);\n            applicationFetcher.fetch(applicationCallback);\n        }\n    }\n\n    @Subscribe\n    public void onCountryCodeChangeRequest(@NonNull CountryCodeChangeEvent event) {\n        Intent intent = new Intent(this, CountryCodeActivity.class);\n        startActivityForResult(intent, COUNTRY_CODE_REQUEST_CODE);\n    }\n\n    @Subscribe\n    public void onPasswordlessAuthenticationRequest(@NonNull PasswordlessLoginEvent event) {\n        if (configuration.getPasswordlessConnection() == null) {\n            Log.w(TAG, \"There is no default Passwordless strategy to authenticate with\");\n            return;\n        }\n\n        lockView.showProgress(true);\n        AuthenticationAPIClient apiClient = options.getAuthenticationAPIClient();\n        String connectionName = configuration.getPasswordlessConnection().getName();\n        if (event.getCode() != null) {\n            AuthenticationRequest request = event.getLoginRequest(apiClient, lastPasswordlessIdentity)\n                    .setConnection(connectionName);\n            request.addParameters(options.getAuthenticationParameters())\n                    .addParameter(\"connection\", connectionName);\n            if (options.getScope() != null) {\n                request.setScope(options.getScope());\n            }\n            if (options.getAudience() != null) {\n                request.setAudience(options.getAudience());\n            }\n            request.start(authCallback);\n            return;\n        }\n\n        lastPasswordlessIdentity = event.getEmailOrNumber();\n        lastPasswordlessCountry = event.getCountry();\n        event.getCodeRequest(apiClient, connectionName)\n                .start(passwordlessCodeCallback);\n    }\n\n    @Subscribe\n    public void onOAuthAuthenticationRequest(@NonNull OAuthLoginEvent event) {\n        lastPasswordlessIdentity = null;\n        lastPasswordlessCountry = null;\n        Log.v(TAG, \"Looking for a provider to use with the connection \" + event.getConnection());\n        currentProvider = AuthResolver.providerFor(event.getStrategy(), event.getConnection());\n        if (currentProvider != null) {\n            Map<String, Object> authParameters = new HashMap<>();\n            for (Map.Entry<String, String> e : options.getAuthenticationParameters().entrySet()) {\n                authParameters.put(e.getKey(), e.getValue());\n            }\n            final String connectionScope = options.getConnectionsScope().get(event.getConnection());\n            if (connectionScope != null) {\n                authParameters.put(Constants.CONNECTION_SCOPE_KEY, connectionScope);\n            }\n            final String scope = options.getScope();\n            if (scope != null) {\n                authParameters.put(ParameterBuilder.SCOPE_KEY, scope);\n            }\n            final String audience = options.getAudience();\n            if (audience != null) {\n                authParameters.put(ParameterBuilder.AUDIENCE_KEY, audience);\n            }\n            currentProvider.setParameters(authParameters);\n            currentProvider.start(this, authProviderCallback, PERMISSION_REQUEST_CODE, CUSTOM_AUTH_REQUEST_CODE);\n            return;\n        }\n\n        Log.d(TAG, \"Couldn't find an specific provider, using the default: \" + WebAuthProvider.class.getSimpleName());\n        webProvider.start(this, event.getConnection(), null, new WebCallbackWrapper(authProviderCallback));\n    }\n\n    //Callbacks\n    private final Callback<List<Connection>, Auth0Exception> applicationCallback = new Callback<List<Connection>, Auth0Exception>() {\n        @Override\n        public void onSuccess(@Nullable final List<Connection> connections) {\n            configuration = new Configuration(connections, options);\n            identityHelper = new PasswordlessIdentityHelper(PasswordlessLockActivity.this, configuration.getPasswordlessMode());\n            handler.post(() -> {\n                lockView.configure(configuration);\n                reloadRecentPasswordlessData(true);\n            });\n            applicationFetcher = null;\n        }\n\n        @Override\n        public void onFailure(@NonNull final Auth0Exception error) {\n            Log.e(TAG, \"Failed to fetch the application: \" + error.getMessage(), error);\n            applicationFetcher = null;\n            handler.post(() -> lockView.configure(null));\n        }\n    };\n\n    private final com.auth0.android.callback.AuthenticationCallback<Void> passwordlessCodeCallback = new com.auth0.android.callback.AuthenticationCallback<Void>() {\n        @Override\n        public void onSuccess(@Nullable Void payload) {\n            handler.post(() -> {\n                lockView.showProgress(false);\n                lockView.onPasswordlessCodeSent(lastPasswordlessIdentity);\n                if (!options.useCodePasswordless()) {\n                    showLinkSentLayout();\n                }\n            });\n        }\n\n        @Override\n        public void onFailure(@NonNull final AuthenticationException error) {\n            Log.e(TAG, \"Failed to request a passwordless Code/Link: \" + error.getMessage(), error);\n            handler.post(() -> {\n                String message = loginErrorBuilder.buildFrom(error).getMessage(PasswordlessLockActivity.this);\n                showErrorMessage(message);\n            });\n        }\n    };\n\n    private final com.auth0.android.callback.AuthenticationCallback<Credentials> authCallback = new com.auth0.android.callback.AuthenticationCallback<Credentials>() {\n        @Override\n        public void onSuccess(@Nullable Credentials credentials) {\n            if (configuration.usePasswordlessAutoSubmit()) {\n                Log.d(TAG, \"Saving passwordless identity for a future log in request.\");\n                identityHelper.saveIdentity(lastPasswordlessIdentity, lastPasswordlessCountry);\n            }\n            deliverAuthenticationResult(credentials);\n        }\n\n        @Override\n        public void onFailure(@NonNull final AuthenticationException error) {\n            Log.e(TAG, \"Failed to authenticate the user: \" + error.getMessage(), error);\n            if (error.isRuleError() || error.isAccessDenied()) {\n                deliverAuthenticationError(error);\n                return;\n            }\n            handler.post(() -> showErrorMessage(loginErrorBuilder.buildFrom(error).getMessage(PasswordlessLockActivity.this)));\n        }\n    };\n\n    private final AuthCallback authProviderCallback = new AuthCallback() {\n        @Override\n        public void onFailure(@NonNull final Dialog dialog) {\n            Log.e(TAG, \"Failed to authenticate the user. A dialog is going to be shown with more information.\");\n            handler.post(dialog::show);\n        }\n\n        @Override\n        public void onFailure(@NonNull final AuthenticationException exception) {\n            Log.e(TAG, \"Failed to authenticate the user: \" + exception.getCode(), exception);\n            if (exception.isRuleError() || exception.isAccessDenied()) {\n                deliverAuthenticationError(exception);\n                return;\n            }\n            final AuthenticationError authError = loginErrorBuilder.buildFrom(exception);\n            final String message = authError.getMessage(PasswordlessLockActivity.this);\n            handler.post(() -> showErrorMessage(message));\n        }\n\n        @Override\n        public void onSuccess(@NonNull final Credentials credentials) {\n            deliverAuthenticationResult(credentials);\n        }\n    };\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/UsernameStyle.java",
    "content": "/*\n * UsernameStyle.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.UsernameStyle.DEFAULT;\nimport static com.auth0.android.lock.UsernameStyle.EMAIL;\nimport static com.auth0.android.lock.UsernameStyle.USERNAME;\n\n@IntDef({DEFAULT, USERNAME, EMAIL})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface UsernameStyle {\n    int DEFAULT = 0;\n    int USERNAME = 1;\n    int EMAIL = 2;\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/WebCallbackWrapper.java",
    "content": "package com.auth0.android.lock;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.provider.AuthCallback;\nimport com.auth0.android.result.Credentials;\n\n\n/**\n * Internal class, meant to wrap a {@link AuthCallback} instance and expose it as a {@link Callback}\n */\nclass WebCallbackWrapper implements Callback<Credentials, AuthenticationException> {\n\n    private final AuthCallback baseCallback;\n\n    public WebCallbackWrapper(@NonNull AuthCallback callback) {\n        this.baseCallback = callback;\n    }\n\n    @Override\n    public void onFailure(@NonNull AuthenticationException error) {\n        baseCallback.onFailure(error);\n    }\n\n    @Override\n    public void onSuccess(@NonNull Credentials credentials) {\n        baseCallback.onSuccess(credentials);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/WebProvider.java",
    "content": "package com.auth0.android.lock;\n\nimport android.app.Activity;\nimport android.content.Intent;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.provider.CustomTabsOptions;\nimport com.auth0.android.provider.WebAuthProvider;\nimport com.auth0.android.result.Credentials;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * The WebProvider class is an internal wrapper for calls to the WebAuthProvider static methods.\n * This is only for testing purposes.\n */\nclass WebProvider {\n\n    private final Options options;\n\n    /**\n     * Creates a new instance with the given account.\n     *\n     * @param options to use in the WebAuthProvider.Builder instances.\n     */\n    WebProvider(@NonNull Options options) {\n        this.options = options;\n    }\n\n    /**\n     * Configures a new instance of the WebAuthProvider.Builder and starts it.\n     *\n     * @param activity            a valid Activity context\n     * @param connection          to use in the authentication\n     * @param extraAuthParameters extra authentication parameters to use along with the provided in the Options instance\n     * @param callback            to deliver the authentication result to\n     */\n    public void start(@NonNull Activity activity, @NonNull String connection, @Nullable Map<String, String> extraAuthParameters, @NonNull Callback<Credentials, AuthenticationException> callback) {\n        HashMap<String, String> parameters;\n        if (extraAuthParameters == null) {\n            parameters = options.getAuthenticationParameters();\n        } else {\n            parameters = new HashMap<>(options.getAuthenticationParameters());\n            parameters.putAll(extraAuthParameters);\n        }\n\n        WebAuthProvider.Builder builder = WebAuthProvider.login(options.getAccount())\n                .withParameters(parameters)\n                .withConnection(connection);\n\n        final String connectionScope = options.getConnectionsScope().get(connection);\n        if (connectionScope != null) {\n            builder.withConnectionScope(connectionScope);\n        }\n        final String scope = options.getScope();\n        if (scope != null) {\n            builder.withScope(scope);\n        }\n        final String audience = options.getAudience();\n        if (audience != null) {\n            builder.withAudience(audience);\n        }\n        final String scheme = options.getScheme();\n        if (scheme != null) {\n            builder.withScheme(scheme);\n        }\n        final CustomTabsOptions customTabsOptions = options.getCustomTabsOptions();\n        if (customTabsOptions != null) {\n            builder.withCustomTabsOptions(customTabsOptions);\n        }\n        builder.start(activity, callback);\n    }\n\n    /**\n     * Finishes the authentication flow in the WebAuthProvider\n     *\n     * @param intent the intent received in the onNewIntent method.\n     * @return true if a result was expected and has a valid format, or false if not\n     */\n    public boolean resume(Intent intent) {\n        return WebAuthProvider.resume(intent);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/adapters/Country.java",
    "content": "/*\n * Country.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.adapters;\n\nimport androidx.annotation.NonNull;\n\nimport java.util.Locale;\n\npublic class Country implements Comparable<Country> {\n    private final String isoCode;\n    private final String dialCode;\n\n    public Country(@NonNull String isoCode, @NonNull String dialCode) {\n        this.isoCode = isoCode;\n        this.dialCode = dialCode;\n    }\n\n    @NonNull\n    public String getDialCode() {\n        return dialCode;\n    }\n\n    @NonNull\n    public String getIsoCode() {\n        return isoCode;\n    }\n\n    @NonNull\n    public String getDisplayName() {\n        Locale locale = new Locale(\"\", isoCode);\n        return locale.getDisplayName();\n    }\n\n    @Override\n    public int compareTo(@NonNull Country another) {\n        return getDisplayName().compareToIgnoreCase(another.getDisplayName());\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/adapters/CountryAdapter.java",
    "content": "/*\n * CountryAdapter.java\n *\n * Copyright (c) 2015 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.adapters;\n\nimport android.content.Context;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.Filter;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.lock.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CountryAdapter extends BaseAdapter {\n\n    private final CountryFilter filter;\n    private final Context context;\n    protected @NonNull\n    List<Country> allData;\n    protected @NonNull\n    List<Country> filteredData;\n\n    public CountryAdapter(@NonNull Context context, @NonNull List<Country> countries) {\n        this.context = context;\n        this.allData = countries;\n        this.filteredData = countries;\n        this.filter = new CountryFilter();\n    }\n\n    @Override\n    public int getCount() {\n        return filteredData.size();\n    }\n\n    @Nullable\n    @Override\n    public Country getItem(int position) {\n        return filteredData.get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return position;\n    }\n\n    @NonNull\n    @Override\n    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {\n        if (convertView == null) {\n            convertView = LayoutInflater.from(context).inflate(R.layout.com_auth0_lock_passwordless_item_country_code, parent, false);\n        }\n\n        TextView countryNameTextView = convertView.findViewById(R.id.com_auth0_lock_passwordless_sms_country_name_text_view);\n        TextView countryCodeTextView = convertView.findViewById(R.id.com_auth0_lock_passwordless_sms_country_code_text_view);\n        Country country = getItem(position);\n        countryNameTextView.setText(country.getDisplayName());\n        countryCodeTextView.setText(country.getDialCode());\n        return convertView;\n    }\n\n    @NonNull\n    public Filter getFilter() {\n        return filter;\n    }\n\n    private class CountryFilter extends Filter {\n\n        @Override\n        protected FilterResults performFiltering(CharSequence constraint) {\n            String search = constraint.toString().toLowerCase();\n            FilterResults results = new FilterResults();\n            List<Country> filtered = new ArrayList<>();\n            for (Country country : allData) {\n                if (country.getDisplayName().toLowerCase().contains(search) || country.getIsoCode().toLowerCase().contains(search)) {\n                    filtered.add(country);\n                }\n            }\n            results.values = filtered;\n            results.count = filtered.size();\n            return results;\n        }\n\n        @Override\n        @SuppressWarnings(\"unchecked\")\n        protected void publishResults(CharSequence constraint, FilterResults results) {\n            filteredData = (List<Country>) results.values;\n            notifyDataSetChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/errors/AuthenticationError.java",
    "content": "/*\n * AuthenticationError.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.errors;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StringRes;\n\npublic class AuthenticationError {\n\n    @StringRes\n    private final int message;\n    private final String customMessage;\n\n    public AuthenticationError(@StringRes int message) {\n        this(message, null);\n    }\n\n    AuthenticationError(@StringRes int message, @Nullable String description) {\n        this.message = message;\n        this.customMessage = description;\n    }\n\n    /**\n     * Getter for the error message.\n     *\n     * @param context a valid context.\n     * @return the user friendly message\n     */\n    @NonNull\n    public String getMessage(@NonNull Context context) {\n        if (customMessage != null) {\n            return customMessage;\n        }\n        return context.getResources().getString(message);\n    }\n\n    int getMessageRes() {\n        return message;\n    }\n\n    String getCustomMessage() {\n        return customMessage;\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/errors/ErrorMessageBuilder.java",
    "content": "package com.auth0.android.lock.errors;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.Auth0Exception;\n\npublic interface ErrorMessageBuilder<U extends Auth0Exception> {\n\n    @NonNull\n    AuthenticationError buildFrom(@NonNull U exception);\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/errors/LoginErrorMessageBuilder.java",
    "content": "/*\n * LoginAuthenticationError.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.errors;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.StringRes;\nimport android.util.Log;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.R;\n\n\npublic class LoginErrorMessageBuilder implements ErrorMessageBuilder<AuthenticationException> {\n\n    private static final String USER_EXISTS_ERROR = \"user_exists\";\n    private static final String USERNAME_EXISTS_ERROR = \"username_exists\";\n    private static final String USER_IS_BLOCKED_DESCRIPTION = \"user is blocked\";\n    private static final String TOO_MANY_ATTEMPTS_ERROR = \"too_many_attempts\";\n    private static final String WRONG_CLIENT_TYPE_ERROR = \"Unauthorized\";\n\n    private static final int userExistsResource = R.string.com_auth0_lock_db_signup_user_already_exists_error_message;\n    private static final int unauthorizedResource = R.string.com_auth0_lock_db_login_error_unauthorized_message;\n    private static final int invalidMFACodeResource = R.string.com_auth0_lock_db_login_error_invalid_mfa_code_message;\n    private static final int mfaEnrollRequiredResource = R.string.com_auth0_lock_db_login_error_mfa_enroll_required;\n    private static final int tooManyAttemptsResource = R.string.com_auth0_lock_db_too_many_attempts_error_message;\n    private static final int passwordLeakedResource = R.string.com_auth0_lock_db_password_leaked_error_message;\n\n    private final int invalidCredentialsResource;\n    private final int defaultMessage;\n\n    public LoginErrorMessageBuilder(@StringRes int defaultMessage, @StringRes int invalidCredentialsMessage) {\n        this.defaultMessage = defaultMessage;\n        this.invalidCredentialsResource = invalidCredentialsMessage;\n    }\n\n    public LoginErrorMessageBuilder() {\n        this(R.string.com_auth0_lock_db_login_error_message, R.string.com_auth0_lock_db_login_error_invalid_credentials_message);\n    }\n\n    @NonNull\n    @Override\n    public AuthenticationError buildFrom(@NonNull AuthenticationException exception) {\n        int messageRes;\n        String description = null;\n\n        if (exception.isInvalidCredentials()) {\n            messageRes = invalidCredentialsResource;\n        } else if (exception.isMultifactorCodeInvalid() || exception.isMultifactorTokenInvalid()) {\n            messageRes = invalidMFACodeResource;\n        } else if (exception.isMultifactorEnrollRequired()) {\n            messageRes = mfaEnrollRequiredResource;\n        } else if (USER_EXISTS_ERROR.equals(exception.getCode()) || USERNAME_EXISTS_ERROR.equals(exception.getCode())) {\n            messageRes = userExistsResource;\n        } else if (exception.isPasswordLeaked()) {\n            messageRes = passwordLeakedResource;\n        } else if (exception.isRuleError()) {\n            messageRes = unauthorizedResource;\n            if (!USER_IS_BLOCKED_DESCRIPTION.equals(exception.getDescription())) {\n                description = exception.getDescription();\n            }\n        } else if (WRONG_CLIENT_TYPE_ERROR.equals(exception.getDescription())) {\n            Log.w(\"Lock\", \"The Client Type must be set to 'native' in order to authenticate using Code Grant (PKCE). Please change the type in your Auth0 Application's dashboard: https://manage.auth0.com/#/applications\");\n            messageRes = defaultMessage;\n        } else if (TOO_MANY_ATTEMPTS_ERROR.equals(exception.getCode())) {\n            messageRes = tooManyAttemptsResource;\n        } else {\n            messageRes = defaultMessage;\n        }\n        return new AuthenticationError(messageRes, description);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/errors/SignUpErrorMessageBuilder.java",
    "content": "/*\n * SignUpAuthenticationErrorBuilder.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.errors;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.StringRes;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.R;\n\npublic class SignUpErrorMessageBuilder implements ErrorMessageBuilder<AuthenticationException> {\n\n    private static final String USER_EXISTS_ERROR = \"user_exists\";\n    private static final String USERNAME_EXISTS_ERROR = \"username_exists\";\n    private static final String TOO_MANY_ATTEMPTS_ERROR = \"too_many_attempts\";\n\n    @StringRes\n    private final int defaultMessage;\n\n    private static final int userExistsResource = R.string.com_auth0_lock_db_signup_user_already_exists_error_message;\n    private static final int passwordAlreadyUsedResource = R.string.com_auth0_lock_db_signup_password_already_used_error_message;\n    private static final int passwordNotStrongResource = R.string.com_auth0_lock_db_signup_password_not_strong_error_message;\n    private static final int tooManyAttemptsResource = R.string.com_auth0_lock_db_too_many_attempts_error_message;\n\n    public SignUpErrorMessageBuilder(@StringRes int defaultMessage) {\n        this.defaultMessage = defaultMessage;\n    }\n\n    public SignUpErrorMessageBuilder() {\n        this(R.string.com_auth0_lock_db_sign_up_error_message);\n    }\n\n    @NonNull\n    @Override\n    public AuthenticationError buildFrom(@NonNull AuthenticationException exception) {\n        int messageRes;\n        String description = null;\n\n        if (USER_EXISTS_ERROR.equals(exception.getCode()) || USERNAME_EXISTS_ERROR.equals(exception.getCode())) {\n            messageRes = userExistsResource;\n        } else if (exception.isPasswordAlreadyUsed()) {\n            messageRes = passwordAlreadyUsedResource;\n        } else if (exception.isPasswordNotStrongEnough()) {\n            messageRes = passwordNotStrongResource;\n        } else if (exception.isRuleError()) {\n            messageRes = defaultMessage;\n            description = exception.getDescription();\n        } else if (TOO_MANY_ATTEMPTS_ERROR.equals(exception.getCode())) {\n            messageRes = tooManyAttemptsResource;\n        } else {\n            messageRes = defaultMessage;\n        }\n        return new AuthenticationError(messageRes, description);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/CountryCodeChangeEvent.java",
    "content": "/*\n * CountryCodeEventRequest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\npublic class CountryCodeChangeEvent {\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/DatabaseChangePasswordEvent.java",
    "content": "/*\n * DbChangePasswordEvent.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\n\nimport androidx.annotation.NonNull;\n\npublic class DatabaseChangePasswordEvent extends DatabaseEvent {\n\n    /**\n     * Creates a new Database Change Password event with the given email.\n     *\n     * @param email a valid email to request a password change.\n     */\n    public DatabaseChangePasswordEvent(@NonNull String email) {\n        super(email);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/DatabaseEvent.java",
    "content": "/*\n * EmailEvent.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.lock.views.ValidatedInputView;\n\npublic class DatabaseEvent {\n    private String username;\n    private String email;\n\n    public DatabaseEvent(@NonNull String identity) {\n        if (isEmail(identity)) {\n            this.email = identity;\n        } else if (isUsername(identity)) {\n            this.username = identity;\n        }\n    }\n\n    public DatabaseEvent(@NonNull String email, @Nullable String username) {\n        this.email = email;\n        this.username = username;\n    }\n\n    @Nullable\n    public String getEmail() {\n        return email;\n    }\n\n    @Nullable\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(@Nullable String username) {\n        this.username = username;\n    }\n\n    private boolean isUsername(String input) {\n        return input != null && input.matches(ValidatedInputView.USERNAME_REGEX);\n    }\n\n    private boolean isEmail(String input) {\n        return input != null && input.matches(ValidatedInputView.EMAIL_REGEX);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/DatabaseLoginEvent.java",
    "content": "/*\n * DbConnectionEvent.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\npublic class DatabaseLoginEvent extends DatabaseEvent {\n\n    private final String password;\n    private String mfaOTP;\n    private String mfaOOBCode;\n    private String mfaToken;\n    private String mfaChallengeType;\n\n    public DatabaseLoginEvent(@NonNull String usernameOrEmail, @NonNull String password) {\n        super(usernameOrEmail);\n        this.password = password;\n    }\n\n    @NonNull\n    public String getUsernameOrEmail() {\n        return getEmail() != null ? getEmail() : getUsername();\n    }\n\n    @NonNull\n    public String getPassword() {\n        return password;\n    }\n\n    public void setMultifactorOTP(@NonNull String code) {\n        this.mfaOTP = code;\n    }\n\n    @Nullable\n    public String getMultifactorOTP() {\n        return mfaOTP;\n    }\n\n    public void setMultifactorOOBCode(@Nullable String code) {\n        this.mfaOOBCode = code;\n    }\n\n    @Nullable\n    public String getMultifactorOOBCode() {\n        return mfaOOBCode;\n    }\n\n    public void setMultifactorToken(@NonNull String mfaToken) {\n        this.mfaToken = mfaToken;\n    }\n\n    @Nullable\n    public String getMultifactorToken() {\n        return mfaToken;\n    }\n\n    public void setMultifactorChallengeType(@NonNull String challengeType) {\n        this.mfaChallengeType = challengeType;\n    }\n\n    @Nullable\n    public String getMultifactorChallengeType() {\n        return mfaChallengeType;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/DatabaseSignUpEvent.java",
    "content": "/*\n * DbSignUpEvent.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.request.Request;\nimport com.auth0.android.request.SignUpRequest;\nimport com.auth0.android.result.DatabaseUser;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class DatabaseSignUpEvent extends DatabaseEvent {\n\n    private static final String KEY_USER_METADATA = \"user_metadata\";\n\n    @NonNull\n    private final String password;\n    private final Map<String, String> rootAttributes;\n    private final Map<String, String> userMetadata;\n\n    public DatabaseSignUpEvent(@NonNull String email, @NonNull String password, @Nullable String username) {\n        super(email, username);\n        this.password = password;\n        this.rootAttributes = new HashMap<>();\n        this.userMetadata = new HashMap<>();\n    }\n\n    @NonNull\n    public String getPassword() {\n        return password;\n    }\n\n    public void setRootAttributes(@NonNull Map<String, String> attributes) {\n        this.rootAttributes.putAll(attributes);\n    }\n\n    /**\n     * Set the fields to set as user_metadata\n     *\n     * @param customFields user_metadata fields to set\n     */\n    public void setExtraFields(@NonNull Map<String, String> customFields) {\n        this.userMetadata.putAll(customFields);\n    }\n\n\n    @NonNull\n    public SignUpRequest getSignUpRequest(@NonNull AuthenticationAPIClient apiClient, @NonNull String connection) {\n        SignUpRequest request = apiClient.signUp(getEmail(), getPassword(), getUsername(), connection, userMetadata);\n        if (!rootAttributes.isEmpty()) {\n            request.addSignUpParameters(rootAttributes);\n        }\n        return request;\n    }\n\n    @NonNull\n    public Request<DatabaseUser, AuthenticationException> getCreateUserRequest(@NonNull AuthenticationAPIClient apiClient, @NonNull String connection) {\n        Request<DatabaseUser, AuthenticationException> request = apiClient.createUser(getEmail(), getPassword(), getUsername(), connection, userMetadata);\n        if (!rootAttributes.isEmpty()) {\n            request.addParameters(rootAttributes);\n        }\n        return request;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/FetchApplicationEvent.java",
    "content": "/*\n * FetchApplicationEvent.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\npublic class FetchApplicationEvent {\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/LockMessageEvent.java",
    "content": "package com.auth0.android.lock.events;\n\nimport androidx.annotation.StringRes;\n\npublic class LockMessageEvent {\n\n    @StringRes\n    private final int messageRes;\n\n    public LockMessageEvent(@StringRes int messageRes) {\n        this.messageRes = messageRes;\n    }\n\n    @StringRes\n    public int getMessageRes() {\n        return messageRes;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/OAuthLoginEvent.java",
    "content": "package com.auth0.android.lock.events;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\n\npublic class OAuthLoginEvent {\n\n    private final OAuthConnection connection;\n    private String username;\n    private String password;\n\n    /**\n     * Creates a new OAuthLoginEvent to authenticate using the Active Flow.\n     *\n     * @param connection the connection instance.\n     * @param username   the username to use.\n     * @param password   the password to use.\n     */\n    public OAuthLoginEvent(@NonNull OAuthConnection connection, @NonNull String username, @Nullable String password) {\n        this(connection);\n        this.username = username;\n        this.password = password;\n    }\n\n    /**\n     * Creates a new OAuthLoginEvent to authenticate using the WebAuth flow.\n     *\n     * @param connection the connection instance.\n     */\n    public OAuthLoginEvent(@NonNull OAuthConnection connection) {\n        this.connection = connection;\n    }\n\n    /**\n     * Returns if this login event should use Resource Owner to authenticate, instead of the WebAuth flow.\n     *\n     * @return if the Active Flow (Resource Owner) is enabled.\n     */\n    public boolean useActiveFlow() {\n        return username != null && password != null;\n    }\n\n    /**\n     * Returns the connection name to use.\n     *\n     * @return the connection name.\n     */\n    @NonNull\n    public String getConnection() {\n        return connection.getName();\n    }\n\n    /**\n     * Returns the strategy name to use.\n     *\n     * @return the strategy name.\n     */\n    @Nullable\n    public String getStrategy() {\n        return connection.getStrategy();\n    }\n\n    /**\n     * Getter for the username. Will only be available if this login event uses Active Flow.\n     *\n     * @return the username to use, or null if this connection doesn't use Active Flow.\n     */\n    @Nullable\n    public String getUsername() {\n        return username;\n    }\n\n    /**\n     * Getter for the password. Will only be available if this login request uses Active Flow.\n     *\n     * @return the password to use, or null if this connection doesn't use Active Flow.\n     */\n    @Nullable\n    public String getPassword() {\n        return password;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/events/PasswordlessLoginEvent.java",
    "content": "/*\n * PasswordlessLoginEvent.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\nimport android.util.Log;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.authentication.PasswordlessType;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.request.AuthenticationRequest;\nimport com.auth0.android.request.Request;\n\npublic class PasswordlessLoginEvent {\n    private static final String TAG = PasswordlessLoginEvent.class.getSimpleName();\n    private static final String KEY_CONNECTION = \"connection\";\n    @PasswordlessMode\n    private final int mode;\n    private final String emailOrNumber;\n    private final String code;\n    private final Country country;\n\n\n    private PasswordlessLoginEvent(@PasswordlessMode int mode, String emailOrNumber, String code, Country country) {\n        this.mode = mode;\n        this.emailOrNumber = emailOrNumber;\n        this.code = code;\n        this.country = country;\n    }\n\n    @NonNull\n    public static PasswordlessLoginEvent requestCode(@PasswordlessMode int mode, @NonNull String email) {\n        return new PasswordlessLoginEvent(mode, email, null, null);\n    }\n\n    @NonNull\n    public static PasswordlessLoginEvent requestCode(@PasswordlessMode int mode, @NonNull String number, @NonNull Country country) {\n        String fullNumber = country.getDialCode() + number;\n        return new PasswordlessLoginEvent(mode, fullNumber, null, country);\n    }\n\n    @NonNull\n    public static PasswordlessLoginEvent submitCode(@PasswordlessMode int mode, @NonNull String code) {\n        return new PasswordlessLoginEvent(mode, null, code, null);\n    }\n\n    @PasswordlessMode\n    public int getMode() {\n        return mode;\n    }\n\n    @Nullable\n    public String getEmailOrNumber() {\n        return emailOrNumber;\n    }\n\n    @Nullable\n    public Country getCountry() {\n        return country;\n    }\n\n    @Nullable\n    public String getCode() {\n        return code;\n    }\n\n    /**\n     * Creates the ParameterizableRequest that will initiate the Passwordless Authentication flow.\n     *\n     * @param apiClient      the API Client instance\n     * @param connectionName the name of the passwordless connection to request the login with. Only 'sms' and 'email' connections are allowed here.\n     * @return the Passwordless code request request.\n     */\n    @NonNull\n    public Request<Void, AuthenticationException> getCodeRequest(@NonNull AuthenticationAPIClient apiClient, @NonNull String connectionName) {\n        Log.d(TAG, String.format(\"Generating Passwordless Code/Link request for connection %s\", connectionName));\n        Request<Void, AuthenticationException> request;\n        if (getMode() == PasswordlessMode.EMAIL_CODE) {\n            request = apiClient.passwordlessWithEmail(getEmailOrNumber(), PasswordlessType.CODE);\n        } else if (getMode() == PasswordlessMode.EMAIL_LINK) {\n            request = apiClient.passwordlessWithEmail(getEmailOrNumber(), PasswordlessType.ANDROID_LINK);\n        } else if (getMode() == PasswordlessMode.SMS_CODE) {\n            request = apiClient.passwordlessWithSMS(getEmailOrNumber(), PasswordlessType.CODE);\n        } else {\n            request = apiClient.passwordlessWithSMS(getEmailOrNumber(), PasswordlessType.ANDROID_LINK);\n        }\n        return request.addParameter(KEY_CONNECTION, connectionName);\n    }\n\n    /**\n     * Creates the AuthenticationRequest that will finish the Passwordless Authentication flow.\n     *\n     * @param apiClient     the API Client instance\n     * @param emailOrNumber the email or phone number used on the code request.\n     * @return the Passwordless login request.\n     */\n    @NonNull\n    public AuthenticationRequest getLoginRequest(@NonNull AuthenticationAPIClient apiClient, @NonNull String emailOrNumber) {\n        Log.d(TAG, String.format(\"Generating Passwordless Login request for identity %s\", emailOrNumber));\n        if (getMode() == PasswordlessMode.EMAIL_CODE || getMode() == PasswordlessMode.EMAIL_LINK) {\n            return apiClient.loginWithEmail(emailOrNumber, getCode());\n        } else {\n            return apiClient.loginWithPhoneNumber(emailOrNumber, getCode());\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/ApplicationDeserializer.java",
    "content": "/*\n * ApplicationDeserializer.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonDeserializationContext;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParseException;\nimport com.google.gson.internal.LinkedTreeMap;\nimport com.google.gson.reflect.TypeToken;\n\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nclass ApplicationDeserializer extends GsonDeserializer<List<Connection>> {\n\n    @Override\n    public List<Connection> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {\n        assertJsonObject(json);\n\n        final JsonObject object = json.getAsJsonObject();\n\n        requiredValue(\"id\", String.class, object, context);\n        requiredValue(\"tenant\", String.class, object, context);\n        requiredValue(\"authorize\", String.class, object, context);\n        requiredValue(\"callback\", String.class, object, context);\n\n        requiredValue(\"strategies\", JsonArray.class, object, context);\n        final JsonArray strategies = object.getAsJsonArray(\"strategies\");\n        return mergeConnections(strategies, context);\n    }\n\n    private List<Connection> mergeConnections(JsonArray list, JsonDeserializationContext context) {\n        List<Connection> connections = new ArrayList<>();\n        for (JsonElement strategy : list) {\n            final List<Connection> c = parseStrategy(strategy, context);\n            connections.addAll(c);\n        }\n        return connections;\n    }\n\n    private List<Connection> parseStrategy(JsonElement json, JsonDeserializationContext context) {\n        final JsonObject strategy = json.getAsJsonObject();\n        String name = requiredValue(\"name\", String.class, strategy, context);\n        requiredValue(\"connections\", Object.class, strategy, context);\n\n        JsonArray connectionsArray = strategy.getAsJsonArray(\"connections\");\n        List<Connection> connections = new ArrayList<>();\n        for (int i = 0; i < connectionsArray.size(); i++) {\n            final JsonObject connectionJson = connectionsArray.get(i).getAsJsonObject();\n            requiredValue(\"name\", String.class, connectionJson, context);\n            Type mapType = new TypeToken<LinkedTreeMap<String, Object>>() {}.getType();\n            Map<String, Object> values = context.deserialize(connectionJson, mapType);\n            connections.add(Connection.newConnectionFor(name, values));\n        }\n        return connections;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/ApplicationFetcher.java",
    "content": "/*\n * ApplicationFetcher.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport android.net.Uri;\nimport android.os.AsyncTask;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.VisibleForTesting;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.Auth0Exception;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.request.HttpMethod;\nimport com.auth0.android.request.RequestOptions;\nimport com.auth0.android.request.ServerResponse;\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport com.google.gson.reflect.TypeToken;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\nimport org.json.JSONTokener;\n\nimport java.io.BufferedInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.Type;\nimport java.nio.charset.Charset;\nimport java.util.List;\n\npublic class ApplicationFetcher {\n\n    private static final String JSONP_PREFIX = \"Auth0.setClient(\";\n\n    private final Auth0 account;\n\n    /**\n     * Helper class to fetch the Application information from Auth0 Dashboard.\n     *\n     * @param account the Application details to build the request uri.\n     */\n    public ApplicationFetcher(@NonNull Auth0 account) {\n        this.account = account;\n    }\n\n    /**\n     * Fetch application information from Auth0\n     *\n     * @param callback to notify on success/error\n     */\n    public void fetch(@NonNull Callback<List<Connection>, Auth0Exception> callback) {\n        FetchTask task = new FetchTask(account);\n        task.execute(callback);\n    }\n\n    @VisibleForTesting\n    static Gson createGson() {\n        Type applicationType = new TypeToken<List<Connection>>() {\n        }.getType();\n        return new GsonBuilder()\n                .excludeFieldsWithoutExposeAnnotation()\n                .registerTypeAdapter(applicationType, new ApplicationDeserializer())\n                .create();\n    }\n\n    private static class FetchTask extends AsyncTask<Callback<List<Connection>, Auth0Exception>, Void, Void> {\n\n        private final Auth0 account;\n\n        public FetchTask(Auth0 account) {\n            this.account = account;\n        }\n\n        @SafeVarargs\n        @Override\n        protected final Void doInBackground(Callback<List<Connection>, Auth0Exception>... callbacks) {\n            makeApplicationRequest(account, callbacks[0]);\n            return null;\n        }\n\n        private void makeApplicationRequest(Auth0 account, Callback<List<Connection>, Auth0Exception> callback) {\n            Uri uri = Uri.parse(account.getConfigurationUrl()).buildUpon().appendPath(\"client\")\n                    .appendPath(account.getClientId() + \".js\").build();\n\n            try {\n                ServerResponse res = account.getNetworkingClient().load(uri.toString(), new RequestOptions(HttpMethod.GET.INSTANCE));\n                List<Connection> connections = parseJSONP(res.getBody());\n                callback.onSuccess(connections);\n            } catch (IOException e) {\n                Auth0Exception exception = new Auth0Exception(\"An error occurred while fetching the client information from the CDN.\", e);\n                callback.onFailure(new AuthenticationException(\"Failed to fetch the Application\", exception));\n            } catch (Auth0Exception e) {\n                callback.onFailure(new AuthenticationException(\"Could not parse Application JSONP\", e));\n            }\n        }\n\n        private List<Connection> parseJSONP(InputStream is) throws Auth0Exception {\n            try {\n                BufferedInputStream bis = new BufferedInputStream(is);\n                ByteArrayOutputStream buf = new ByteArrayOutputStream();\n                for (int result = bis.read(); result != -1; result = bis.read()) {\n                    buf.write((byte) result);\n                }\n                String json = buf.toString(Charset.defaultCharset().name());\n                final int length = JSONP_PREFIX.length();\n                if (json.length() < length) {\n                    throw new JSONException(\"Invalid App Info JSONP\");\n                }\n                json = json.substring(length);\n                JSONTokener tokenizer = new JSONTokener(json);\n                if (!tokenizer.more()) {\n                    throw tokenizer.syntaxError(\"Invalid App Info JSONP\");\n                }\n                Object nextValue = tokenizer.nextValue();\n                if (!(nextValue instanceof JSONObject)) {\n                    tokenizer.back();\n                    throw tokenizer.syntaxError(\"Invalid JSON value of App Info\");\n                }\n                JSONObject jsonObject = (JSONObject) nextValue;\n                Type applicationType = new TypeToken<List<Connection>>() {\n                }.getType();\n                return createGson().fromJson(jsonObject.toString(), applicationType);\n            } catch (IOException | JSONException e) {\n                throw new Auth0Exception(\"Failed to parse response to request\", e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/AuthMode.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.internal.configuration.AuthMode.LOG_IN;\nimport static com.auth0.android.lock.internal.configuration.AuthMode.SIGN_UP;\n\n@IntDef({LOG_IN, SIGN_UP})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface AuthMode {\n    int LOG_IN = 0;\n    int SIGN_UP = 1;\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/AuthType.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.internal.configuration.AuthType.DATABASE;\nimport static com.auth0.android.lock.internal.configuration.AuthType.ENTERPRISE;\nimport static com.auth0.android.lock.internal.configuration.AuthType.PASSWORDLESS;\nimport static com.auth0.android.lock.internal.configuration.AuthType.SOCIAL;\n\n@IntDef({DATABASE, ENTERPRISE, PASSWORDLESS, SOCIAL})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface AuthType {\n    int DATABASE = 0;\n    int ENTERPRISE = 1;\n    int PASSWORDLESS = 2;\n    int SOCIAL = 3;\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/BaseConnection.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\ninterface BaseConnection {\n\n    /**\n     * Getter for the connection name.\n     *\n     * @return the connection name\n     */\n    @NonNull\n    String getName();\n\n    /**\n     * Getter for the strategy name.\n     *\n     * @return the strategy name\n     */\n    @NonNull\n    String getStrategy();\n\n    /**\n     * Returns a value using its key\n     *\n     * @param key    a key\n     * @param tClazz type of value to retrieve from the map\n     * @param <T>    type of value to return\n     * @return a value\n     */\n    @Nullable\n    <T> T valueForKey(String key, Class<T> tClazz);\n\n    /**\n     * Returns a boolean value for the given key\n     *\n     * @param key a key\n     * @return a boolean value\n     */\n    boolean booleanForKey(String key);\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/Configuration.java",
    "content": "/*\n * Configuration.java\n *\n * Copyright (c) 2015 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport android.util.Log;\n\nimport com.auth0.android.lock.InitialScreen;\nimport com.auth0.android.lock.UsernameStyle;\nimport com.auth0.android.lock.utils.CustomField;\nimport com.auth0.android.lock.utils.HiddenField;\nimport com.auth0.android.lock.utils.SignUpField;\nimport com.auth0.android.lock.views.AuthConfig;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Configuration class to resolve which connections are available after parsing the local options.\n * Disclaimer: The classes in the internal package may change in the future. Don't use them directly.\n */\npublic class Configuration {\n\n    private static final String TAG = Configuration.class.getSimpleName();\n\n    private final DatabaseConnection defaultDatabaseConnection;\n    private final List<PasswordlessConnection> passwordlessConnections;\n    private final List<OAuthConnection> socialConnections;\n    private final List<OAuthConnection> enterpriseConnections;\n\n    private boolean allowLogIn;\n    private boolean allowSignUp;\n    private boolean allowForgotPassword;\n    private boolean allowShowPassword;\n    private boolean usernameRequired;\n    private boolean mustAcceptTerms;\n    private boolean showTerms;\n    private boolean useLabeledSubmitButton;\n    private boolean hideMainScreenTitle;\n    private boolean passwordlessAutoSubmit;\n    @UsernameStyle\n    private int usernameStyle;\n    private boolean loginAfterSignUp;\n    @PasswordlessMode\n    private int passwordlessMode;\n    @InitialScreen\n    private int initialScreen;\n    private String termsURL;\n    private String privacyURL;\n    private String supportURL;\n    private List<HiddenField> extraHiddenSignUpFields;\n    private List<CustomField> extraVisibleSignUpFields;\n    private Map<String, Integer> authStyles;\n    private int visibleSignUpFieldsThreshold;\n\n    public Configuration(@NonNull List<Connection> connections, @NonNull Options options) {\n        List<String> allowedConnections = options.getConnections();\n        String defaultDatabaseName = options.getDefaultDatabaseConnection();\n        Set<String> connectionSet = allowedConnections != null ? new HashSet<>(allowedConnections) : new HashSet<>();\n        this.defaultDatabaseConnection = filterDatabaseConnections(connections, connectionSet, defaultDatabaseName);\n\n        List<String> webAuthEnabledConnections = options.getEnterpriseConnectionsUsingWebForm();\n        Set<String> webAuthEnabledConnectionSet = webAuthEnabledConnections != null ? new HashSet<>(webAuthEnabledConnections) : new HashSet<>();\n        List<OAuthConnection> allEnterprise = filterConnections(connections, connectionSet, AuthType.ENTERPRISE);\n        this.enterpriseConnections = enableWebAuthentication(allEnterprise, webAuthEnabledConnectionSet);\n\n        this.passwordlessConnections = filterConnections(connections, connectionSet, AuthType.PASSWORDLESS);\n        this.socialConnections = filterConnections(connections, connectionSet, AuthType.SOCIAL);\n        parseLocalOptions(options);\n    }\n\n    @NonNull\n    public List<CustomField> getVisibleSignUpFields() {\n        return extraVisibleSignUpFields;\n    }\n\n    @NonNull\n    public List<HiddenField> getHiddenSignUpFields() {\n        return extraHiddenSignUpFields;\n    }\n\n    @Nullable\n    public DatabaseConnection getDatabaseConnection() {\n        return defaultDatabaseConnection;\n    }\n\n    @Nullable\n    public PasswordlessConnection getPasswordlessConnection() {\n        if (passwordlessConnections.isEmpty()) {\n            return null;\n        }\n\n        if (passwordlessConnections.size() == 1) {\n            return passwordlessConnections.get(0);\n        }\n\n        PasswordlessConnection connection = null;\n        for (PasswordlessConnection c : passwordlessConnections) {\n            if (c.getName().equals(\"email\")) {\n                connection = c;\n                break;\n            }\n        }\n\n        return connection != null ? connection : passwordlessConnections.get(0);\n    }\n\n    @NonNull\n    public List<OAuthConnection> getSocialConnections() {\n        return socialConnections;\n    }\n\n    @NonNull\n    public List<OAuthConnection> getEnterpriseConnections() {\n        return enterpriseConnections;\n    }\n\n    @NonNull\n    public List<PasswordlessConnection> getPasswordlessConnections() {\n        return passwordlessConnections;\n    }\n\n    @Nullable\n    private DatabaseConnection filterDatabaseConnections(@NonNull List<Connection> connections, Set<String> allowedConnections, String defaultDatabaseName) {\n        if (connections.isEmpty()) {\n            return null;\n        }\n        final List<DatabaseConnection> filteredConnections = filterConnections(connections, allowedConnections, AuthType.DATABASE);\n        for (DatabaseConnection connection : filteredConnections) {\n            if (connection.getName().equals(defaultDatabaseName)) {\n                return connection;\n            }\n        }\n        Log.w(TAG, String.format(\"You've chosen '%s' as your default database name, but it wasn't found in your Auth0 connections configuration.\", defaultDatabaseName));\n\n        return filteredConnections.isEmpty() ? null : filteredConnections.get(0);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @NonNull\n    private <T extends BaseConnection> List<T> filterConnections(@NonNull List<Connection> connections, Set<String> allowedConnections, @AuthType int type) {\n        if (connections.isEmpty()) {\n            return (List<T>) connections;\n        }\n        List<T> filtered = new ArrayList<>(connections.size());\n        for (Connection connection : connections) {\n            boolean allowed = allowedConnections.isEmpty() || allowedConnections.contains(connection.getName());\n            if (connection.getType() == type && allowed) {\n                filtered.add((T) connection);\n            }\n        }\n        return filtered;\n    }\n\n    @NonNull\n    private List<OAuthConnection> enableWebAuthentication(@NonNull List<OAuthConnection> connections, @NonNull Set<String> webAuthEnabledConnections) {\n        for (OAuthConnection c : connections) {\n            if (webAuthEnabledConnections.contains(c.getName())) {\n                ((Connection) c).disableActiveFlow();\n            }\n        }\n        return connections;\n    }\n\n    private void parseLocalOptions(Options options) {\n        usernameStyle = options.usernameStyle();\n        loginAfterSignUp = options.loginAfterSignUp();\n        mustAcceptTerms = options.mustAcceptTerms();\n        showTerms = options.showTerms();\n        useLabeledSubmitButton = options.useLabeledSubmitButton();\n        hideMainScreenTitle = options.hideMainScreenTitle();\n        passwordlessAutoSubmit = options.rememberLastPasswordlessAccount();\n        visibleSignUpFieldsThreshold = options.visibleSignUpFieldsThreshold();\n\n        authStyles = options.getAuthStyles();\n        extraHiddenSignUpFields = new ArrayList<>();\n        extraVisibleSignUpFields = new ArrayList<>();\n        boolean hasSignUpFields = options.getSignUpFields() != null;\n        if (hasSignUpFields) {\n            for (SignUpField sf : options.getSignUpFields()) {\n                if (sf instanceof HiddenField) {\n                    extraHiddenSignUpFields.add((HiddenField) sf);\n                } else {\n                    extraVisibleSignUpFields.add((CustomField) sf);\n                }\n            }\n        }\n\n        if (getDatabaseConnection() != null) {\n            allowLogIn = options.allowLogIn();\n            allowSignUp = options.allowSignUp() && getDatabaseConnection().showSignUp();\n            //let user disable password reset only if connection have enabled it.\n            allowForgotPassword = getDatabaseConnection().showForgot() && options.allowForgotPassword();\n            usernameRequired = getDatabaseConnection().requiresUsername();\n\n            initialScreen = options.initialScreen();\n        }\n\n        allowShowPassword = options.allowShowPassword();\n        passwordlessMode = parsePasswordlessMode(options.useCodePasswordless());\n\n        this.termsURL = options.getTermsURL() == null ? \"https://auth0.com/terms\" : options.getTermsURL();\n        this.privacyURL = options.getPrivacyURL() == null ? \"https://auth0.com/privacy\" : options.getPrivacyURL();\n        this.supportURL = options.getSupportURL();\n    }\n\n    @StyleRes\n    public int authStyleForConnection(@NonNull String strategy, @NonNull String connection) {\n        if (authStyles.containsKey(connection)) {\n            return authStyles.get(connection);\n        }\n        return AuthConfig.styleForStrategy(strategy);\n    }\n\n    @PasswordlessMode\n    private int parsePasswordlessMode(boolean requestCode) {\n        int mode = PasswordlessMode.DISABLED;\n        PasswordlessConnection connection = getPasswordlessConnection();\n        if (connection != null) {\n            if (connection.getName().equals(\"email\")) {\n                mode = requestCode ? PasswordlessMode.EMAIL_CODE : PasswordlessMode.EMAIL_LINK;\n            } else if (connection.getName().equals(\"sms\")) {\n                mode = requestCode ? PasswordlessMode.SMS_CODE : PasswordlessMode.SMS_LINK;\n            }\n        }\n        return mode;\n    }\n\n    public boolean allowLogIn() {\n        return allowLogIn;\n    }\n\n    public boolean allowSignUp() {\n        return allowSignUp;\n    }\n\n    public boolean allowForgotPassword() {\n        return allowForgotPassword;\n    }\n\n    public boolean allowShowPassword() {\n        return allowShowPassword;\n    }\n\n    public boolean isUsernameRequired() {\n        return usernameRequired;\n    }\n\n    @InitialScreen\n    public int getInitialScreen() {\n        return initialScreen;\n    }\n\n    @UsernameStyle\n    public int getUsernameStyle() {\n        return usernameStyle;\n    }\n\n    @PasswordlessMode\n    public int getPasswordlessMode() {\n        return passwordlessMode;\n    }\n\n    @NonNull\n    public PasswordComplexity getPasswordComplexity() {\n        return defaultDatabaseConnection == null ? new PasswordComplexity(PasswordStrength.NONE, null) : defaultDatabaseConnection.getPasswordComplexity();\n    }\n\n    public boolean loginAfterSignUp() {\n        return loginAfterSignUp;\n    }\n\n    public boolean hasClassicConnections() {\n        return !socialConnections.isEmpty() || !enterpriseConnections.isEmpty() || defaultDatabaseConnection != null;\n    }\n\n    public boolean hasPasswordlessConnections() {\n        return !socialConnections.isEmpty() || !passwordlessConnections.isEmpty();\n    }\n\n    @NonNull\n    public String getTermsURL() {\n        return termsURL;\n    }\n\n    @NonNull\n    public String getPrivacyURL() {\n        return privacyURL;\n    }\n\n    @Nullable\n    public String getSupportURL() {\n        return supportURL;\n    }\n\n    public boolean mustAcceptTerms() {\n        return mustAcceptTerms;\n    }\n\n    public boolean showTerms() {\n        return showTerms;\n    }\n\n    public boolean useLabeledSubmitButton() {\n        return useLabeledSubmitButton;\n    }\n\n    public boolean hideMainScreenTitle() {\n        return hideMainScreenTitle;\n    }\n\n    public boolean usePasswordlessAutoSubmit() {\n        return passwordlessAutoSubmit;\n    }\n\n    public int getVisibleSignUpFieldsThreshold() {\n        return visibleSignUpFieldsThreshold;\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/Connection.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n\npublic class Connection implements BaseConnection, DatabaseConnection, OAuthConnection, PasswordlessConnection {\n\n    private final String strategy;\n    private final String name;\n    private final Map<String, Object> values;\n    private int minUsernameLength;\n    private int maxUsernameLength;\n    private boolean isCustomDatabase;\n    private boolean allowActiveFlow = true;\n    private PasswordComplexity passwordComplexity;\n\n    private Connection(@NonNull String strategy, Map<String, Object> values) {\n        if (values == null || values.isEmpty()) {\n            throw new IllegalArgumentException(\"Must have at least one value\");\n        }\n        final String name = (String) values.remove(\"name\");\n        if (name == null) {\n            throw new IllegalArgumentException(\"Must have a non-null name\");\n        }\n        this.strategy = strategy;\n        this.name = name;\n        this.values = values;\n        parseUsernameLength();\n        parsePasswordComplexity();\n    }\n\n    private void parsePasswordComplexity() {\n        int policy = PasswordStrength.NONE;\n        String value = valueForKey(\"passwordPolicy\", String.class);\n        if (\"excellent\".equals(value)) {\n            policy = PasswordStrength.EXCELLENT;\n        }\n        if (\"good\".equals(value)) {\n            policy = PasswordStrength.GOOD;\n        }\n        if (\"fair\".equals(value)) {\n            policy = PasswordStrength.FAIR;\n        }\n        if (\"low\".equals(value)) {\n            policy = PasswordStrength.LOW;\n        }\n\n        //noinspection unchecked\n        final Map<String, Object> complexityOptions = valueForKey(\"password_complexity_options\", Map.class);\n        Integer minLength = null;\n        if (complexityOptions != null && complexityOptions.containsKey(\"min_length\")) {\n            minLength = ((Number) complexityOptions.remove(\"min_length\")).intValue();\n        }\n        passwordComplexity = new PasswordComplexity(policy, minLength);\n    }\n\n    @NonNull\n    @Override\n    public String getName() {\n        return name;\n    }\n\n    @NonNull\n    @Override\n    public String getStrategy() {\n        return strategy;\n    }\n\n    /**\n     * Getter for the Type of Connection\n     *\n     * @return the connection Type.\n     */\n    @AuthType\n    int getType() {\n        switch (strategy) {\n            case \"auth0\":\n                return AuthType.DATABASE;\n            case \"sms\":\n            case \"email\":\n                return AuthType.PASSWORDLESS;\n            case \"ad\":\n            case \"adfs\":\n            case \"auth0-adldap\":\n            case \"custom\":\n            case \"google-apps\":\n            case \"google-openid\":\n            case \"ip\":\n            case \"mscrm\":\n            case \"office365\":\n            case \"pingfederate\":\n            case \"samlp\":\n            case \"sharepoint\":\n            case \"waad\":\n                return AuthType.ENTERPRISE;\n            default:\n                return AuthType.SOCIAL;\n        }\n    }\n\n    @Nullable\n    public <T> T valueForKey(@NonNull String key, @NonNull Class<T> tClazz) {\n        final Object value = this.values.get(key);\n        return tClazz.isInstance(value) ? tClazz.cast(value) : null;\n    }\n\n    @Override\n    public boolean booleanForKey(@NonNull String key) {\n        final Boolean value = valueForKey(key, Boolean.class);\n        return value != null && value;\n    }\n\n    @Override\n    @NonNull\n    public PasswordComplexity getPasswordComplexity() {\n        return passwordComplexity;\n    }\n\n    @Override\n    public boolean requiresUsername() {\n        return booleanForKey(\"requires_username\");\n    }\n\n    @Override\n    public boolean showSignUp() {\n        return booleanForKey(\"showSignup\");\n    }\n\n    @Override\n    public boolean showForgot() {\n        return booleanForKey(\"showForgot\");\n    }\n\n    @Override\n    public int getMinUsernameLength() {\n        return minUsernameLength;\n    }\n\n    @Override\n    public int getMaxUsernameLength() {\n        return maxUsernameLength;\n    }\n\n    @Override\n    public boolean isCustomDatabase() {\n        return isCustomDatabase;\n    }\n\n    @Override\n    public boolean isActiveFlowEnabled() {\n        return allowActiveFlow && (\"ad\".equals(getStrategy()) || \"adfs\".equals(getStrategy()) || \"waad\".equals(getStrategy()));\n    }\n\n    void disableActiveFlow() {\n        this.allowActiveFlow = false;\n    }\n\n    @Override\n    @NonNull\n    public Set<String> getDomainSet() {\n        Set<String> domains = new HashSet<>();\n        String domain = valueForKey(\"domain\", String.class);\n        if (domain != null) {\n            domains.add(domain.toLowerCase());\n            //noinspection unchecked\n            List<String> aliases = valueForKey(\"domain_aliases\", List.class);\n            if (aliases != null) {\n                for (String alias : aliases) {\n                    domains.add(alias.toLowerCase());\n                }\n            }\n        }\n        return domains;\n    }\n\n    /**\n     * Creates a new Connection given a Strategy name and the map of values.\n     *\n     * @param strategy strategy name for this connection\n     * @param values   additional values associated to this connection\n     * @return a new instance of Connection. Can be either DatabaseConnection, PasswordlessConnection or OAuthConnection.\n     */\n    static Connection newConnectionFor(@NonNull String strategy, Map<String, Object> values) {\n        return new Connection(strategy, values);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private void parseUsernameLength() {\n        Map<String, Object> validations = valueForKey(\"validation\", Map.class);\n        if (validations == null || !validations.containsKey(\"username\")) {\n            isCustomDatabase = true;\n            minUsernameLength = 1;\n            maxUsernameLength = Integer.MAX_VALUE;\n            return;\n        }\n\n        final Map<String, Object> usernameValidation = (Map<String, Object>) validations.get(\"username\");\n        minUsernameLength = intValue(usernameValidation.get(\"min\"));\n        maxUsernameLength = intValue(usernameValidation.get(\"max\"));\n        if (minUsernameLength < 1 || maxUsernameLength < 1 || minUsernameLength > maxUsernameLength) {\n            minUsernameLength = 1;\n            maxUsernameLength = Integer.MAX_VALUE;\n        }\n    }\n\n    /**\n     * Will try to get the int value of a given object. If the value cannot be obtained, it will return the default value.\n     *\n     * @param object to get an int from.\n     * @return the int value of the object or 0 if it cannot be obtained.\n     */\n    private int intValue(@Nullable Object object) {\n        if (object instanceof Number) {\n            return ((Number) object).intValue();\n        }\n        if (object instanceof String) {\n            return Integer.parseInt((String) object, 10);\n        }\n        return 0;\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/DatabaseConnection.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.NonNull;\n\npublic interface DatabaseConnection extends BaseConnection {\n\n    int MIN_USERNAME_LENGTH = 1;\n    int MAX_USERNAME_LENGTH = 15;\n\n    /**\n     * Getter for the Password Validation settings\n     *\n     * @return The Password Validation for this connection.\n     */\n    @NonNull\n    PasswordComplexity getPasswordComplexity();\n\n    /**\n     * Whether this connection requires username or not.\n     *\n     * @return true if this connection requires username.\n     */\n    boolean requiresUsername();\n\n    /**\n     * Whether this connection is allowed to show the Sign Up screen.\n     *\n     * @return true if this connection can show the Sign Up screen.\n     */\n    boolean showSignUp();\n\n    /**\n     * Whether this connection is allowed to show the Forgot Password screen.\n     *\n     * @return true if this connection can show the Forgot Password screen.\n     */\n    boolean showForgot();\n\n    /**\n     * Getter for the minimum username length. Will default to 1 if not available.\n     *\n     * @return the minimum username length.\n     */\n    int getMinUsernameLength();\n\n    /**\n     * Getter for the maximum username length. Will default to 15 if not available.\n     *\n     * @return the maximum username length.\n     */\n    int getMaxUsernameLength();\n\n    /**\n     * Whether this connection is a Custom/Imported Database.\n     *\n     * @return true if this connection is a Custom/Imported Database.\n     */\n    boolean isCustomDatabase();\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/GsonDeserializer.java",
    "content": "/*\n * JsonUtils.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.google.gson.JsonDeserializationContext;\nimport com.google.gson.JsonDeserializer;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParseException;\n\nimport java.lang.reflect.Type;\n\nabstract class GsonDeserializer<T> implements JsonDeserializer<T> {\n\n    <U> U requiredValue(String name, Type type, JsonObject object, JsonDeserializationContext context) throws JsonParseException {\n        U value = context.deserialize(object.get(name), type);\n        if (value == null) {\n            throw new JsonParseException(String.format(\"Missing required attribute %s\", name));\n        }\n        return value;\n    }\n\n    void assertJsonObject(JsonElement jsonObject) throws JsonParseException {\n        if (jsonObject.isJsonNull() || !jsonObject.isJsonObject()) {\n            throw new JsonParseException(\"Received json is not a valid json object.\");\n        }\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/OAuthConnection.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.NonNull;\n\nimport java.util.Set;\n\npublic interface OAuthConnection extends BaseConnection {\n\n    /**\n     * Returns if this Connection can use Resource Owner to authenticate\n     *\n     * @return if the Active Flow (Resource Owner) is enabled.\n     */\n    boolean isActiveFlowEnabled();\n\n    /**\n     * If this connection is of type Enterprise it will return the configured Domains.\n     *\n     * @return a set with all domains configured\n     */\n    @NonNull\n    Set<String> getDomainSet();\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/Options.java",
    "content": "/*\n * LockOptions.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport android.annotation.SuppressLint;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.util.Patterns;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.lock.Auth0Parcelable;\nimport com.auth0.android.lock.InitialScreen;\nimport com.auth0.android.lock.UsernameStyle;\nimport com.auth0.android.lock.utils.SignUpField;\nimport com.auth0.android.provider.CustomTabsOptions;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Helper class to resolve Local settings for configuring the Lock Widget.\n * <p>\n * Disclaimer: The classes in the internal package may change in the future. Don't use them directly.\n */\n@SuppressLint(\"KotlinPropertyAccess\")\npublic class Options implements Parcelable {\n    private static final int WITHOUT_DATA = 0x00;\n    private static final int HAS_DATA = 0x01;\n    private static final int DEFAULT_VISIBLE_SIGN_UP_FIELDS_THRESHOLD = 2;\n    private static final String KEY_AUTHENTICATION_PARAMETERS = \"authenticationParameters\";\n    private static final String KEY_CONNECTIONS_SCOPE = \"connectionsScope\";\n    private static final String SCOPE_KEY = \"scope\";\n    private static final String DEVICE_KEY = \"device\";\n    private static final String SCOPE_OFFLINE_ACCESS = \"offline_access\";\n\n    private Auth0 account;\n    private boolean closable;\n    private int usernameStyle;\n    private boolean useCodePasswordless;\n    private boolean allowLogIn;\n    private boolean allowSignUp;\n    private boolean allowForgotPassword;\n    private boolean allowShowPassword;\n    private boolean loginAfterSignUp;\n    private boolean mustAcceptTerms;\n    private boolean showTerms;\n    private boolean useLabeledSubmitButton;\n    private boolean hideMainScreenTitle;\n    private boolean rememberLastPasswordlessLogin;\n    private String defaultDatabaseConnection;\n    private List<String> connections;\n    private List<String> enterpriseConnectionsUsingWebForm;\n    private final HashMap<String, Integer> authStyles;\n    private HashMap<String, String> authenticationParameters;\n    private final HashMap<String, String> connectionsScope;\n    private List<SignUpField> signUpFields;\n    private int initialScreen;\n    private int visibleSignUpFieldsthreshold;\n    private Theme theme;\n    private CustomTabsOptions customTabsOptions;\n    private String privacyURL;\n    private String termsURL;\n    private String supportURL;\n    private String scope;\n    private String audience;\n    private String scheme;\n\n    public Options() {\n        usernameStyle = UsernameStyle.DEFAULT;\n        initialScreen = InitialScreen.LOG_IN;\n        visibleSignUpFieldsthreshold = DEFAULT_VISIBLE_SIGN_UP_FIELDS_THRESHOLD;\n        allowLogIn = true;\n        allowSignUp = true;\n        allowForgotPassword = true;\n        allowShowPassword = true;\n        loginAfterSignUp = true;\n        showTerms = true;\n        useCodePasswordless = true;\n        useLabeledSubmitButton = true;\n        authenticationParameters = new HashMap<>();\n        authStyles = new HashMap<>();\n        connectionsScope = new HashMap<>();\n        signUpFields = new ArrayList<>();\n        theme = Theme.newBuilder().build();\n    }\n\n    protected Options(@NonNull Parcel in) {\n        Auth0Parcelable auth0Parcelable = (Auth0Parcelable) in.readValue(Auth0Parcelable.class.getClassLoader());\n        account = auth0Parcelable.getAuth0();\n        closable = in.readByte() != WITHOUT_DATA;\n        allowLogIn = in.readByte() != WITHOUT_DATA;\n        allowSignUp = in.readByte() != WITHOUT_DATA;\n        allowForgotPassword = in.readByte() != WITHOUT_DATA;\n        allowShowPassword = in.readByte() != WITHOUT_DATA;\n        loginAfterSignUp = in.readByte() != WITHOUT_DATA;\n        mustAcceptTerms = in.readByte() != WITHOUT_DATA;\n        showTerms = in.readByte() != WITHOUT_DATA;\n        useCodePasswordless = in.readByte() != WITHOUT_DATA;\n        useLabeledSubmitButton = in.readByte() != WITHOUT_DATA;\n        hideMainScreenTitle = in.readByte() != WITHOUT_DATA;\n        rememberLastPasswordlessLogin = in.readByte() != WITHOUT_DATA;\n        defaultDatabaseConnection = in.readString();\n        usernameStyle = in.readInt();\n        initialScreen = in.readInt();\n        visibleSignUpFieldsthreshold = in.readInt();\n        theme = in.readParcelable(Theme.class.getClassLoader());\n        customTabsOptions = in.readParcelable(CustomTabsOptions.class.getClassLoader());\n        privacyURL = in.readString();\n        termsURL = in.readString();\n        supportURL = in.readString();\n        scope = in.readString();\n        audience = in.readString();\n        scheme = in.readString();\n        if (in.readByte() == HAS_DATA) {\n            connections = new ArrayList<>();\n            in.readList(connections, String.class.getClassLoader());\n        } else {\n            connections = null;\n        }\n        if (in.readByte() == HAS_DATA) {\n            enterpriseConnectionsUsingWebForm = new ArrayList<>();\n            in.readList(enterpriseConnectionsUsingWebForm, String.class.getClassLoader());\n        } else {\n            enterpriseConnectionsUsingWebForm = null;\n        }\n        if (in.readByte() == HAS_DATA) {\n            // FIXME this is something to improve\n            Bundle mapBundle = in.readBundle(getClass().getClassLoader());\n            authenticationParameters = (HashMap<String, String>) mapBundle.getSerializable(KEY_AUTHENTICATION_PARAMETERS);\n        } else {\n            authenticationParameters = null;\n        }\n        if (in.readByte() == HAS_DATA) {\n            List<String> authStylesKeys = new ArrayList<>();\n            List<Integer> authStylesValues = new ArrayList<>();\n            in.readList(authStylesKeys, String.class.getClassLoader());\n            in.readList(authStylesValues, Integer.class.getClassLoader());\n            authStyles = new HashMap<>();\n            for (int i = 0; i < authStylesKeys.size(); i++) {\n                authStyles.put(authStylesKeys.get(i), authStylesValues.get(i));\n            }\n        } else {\n            authStyles = null;\n        }\n        if (in.readByte() == HAS_DATA) {\n            // FIXME this is something to improve\n            Bundle mapBundle = in.readBundle(getClass().getClassLoader());\n            connectionsScope = (HashMap<String, String>) mapBundle.getSerializable(KEY_CONNECTIONS_SCOPE);\n        } else {\n            connectionsScope = null;\n        }\n        if (in.readByte() == HAS_DATA) {\n            signUpFields = new ArrayList<>();\n            in.readList(signUpFields, SignUpField.class.getClassLoader());\n        } else {\n            signUpFields = null;\n        }\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(@NonNull Parcel dest, int flags) {\n        dest.writeValue(new Auth0Parcelable(account));\n        dest.writeByte((byte) (closable ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (allowLogIn ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (allowSignUp ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (allowForgotPassword ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (allowShowPassword ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (loginAfterSignUp ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (mustAcceptTerms ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (showTerms ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (useCodePasswordless ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (useLabeledSubmitButton ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (hideMainScreenTitle ? HAS_DATA : WITHOUT_DATA));\n        dest.writeByte((byte) (rememberLastPasswordlessLogin ? HAS_DATA : WITHOUT_DATA));\n        dest.writeString(defaultDatabaseConnection);\n        dest.writeInt(usernameStyle);\n        dest.writeInt(initialScreen);\n        dest.writeInt(visibleSignUpFieldsthreshold);\n        dest.writeParcelable(theme, flags);\n        dest.writeParcelable(customTabsOptions, flags);\n        dest.writeString(privacyURL);\n        dest.writeString(termsURL);\n        dest.writeString(supportURL);\n        dest.writeString(scope);\n        dest.writeString(audience);\n        dest.writeString(scheme);\n        if (connections == null) {\n            dest.writeByte((byte) (WITHOUT_DATA));\n        } else {\n            dest.writeByte((byte) (HAS_DATA));\n            dest.writeList(connections);\n        }\n        if (enterpriseConnectionsUsingWebForm == null) {\n            dest.writeByte((byte) (WITHOUT_DATA));\n        } else {\n            dest.writeByte((byte) (HAS_DATA));\n            dest.writeList(enterpriseConnectionsUsingWebForm);\n        }\n        if (authenticationParameters == null) {\n            dest.writeByte((byte) (WITHOUT_DATA));\n        } else {\n            dest.writeByte((byte) (HAS_DATA));\n            // FIXME this is something to improve\n            Bundle mapBundle = new Bundle();\n            mapBundle.putSerializable(KEY_AUTHENTICATION_PARAMETERS, authenticationParameters);\n            dest.writeBundle(mapBundle);\n        }\n        if (authStyles == null) {\n            dest.writeByte((byte) (WITHOUT_DATA));\n        } else {\n            dest.writeByte((byte) (HAS_DATA));\n            dest.writeList(new ArrayList<>(authStyles.keySet()));\n            dest.writeList(new ArrayList<>(authStyles.values()));\n        }\n        if (connectionsScope == null) {\n            dest.writeByte((byte) (WITHOUT_DATA));\n        } else {\n            dest.writeByte((byte) (HAS_DATA));\n            // FIXME this is something to improve\n            Bundle mapBundle = new Bundle();\n            mapBundle.putSerializable(KEY_CONNECTIONS_SCOPE, connectionsScope);\n            dest.writeBundle(mapBundle);\n        }\n        if (signUpFields == null) {\n            dest.writeByte((byte) (WITHOUT_DATA));\n        } else {\n            dest.writeByte((byte) (HAS_DATA));\n            dest.writeList(signUpFields);\n        }\n    }\n\n    public static final Parcelable.Creator<Options> CREATOR = new Parcelable.Creator<Options>() {\n        @Override\n        public Options createFromParcel(Parcel in) {\n            return new Options(in);\n        }\n\n        @Override\n        public Options[] newArray(int size) {\n            return new Options[size];\n        }\n    };\n\n    @NonNull\n    public Auth0 getAccount() {\n        return account;\n    }\n\n    public void setAccount(@NonNull Auth0 account) {\n        this.account = account;\n    }\n\n    public void withTheme(@NonNull Theme theme) {\n        this.theme = theme;\n    }\n\n    @NonNull\n    public Theme getTheme() {\n        return theme;\n    }\n\n    public boolean isClosable() {\n        return closable;\n    }\n\n    public void setClosable(boolean closable) {\n        this.closable = closable;\n    }\n\n    @UsernameStyle\n    public int usernameStyle() {\n        return usernameStyle;\n    }\n\n    public void setUsernameStyle(@UsernameStyle int usernameStyle) {\n        this.usernameStyle = usernameStyle;\n    }\n\n    public void setAllowLogIn(boolean allowLogIn) {\n        this.allowLogIn = allowLogIn;\n    }\n\n    public boolean allowLogIn() {\n        return allowLogIn;\n    }\n\n    public boolean allowSignUp() {\n        return allowSignUp;\n    }\n\n    public void setAllowSignUp(boolean allowSignUp) {\n        this.allowSignUp = allowSignUp;\n    }\n\n    public void setAllowForgotPassword(boolean allowForgotPassword) {\n        this.allowForgotPassword = allowForgotPassword;\n    }\n\n    public boolean allowForgotPassword() {\n        return allowForgotPassword;\n    }\n\n    public boolean allowShowPassword() {\n        return allowShowPassword;\n    }\n\n    public void setAllowShowPassword(boolean allow) {\n        allowShowPassword = allow;\n    }\n\n    @Nullable\n    public String getDefaultDatabaseConnection() {\n        return defaultDatabaseConnection;\n    }\n\n    public void useDatabaseConnection(@NonNull String defaultDatabaseConnection) {\n        this.defaultDatabaseConnection = defaultDatabaseConnection;\n    }\n\n    @Nullable\n    public List<String> getConnections() {\n        return connections;\n    }\n\n    public void setConnections(@NonNull List<String> connections) {\n        this.connections = connections;\n    }\n\n    @Nullable\n    public List<String> getEnterpriseConnectionsUsingWebForm() {\n        return enterpriseConnectionsUsingWebForm;\n    }\n\n    public void setEnterpriseConnectionsUsingWebForm(@NonNull List<String> enterpriseConnectionsUsingWebForm) {\n        this.enterpriseConnectionsUsingWebForm = enterpriseConnectionsUsingWebForm;\n    }\n\n    @Nullable\n    public HashMap<String, String> getAuthenticationParameters() {\n        return authenticationParameters;\n    }\n\n    public void setAuthenticationParameters(@NonNull HashMap<String, String> authenticationParameters) {\n        final String scope = authenticationParameters.get(SCOPE_KEY);\n        final String device = authenticationParameters.get(DEVICE_KEY);\n\n        if (scope != null && scope.contains(SCOPE_OFFLINE_ACCESS) && device == null) {\n            authenticationParameters.put(DEVICE_KEY, Build.MODEL);\n        }\n        this.authenticationParameters = authenticationParameters;\n    }\n\n    public boolean loginAfterSignUp() {\n        return loginAfterSignUp;\n    }\n\n    public void setLoginAfterSignUp(boolean loginAfterSignUp) {\n        this.loginAfterSignUp = loginAfterSignUp;\n    }\n\n    @NonNull\n    public AuthenticationAPIClient getAuthenticationAPIClient() {\n        return new AuthenticationAPIClient(account);\n    }\n\n    public void setUseCodePasswordless(boolean useCode) {\n        this.useCodePasswordless = useCode;\n    }\n\n    public boolean useCodePasswordless() {\n        return this.useCodePasswordless;\n    }\n\n    public void setSignUpFields(@NonNull List<SignUpField> signUpFields) {\n        this.signUpFields = signUpFields;\n    }\n\n    @Nullable\n    public List<SignUpField> getSignUpFields() {\n        return signUpFields;\n    }\n\n    public void setInitialScreen(@InitialScreen int screen) {\n        this.initialScreen = screen;\n    }\n\n    @InitialScreen\n    public int initialScreen() {\n        return initialScreen;\n    }\n\n    public void setPrivacyURL(@NonNull String url) throws IllegalArgumentException {\n        if (!Patterns.WEB_URL.matcher(url).matches()) {\n            throw new IllegalArgumentException(\"The given Policy Privacy URL doesn't have a valid URL format: \" + url);\n        }\n        this.privacyURL = url;\n    }\n\n    @Nullable\n    public String getPrivacyURL() {\n        return privacyURL;\n    }\n\n    public void setTermsURL(@NonNull String url) throws IllegalArgumentException {\n        if (!Patterns.WEB_URL.matcher(url).matches()) {\n            throw new IllegalArgumentException(\"The given Terms of Service URL doesn't have a valid URL format: \" + url);\n        }\n        this.termsURL = url;\n    }\n\n    @Nullable\n    public String getTermsURL() {\n        return termsURL;\n    }\n\n    public void setSupportURL(@NonNull String url) {\n        if (!Patterns.WEB_URL.matcher(url).matches()) {\n            throw new IllegalArgumentException(\"The given Support URL doesn't have a valid URL format: \" + url);\n        }\n        this.supportURL = url;\n    }\n\n    @Nullable\n    public String getSupportURL() {\n        return supportURL;\n    }\n\n    public void setMustAcceptTerms(boolean mustAcceptTerms) {\n        this.mustAcceptTerms = mustAcceptTerms;\n    }\n\n    public boolean mustAcceptTerms() {\n        return mustAcceptTerms;\n    }\n\n    public void setShowTerms(boolean showTerms) {\n        this.showTerms = showTerms;\n    }\n\n    public boolean showTerms() {\n        return showTerms;\n    }\n\n    public void withAuthStyle(@NonNull String connectionName, @StyleRes int style) {\n        authStyles.put(connectionName, style);\n    }\n\n    @Nullable\n    public Map<String, Integer> getAuthStyles() {\n        return new HashMap<>(authStyles);\n    }\n\n    public void setUseLabeledSubmitButton(boolean useLabeledSubmitButton) {\n        this.useLabeledSubmitButton = useLabeledSubmitButton;\n    }\n\n    public boolean useLabeledSubmitButton() {\n        return useLabeledSubmitButton;\n    }\n\n    public void setHideMainScreenTitle(boolean hideMainScreenTitle) {\n        this.hideMainScreenTitle = hideMainScreenTitle;\n    }\n\n    public boolean hideMainScreenTitle() {\n        return hideMainScreenTitle;\n    }\n\n    public void setRememberLastPasswordlessLogin(boolean remember) {\n        this.rememberLastPasswordlessLogin = remember;\n    }\n\n    public boolean rememberLastPasswordlessAccount() {\n        return rememberLastPasswordlessLogin;\n    }\n\n    public void withConnectionScope(@NonNull String connectionName, @NonNull String scope) {\n        connectionsScope.put(connectionName, scope);\n    }\n\n    @Nullable\n    public Map<String, String> getConnectionsScope() {\n        return connectionsScope;\n    }\n\n    public void withScope(@NonNull String scope) {\n        this.scope = scope;\n    }\n\n    @Nullable\n    public String getScope() {\n        return scope;\n    }\n\n    public void withAudience(@NonNull String audience) {\n        this.audience = audience;\n    }\n\n    @Nullable\n    public String getAudience() {\n        return audience;\n    }\n\n    public void withScheme(@NonNull String scheme) {\n        this.scheme = scheme;\n    }\n\n    @Nullable\n    public String getScheme() {\n        return scheme;\n    }\n\n    public void setVisibleSignUpFieldsThreshold(int threshold) {\n        this.visibleSignUpFieldsthreshold = threshold;\n    }\n\n    public int visibleSignUpFieldsThreshold() {\n        return visibleSignUpFieldsthreshold;\n    }\n\n    public void withCustomTabsOptions(@NonNull CustomTabsOptions customTabsOptions) {\n        this.customTabsOptions = customTabsOptions;\n    }\n\n    @Nullable\n    public CustomTabsOptions getCustomTabsOptions() {\n        return customTabsOptions;\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/PasswordComplexity.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.Nullable;\n\npublic class PasswordComplexity {\n\n    private final int policy;\n    private final Integer minLengthOverride;\n\n    public PasswordComplexity(@PasswordStrength int policy, @Nullable Integer minLengthOverride) {\n        this.policy = policy;\n        this.minLengthOverride = minLengthOverride;\n    }\n\n    /**\n     * Getter for the Password Policy associated to this connection.\n     *\n     * @return the Password Policy level for this connection.\n     */\n    @PasswordStrength\n    public int getPasswordPolicy() {\n        return policy;\n    }\n\n    /**\n     * Getter for the minimum length the password requires\n     *\n     * @return the minimum length the password requires\n     */\n    @Nullable\n    public Integer getMinLengthOverride() {\n        return minLengthOverride;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/PasswordStrength.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.internal.configuration.PasswordStrength.EXCELLENT;\nimport static com.auth0.android.lock.internal.configuration.PasswordStrength.FAIR;\nimport static com.auth0.android.lock.internal.configuration.PasswordStrength.GOOD;\nimport static com.auth0.android.lock.internal.configuration.PasswordStrength.LOW;\nimport static com.auth0.android.lock.internal.configuration.PasswordStrength.NONE;\n\n@IntDef({NONE, LOW, FAIR, GOOD, EXCELLENT})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface PasswordStrength {\n    int NONE = 0;\n    int LOW = 1;\n    int FAIR = 2;\n    int GOOD = 3;\n    int EXCELLENT = 4;\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/PasswordlessConnection.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\npublic interface PasswordlessConnection extends BaseConnection {\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/PasswordlessMode.java",
    "content": "/*\n * PasswordlessMode.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.DISABLED;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_LINK;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_LINK;\n\n@IntDef({DISABLED, SMS_LINK, SMS_CODE, EMAIL_LINK, EMAIL_CODE})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface PasswordlessMode {\n    int DISABLED = 0;\n    int SMS_LINK = 1;\n    int SMS_CODE = 2;\n    int EMAIL_LINK = 3;\n    int EMAIL_CODE = 4;\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/internal/configuration/Theme.java",
    "content": "/*\n * Theme.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.ColorInt;\nimport androidx.annotation.ColorRes;\nimport androidx.annotation.DrawableRes;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.StringRes;\nimport androidx.core.content.ContextCompat;\nimport android.util.TypedValue;\n\nimport com.auth0.android.lock.R;\n\n/**\n * Helper class to resolve Lock.Theme values.\n * <p>\n * Disclaimer: The classes in the internal package may change in the future. Don't use them directly.\n */\npublic class Theme implements Parcelable {\n\n    private final int headerTitle;\n    private final int headerLogo;\n    private final int headerColor;\n    private final int headerTitleColor;\n    private final int primaryColor;\n    private final int darkPrimaryColor;\n\n    private Theme(int headerTitle, int headerLogo, int headerColor, int headerTitleColor, int primaryColor, int darkPrimaryColor) {\n        this.headerTitle = headerTitle;\n        this.headerLogo = headerLogo;\n        this.headerColor = headerColor;\n        this.headerTitleColor = headerTitleColor;\n        this.primaryColor = primaryColor;\n        this.darkPrimaryColor = darkPrimaryColor;\n    }\n\n    @SuppressLint(\"ResourceType\")\n    private String resolveStringResource(Context context, @StringRes int res, @AttrRes int attrName) {\n        if (res > 0) {\n            return context.getString(res);\n        }\n\n        TypedValue typedValue = new TypedValue();\n        context.getTheme().resolveAttribute(attrName, typedValue, true);\n        return context.getString(typedValue.resourceId);\n    }\n\n    @SuppressLint(\"ResourceType\")\n    @ColorInt\n    private int resolveColorResource(Context context, @ColorRes int res, @AttrRes int attrName) {\n        if (res > 0) {\n            return ContextCompat.getColor(context, res);\n        }\n\n        TypedValue typedValue = new TypedValue();\n        context.getTheme().resolveAttribute(attrName, typedValue, true);\n        return ContextCompat.getColor(context, typedValue.resourceId);\n    }\n\n    @SuppressLint(\"ResourceType\")\n    private Drawable resolveDrawableResource(Context context, @DrawableRes int res, @AttrRes int attrName) {\n        if (res > 0) {\n            return ContextCompat.getDrawable(context, res);\n        }\n\n        TypedValue typedValue = new TypedValue();\n        context.getTheme().resolveAttribute(attrName, typedValue, true);\n        return ContextCompat.getDrawable(context, typedValue.resourceId);\n    }\n\n    @NonNull\n    public String getHeaderTitle(@NonNull Context context) {\n        return resolveStringResource(context, headerTitle, R.attr.Auth0_HeaderTitle);\n    }\n\n    @NonNull\n    public Drawable getHeaderLogo(@NonNull Context context) {\n        return resolveDrawableResource(context, headerLogo, R.attr.Auth0_HeaderLogo);\n    }\n\n    @ColorInt\n    public int getHeaderColor(@NonNull Context context) {\n        return resolveColorResource(context, headerColor, R.attr.Auth0_HeaderBackground);\n    }\n\n    @ColorInt\n    public int getHeaderTitleColor(@NonNull Context context) {\n        return resolveColorResource(context, headerTitleColor, R.attr.Auth0_HeaderTitleColor);\n    }\n\n    @ColorInt\n    public int getPrimaryColor(@NonNull Context context) {\n        return resolveColorResource(context, primaryColor, R.attr.Auth0_PrimaryColor);\n    }\n\n    @ColorInt\n    public int getDarkPrimaryColor(@NonNull Context context) {\n        return resolveColorResource(context, darkPrimaryColor, R.attr.Auth0_DarkPrimaryColor);\n    }\n\n    int getCustomHeaderTitleRes() {\n        return headerTitle;\n    }\n\n    int getCustomHeaderLogoRes() {\n        return headerLogo;\n    }\n\n    int getCustomHeaderColorRes() {\n        return headerColor;\n    }\n\n    int getCustomHeaderTitleColorRes() {\n        return headerTitleColor;\n    }\n\n    int getCustomPrimaryColorRes() {\n        return primaryColor;\n    }\n\n    int getCustomDarkPrimaryColorRes() {\n        return darkPrimaryColor;\n    }\n\n    protected Theme(@NonNull Parcel in) {\n        headerTitle = in.readInt();\n        headerLogo = in.readInt();\n        headerColor = in.readInt();\n        headerTitleColor = in.readInt();\n        primaryColor = in.readInt();\n        darkPrimaryColor = in.readInt();\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(@NonNull Parcel dest, int flags) {\n        dest.writeInt(headerTitle);\n        dest.writeInt(headerLogo);\n        dest.writeInt(headerColor);\n        dest.writeInt(headerTitleColor);\n        dest.writeInt(primaryColor);\n        dest.writeInt(darkPrimaryColor);\n    }\n\n    public static final Parcelable.Creator<Theme> CREATOR = new Parcelable.Creator<Theme>() {\n        @Override\n        public Theme createFromParcel(Parcel in) {\n            return new Theme(in);\n        }\n\n        @Override\n        public Theme[] newArray(int size) {\n            return new Theme[size];\n        }\n    };\n\n\n    static Builder newBuilder() {\n        return new Theme.Builder();\n    }\n\n    static class Builder {\n\n        private int headerTitleRes;\n        private int headerLogoRes;\n        private int headerColorRes;\n        private int headerTitleColorRes;\n        private int primaryColorRes;\n        private int darkPrimaryColorRes;\n\n        public Builder withHeaderTitle(@StringRes int title) {\n            headerTitleRes = title;\n            return this;\n        }\n\n        public Builder withHeaderLogo(@DrawableRes int logo) {\n            headerLogoRes = logo;\n            return this;\n        }\n\n        public Builder withHeaderColor(@ColorRes int color) {\n            headerColorRes = color;\n            return this;\n        }\n\n        public Builder withHeaderTitleColor(@ColorRes int color) {\n            headerTitleColorRes = color;\n            return this;\n        }\n\n        public Builder withPrimaryColor(@ColorRes int primary) {\n            primaryColorRes = primary;\n            return this;\n        }\n\n        public Builder withDarkPrimaryColor(@ColorRes int darkPrimary) {\n            darkPrimaryColorRes = darkPrimary;\n            return this;\n        }\n\n        public Theme build() {\n            return new Theme(headerTitleRes, headerLogoRes, headerColorRes, headerTitleColorRes, primaryColorRes, darkPrimaryColorRes);\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/provider/AuthResolver.java",
    "content": "package com.auth0.android.lock.provider;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.provider.AuthHandler;\nimport com.auth0.android.provider.AuthProvider;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\n/**\n * Holds instances of AuthHandlers that can be used to query for AuthProviders given\n * a strategy and connection name.\n * When no AuthProvider is matched, it will return null\n */\npublic final class AuthResolver {\n    private static List<AuthHandler> authHandlers;\n\n    private AuthResolver() {\n    }\n\n    /**\n     * Sets the AuthHandler list to use on this instance.\n     *\n     * @param handlers the list of AuthHandlers to use.\n     */\n    public static void setAuthHandlers(@NonNull List<AuthHandler> handlers) {\n        authHandlers = new ArrayList<>(handlers);\n    }\n\n    /**\n     * Get an AuthProvider that can handle a given strategy and connection name, or null if there are no\n     * providers to handle them.\n     *\n     * @param strategy   to handle\n     * @param connection to handle\n     * @return an AuthProvider to handle the authentication or null if no providers are available.\n     */\n    @Nullable\n    public static AuthProvider providerFor(@Nullable String strategy, @NonNull String connection) {\n        if (authHandlers == null) {\n            return null;\n        }\n\n        AuthProvider provider = null;\n        for (AuthHandler p : authHandlers) {\n            provider = p.providerFor(strategy, connection);\n            if (provider != null) {\n                break;\n            }\n        }\n        return provider;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/utils/CustomField.java",
    "content": "/*\n * CustomField.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotation.DrawableRes;\nimport androidx.annotation.IntDef;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StringRes;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.auth0.android.lock.views.ValidatedInputView;\nimport com.auth0.android.lock.views.ValidatedInputView.DataType;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.utils.CustomField.FieldType.TYPE_EMAIL;\nimport static com.auth0.android.lock.utils.CustomField.FieldType.TYPE_NAME;\nimport static com.auth0.android.lock.utils.CustomField.FieldType.TYPE_NUMBER;\nimport static com.auth0.android.lock.utils.CustomField.FieldType.TYPE_PHONE_NUMBER;\nimport static com.auth0.android.lock.utils.CustomField.Storage.PROFILE_ROOT;\nimport static com.auth0.android.lock.utils.CustomField.Storage.USER_METADATA;\n\npublic class CustomField extends SignUpField {\n\n    @IntDef({TYPE_NAME, TYPE_NUMBER, TYPE_PHONE_NUMBER, TYPE_EMAIL})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface FieldType {\n        int TYPE_NAME = 0;\n        int TYPE_NUMBER = 1;\n        int TYPE_PHONE_NUMBER = 2;\n        int TYPE_EMAIL = 3;\n    }\n\n    /**\n     * Location to store the field into.\n     */\n    @IntDef({PROFILE_ROOT, USER_METADATA})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface Storage {\n        /**\n         * Store the field into the user profile root.\n         * The list of attributes that can be added to your root profile is here https://auth0.com/docs/api/authentication#signup.\n         */\n        int PROFILE_ROOT = 0;\n\n        /**\n         * Store the field into the user_metadata object.\n         */\n        int USER_METADATA = 1;\n    }\n\n    @DrawableRes\n    private final int icon;\n    @FieldType\n    private final int type;\n    @StringRes\n    private final int hint;\n\n    /**\n     * Constructor for CustomField instance\n     * When this constructor is used the field will be stored under the {@link Storage#USER_METADATA} attribute.\n     * If you want to change the storage location use the constructor that accepts a {@link Storage} value.\n     *\n     * @param icon the icon resource to display next to the field.\n     * @param type the type of input this field will receive. Used to determine the applied validation.\n     * @param key  the key to store this field as.\n     * @param hint the placeholder to display when this field is empty.\n     */\n    public CustomField(@DrawableRes int icon, @FieldType int type, @NonNull String key, @StringRes int hint) {\n        this(icon, type, key, hint, USER_METADATA);\n    }\n\n    /**\n     * Constructor for CustomField instance\n     *\n     * @param icon    the icon resource to display next to the field.\n     * @param type    the type of input this field will receive. Used to determine the applied validation.\n     * @param key     the key to store this field as.\n     * @param hint    the placeholder to display when this field is empty.\n     * @param storage the location to store this value into.\n     */\n    public CustomField(@DrawableRes int icon, @FieldType int type, @NonNull String key, @StringRes int hint, @Storage int storage) {\n        super(key, storage);\n        this.icon = icon;\n        this.type = type;\n        this.hint = hint;\n    }\n\n    public void configureField(@NonNull ValidatedInputView field) {\n        switch (type) {\n            case TYPE_NAME:\n                field.setDataType(DataType.TEXT_NAME);\n                break;\n            case TYPE_NUMBER:\n                field.setDataType(DataType.NUMBER);\n                break;\n            case TYPE_PHONE_NUMBER:\n                field.setDataType(DataType.PHONE_NUMBER);\n                break;\n            case TYPE_EMAIL:\n                field.setDataType(DataType.EMAIL);\n                break;\n        }\n        field.setHint(hint);\n        field.setIcon(icon);\n        field.setTag(getKey());\n    }\n\n    @Nullable\n    public String findValue(@NonNull ViewGroup container) {\n        String value = null;\n        View view = container.findViewWithTag(getKey());\n        if (view != null) {\n            value = ((ValidatedInputView) view).getText();\n        }\n        return value;\n    }\n\n    @StringRes\n    int getHint() {\n        return hint;\n    }\n\n    @DrawableRes\n    int getIcon() {\n        return icon;\n    }\n\n    @FieldType\n    int getType() {\n        return type;\n    }\n\n    protected CustomField(@NonNull Parcel in) {\n        super(in);\n        icon = in.readInt();\n        type = in.readInt();\n        hint = in.readInt();\n    }\n\n    @Override\n    public void writeToParcel(@NonNull Parcel dest, int flags) {\n        super.writeToParcel(dest, flags);\n        dest.writeInt(icon);\n        dest.writeInt(type);\n        dest.writeInt(hint);\n    }\n\n    public static final Parcelable.Creator<CustomField> CREATOR = new Parcelable.Creator<CustomField>() {\n        @Override\n        public CustomField createFromParcel(Parcel in) {\n            return new CustomField(in);\n        }\n\n        @Override\n        public CustomField[] newArray(int size) {\n            return new CustomField[size];\n        }\n    };\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/utils/EnterpriseConnectionMatcher.java",
    "content": "/*\n * DomainParser.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.util.Log;\n\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Helper class to find out which email domains can be valid for the current Auth0 configuration.\n */\npublic class EnterpriseConnectionMatcher {\n\n    private static final String TAG = EnterpriseConnectionMatcher.class.getSimpleName();\n    private static final String DOMAIN_KEY = \"domain\";\n    private static final String DOMAIN_ALIASES_KEY = \"domain_aliases\";\n    private static final String AT_SYMBOL = \"@\";\n\n    private final List<OAuthConnection> connections;\n\n    public EnterpriseConnectionMatcher(@NonNull List<OAuthConnection> connections) {\n        this.connections = new ArrayList<>(connections);\n        Log.v(TAG, String.format(\"Creating a new instance to match %d Enterprise Connections\", this.connections.size()));\n    }\n\n    /**\n     * Tries to find a valid domain with the given input.\n     *\n     * @param email to search the Domain for.\n     * @return a Connection if found, null otherwise.\n     */\n    @Nullable\n    public OAuthConnection parse(@NonNull String email) {\n        String domain = extractDomain(email);\n        if (domain == null) {\n            return null;\n        }\n\n        domain = domain.toLowerCase();\n        for (OAuthConnection c : connections) {\n            String mainDomain = domainForConnection(c);\n            if (domain.equalsIgnoreCase(mainDomain)) {\n                return c;\n            }\n\n            //noinspection unchecked\n            List<String> aliases = c.valueForKey(DOMAIN_ALIASES_KEY, List.class);\n            if (aliases != null) {\n                for (String d : aliases) {\n                    if (d.equalsIgnoreCase(domain)) {\n                        return c;\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    /**\n     * Extracts the username part from the email\n     *\n     * @param email to parse\n     * @return the username String if found, an empty String otherwise\n     */\n    @Nullable\n    public String extractUsername(@NonNull String email) {\n        int indexAt = email.indexOf(AT_SYMBOL);\n        if (indexAt == -1) {\n            return null;\n        }\n        return email.substring(0, indexAt);\n    }\n\n    /**\n     * Extracts the domain part from the email\n     *\n     * @param email to parse\n     * @return the domain String if found, an empty String otherwise\n     */\n    @Nullable\n    private String extractDomain(String email) {\n        int indexAt = email.indexOf(AT_SYMBOL) + 1;\n        if (indexAt == 0) {\n            return null;\n        }\n        String domain = email.substring(indexAt);\n        if (domain.isEmpty()) {\n            return null;\n        }\n        return domain;\n    }\n\n    /**\n     * Extracts the Connection's main domain.\n     *\n     * @param connection to extract the domain from\n     * @return the main domain.\n     */\n    @Nullable\n    public String domainForConnection(@NonNull OAuthConnection connection) {\n        return connection.valueForKey(DOMAIN_KEY, String.class);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/utils/HiddenField.java",
    "content": "package com.auth0.android.lock.utils;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotation.NonNull;\n\npublic class HiddenField extends SignUpField {\n\n    private final String value;\n\n    /**\n     * Constructor for HiddenField instance\n     *\n     * @param key     the key to store this field as.\n     * @param value   the fixed value to set for this field\n     * @param storage the location to store this value into.\n     */\n    public HiddenField(@NonNull String key, @NonNull String value, @CustomField.Storage int storage) {\n        super(key, storage);\n        this.value = value;\n    }\n\n    @NonNull\n    public String getValue() {\n        return value;\n    }\n\n    protected HiddenField(@NonNull Parcel in) {\n        super(in);\n        value = in.readString();\n    }\n\n    @Override\n    public void writeToParcel(@NonNull Parcel dest, int flags) {\n        super.writeToParcel(dest, flags);\n        dest.writeString(value);\n    }\n\n    public static final Parcelable.Creator<HiddenField> CREATOR = new Parcelable.Creator<HiddenField>() {\n        @Override\n        public HiddenField createFromParcel(Parcel in) {\n            return new HiddenField(in);\n        }\n\n        @Override\n        public HiddenField[] newArray(int size) {\n            return new HiddenField[size];\n        }\n    };\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/utils/LoadCountriesTask.java",
    "content": "/*\n * LoadCountriesTask.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport android.content.Context;\nimport android.os.AsyncTask;\nimport android.util.Log;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.lock.adapters.Country;\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\npublic abstract class LoadCountriesTask extends AsyncTask<Context, Void, List<Country>> {\n\n    private static final String TAG = LoadCountriesTask.class.getName();\n    private static final String COUNTRIES_JSON_FILE = \"com_auth0_lock_passwordless_countries.json\";\n\n    @Override\n    @NonNull\n    protected List<Country> doInBackground(@NonNull Context... params) {\n        final Type mapType = new TypeToken<Map<String, String>>() {\n        }.getType();\n        Map<String, String> codes = Collections.emptyMap();\n        try {\n            final Reader reader = new InputStreamReader(params[0].getAssets().open(COUNTRIES_JSON_FILE));\n            codes = new Gson().fromJson(reader, mapType);\n            Log.d(TAG, String.format(\"Loaded %d countries\", codes.size()));\n        } catch (IOException e) {\n            Log.e(TAG, \"Failed to load the countries list from the JSON file\", e);\n        }\n        final ArrayList<String> names = new ArrayList<>(codes.keySet());\n        Collections.sort(names);\n        List<Country> countries = new ArrayList<>(names.size());\n        for (String name : names) {\n            countries.add(new Country(name, codes.get(name)));\n        }\n        return countries;\n    }\n\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/utils/SignUpField.java",
    "content": "package com.auth0.android.lock.utils;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.NonNull;\n\nimport static com.auth0.android.lock.utils.CustomField.Storage.PROFILE_ROOT;\n\npublic abstract class SignUpField implements Parcelable {\n\n    private final String key;\n    private final int storage;\n\n    SignUpField(@NonNull String key, @CustomField.Storage int storage) {\n        if (key.isEmpty()) {\n            throw new IllegalArgumentException(\"The key cannot be empty.\");\n        }\n        if (key.equalsIgnoreCase(\"user_metadata\") && storage == PROFILE_ROOT) {\n            throw new IllegalArgumentException(\"Update the user_metadata root profile attributes by using Storage.USER_METADATA as storage location.\");\n        }\n        this.key = key;\n        this.storage = storage;\n    }\n\n    @CustomField.Storage\n    public int getStorage() {\n        return storage;\n    }\n\n    @NonNull\n    public String getKey() {\n        return key;\n    }\n\n    SignUpField(Parcel in) {\n        key = in.readString();\n        storage = in.readInt();\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    @CallSuper\n    public void writeToParcel(@NonNull Parcel dest, int flags) {\n        dest.writeString(key);\n        dest.writeInt(storage);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ActionButton.java",
    "content": "/*\n * LockProgress.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.res.ColorStateList;\nimport android.graphics.drawable.ColorDrawable;\nimport android.graphics.drawable.Drawable;\nimport android.graphics.drawable.RippleDrawable;\nimport android.graphics.drawable.StateListDrawable;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StringRes;\nimport androidx.core.content.ContextCompat;\nimport androidx.core.graphics.ColorUtils;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.Theme;\n\n@SuppressLint(\"ViewConstructor\")\npublic class ActionButton extends FrameLayout {\n\n    private static final String TAG = ActionButton.class.getSimpleName();\n    private ProgressBar progress;\n    private ImageView icon;\n    private LinearLayout labeledLayout;\n    private TextView title;\n    private boolean shouldShowLabel;\n\n    public ActionButton(@NonNull Context context, @NonNull Theme lockTheme) {\n        super(context);\n        init(lockTheme);\n    }\n\n    private void init(Theme lockTheme) {\n        inflate(getContext(), R.layout.com_auth0_lock_action_button, this);\n        progress = findViewById(R.id.com_auth0_lock_progress);\n        progress.setVisibility(View.GONE);\n        icon = findViewById(R.id.com_auth0_lock_icon);\n        labeledLayout = findViewById(R.id.com_auth0_lock_labeled);\n        title = findViewById(R.id.com_auth0_lock_title);\n\n        ViewUtils.setBackground(icon, generateStateBackground(lockTheme));\n        ViewUtils.setBackground(labeledLayout, generateStateBackground(lockTheme));\n        showLabel(false);\n        icon.setFocusable(true);\n        icon.setFocusableInTouchMode(false);\n        labeledLayout.setFocusable(true);\n        labeledLayout.setFocusableInTouchMode(false);\n    }\n\n    private Drawable generateStateBackground(Theme lockTheme) {\n        int normalColor = lockTheme.getPrimaryColor(getContext());\n        int pressedColor = lockTheme.getDarkPrimaryColor(getContext());\n        //164 -> 64% alpha\n        int focusedColor = ColorUtils.setAlphaComponent(normalColor, 164);\n        int disabledColor = ContextCompat.getColor(getContext(), R.color.com_auth0_lock_submit_disabled);\n\n        final StateListDrawable buttonDrawable = new StateListDrawable();\n        buttonDrawable.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, new ColorDrawable(pressedColor));\n        buttonDrawable.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, new ColorDrawable(focusedColor));\n        buttonDrawable.addState(new int[]{android.R.attr.state_enabled}, new ColorDrawable(normalColor));\n        buttonDrawable.addState(new int[]{}, new ColorDrawable(disabledColor));\n\n        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {\n            return new RippleDrawable(ColorStateList.valueOf(pressedColor), buttonDrawable, null);\n        }\n        return buttonDrawable;\n    }\n\n    @Override\n    public void setOnClickListener(@Nullable OnClickListener l) {\n        icon.setOnClickListener(l);\n        labeledLayout.setOnClickListener(l);\n    }\n\n    /**\n     * Used to display a progress bar and disable the button.\n     *\n     * @param show whether to show the progress bar or not.\n     */\n    public void showProgress(boolean show) {\n        Log.v(TAG, show ? \"Disabling the button while showing progress\" : \"Enabling the button and hiding progress\");\n        setEnabled(!show);\n        progress.setVisibility(show ? VISIBLE : GONE);\n        if (show) {\n            icon.setVisibility(INVISIBLE);\n            labeledLayout.setVisibility(INVISIBLE);\n            return;\n        }\n        icon.setVisibility(shouldShowLabel ? GONE : VISIBLE);\n        labeledLayout.setVisibility(!shouldShowLabel ? GONE : VISIBLE);\n    }\n\n    /**\n     * Label to display in the button.\n     *\n     * @param stringRes the new resource to display as the button label.\n     */\n    public void setLabel(@StringRes int stringRes) {\n        title.setText(stringRes);\n    }\n\n    /**\n     * Whether to show an icon or a label with the current selected mode.\n     * By default, it will show the icon.\n     *\n     * @param showLabel whether to show an icon or a label.\n     */\n    public void showLabel(boolean showLabel) {\n        shouldShowLabel = showLabel;\n        labeledLayout.setVisibility(showLabel ? VISIBLE : GONE);\n        icon.setVisibility(!showLabel ? VISIBLE : GONE);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/AuthConfig.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.drawable.Drawable;\nimport androidx.annotation.ColorInt;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.StyleRes;\nimport androidx.annotation.StyleableRes;\nimport androidx.core.content.ContextCompat;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\n\npublic class AuthConfig {\n\n    private final OAuthConnection connection;\n    @StyleRes\n    private final int styleRes;\n\n    public AuthConfig(@NonNull OAuthConnection connection, @StyleRes int styleRes) {\n        this.connection = connection;\n        this.styleRes = styleRes;\n    }\n\n    @NonNull\n    public OAuthConnection getConnection() {\n        return connection;\n    }\n\n    @NonNull\n    public String getName(@NonNull Context context) {\n        @SuppressLint(\"ResourceType\")\n        int id = getIdForResource(context, R.attr.Auth0_Name);\n        return id != -1 ? context.getString(id) : connection.getStrategy();\n    }\n\n    @NonNull\n    public Drawable getLogo(@NonNull Context context) {\n        @SuppressLint(\"ResourceType\")\n        int id = getIdForResource(context, R.attr.Auth0_Logo);\n        if (id == -1) {\n            id = R.drawable.com_auth0_lock_ic_social_auth0;\n        }\n        return ContextCompat.getDrawable(context, id);\n    }\n\n    @ColorInt\n    public int getBackgroundColor(@NonNull Context context) {\n        @SuppressLint(\"ResourceType\")\n        int id = getIdForResource(context, R.attr.Auth0_BackgroundColor);\n        if (id == -1) {\n            id = R.color.com_auth0_lock_social_unknown;\n        }\n        return ContextCompat.getColor(context, id);\n    }\n\n    /**\n     * Retrieves the resource id of the given Style index.\n     *\n     * @param context a valid Context\n     * @param index   The index to search on the Style definition.\n     * @return the id if found or -1.\n     */\n    int getIdForResource(@NonNull Context context, @StyleableRes int index) {\n        final int[] attrs = new int[]{index};\n        final TypedArray typedArray = context.getTheme().obtainStyledAttributes(styleRes, attrs);\n        int id = typedArray.getResourceId(0, -1);\n        typedArray.recycle();\n        return id;\n    }\n\n    /**\n     * It will resolve the given Strategy Name to a valid Style.\n     *\n     * @param strategyName to search for.\n     * @return a valid Lock.Theme.AuthStyle\n     */\n    @StyleRes\n    public static int styleForStrategy(@NonNull String strategyName) {\n        int style = R.style.Lock_Theme_AuthStyle;\n        switch (strategyName) {\n            case \"apple\":\n                style = R.style.Lock_Theme_AuthStyle_Apple;\n                break;\n            case \"amazon\":\n                style = R.style.Lock_Theme_AuthStyle_Amazon;\n                break;\n            case \"aol\":\n                style = R.style.Lock_Theme_AuthStyle_AOL;\n                break;\n            case \"bitbucket\":\n                style = R.style.Lock_Theme_AuthStyle_BitBucket;\n                break;\n            case \"dropbox\":\n                style = R.style.Lock_Theme_AuthStyle_Dropbox;\n                break;\n            case \"yahoo\":\n                style = R.style.Lock_Theme_AuthStyle_Yahoo;\n                break;\n            case \"linkedin\":\n                style = R.style.Lock_Theme_AuthStyle_LinkedIn;\n                break;\n            case \"google-oauth2\":\n                style = R.style.Lock_Theme_AuthStyle_GoogleOAuth2;\n                break;\n            case \"twitter\":\n                style = R.style.Lock_Theme_AuthStyle_Twitter;\n                break;\n            case \"facebook\":\n                style = R.style.Lock_Theme_AuthStyle_Facebook;\n                break;\n            case \"box\":\n                style = R.style.Lock_Theme_AuthStyle_Box;\n                break;\n            case \"evernote\":\n                style = R.style.Lock_Theme_AuthStyle_Evernote;\n                break;\n            case \"evernote-sandbox\":\n                style = R.style.Lock_Theme_AuthStyle_EvernoteSandbox;\n                break;\n            case \"exact\":\n                style = R.style.Lock_Theme_AuthStyle_Exact;\n                break;\n            case \"github\":\n                style = R.style.Lock_Theme_AuthStyle_GitHub;\n                break;\n            case \"instagram\":\n                style = R.style.Lock_Theme_AuthStyle_Instagram;\n                break;\n            case \"miicard\":\n                style = R.style.Lock_Theme_AuthStyle_MiiCard;\n                break;\n            case \"paypal\":\n                style = R.style.Lock_Theme_AuthStyle_Paypal;\n                break;\n            case \"paypal-sandbox\":\n                style = R.style.Lock_Theme_AuthStyle_PaypalSandbox;\n                break;\n            case \"salesforce\":\n                style = R.style.Lock_Theme_AuthStyle_Salesforce;\n                break;\n            case \"salesforce-community\":\n                style = R.style.Lock_Theme_AuthStyle_SalesforceCommunity;\n                break;\n            case \"salesforce-sandbox\":\n                style = R.style.Lock_Theme_AuthStyle_SalesforceSandbox;\n                break;\n            case \"soundcloud\":\n                style = R.style.Lock_Theme_AuthStyle_SoundCloud;\n                break;\n            case \"windowslive\":\n                style = R.style.Lock_Theme_AuthStyle_WindowsLive;\n                break;\n            case \"yammer\":\n                style = R.style.Lock_Theme_AuthStyle_Yammer;\n                break;\n            case \"baidu\":\n                style = R.style.Lock_Theme_AuthStyle_Baidu;\n                break;\n            case \"fitbit\":\n                style = R.style.Lock_Theme_AuthStyle_Fitbit;\n                break;\n            case \"planningcenter\":\n                style = R.style.Lock_Theme_AuthStyle_PlanningCenter;\n                break;\n            case \"renren\":\n                style = R.style.Lock_Theme_AuthStyle_RenRen;\n                break;\n            case \"thecity\":\n                style = R.style.Lock_Theme_AuthStyle_TheCity;\n                break;\n            case \"thecity-sandbox\":\n                style = R.style.Lock_Theme_AuthStyle_TheCitySandbox;\n                break;\n            case \"thirtysevensignals\":\n                style = R.style.Lock_Theme_AuthStyle_ThirtySevenSignals;\n                break;\n            case \"vkontakte\":\n                style = R.style.Lock_Theme_AuthStyle_Vkontakte;\n                break;\n            case \"weibo\":\n                style = R.style.Lock_Theme_AuthStyle_Weibo;\n                break;\n            case \"wordpress\":\n                style = R.style.Lock_Theme_AuthStyle_Wordpress;\n                break;\n            case \"yandex\":\n                style = R.style.Lock_Theme_AuthStyle_Yandex;\n                break;\n            case \"shopify\":\n                style = R.style.Lock_Theme_AuthStyle_Shopify;\n                break;\n            case \"dwolla\":\n                style = R.style.Lock_Theme_AuthStyle_Dwolla;\n                break;\n        }\n\n        return style;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ChangePasswordFormView.java",
    "content": "/*\n * ChangePasswordFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.util.Log;\nimport android.view.KeyEvent;\nimport android.view.inputmethod.EditorInfo;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.DatabaseChangePasswordEvent;\nimport com.auth0.android.lock.views.interfaces.IdentityListener;\nimport com.auth0.android.lock.views.interfaces.LockWidgetForm;\n\npublic class ChangePasswordFormView extends FormView implements TextView.OnEditorActionListener, IdentityListener {\n\n    private static final String TAG = ChangePasswordFormView.class.getSimpleName();\n    private final LockWidgetForm lockWidget;\n    private ValidatedInputView emailInput;\n\n    public ChangePasswordFormView(@NonNull Context context) {\n        super(context);\n        lockWidget = null;\n    }\n\n    public ChangePasswordFormView(@NonNull LockWidgetForm lockWidget, @Nullable String email) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        init(email);\n    }\n\n    private void init(String email) {\n        inflate(getContext(), R.layout.com_auth0_lock_changepwd_form_view, this);\n        emailInput = findViewById(R.id.com_auth0_lock_input_email);\n        emailInput.setText(email);\n        emailInput.setIdentityListener(this);\n        emailInput.setOnEditorActionListener(this);\n        requestFocus();\n    }\n\n    @NonNull\n    @Override\n    public Object getActionEvent() {\n        return new DatabaseChangePasswordEvent(getUsernameOrEmail());\n    }\n\n    @NonNull\n    private String getUsernameOrEmail() {\n        return emailInput.getText().trim();\n    }\n\n    @Override\n    public boolean validateForm() {\n        return emailInput.validate();\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        if (validateForm()) {\n            Log.d(TAG, \"Form submitted\");\n            return getActionEvent();\n        }\n        Log.w(TAG, \"Form has some validation issues and won't be submitted.\");\n        return null;\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n\n    @Override\n    public void onEmailChanged(@NonNull String email) {\n        lockWidget.onEmailChanged(email);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/CheckableOptionView.java",
    "content": "/*\n * CheckableOptionView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport androidx.annotation.NonNull;\nimport androidx.core.content.ContextCompat;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\n\npublic class CheckableOptionView extends LinearLayout {\n\n    private ImageView icon;\n    private TextView description;\n\n    private boolean mandatory;\n    private boolean checked;\n\n    public CheckableOptionView(@NonNull Context context) {\n        super(context);\n        init(null);\n    }\n\n    public CheckableOptionView(@NonNull Context context, @NonNull AttributeSet attrs) {\n        super(context, attrs);\n        init(attrs);\n    }\n\n    public CheckableOptionView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(attrs);\n    }\n\n    private void init(AttributeSet attrs) {\n        final View v = inflate(getContext(), R.layout.com_auth0_lock_checkable_option, this);\n        icon = v.findViewById(R.id.com_auth0_lock_checkable_text_icon);\n        description = v.findViewById(R.id.com_auth0_lock_checkable_text_description);\n\n        if (attrs == null) {\n            return;\n        }\n\n        int[] set = {android.R.attr.text};\n        TypedArray a = getContext().obtainStyledAttributes(attrs, set);\n        CharSequence text = a.getText(0);\n        a.recycle();\n        description.setText(text);\n        updateStatus();\n    }\n\n    private void updateStatus() {\n        if (checked) {\n            icon.setImageResource(R.drawable.com_auth0_lock_ic_check_success);\n            description.setTextColor(ContextCompat.getColor(getContext(), R.color.com_auth0_lock_checkable_option_success));\n            return;\n        }\n        icon.setImageResource(mandatory ? R.drawable.com_auth0_lock_ic_check_error : R.drawable.com_auth0_lock_ic_check_unset);\n        description.setTextColor(ContextCompat.getColor(getContext(), mandatory ? R.color.com_auth0_lock_checkable_option_error : R.color.com_auth0_lock_normal_text));\n    }\n\n    /**\n     * Sets the current text/description for this Option.\n     *\n     * @param text to set.\n     */\n    public void setText(@NonNull String text) {\n        this.description.setText(text);\n    }\n\n    /**\n     * Updates the current checked state of this Option widget.\n     *\n     * @param checked whether to check or uncheck the Option.\n     */\n    public void setChecked(boolean checked) {\n        this.checked = checked;\n        updateStatus();\n    }\n\n    /**\n     * If this Option is a requirement that must be met, set it to mandatory.\n     * Used for displaying a different image on the side when unchecked.\n     *\n     * @param mandatory whether this Option is required or not.\n     */\n    public void setMandatory(boolean mandatory) {\n        this.mandatory = mandatory;\n        updateStatus();\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ClassicLockView.java",
    "content": "/*\n * ClassicLockView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.text.Html;\nimport android.text.method.LinkMovementMethod;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StringRes;\nimport androidx.appcompat.app.AlertDialog;\n\nimport com.auth0.android.lock.InitialScreen;\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.DatabaseLoginEvent;\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.events.FetchApplicationEvent;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.internal.configuration.AuthMode;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.Theme;\nimport com.auth0.android.lock.views.interfaces.LockWidgetForm;\nimport com.squareup.otto.Bus;\n\n@SuppressWarnings(\"NullableProblems\")\n@SuppressLint(\"ViewConstructor\")\npublic class ClassicLockView extends LinearLayout implements LockWidgetForm {\n\n    private static final String TAG = ClassicLockView.class.getSimpleName();\n    private static final int FORM_INDEX = 2;\n    private final Bus bus;\n    private final Theme lockTheme;\n    private Configuration configuration;\n\n    private HeaderView headerView;\n    private FormLayout formLayout;\n    private FormView subForm;\n\n    private View topBanner;\n    private View bottomBanner;\n    private ActionButton actionButton;\n    private ProgressBar loadingProgressBar;\n\n    private String lastEmailInput;\n\n    public ClassicLockView(@NonNull Context context, @NonNull Bus lockBus, @NonNull Theme lockTheme) {\n        super(context);\n        this.bus = lockBus;\n        this.configuration = null;\n        this.lockTheme = lockTheme;\n        showWaitForConfigurationLayout();\n    }\n\n    private void init() {\n        setOrientation(VERTICAL);\n        if (configuration == null) {\n            Log.w(TAG, \"Configuration is missing, the view won't init.\");\n            showConfigurationMissingLayout(true);\n        } else {\n            showContentLayout();\n        }\n    }\n\n    private void showWaitForConfigurationLayout() {\n        LayoutParams wrapHeightParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        wrapHeightParams.gravity = Gravity.CENTER;\n        loadingProgressBar = new ProgressBar(getContext());\n        loadingProgressBar.setIndeterminate(true);\n        ViewUtils.tintWidget(loadingProgressBar, lockTheme.getPrimaryColor(getContext()));\n        addView(loadingProgressBar, wrapHeightParams);\n    }\n\n    private void showContentLayout() {\n        LayoutParams wrapHeightParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        LayoutParams formLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);\n\n        boolean displayTerms = configuration.showTerms() || configuration.mustAcceptTerms();\n\n        headerView = new HeaderView(getContext(), lockTheme);\n        resetHeaderTitle();\n        addView(headerView, wrapHeightParams);\n\n        topBanner = inflate(getContext(), R.layout.com_auth0_lock_sso_layout, null);\n        topBanner.setVisibility(GONE);\n        addView(topBanner, wrapHeightParams);\n\n        formLayout = new FormLayout(this);\n        addView(formLayout, formLayoutParams);\n\n        if (displayTerms) {\n            bottomBanner = inflate(getContext(), R.layout.com_auth0_lock_terms_layout, null);\n            bottomBanner.setOnClickListener(v -> showSignUpTermsDialog(null));\n            bottomBanner.setVisibility(GONE);\n            addView(bottomBanner, wrapHeightParams);\n        }\n\n        actionButton = new ActionButton(getContext(), lockTheme);\n        actionButton.setOnClickListener(v -> {\n            final Object event = subForm != null ? subForm.submitForm() : formLayout.onActionPressed();\n            if (event == null) {\n                return;\n            }\n            if (!configuration.mustAcceptTerms() || !(event instanceof DatabaseSignUpEvent)) {\n                bus.post(event);\n                return;\n            }\n            showSignUpTermsDialog((dialog, which) -> bus.post(event));\n        });\n        actionButton.showLabel(configuration.useLabeledSubmitButton() || configuration.hideMainScreenTitle());\n        addView(actionButton, wrapHeightParams);\n\n        boolean showDatabase = configuration.getDatabaseConnection() != null;\n        boolean showEnterprise = !configuration.getEnterpriseConnections().isEmpty();\n        boolean singleEnterprise = configuration.getEnterpriseConnections().size() == 1 && configuration.getSocialConnections().isEmpty();\n        if (!showDatabase && (singleEnterprise || !showEnterprise)) {\n            actionButton.setVisibility(GONE);\n        }\n\n        if (configuration.getInitialScreen() == InitialScreen.SIGN_UP) {\n            showBottomBanner(displayTerms);\n            updateButtonLabel(R.string.com_auth0_lock_action_sign_up);\n        } else if (configuration.allowForgotPassword() && configuration.getInitialScreen() == InitialScreen.FORGOT_PASSWORD) {\n            showChangePasswordForm(true);\n        }\n    }\n\n    /**\n     * Setup the panel to show the correct forms by reading the Auth0 Configuration.\n     *\n     * @param configuration the configuration to use on this view, or null if it is missing.\n     */\n    public void configure(@Nullable Configuration configuration) {\n        removeView(loadingProgressBar);\n        loadingProgressBar = null;\n        this.configuration = configuration;\n        if (configuration != null && configuration.hasClassicConnections()) {\n            init();\n        } else {\n            showConfigurationMissingLayout(configuration == null);\n        }\n    }\n\n    private void showConfigurationMissingLayout(final boolean showRetry) {\n        final View errorLayout = LayoutInflater.from(getContext()).inflate(R.layout.com_auth0_lock_error_layout, this, false);\n        TextView tvTitle = errorLayout.findViewById(R.id.com_auth0_lock_error_title);\n        TextView tvError = errorLayout.findViewById(R.id.com_auth0_lock_error_subtitle);\n        TextView tvAction = errorLayout.findViewById(R.id.com_auth0_lock_error_action);\n\n        if (showRetry) {\n            tvTitle.setText(R.string.com_auth0_lock_recoverable_error_title);\n            tvError.setText(R.string.com_auth0_lock_recoverable_error_subtitle);\n            tvAction.setText(R.string.com_auth0_lock_recoverable_error_action);\n            tvAction.setOnClickListener(v -> {\n                bus.post(new FetchApplicationEvent());\n                removeView(errorLayout);\n                showWaitForConfigurationLayout();\n            });\n        } else if (configuration.getSupportURL() == null) {\n            tvTitle.setText(R.string.com_auth0_lock_unrecoverable_error_title);\n            tvError.setText(R.string.com_auth0_lock_unrecoverable_error_subtitle_without_action);\n            tvAction.setVisibility(GONE);\n        } else {\n            tvTitle.setText(R.string.com_auth0_lock_unrecoverable_error_title);\n            tvError.setText(R.string.com_auth0_lock_unrecoverable_error_subtitle);\n            tvAction.setText(R.string.com_auth0_lock_unrecoverable_error_action);\n            tvAction.setOnClickListener(v -> getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(configuration.getSupportURL()))));\n        }\n        addView(errorLayout);\n    }\n\n    @Override\n    public void showChangePasswordForm(boolean show) {\n        if (show) {\n            ChangePasswordFormView form = new ChangePasswordFormView(this, lastEmailInput);\n            updateHeaderTitle(R.string.com_auth0_lock_title_change_password);\n            addSubForm(form);\n            updateButtonLabel(R.string.com_auth0_lock_action_send_email);\n        } else {\n            removeSubForm();\n        }\n    }\n\n    private void updateHeaderTitle(@StringRes int titleRes) {\n        headerView.setTitle(getContext().getString(titleRes));\n        headerView.showTitle(true);\n    }\n\n    private void resetHeaderTitle() {\n        headerView.setTitle(lockTheme.getHeaderTitle(getContext()));\n        headerView.showTitle(!configuration.hideMainScreenTitle());\n    }\n\n    private void addSubForm(@NonNull FormView form) {\n        if (subForm != null) {\n            return;\n        }\n        removeView(formLayout);\n        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);\n        this.subForm = form;\n        addView(subForm, FORM_INDEX, params);\n    }\n\n    private void removeSubForm() {\n        if (subForm == null) {\n            return;\n        }\n        removeView(subForm);\n        subForm = null;\n        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);\n        formLayout.refreshIdentityInput();\n        addView(formLayout, FORM_INDEX, params);\n        updateButtonLabel(formLayout.getSelectedMode() == AuthMode.SIGN_UP ? R.string.com_auth0_lock_action_sign_up : R.string.com_auth0_lock_action_log_in);\n        resetHeaderTitle();\n    }\n\n    /**\n     * Triggers the back action on the form.\n     *\n     * @return true if it was handled, false otherwise\n     */\n    public boolean onBackPressed() {\n        if (subForm != null) {\n            final boolean shouldDisplayPreviousForm = configuration.allowLogIn() || configuration.allowSignUp();\n            if (shouldDisplayPreviousForm) {\n                resetHeaderTitle();\n                showSignUpTerms(subForm instanceof CustomFieldsFormView);\n                removeSubForm();\n                clearFocus();\n                return true;\n            }\n        }\n\n        return formLayout != null && formLayout.onBackPressed();\n    }\n\n    /**\n     * Displays a progress bar on top of the action button. This will also\n     * enable or disable the action button.\n     *\n     * @param show whether to show or hide the action bar.\n     */\n    public void showProgress(boolean show) {\n        if (actionButton != null) {\n            actionButton.showProgress(show);\n        }\n        if (formLayout != null) {\n            formLayout.setEnabled(!show);\n        }\n    }\n\n    private void showSignUpTerms(boolean show) {\n        if (bottomBanner != null) {\n            bottomBanner.setVisibility(show ? VISIBLE : GONE);\n        }\n    }\n\n    /**\n     * Create a dialog to show the Privacy Policy and Terms of Service text.\n     * If the provided callback it's not null, it will ask for acceptance.\n     *\n     * @param acceptCallback the callback to receive the acceptance. Can be null.\n     */\n    @SuppressLint(\"StringFormatInvalid\")\n    private void showSignUpTermsDialog(@Nullable DialogInterface.OnClickListener acceptCallback) {\n        final String content = getResources().getString(R.string.com_auth0_lock_sign_up_terms_dialog_message, configuration.getTermsURL(), configuration.getPrivacyURL());\n        final AlertDialog.Builder builder = new AlertDialog.Builder(getContext())\n                .setTitle(getResources().getString(R.string.com_auth0_lock_sign_up_terms_dialog_title))\n                .setPositiveButton(R.string.com_auth0_lock_action_ok, null)\n                .setMessage(Html.fromHtml(content));\n        if (acceptCallback != null) {\n            builder.setNegativeButton(R.string.com_auth0_lock_action_cancel, null)\n                    .setPositiveButton(R.string.com_auth0_lock_action_accept, acceptCallback)\n                    .setCancelable(false);\n        }\n\n        //the dialog needs to be shown before we can get it's view.\n        final TextView message = builder.show().findViewById(android.R.id.message);\n        if (message != null) {\n            message.setMovementMethod(LinkMovementMethod.getInstance());\n        }\n    }\n\n    @NonNull\n    @Override\n    public Configuration getConfiguration() {\n        return configuration;\n    }\n\n    @Override\n    public void onFormSubmit() {\n        actionButton.callOnClick();\n    }\n\n    @Override\n    public void showCustomFieldsForm(@NonNull DatabaseSignUpEvent event) {\n        CustomFieldsFormView form = new CustomFieldsFormView(this, event.getEmail(), event.getPassword(), event.getUsername());\n        addSubForm(form);\n        updateHeaderTitle(R.string.com_auth0_lock_action_sign_up);\n        showSignUpTerms(false);\n    }\n\n    public void showMFACodeForm(@NonNull DatabaseLoginEvent event) {\n        MFACodeFormView form = new MFACodeFormView(this, event.getUsernameOrEmail(), event.getPassword(), event.getMultifactorToken(), event.getMultifactorChallengeType(), event.getMultifactorOOBCode());\n        updateHeaderTitle(R.string.com_auth0_lock_title_mfa_input_code);\n        addSubForm(form);\n    }\n\n    @Override\n    public void onOAuthLoginRequest(@NonNull OAuthLoginEvent event) {\n        bus.post(event);\n    }\n\n    @Override\n    public void showTopBanner(boolean show) {\n        topBanner.setVisibility(show ? VISIBLE : GONE);\n        if (formLayout != null) {\n            formLayout.showOnlyEnterprise(show);\n        }\n    }\n\n    @Override\n    public void showBottomBanner(boolean show) {\n        if (bottomBanner != null) {\n            bottomBanner.setVisibility(show ? VISIBLE : GONE);\n        }\n    }\n\n    @Override\n    public void updateButtonLabel(@StringRes int stringRes) {\n        if (actionButton != null) {\n            actionButton.setLabel(stringRes);\n        }\n    }\n\n    @Override\n    public void onEmailChanged(@NonNull String email) {\n        lastEmailInput = email;\n        formLayout.onEmailChanged(email);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/CountryCodeSelectorView.java",
    "content": "/*\n * ValidatedPhoneNumber.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport android.graphics.drawable.ShapeDrawable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.core.content.ContextCompat;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.utils.LoadCountriesTask;\n\nimport java.util.List;\nimport java.util.Locale;\n\npublic class CountryCodeSelectorView extends LinearLayout {\n    private static final String TAG = CountryCodeSelectorView.class.getSimpleName();\n    private LoadCountriesTask task;\n    private Country selectedCountry;\n\n    private ImageView icon;\n    private TextView countryNameTextView;\n    private TextView countryCodeTextView;\n    private ImageView chevron;\n    private View outline;\n    private ShapeDrawable focusedBackground;\n    private ShapeDrawable normalBackground;\n\n    public CountryCodeSelectorView(@NonNull Context context) {\n        super(context);\n        init();\n    }\n\n    public CountryCodeSelectorView(@NonNull Context context, @NonNull AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public CountryCodeSelectorView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_passwordless_country_code_selector, this);\n        icon = findViewById(R.id.com_auth0_lock_icon);\n        chevron = findViewById(R.id.com_auth0_lock_chevron);\n        countryNameTextView = findViewById(R.id.com_auth0_lock_country_name);\n        countryCodeTextView = findViewById(R.id.com_auth0_lock_country_code);\n        outline = findViewById(R.id.com_auth0_lock_outline);\n        prepareTask();\n        setupBackground();\n        setOnFocusChangeListener((v, hasFocus) -> ViewUtils.setBackground(outline, hasFocus ? focusedBackground : normalBackground));\n    }\n\n    private void setupBackground() {\n        Drawable leftBackground = ViewUtils.getRoundedBackground(this, ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_normal), ViewUtils.Corners.ONLY_LEFT);\n        Drawable rightBackground = ViewUtils.getRoundedBackground(this, ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_country_code_background), ViewUtils.Corners.ONLY_RIGHT);\n        ViewUtils.setBackground(icon, leftBackground);\n        ViewUtils.setBackground(chevron, rightBackground);\n\n        focusedBackground = ViewUtils.getRoundedOutlineBackground(getResources(), ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_focused));\n        normalBackground = ViewUtils.getRoundedOutlineBackground(getResources(), ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_normal));\n        ViewUtils.setBackground(outline, normalBackground);\n    }\n\n    private void prepareTask() {\n        task = new LoadCountriesTask() {\n            @Override\n            protected void onPostExecute(List<Country> result) {\n                task = null;\n                String defaultCountry = Locale.getDefault().getCountry();\n                Country selectedCountry = new Country(getContext().getString(R.string.com_auth0_lock_default_country_name_fallback), getContext().getString(R.string.com_auth0_lock_default_country_code_fallback));\n\n                for (Country c : result) {\n                    if (c.getDisplayName().equalsIgnoreCase(defaultCountry)) {\n                        selectedCountry = c;\n                        break;\n                    }\n                }\n                if (CountryCodeSelectorView.this.selectedCountry == null) {\n                    setSelectedCountry(selectedCountry);\n                }\n            }\n        };\n        task.execute(getContext());\n    }\n\n    /**\n     * Sets the current Country to the one given.\n     *\n     * @param country the country to set.\n     */\n    public void setSelectedCountry(@NonNull Country country) {\n        Log.d(TAG, \"Selected country changed to \" + country.getDisplayName());\n        countryNameTextView.setText(country.getDisplayName());\n        countryCodeTextView.setText(country.getDialCode());\n        selectedCountry = country;\n    }\n\n    /**\n     * Gets the currently selected Country.\n     *\n     * @return the country that is currently set.\n     */\n    @Nullable\n    public Country getSelectedCountry() {\n        return selectedCountry;\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        if (task != null) {\n            task.cancel(true);\n            task = null;\n        }\n        super.onDetachedFromWindow();\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/CustomFieldsFormView.java",
    "content": "/*\n * CustomFieldsFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.KeyEvent;\nimport android.view.ViewGroup;\nimport android.view.inputmethod.EditorInfo;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.utils.CustomField;\nimport com.auth0.android.lock.utils.HiddenField;\nimport com.auth0.android.lock.views.interfaces.LockWidgetForm;\n\nimport java.util.HashMap;\nimport java.util.List;\n\nimport static com.auth0.android.lock.utils.CustomField.Storage;\n\n@SuppressLint(\"ViewConstructor\")\npublic class CustomFieldsFormView extends FormView implements TextView.OnEditorActionListener {\n\n    private static final String TAG = CustomFieldsFormView.class.getSimpleName();\n\n    @NonNull\n    private final String email;\n    @NonNull\n    private final String password;\n    @Nullable\n    private final String username;\n    private final LockWidgetForm lockWidget;\n    private final List<CustomField> visibleSignUpFields;\n    private final List<HiddenField> hiddenSignUpFields;\n    private LinearLayout fieldContainer;\n    private LinearLayout.LayoutParams fieldParams;\n\n    public CustomFieldsFormView(@NonNull LockWidgetForm lockWidget, @NonNull String email, @NonNull String password, @Nullable String username) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        this.email = email;\n        this.username = username;\n        this.password = password;\n        this.visibleSignUpFields = lockWidget.getConfiguration().getVisibleSignUpFields();\n        this.hiddenSignUpFields = lockWidget.getConfiguration().getHiddenSignUpFields();\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_custom_fields_form_view, this);\n        fieldContainer = findViewById(R.id.com_auth0_lock_container);\n        fieldParams = defineFieldParams();\n        addCustomFields();\n    }\n\n    private LinearLayout.LayoutParams defineFieldParams() {\n        int horizontalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_horizontal_margin);\n        int verticalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        params.gravity = Gravity.CENTER_HORIZONTAL;\n        params.setMargins(horizontalMargin, verticalMargin / 2, horizontalMargin, verticalMargin / 2);\n        params.setMarginStart(horizontalMargin);\n        params.setMarginEnd(horizontalMargin);\n        return params;\n    }\n\n    private void addCustomFields() {\n        Log.d(TAG, String.format(\"Adding %d custom fields.\", visibleSignUpFields.size()));\n\n        for (CustomField data : visibleSignUpFields) {\n            ValidatedInputView field = new ValidatedInputView(getContext());\n            data.configureField(field);\n            field.setLayoutParams(fieldParams);\n            field.setOnEditorActionListener(this);\n            fieldContainer.addView(field);\n        }\n    }\n\n    static void setEventRootProfileAttributes(DatabaseSignUpEvent event, List<CustomField> visibleFields, List<HiddenField> hiddenFields, ViewGroup container) {\n        HashMap<String, String> rootMap = new HashMap<>();\n        HashMap<String, String> userMetadataMap = new HashMap<>();\n\n        for (CustomField data : visibleFields) {\n            String value = data.findValue(container);\n            if (data.getStorage() == Storage.USER_METADATA) {\n                userMetadataMap.put(data.getKey(), value);\n            } else {\n                rootMap.put(data.getKey(), value);\n            }\n        }\n        for (HiddenField hf : hiddenFields) {\n            if (hf.getStorage() == Storage.USER_METADATA) {\n                userMetadataMap.put(hf.getKey(), hf.getValue());\n            } else {\n                rootMap.put(hf.getKey(), hf.getValue());\n            }\n        }\n        if (!rootMap.isEmpty()) {\n            event.setRootAttributes(rootMap);\n        }\n        if (!userMetadataMap.isEmpty()) {\n            event.setExtraFields(userMetadataMap);\n        }\n    }\n\n    @NonNull\n    @Override\n    public Object getActionEvent() {\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(email, password, username);\n        setEventRootProfileAttributes(event, visibleSignUpFields, hiddenSignUpFields, fieldContainer);\n        return event;\n    }\n\n    @Override\n    public boolean validateForm() {\n        boolean valid = true;\n        for (int i = 0; i < fieldContainer.getChildCount(); i++) {\n            ValidatedInputView input = (ValidatedInputView) fieldContainer.getChildAt(i);\n            if (input.isEnabled()) {\n                valid = input.validate() && valid;\n            }\n        }\n        Log.d(TAG, \"Is form data valid? \" + valid);\n        return valid;\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        return validateForm() ? getActionEvent() : null;\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/FormLayout.java",
    "content": "/*\n * DbLayout.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.appcompat.widget.AppCompatTextView;\nimport androidx.core.content.ContextCompat;\nimport android.util.Log;\nimport android.util.TypedValue;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.InitialScreen;\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.internal.configuration.AuthMode;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.views.interfaces.IdentityListener;\nimport com.auth0.android.lock.views.interfaces.LockWidgetForm;\n\npublic class FormLayout extends RelativeLayout implements ModeSelectionView.ModeSelectedListener, IdentityListener {\n    private static final String TAG = FormLayout.class.getSimpleName();\n    private static final int SINGLE_FORM_POSITION = 0;\n    private static final int MULTIPLE_FORMS_POSITION = 2;\n\n    private final LockWidgetForm lockWidget;\n    private boolean showDatabase;\n    private boolean showEnterprise;\n\n    private SignUpFormView signUpForm;\n    private LogInFormView logInForm;\n    private SocialView socialLayout;\n    private CustomFieldsFormView customFieldsForm;\n    private TextView orSeparatorMessage;\n\n    private LinearLayout formsHolder;\n    private ModeSelectionView modeSelectionView;\n\n    private String lastEmailInput;\n\n    @SuppressLint(\"WrongConstant\")\n    @AuthMode\n    private int lastFormMode = -1;\n\n    public FormLayout(@NonNull Context context) {\n        super(context);\n        lockWidget = null;\n    }\n\n    public FormLayout(@NonNull LockWidgetForm lockWidget) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        init();\n    }\n\n    private void init() {\n        boolean showSocial = !lockWidget.getConfiguration().getSocialConnections().isEmpty();\n        showDatabase = lockWidget.getConfiguration().getDatabaseConnection() != null;\n        showEnterprise = !lockWidget.getConfiguration().getEnterpriseConnections().isEmpty();\n        boolean showModeSelection = showDatabase && lockWidget.getConfiguration().allowLogIn() && lockWidget.getConfiguration().allowSignUp();\n\n        int verticalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        int horizontalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_horizontal_margin);\n\n        if (showModeSelection) {\n            Log.v(TAG, \"Showing the LogIn/SignUp tabs\");\n            modeSelectionView = new ModeSelectionView(getContext(), this);\n            modeSelectionView.setId(R.id.com_auth0_lock_form_selector);\n            LayoutParams modeSelectionParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n            modeSelectionParams.addRule(ALIGN_PARENT_TOP);\n            addView(modeSelectionView, modeSelectionParams);\n        }\n        formsHolder = new LinearLayout(getContext());\n        formsHolder.setOrientation(LinearLayout.VERTICAL);\n        formsHolder.setGravity(Gravity.CENTER);\n        formsHolder.setPadding(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);\n        formsHolder.setPaddingRelative(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);\n        LayoutParams holderParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n        holderParams.addRule(BELOW, R.id.com_auth0_lock_form_selector);\n        holderParams.addRule(CENTER_VERTICAL);\n        addView(formsHolder, holderParams);\n\n        if (showSocial) {\n            addSocialLayout();\n            if (showDatabase || showEnterprise) {\n                addSeparator();\n            }\n        }\n        displayInitialScreen();\n    }\n\n    private void displayInitialScreen() {\n        if (!showDatabase && !showEnterprise) {\n            return;\n        }\n        int mode;\n        int initialScreen = lockWidget.getConfiguration().getInitialScreen();\n        if (initialScreen == InitialScreen.FORGOT_PASSWORD) {\n            mode = lockWidget.getConfiguration().allowLogIn() ? AuthMode.LOG_IN : AuthMode.SIGN_UP;\n        } else {\n            mode = initialScreen == InitialScreen.SIGN_UP ? AuthMode.SIGN_UP : AuthMode.LOG_IN;\n        }\n\n        if (modeSelectionView != null) {\n            modeSelectionView.setSelectedMode(mode);\n        } else {\n            changeFormMode(mode);\n        }\n    }\n\n    private void addSocialLayout() {\n        socialLayout = new SocialView(lockWidget, false);\n        formsHolder.addView(socialLayout);\n    }\n\n    private void addSeparator() {\n        orSeparatorMessage = new AppCompatTextView(getContext());\n        orSeparatorMessage.setText(R.string.com_auth0_lock_forms_separator);\n        orSeparatorMessage.setTextColor(ContextCompat.getColor(getContext(), R.color.com_auth0_lock_text));\n        orSeparatorMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.com_auth0_lock_title_text));\n        orSeparatorMessage.setGravity(Gravity.CENTER);\n        int verticalPadding = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        orSeparatorMessage.setPadding(0, verticalPadding, 0, verticalPadding);\n        orSeparatorMessage.setPaddingRelative(0, verticalPadding, 0, verticalPadding);\n        formsHolder.addView(orSeparatorMessage, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n    }\n\n    /**\n     * Change the current form mode\n     *\n     * @param mode the new DatabaseMode to change to\n     */\n    @SuppressLint(\"WrongConstant\")\n    private void changeFormMode(@AuthMode int mode) {\n        Log.d(TAG, \"Mode changed to \" + mode);\n        if (lastFormMode == mode || !showDatabase && !showEnterprise) {\n            return;\n        }\n        Log.d(TAG, \"Mode changed to \" + mode);\n        lastFormMode = mode;\n        lockWidget.showTopBanner(false);\n        if (socialLayout != null) {\n            socialLayout.setCurrentMode(mode);\n        }\n        switch (mode) {\n            case AuthMode.LOG_IN:\n                showLogInForm();\n                lockWidget.showBottomBanner(false);\n                lockWidget.updateButtonLabel(R.string.com_auth0_lock_action_log_in);\n                break;\n            case AuthMode.SIGN_UP:\n                showSignUpForm();\n                lockWidget.showBottomBanner(true);\n                lockWidget.updateButtonLabel(R.string.com_auth0_lock_action_sign_up);\n                break;\n        }\n    }\n\n    public void showOnlyEnterprise(boolean show) {\n        if (socialLayout != null) {\n            socialLayout.setVisibility(show ? GONE : VISIBLE);\n        }\n        if (orSeparatorMessage != null) {\n            orSeparatorMessage.setVisibility(show ? GONE : VISIBLE);\n        }\n        if (modeSelectionView != null) {\n            modeSelectionView.setVisibility(show ? GONE : VISIBLE);\n        }\n    }\n\n    private void showSignUpForm() {\n        removePreviousForm();\n\n        if (signUpForm == null) {\n            signUpForm = new SignUpFormView(lockWidget);\n        }\n        signUpForm.setLastEmail(lastEmailInput);\n        signUpForm.clearEmptyFieldsError();\n        formsHolder.addView(signUpForm);\n    }\n\n    private void showLogInForm() {\n        removePreviousForm();\n\n        if (logInForm == null) {\n            logInForm = new LogInFormView(lockWidget);\n        }\n        logInForm.setLastEmail(lastEmailInput);\n        logInForm.clearEmptyFieldsError();\n        formsHolder.addView(logInForm);\n    }\n\n    private void showCustomFieldsForm(@NonNull DatabaseSignUpEvent event) {\n        removePreviousForm();\n\n        if (customFieldsForm == null) {\n            customFieldsForm = new CustomFieldsFormView(lockWidget, event.getEmail(), event.getPassword(), event.getUsername());\n        }\n        formsHolder.addView(customFieldsForm);\n    }\n\n    private void removePreviousForm() {\n        View existingForm = getExistingForm();\n        if (existingForm != null) {\n            formsHolder.removeView(existingForm);\n        }\n    }\n\n    @Nullable\n    private View getExistingForm() {\n        return formsHolder == null ? null : formsHolder.getChildAt(formsHolder.getChildCount() == 1 ? SINGLE_FORM_POSITION : MULTIPLE_FORMS_POSITION);\n    }\n\n    /**\n     * Triggers the back action on the form.\n     *\n     * @return true if it was handled, false otherwise\n     */\n    public boolean onBackPressed() {\n        return logInForm != null && logInForm.onBackPressed();\n    }\n\n    /**\n     * ActionButton has been clicked, and validation should be run on the current\n     * visible form. If this validation passes, an action event will be returned.\n     *\n     * @return the action event of the current visible form or null if validation failed\n     */\n    @Nullable\n    public Object onActionPressed() {\n        View existingForm = getExistingForm();\n        if (existingForm == null) {\n            return null;\n        }\n\n        FormView form = (FormView) existingForm;\n        Object ev = form.submitForm();\n        Configuration configuration = lockWidget.getConfiguration();\n        if (ev == null || configuration.getVisibleSignUpFields().size() <= configuration.getVisibleSignUpFieldsThreshold()) {\n            return ev;\n        } else if (existingForm == signUpForm) {\n            //User has configured some extra SignUp custom fields.\n            DatabaseSignUpEvent event = (DatabaseSignUpEvent) ev;\n            showCustomFieldsForm(event);\n            return null;\n        }\n        return ev;\n    }\n\n    @Override\n    public void onModeSelected(@AuthMode int mode) {\n        Log.d(TAG, \"Mode changed to \" + mode);\n        changeFormMode(mode);\n    }\n\n    @SuppressLint(\"WrongConstant\")\n    @Override\n    @AuthMode\n    public int getSelectedMode() {\n        return lastFormMode;\n    }\n\n    @Override\n    public void onEmailChanged(@NonNull String currentValue) {\n        lastEmailInput = currentValue;\n    }\n\n    public void refreshIdentityInput() {\n        if (logInForm != null) {\n            logInForm.setLastEmail(lastEmailInput);\n        }\n        if (signUpForm != null) {\n            signUpForm.setLastEmail(lastEmailInput);\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/FormView.java",
    "content": "/*\n * FormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.widget.RelativeLayout;\n\npublic abstract class FormView extends RelativeLayout {\n\n    public FormView(@NonNull Context context) {\n        super(context);\n    }\n\n    @Nullable\n    public abstract Object getActionEvent();\n\n    public abstract boolean validateForm();\n\n\n    /**\n     * ActionButton has been clicked, and validation should be run on the current\n     * visible form. If this validation passes, an action event will be returned.\n     *\n     * @return the action event of the current visible form or null if validation failed\n     */\n    @Nullable\n    public abstract Object submitForm();\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/HeaderView.java",
    "content": "/*\n * HeaderView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport androidx.annotation.ColorRes;\nimport androidx.annotation.DrawableRes;\nimport androidx.annotation.NonNull;\nimport androidx.core.content.ContextCompat;\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.Theme;\n\n@SuppressLint(\"ViewConstructor\")\npublic class HeaderView extends RelativeLayout {\n    private View header;\n    private ImageView logo;\n    private TextView text;\n\n    public HeaderView(@NonNull Context context, @NonNull Theme lockTheme) {\n        super(context);\n        init(lockTheme);\n    }\n\n    private void init(Theme lockTheme) {\n        inflate(getContext(), R.layout.com_auth0_lock_header, this);\n        header = findViewById(R.id.com_auth0_lock_header_background);\n        logo = findViewById(R.id.com_auth0_lock_header_logo);\n        text = findViewById(R.id.com_auth0_lock_header_text);\n        header.setBackgroundColor(lockTheme.getHeaderColor(getContext()));\n        logo.setImageDrawable(lockTheme.getHeaderLogo(getContext()));\n        text.setText(lockTheme.getHeaderTitle(getContext()));\n        text.setTextColor(lockTheme.getHeaderTitleColor(getContext()));\n    }\n\n    /**\n     * Setter for the Header's background color.\n     *\n     * @param color the color to use\n     */\n    public void setColor(@ColorRes int color) {\n        this.header.setBackgroundColor(ContextCompat.getColor(getContext(), color));\n    }\n\n    /**\n     * Setter for the Header's title.\n     *\n     * @param title the title to use\n     */\n    public void setTitle(@NonNull String title) {\n        this.text.setText(title);\n    }\n\n    public void showTitle(boolean show) {\n        text.setVisibility(show ? VISIBLE : GONE);\n    }\n\n    /**\n     * Setter for the Header's logo.\n     *\n     * @param logo the logo to use\n     */\n    public void setLogo(@DrawableRes int logo) {\n        this.logo.setImageResource(logo);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ImageCheckbox.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport android.graphics.Rect;\nimport android.graphics.drawable.Drawable;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.core.content.ContextCompat;\nimport androidx.core.view.AccessibilityDelegateCompat;\nimport androidx.core.view.ViewCompat;\nimport androidx.core.view.accessibility.AccessibilityEventCompat;\nimport androidx.core.view.accessibility.AccessibilityNodeInfoCompat;\nimport androidx.appcompat.widget.AppCompatImageButton;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.view.accessibility.AccessibilityEvent;\nimport android.widget.Checkable;\nimport android.widget.ImageButton;\n\nimport com.auth0.android.lock.R;\n\n/**\n * A custom CheckBox implementation that doesn't have a TextView next to the ImageView, and changes the background drawable when focused.\n */\npublic class ImageCheckbox extends AppCompatImageButton implements Checkable {\n\n    private static final int[] DRAWABLE_STATE_CHECKED = new int[]{android.R.attr.state_checked};\n    private final Drawable focusedBackground;\n\n    private boolean mChecked;\n    private OnCheckedChangeListener checkedChangedListener;\n\n    public ImageCheckbox(@NonNull Context context) {\n        this(context, null);\n    }\n\n    public ImageCheckbox(@NonNull Context context, @NonNull AttributeSet attrs) {\n        this(context, attrs, R.attr.imageButtonStyle);\n    }\n\n    public ImageCheckbox(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n\n        ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegateCompat() {\n            @Override\n            public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {\n                super.onInitializeAccessibilityEvent(host, event);\n                event.setChecked(isChecked());\n            }\n\n            @Override\n            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {\n                super.onInitializeAccessibilityNodeInfo(host, info);\n                info.setCheckable(true);\n                info.setChecked(isChecked());\n            }\n        });\n        setOnClickListener(v -> toggle());\n        ViewUtils.setBackground(this, null);\n        focusedBackground = ContextCompat.getDrawable(getContext(), R.drawable.com_auth0_lock_link_background);\n    }\n\n\n    @Override\n    public void setChecked(boolean checked) {\n        if (mChecked != checked) {\n            mChecked = checked;\n            refreshDrawableState();\n            //noinspection deprecation\n            sendAccessibilityEvent(AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);\n            if (checkedChangedListener != null) {\n                checkedChangedListener.onCheckedChanged(this, checked);\n            }\n        }\n    }\n\n    @Override\n    public boolean isChecked() {\n        return mChecked;\n    }\n\n    @Override\n    public void toggle() {\n        setChecked(!mChecked);\n    }\n\n    @NonNull\n    @Override\n    public int[] onCreateDrawableState(int extraSpace) {\n        if (mChecked) {\n            return mergeDrawableStates(super.onCreateDrawableState(extraSpace + DRAWABLE_STATE_CHECKED.length), DRAWABLE_STATE_CHECKED);\n        } else {\n            return super.onCreateDrawableState(extraSpace);\n        }\n    }\n\n    @Override\n    protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {\n        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);\n        ViewUtils.setBackground(this, gainFocus ? focusedBackground : null);\n    }\n\n    void setOnCheckedChangeListener(OnCheckedChangeListener listener) {\n        checkedChangedListener = listener;\n    }\n\n    interface OnCheckedChangeListener {\n        void onCheckedChanged(ImageButton view, boolean isChecked);\n    }\n\n}\n\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/LinkTextView.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport android.graphics.Rect;\nimport android.graphics.drawable.Drawable;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.core.content.ContextCompat;\nimport android.util.AttributeSet;\n\nimport com.auth0.android.lock.R;\n\n/**\n * A custom AppCompatTextView implementation that changes the background drawable when focused.\n */\npublic class LinkTextView extends androidx.appcompat.widget.AppCompatTextView {\n    private Drawable focusedBackground;\n\n    public LinkTextView(@NonNull Context context) {\n        super(context);\n        init();\n    }\n\n    public LinkTextView(@NonNull Context context, @NonNull AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public LinkTextView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init();\n    }\n\n    private void init() {\n        focusedBackground = ContextCompat.getDrawable(getContext(), R.drawable.com_auth0_lock_link_background);\n        setFocusableInTouchMode(false);\n        setFocusable(true);\n    }\n\n    @Override\n    protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {\n        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);\n        ViewUtils.setBackground(this, gainFocus ? focusedBackground : null);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/LogInFormView.java",
    "content": "/*\n * LogInFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android.util.Log;\nimport android.view.KeyEvent;\nimport android.view.View;\nimport android.view.inputmethod.EditorInfo;\nimport android.view.inputmethod.InputMethodManager;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.DatabaseLoginEvent;\nimport com.auth0.android.lock.events.LockMessageEvent;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.internal.configuration.AuthMode;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\nimport com.auth0.android.lock.utils.EnterpriseConnectionMatcher;\nimport com.auth0.android.lock.views.interfaces.IdentityListener;\nimport com.auth0.android.lock.views.interfaces.LockWidgetForm;\n\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType;\n\npublic class LogInFormView extends FormView implements TextView.OnEditorActionListener, IdentityListener {\n\n    private static final String TAG = LogInFormView.class.getSimpleName();\n    private final LockWidgetForm lockWidget;\n    private ValidatedUsernameInputView emailInput;\n    private ValidatedUsernameInputView usernameInput;\n    private ValidatedInputView passwordInput;\n    private SocialButton enterpriseBtn;\n    private View changePasswordBtn;\n    private TextView topMessage;\n    private OAuthConnection currentConnection;\n    private String currentUsername;\n    private EnterpriseConnectionMatcher domainParser;\n    private boolean fallbackToDatabase;\n    private boolean corporateSSO;\n    private boolean changePasswordEnabled;\n\n    public LogInFormView(@NonNull Context context) {\n        super(context);\n        lockWidget = null;\n    }\n\n    public LogInFormView(@NonNull LockWidgetForm lockWidget) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_login_form_view, this);\n        changePasswordBtn = findViewById(R.id.com_auth0_lock_change_password_btn);\n        enterpriseBtn = findViewById(R.id.com_auth0_lock_enterprise_button);\n        topMessage = findViewById(R.id.com_auth0_lock_text);\n        Configuration configuration = lockWidget.getConfiguration();\n        domainParser = new EnterpriseConnectionMatcher(configuration.getEnterpriseConnections());\n        usernameInput = findViewById(R.id.com_auth0_lock_input_username);\n        usernameInput.setDataType(DataType.NON_EMPTY_USERNAME);\n        passwordInput = findViewById(R.id.com_auth0_lock_input_password);\n        passwordInput.setDataType(DataType.PASSWORD);\n        passwordInput.setAllowShowPassword(configuration.allowShowPassword());\n        passwordInput.setOnEditorActionListener(this);\n\n        emailInput = findViewById(R.id.com_auth0_lock_input_username_email);\n        emailInput.configureFrom(configuration.getDatabaseConnection());\n        emailInput.setUsernameStyle(configuration.getUsernameStyle());\n        emailInput.setIdentityListener(this);\n\n        fallbackToDatabase = configuration.getDatabaseConnection() != null;\n        changePasswordEnabled = fallbackToDatabase && configuration.allowForgotPassword();\n        changePasswordBtn.setVisibility(changePasswordEnabled ? VISIBLE : GONE);\n        changePasswordBtn.setOnClickListener(v -> lockWidget.showChangePasswordForm(true));\n        boolean socialAvailable = !configuration.getSocialConnections().isEmpty();\n        boolean singleEnterprise = configuration.getEnterpriseConnections().size() == 1;\n        if (!fallbackToDatabase && !socialAvailable && singleEnterprise) {\n            Log.v(TAG, \"Only one enterprise connection was found.\");\n            setupSingleConnectionUI(configuration.getEnterpriseConnections().get(0));\n        } else {\n            Log.v(TAG, \"Multiple enterprise/database connections found.\");\n            setupMultipleConnectionUI();\n        }\n    }\n\n    private void setupMultipleConnectionUI() {\n        usernameInput.setVisibility(View.GONE);\n        passwordInput.setVisibility(fallbackToDatabase ? VISIBLE : GONE);\n        emailInput.setOnEditorActionListener(this);\n        emailInput.addTextChangedListener(new TextWatcher() {\n            @Override\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n            }\n\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n            }\n\n            @Override\n            public void afterTextChanged(Editable s) {\n                String text = s.toString();\n                if (text.isEmpty()) {\n                    return;\n                }\n\n                currentConnection = domainParser.parse(text);\n                currentUsername = domainParser.extractUsername(text);\n                if (currentConnection != null) {\n                    Log.v(TAG, String.format(\"Matched results are connection %s with username %s\", currentConnection, currentUsername));\n                    passwordInput.setVisibility(GONE);\n                    showSSOMessage(true);\n                } else if (fallbackToDatabase) {\n                    passwordInput.setVisibility(VISIBLE);\n                    showSSOMessage(false);\n                } else {\n                    resetDomain();\n                }\n            }\n        });\n    }\n\n    private void setupSingleConnectionUI(final OAuthConnection connection) {\n        final int strategyStyle = AuthConfig.styleForStrategy(connection.getStrategy());\n        final AuthConfig authConfig = new AuthConfig(connection, strategyStyle);\n        enterpriseBtn.setStyle(authConfig, AuthMode.LOG_IN);\n        enterpriseBtn.setVisibility(View.VISIBLE);\n        enterpriseBtn.setOnClickListener(v -> lockWidget.onOAuthLoginRequest(new OAuthLoginEvent(connection)));\n        topMessage.setText(R.string.com_auth0_lock_action_single_login_with_corporate);\n        topMessage.setVisibility(View.VISIBLE);\n        emailInput.setVisibility(GONE);\n    }\n\n    private void resetDomain() {\n        emailInput.setVisibility(View.VISIBLE);\n        passwordInput.setVisibility(View.GONE);\n        passwordInput.clearInput();\n        usernameInput.setVisibility(View.GONE);\n        usernameInput.clearInput();\n        topMessage.setText(null);\n        topMessage.setVisibility(View.GONE);\n        corporateSSO = false;\n        showSSOMessage(false);\n    }\n\n    private String getUsername() {\n        boolean usingDatabase = currentConnection == null && fallbackToDatabase;\n        boolean usingOAuthEnterprise = currentConnection != null && !currentConnection.isActiveFlowEnabled();\n        if (usingDatabase || usingOAuthEnterprise) {\n            return emailInput.getText().trim();\n        } else {\n            //Using RO: we get the Username from the \"second screen\".\n            return usernameInput.getText().trim();\n        }\n    }\n\n    private String getPassword() {\n        return passwordInput.getText();\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        if (!validateForm()) {\n            Log.w(TAG, \"Form has some validation issues and won't be submitted.\");\n            return null;\n        }\n\n        if (currentConnection == null || !currentConnection.isActiveFlowEnabled() || passwordInput.getVisibility() == VISIBLE) {\n            return getActionEvent();\n        }\n\n        Log.d(TAG, \"Now showing SSO Login Form for connection \" + currentConnection);\n        String loginWithCorporate = String.format(getResources().getString(R.string.com_auth0_lock_action_login_with_corporate), domainParser.domainForConnection(currentConnection));\n        topMessage.setText(loginWithCorporate);\n        topMessage.setVisibility(View.VISIBLE);\n        emailInput.setVisibility(GONE);\n        passwordInput.setVisibility(View.VISIBLE);\n        usernameInput.setVisibility(VISIBLE);\n        if (currentUsername != null && !currentUsername.isEmpty()) {\n            usernameInput.setText(currentUsername);\n        }\n        changePasswordBtn.setVisibility(GONE);\n        corporateSSO = true;\n        usernameInput.clearFocus();\n        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);\n        imm.hideSoftInputFromWindow(getWindowToken(), 0);\n        return null;\n    }\n\n    @NonNull\n    @Override\n    public Object getActionEvent() {\n        if (currentConnection != null && currentConnection.isActiveFlowEnabled()) {\n            Log.d(TAG, String.format(\"Form submitted. Logging in with enterprise connection %s using active flow\", currentConnection.getName()));\n            return new OAuthLoginEvent(currentConnection, getUsername(), getPassword());\n        }\n        if (currentConnection != null) {\n            Log.d(TAG, String.format(\"Form submitted. Logging in with enterprise connection %s using authorize screen\", currentConnection.getName()));\n            return new OAuthLoginEvent(currentConnection, getUsername(), null);\n        }\n        if (fallbackToDatabase) {\n            Log.d(TAG, \"Logging in with database connection using active flow\");\n            return new DatabaseLoginEvent(getUsername(), getPassword());\n        }\n        return new LockMessageEvent(R.string.com_auth0_lock_enterprise_no_connection_message);\n    }\n\n    @Override\n    public boolean validateForm() {\n        boolean valid = true;\n        if (emailInput.getVisibility() == VISIBLE) {\n            valid = emailInput.validate();\n        }\n        if (usernameInput.getVisibility() == VISIBLE) {\n            valid = usernameInput.validate() && valid;\n        }\n        if (passwordInput.getVisibility() == VISIBLE) {\n            valid = passwordInput.validate() && valid;\n        }\n        return valid;\n    }\n\n    /**\n     * Triggers the back action on the form.\n     *\n     * @return true if it was handled, false otherwise\n     */\n    public boolean onBackPressed() {\n        if (corporateSSO) {\n            Log.d(TAG, \"Removing the SSO Login Form, going back to the Username/Password Form.\");\n            resetDomain();\n            showSSOMessage(true);\n            return true;\n        }\n        return false;\n    }\n\n    private void showSSOMessage(boolean show) {\n        lockWidget.showTopBanner(show);\n        if (changePasswordEnabled) {\n            changePasswordBtn.setVisibility(show ? GONE : VISIBLE);\n        }\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT && currentConnection != null) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n\n    public void setLastEmail(@Nullable String email) {\n        emailInput.setText(email);\n        passwordInput.clearInput();\n    }\n\n    @Override\n    public void onEmailChanged(@NonNull String email) {\n        lockWidget.onEmailChanged(email);\n    }\n\n    public void clearEmptyFieldsError() {\n        if (usernameInput.getText().isEmpty()) {\n            usernameInput.clearInput();\n        }\n        if (emailInput.getText().isEmpty()) {\n            emailInput.clearInput();\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/MFACodeFormView.java",
    "content": "/*\n * MFACodeFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.view.KeyEvent;\nimport android.view.inputmethod.EditorInfo;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.DatabaseLoginEvent;\nimport com.auth0.android.lock.views.interfaces.LockWidget;\n\n@SuppressLint(\"ViewConstructor\")\npublic class MFACodeFormView extends FormView implements TextView.OnEditorActionListener {\n\n    private final String usernameOrEmail;\n    private final String password;\n    private final String mfaToken;\n    private final String mfaChallengeType;\n    private final String mfaOOBCode;\n\n    private final LockWidget lockWidget;\n    private ValidatedInputView codeInput;\n\n\n    public MFACodeFormView(@NonNull LockWidget lockWidget, @Nullable String usernameOrEmail, @Nullable String password, @Nullable String mfaToken, @Nullable String mfaChallengeType, @Nullable String mfaOOBCode) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        this.usernameOrEmail = usernameOrEmail;\n        this.password = password;\n        this.mfaToken = mfaToken;\n        this.mfaChallengeType = mfaChallengeType;\n        this.mfaOOBCode = mfaOOBCode;\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_mfa_input_code_form_view, this);\n        codeInput = findViewById(R.id.com_auth0_lock_input_code);\n        codeInput.setHint(R.string.com_auth0_lock_hint_mfa_code);\n        codeInput.setOnEditorActionListener(this);\n    }\n\n    @NonNull\n    @Override\n    public Object getActionEvent() {\n        DatabaseLoginEvent event = new DatabaseLoginEvent(usernameOrEmail, password);\n        event.setMultifactorOTP(getInputText());\n        event.setMultifactorToken(mfaToken);\n        event.setMultifactorChallengeType(mfaChallengeType);\n        event.setMultifactorOOBCode(mfaOOBCode);\n        return event;\n    }\n\n    private String getInputText() {\n        return codeInput.getText().replace(\" \", \"\");\n    }\n\n    @Override\n    public boolean validateForm() {\n        return codeInput.validate();\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        return validateForm() ? getActionEvent() : null;\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ModeSelectionView.java",
    "content": "/*\n * ModeSelectionView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.graphics.Typeface;\nimport androidx.annotation.NonNull;\nimport com.google.android.material.tabs.TabLayout;\nimport android.view.View;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.AuthMode;\n\n@SuppressLint(\"ViewConstructor\")\npublic class ModeSelectionView extends LinearLayout implements TabLayout.OnTabSelectedListener {\n\n    private final ModeSelectedListener callback;\n    private TabLayout tabLayout;\n    private View firstTabView;\n    private View secondTabView;\n\n    public ModeSelectionView(@NonNull Context context, @NonNull ModeSelectedListener listener) {\n        super(context);\n        this.callback = listener;\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_tab_layout, this);\n        tabLayout = findViewById(R.id.com_auth0_lock_tab_layout);\n\n        View tabDescription1 = inflate(getContext(), R.layout.com_auth0_lock_tab, null);\n        View tabDescription2 = inflate(getContext(), R.layout.com_auth0_lock_tab, null);\n\n        final TabLayout.Tab firstTab = tabLayout.newTab()\n                .setCustomView(tabDescription1)\n                .setText(R.string.com_auth0_lock_mode_log_in);\n        final TabLayout.Tab secondTab = tabLayout.newTab()\n                .setCustomView(tabDescription2)\n                .setText(R.string.com_auth0_lock_mode_sign_up);\n        firstTabView = (View) tabDescription1.getParent();\n        secondTabView = (View) tabDescription2.getParent();\n\n        firstTabView.setOnClickListener(view -> setSelectedMode(AuthMode.LOG_IN));\n        secondTabView.setOnClickListener(view -> setSelectedMode(AuthMode.SIGN_UP));\n\n        tabLayout.addTab(firstTab);\n        tabLayout.addTab(secondTab);\n    }\n\n    public void setSelectedMode(@AuthMode int mode) {\n        TabLayout.Tab tab = tabLayout.getTabAt(mode);\n        tab.select();\n        toggleBoldText(firstTabView, mode == AuthMode.LOG_IN);\n        toggleBoldText(secondTabView, mode == AuthMode.SIGN_UP);\n        callback.onModeSelected(mode);\n    }\n\n    private void toggleBoldText(View tabView, boolean bold) {\n        final TextView text = tabView.findViewById(android.R.id.text1);\n        text.setTypeface(bold ? text.getTypeface() : null, bold ? Typeface.BOLD : Typeface.NORMAL);\n    }\n\n    @Override\n    @Deprecated\n    public void onTabSelected(@NonNull TabLayout.Tab tab) {\n        //No-Op\n    }\n\n    @Override\n    @Deprecated\n    public void onTabUnselected(@NonNull TabLayout.Tab tab) {\n        //No-Op\n    }\n\n    @Override\n    @Deprecated\n    public void onTabReselected(@NonNull TabLayout.Tab tab) {\n        //No-Op\n    }\n\n    public interface ModeSelectedListener {\n        void onModeSelected(@AuthMode int mode);\n\n        @AuthMode\n        int getSelectedMode();\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/PasswordStrengthView.java",
    "content": "/*\n * CheckableOptionView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.PasswordComplexity;\nimport com.auth0.android.lock.internal.configuration.PasswordStrength;\n\nimport java.util.regex.Pattern;\n\n\npublic class PasswordStrengthView extends LinearLayout {\n\n    private static final int MAX_IDENTICAL_CHARACTERS = 2;\n    private static final int MAX_LENGTH = 128;\n    private static final int MIN_LENGTH_EXCELLENT = 10;\n    private static final int MIN_LENGTH_GOOD = 8;\n    private static final int MIN_LENGTH_FAIR = 8;\n    private static final int MIN_LENGTH_LOW = 6;\n    private static final int MIN_LENGTH_NONE = 1;\n\n    private final Pattern patternUppercase = Pattern.compile(\"^.*[A-Z]+.*$\");\n    private final Pattern patternLowercase = Pattern.compile(\"^.*[a-z]+.*$\");\n    private final Pattern patternSpecial = Pattern.compile(\"^.*[ !\\\"#$%&'()*+,-./:;<=>?@\\\\[\\\\\\\\\\\\]^_`{|}~]+.*$\");\n    private final Pattern patternNumeric = Pattern.compile(\"^.*[0-9]+.*$\");\n    private final Pattern patternIdentical = Pattern.compile(\"^.*(?=(.)\\\\1{\" + MAX_IDENTICAL_CHARACTERS + \",}).*$\");\n\n    private PasswordComplexity complexity;\n\n    private TextView titleAtLeast;\n    private CheckableOptionView optionLength;\n    private CheckableOptionView optionIdenticalCharacters;\n    private CheckableOptionView optionLowercase;\n    private CheckableOptionView optionUppercase;\n    private CheckableOptionView optionNumeric;\n    private CheckableOptionView optionSpecialCharacters;\n\n    public PasswordStrengthView(@NonNull Context context) {\n        super(context);\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_password_strength, this);\n        titleAtLeast = findViewById(R.id.com_auth0_lock_password_strength_title_at_least);\n\n        optionLength = findViewById(R.id.com_auth0_lock_password_strength_option_length);\n        optionLength.setMandatory(true);\n        optionIdenticalCharacters = findViewById(R.id.com_auth0_lock_password_strength_option_identical_characters);\n        optionIdenticalCharacters.setMandatory(true);\n        optionIdenticalCharacters.setChecked(true);\n        optionLowercase = findViewById(R.id.com_auth0_lock_password_strength_option_lowercase);\n        optionUppercase = findViewById(R.id.com_auth0_lock_password_strength_option_uppercase);\n        optionNumeric = findViewById(R.id.com_auth0_lock_password_strength_option_numeric);\n        optionSpecialCharacters = findViewById(R.id.com_auth0_lock_password_strength_option_special_characters);\n        //noinspection deprecation\n        setStrength(PasswordStrength.NONE);\n    }\n\n    /**\n     * @see \"https://auth0.com/docs/connections/database/password-strength\"\n     */\n    @SuppressLint(\"StringFormatInvalid\")\n    private void showPolicy() {\n        int strength = complexity.getPasswordPolicy();\n        if (strength == PasswordStrength.NONE) {\n            setEnabled(false);\n            setVisibility(GONE);\n            return;\n        }\n        setEnabled(true);\n        setVisibility(VISIBLE);\n\n        optionLowercase.setMandatory(strength == PasswordStrength.FAIR);\n        optionUppercase.setMandatory(strength == PasswordStrength.FAIR);\n        optionNumeric.setMandatory(strength == PasswordStrength.FAIR);\n\n        titleAtLeast.setVisibility(strength == PasswordStrength.FAIR || strength == PasswordStrength.LOW ? GONE : VISIBLE);\n        String lengthRequirements = getContext().getResources().getString(R.string.com_auth0_lock_password_strength_chars_length);\n        optionLength.setText(String.format(lengthRequirements, getMinimumLength()));\n\n        optionLowercase.setVisibility(strength == PasswordStrength.LOW ? GONE : VISIBLE);\n        optionUppercase.setVisibility(strength == PasswordStrength.LOW ? GONE : VISIBLE);\n        optionNumeric.setVisibility(strength == PasswordStrength.LOW ? GONE : VISIBLE);\n        optionSpecialCharacters.setVisibility(strength == PasswordStrength.EXCELLENT || strength == PasswordStrength.GOOD ? VISIBLE : GONE);\n        optionIdenticalCharacters.setVisibility(strength == PasswordStrength.EXCELLENT ? VISIBLE : GONE);\n    }\n\n    private boolean hasIdenticalCharacters(@NonNull String input) {\n        boolean v = !patternIdentical.matcher(input).matches();\n        optionIdenticalCharacters.setChecked(v);\n        return v;\n    }\n\n    private boolean hasUppercaseCharacters(@NonNull String input) {\n        boolean v = patternUppercase.matcher(input).matches();\n        optionUppercase.setChecked(v);\n        return v;\n    }\n\n    private boolean hasLowercaseCharacters(@NonNull String input) {\n        boolean v = patternLowercase.matcher(input).matches();\n        optionLowercase.setChecked(v);\n        return v;\n    }\n\n    private boolean hasNumericCharacters(@NonNull String input) {\n        boolean v = patternNumeric.matcher(input).matches();\n        optionNumeric.setChecked(v);\n        return v;\n    }\n\n    private boolean hasSpecialCharacters(@NonNull String input) {\n        boolean v = patternSpecial.matcher(input).matches();\n        optionSpecialCharacters.setChecked(v);\n        return v;\n    }\n\n    private boolean hasMinimumLength(@NonNull String input, int length) {\n        boolean v = input.length() >= length && input.length() <= MAX_LENGTH;\n        optionLength.setChecked(v);\n        return v;\n    }\n\n    private boolean atLeastThree(boolean a, boolean b, boolean c, boolean d) {\n        boolean all = a && b && c && d;\n        boolean one = a && b && (c ^ d);\n        boolean two = b && c && (d ^ a);\n        boolean three = c && d && (a ^ b);\n\n        return all || one || two || three;\n    }\n\n    private boolean allThree(boolean a, boolean b, boolean c) {\n        return a && b && c;\n    }\n\n    private int getMinimumLength() {\n        Integer minLengthOverride = complexity.getMinLengthOverride();\n        if (minLengthOverride != null) {\n            return minLengthOverride;\n        }\n        switch (complexity.getPasswordPolicy()) {\n            case PasswordStrength.EXCELLENT:\n                return MIN_LENGTH_EXCELLENT;\n            case PasswordStrength.GOOD:\n                return MIN_LENGTH_GOOD;\n            case PasswordStrength.FAIR:\n                return MIN_LENGTH_FAIR;\n            case PasswordStrength.LOW:\n                return MIN_LENGTH_LOW;\n            default:\n            case PasswordStrength.NONE:\n                return MIN_LENGTH_NONE;\n        }\n    }\n\n    /**\n     * Sets the current level of Strength that this widget is going to validate.\n     *\n     * @param strength the required strength level.\n     * @deprecated use the {@link #setPasswordComplexity(PasswordComplexity)} method\n     */\n    @SuppressWarnings(\"DeprecatedIsStillUsed\")\n    @Deprecated\n    public void setStrength(@PasswordStrength int strength) {\n        this.setPasswordComplexity(new PasswordComplexity(strength, null));\n    }\n\n    /**\n     * Sets the password complexity options that this widget is going to validate.\n     *\n     * @param complexity the password complexity to require on this widget\n     */\n    public void setPasswordComplexity(@NonNull PasswordComplexity complexity) {\n        this.complexity = complexity;\n        showPolicy();\n    }\n\n    /**\n     * Checks that all the requirements are meet.\n     *\n     * @param password the current password to validate\n     * @return whether the given password complies with this password policy or not.\n     */\n    public boolean isValid(@Nullable String password) {\n        if (password == null) {\n            return false;\n        }\n\n        boolean length = hasMinimumLength(password, getMinimumLength());\n        boolean other = true;\n        switch (complexity.getPasswordPolicy()) {\n            case PasswordStrength.EXCELLENT:\n                boolean atLeast = atLeastThree(hasLowercaseCharacters(password), hasUppercaseCharacters(password), hasNumericCharacters(password), hasSpecialCharacters(password));\n                other = hasIdenticalCharacters(password) && atLeast;\n                break;\n            case PasswordStrength.GOOD:\n                other = atLeastThree(hasLowercaseCharacters(password), hasUppercaseCharacters(password), hasNumericCharacters(password), hasSpecialCharacters(password));\n                break;\n            case PasswordStrength.FAIR:\n                other = allThree(hasLowercaseCharacters(password), hasUppercaseCharacters(password), hasNumericCharacters(password));\n                break;\n            case PasswordStrength.LOW:\n            case PasswordStrength.NONE:\n        }\n        return length && other;\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/PasswordlessFormLayout.java",
    "content": "/*\n * PasswordlessFormLayout.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.appcompat.widget.AppCompatTextView;\nimport androidx.core.content.ContextCompat;\nimport android.util.Log;\nimport android.util.TypedValue;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.lock.views.interfaces.LockWidgetPasswordless;\n\npublic class PasswordlessFormLayout extends LinearLayout implements PasswordlessInputCodeFormView.OnCodeResendListener {\n\n    private static final String TAG = PasswordlessFormLayout.class.getSimpleName();\n\n    private final LockWidgetPasswordless lockWidget;\n    private SocialView socialLayout;\n    private TextView orSeparatorMessage;\n    private PasswordlessRequestCodeFormView passwordlessRequestCodeLayout;\n    private PasswordlessInputCodeFormView passwordlessInputCodeLayout;\n\n    public PasswordlessFormLayout(@NonNull Context context) {\n        super(context);\n        lockWidget = null;\n    }\n\n    public PasswordlessFormLayout(@NonNull LockWidgetPasswordless lockWidget) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        init();\n    }\n\n    private void init() {\n        setOrientation(VERTICAL);\n        setGravity(Gravity.CENTER);\n        boolean showSocial = !lockWidget.getConfiguration().getSocialConnections().isEmpty();\n        boolean showPasswordless = lockWidget.getConfiguration().getPasswordlessConnection() != null;\n\n        if (showSocial) {\n            addSocialLayout();\n        }\n        if (showPasswordless) {\n            if (showSocial) {\n                addSeparator();\n            }\n            addPasswordlessRequestCodeLayout();\n        }\n        final int verticalPadding = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        setPadding(0, verticalPadding, 0, verticalPadding);\n        setPaddingRelative(0, verticalPadding, 0, verticalPadding);\n    }\n\n    private void addSocialLayout() {\n        socialLayout = new SocialView(lockWidget, false);\n        addView(socialLayout);\n    }\n\n    private void addSeparator() {\n        orSeparatorMessage = new AppCompatTextView(getContext());\n        int passwordlessMode = lockWidget.getConfiguration().getPasswordlessMode();\n        int stringRes = R.string.com_auth0_lock_passwordless_email_forms_separator;\n        if (passwordlessMode == PasswordlessMode.SMS_LINK || passwordlessMode == PasswordlessMode.SMS_CODE) {\n            stringRes = R.string.com_auth0_lock_passwordless_sms_forms_separator;\n        }\n        orSeparatorMessage.setText(stringRes);\n        orSeparatorMessage.setLineSpacing(getResources().getDimension(R.dimen.com_auth0_lock_separator_text_spacing), 1);\n        orSeparatorMessage.setTextColor(ContextCompat.getColor(getContext(), R.color.com_auth0_lock_text));\n        orSeparatorMessage.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.com_auth0_lock_title_text));\n        orSeparatorMessage.setGravity(Gravity.CENTER);\n        int verticalPadding = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        params.setMargins(0, verticalPadding, 0, verticalPadding);\n        params.setMarginStart(0);\n        params.setMarginEnd(0);\n        addView(orSeparatorMessage, params);\n    }\n\n    private void addPasswordlessRequestCodeLayout() {\n        if (passwordlessRequestCodeLayout == null) {\n            passwordlessRequestCodeLayout = new PasswordlessRequestCodeFormView(lockWidget);\n        }\n        addView(passwordlessRequestCodeLayout);\n    }\n\n    private void addPasswordlessInputCodeLayout(@NonNull String emailOrNumber) {\n        passwordlessInputCodeLayout = new PasswordlessInputCodeFormView(lockWidget, this, emailOrNumber);\n        addView(passwordlessInputCodeLayout);\n    }\n\n    /**\n     * Triggers the back action on the form.\n     *\n     * @return true if it was handled, false otherwise\n     */\n    public boolean onBackPressed() {\n        if (passwordlessInputCodeLayout != null) {\n            Log.d(TAG, \"Removing the Code Input Form, going back to the Social/Passwordless Form.\");\n            if (socialLayout != null) {\n                socialLayout.setVisibility(VISIBLE);\n            }\n            if (orSeparatorMessage != null) {\n                orSeparatorMessage.setVisibility(VISIBLE);\n            }\n            removeView(passwordlessInputCodeLayout);\n            addView(passwordlessRequestCodeLayout);\n            passwordlessInputCodeLayout = null;\n            lockWidget.resetHeaderTitle();\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * Notifies the form that the code was correctly sent and it should now wait\n     * for the user to input the valid code.\n     *\n     * @param emailOrNumber the email or phone number to which the code was sent.\n     */\n    public void codeSent(@NonNull String emailOrNumber) {\n        Log.d(TAG, \"Now showing the Code Input Form\");\n        if (passwordlessRequestCodeLayout != null) {\n            removeView(passwordlessRequestCodeLayout);\n            if (socialLayout != null) {\n                socialLayout.setVisibility(GONE);\n            }\n            if (orSeparatorMessage != null) {\n                orSeparatorMessage.setVisibility(GONE);\n            }\n        }\n        addPasswordlessInputCodeLayout(emailOrNumber);\n        lockWidget.updateHeaderTitle(R.string.com_auth0_lock_title_passwordless);\n    }\n\n    /**\n     * ActionButton has been clicked, and validation should be run on the current\n     * visible form. If this validation passes, an action event will be returned.\n     *\n     * @return the action event of the current visible form or null if validation failed\n     */\n    @Nullable\n    public Object onActionPressed() {\n        View existingForm = getChildAt(getChildCount() == 1 ? 0 : 2);\n        if (existingForm != null) {\n            FormView form = (FormView) existingForm;\n            return form.submitForm();\n        }\n        return null;\n    }\n\n    @Override\n    public void onCodeNeedToResend() {\n        if (socialLayout != null) {\n            socialLayout.setVisibility(VISIBLE);\n        }\n        if (orSeparatorMessage != null) {\n            orSeparatorMessage.setVisibility(VISIBLE);\n        }\n        if (passwordlessInputCodeLayout != null) {\n            removeView(passwordlessInputCodeLayout);\n            passwordlessInputCodeLayout = null;\n        }\n        addView(passwordlessRequestCodeLayout);\n        lockWidget.resetHeaderTitle();\n    }\n\n    /**\n     * Notifies the form that a new country code was selected by the user.\n     *\n     * @param country  the selected country iso code (2 chars).\n     * @param dialCode the dial code for this country\n     */\n    public void onCountryCodeSelected(@NonNull String country, @NonNull String dialCode) {\n        if (passwordlessRequestCodeLayout != null) {\n            passwordlessRequestCodeLayout.onCountryCodeSelected(country, dialCode);\n        }\n    }\n\n    public void loadPasswordlessData(@NonNull String emailOrNumber, @Nullable Country country) {\n        if (passwordlessRequestCodeLayout != null) {\n            Log.d(TAG, String.format(\"Loading recent passwordless data into the form. Identity %s with Country %s\", emailOrNumber, country));\n            passwordlessRequestCodeLayout.setInputText(emailOrNumber);\n            if (country != null) {\n                passwordlessRequestCodeLayout.onCountryCodeSelected(country.getIsoCode(), country.getDialCode());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/PasswordlessInputCodeFormView.java",
    "content": "/*\n * PasswordlessFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.util.Log;\nimport android.view.KeyEvent;\nimport android.view.View;\nimport android.view.inputmethod.EditorInfo;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.PasswordlessLoginEvent;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.lock.views.interfaces.LockWidgetPasswordless;\n\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.DISABLED;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_LINK;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_LINK;\n\n@SuppressLint(\"ViewConstructor\")\npublic class PasswordlessInputCodeFormView extends FormView implements View.OnClickListener, TextView.OnEditorActionListener {\n\n    private static final String TAG = PasswordlessInputCodeFormView.class.getSimpleName();\n    private static final long RESEND_TIMEOUT = 20 * 1000;\n\n    private final LockWidgetPasswordless lockWidget;\n    private final OnCodeResendListener listener;\n    private ValidatedInputView passwordlessInput;\n    @PasswordlessMode\n    private final int passwordlessMode;\n    private TextView topMessage;\n    private TextView resendButton;\n\n    /**\n     * Creates a new FormView to request input of the received code.\n     *\n     * @param lockWidget the base passwordless widget\n     * @param listener   a listener to notify when the user clicks \"Resend code\" button.\n     * @param identity   the email or number used to send the passwordless code.\n     */\n    @SuppressLint(\"LambdaLast\")\n    public PasswordlessInputCodeFormView(@NonNull LockWidgetPasswordless lockWidget, @NonNull OnCodeResendListener listener, @NonNull String identity) {\n        super(lockWidget.getContext());\n        passwordlessMode = lockWidget.getConfiguration().getPasswordlessMode();\n        this.lockWidget = lockWidget;\n        this.listener = listener;\n        Log.v(TAG, String.format(\"New instance with mode %s for Identity %s\", passwordlessMode, identity));\n        init(identity);\n    }\n\n    private void init(@NonNull String identity) {\n        inflate(getContext(), R.layout.com_auth0_lock_passwordless_input_code_form_view, this);\n        topMessage = findViewById(R.id.com_auth0_lock_text);\n        resendButton = findViewById(R.id.com_auth0_lock_resend);\n        resendButton.setOnClickListener(this);\n        passwordlessInput = findViewById(R.id.com_auth0_lock_input_passwordless);\n        passwordlessInput.setOnEditorActionListener(this);\n\n        selectPasswordlessMode(identity);\n        removeCallbacks(resendTimeoutShower);\n        postDelayed(resendTimeoutShower, RESEND_TIMEOUT);\n    }\n\n\n    private void selectPasswordlessMode(@NonNull String identity) {\n        int sentMessage = 0;\n        switch (passwordlessMode) {\n            case EMAIL_CODE:\n                sentMessage = R.string.com_auth0_lock_title_passwordless_code_email_sent;\n                break;\n            case EMAIL_LINK:\n                sentMessage = R.string.com_auth0_lock_title_passwordless_link_sent;\n                break;\n            case SMS_CODE:\n                sentMessage = R.string.com_auth0_lock_title_passwordless_code_sms_sent;\n                break;\n            case SMS_LINK:\n                sentMessage = R.string.com_auth0_lock_title_passwordless_link_sent;\n                break;\n            case DISABLED:\n                break;\n        }\n        topMessage.setText(String.format(getContext().getString(sentMessage), identity));\n        passwordlessInput.setDataType(ValidatedInputView.DataType.MFA_CODE);\n        passwordlessInput.setVisibility(VISIBLE);\n        passwordlessInput.clearInput();\n        resendButton.setVisibility(GONE);\n    }\n\n\n    @NonNull\n    @Override\n    public Object getActionEvent() {\n        return PasswordlessLoginEvent.submitCode(passwordlessMode, getInputText());\n    }\n\n    private String getInputText() {\n        return passwordlessInput.getText().replace(\" \", \"\");\n    }\n\n    @Override\n    public boolean validateForm() {\n        return passwordlessInput.validate();\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        return validateForm() ? getActionEvent() : null;\n    }\n\n    final Runnable resendTimeoutShower = new Runnable() {\n        @Override\n        public void run() {\n            resendButton.setVisibility(View.VISIBLE);\n        }\n    };\n\n    @Override\n    public void onClick(@NonNull View v) {\n        int id = v.getId();\n        if (id == R.id.com_auth0_lock_resend) {\n            listener.onCodeNeedToResend();\n        }\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n\n    public interface OnCodeResendListener {\n        /**\n         * Called when the form needs to remove the \"Waiting for the code\" view and show\n         * the email/phone input again.\n         */\n        void onCodeNeedToResend();\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/PasswordlessLockView.java",
    "content": "/*\n * PasswordlessLockView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.net.Uri;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StringRes;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.events.CountryCodeChangeEvent;\nimport com.auth0.android.lock.events.FetchApplicationEvent;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.Theme;\nimport com.auth0.android.lock.views.interfaces.LockWidgetPasswordless;\nimport com.squareup.otto.Bus;\n\n@SuppressWarnings(\"NullableProblems\")\n@SuppressLint(\"ViewConstructor\")\npublic class PasswordlessLockView extends LinearLayout implements LockWidgetPasswordless, View.OnClickListener {\n\n    private static final String TAG = PasswordlessLockView.class.getSimpleName();\n    private final Bus bus;\n    private final Theme lockTheme;\n    private Configuration configuration;\n    private PasswordlessFormLayout formLayout;\n    private ActionButton actionButton;\n    private ProgressBar loadingProgressBar;\n    private HeaderView headerView;\n\n    public PasswordlessLockView(@NonNull Context context, @NonNull Bus lockBus, @NonNull Theme lockTheme) {\n        super(context);\n        this.bus = lockBus;\n        this.lockTheme = lockTheme;\n        showWaitForConfigurationLayout();\n    }\n\n    private void init() {\n        setOrientation(VERTICAL);\n        if (configuration == null) {\n            Log.w(TAG, \"Configuration is missing, the view won't init.\");\n            showConfigurationMissingLayout(true);\n        } else {\n            showContentLayout();\n        }\n    }\n\n    private void showWaitForConfigurationLayout() {\n        LayoutParams wrapHeightParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        wrapHeightParams.gravity = Gravity.CENTER;\n        loadingProgressBar = new ProgressBar(getContext());\n        loadingProgressBar.setIndeterminate(true);\n        addView(loadingProgressBar, wrapHeightParams);\n    }\n\n    private void showContentLayout() {\n        LayoutParams wrapHeightParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n\n        headerView = new HeaderView(getContext(), lockTheme);\n        resetHeaderTitle();\n        addView(headerView, wrapHeightParams);\n\n        int verticalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        int horizontalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_horizontal_margin);\n        formLayout = new PasswordlessFormLayout(this);\n        LayoutParams formLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);\n        formLayout.setPadding(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);\n        formLayout.setPaddingRelative(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);\n        addView(formLayout, formLayoutParams);\n\n        boolean showPasswordless = configuration.getPasswordlessConnection() != null;\n        if (showPasswordless) {\n            actionButton = new ActionButton(getContext(), lockTheme);\n            actionButton.setOnClickListener(this);\n            addView(actionButton, wrapHeightParams);\n        }\n    }\n\n    public void configure(@Nullable Configuration configuration) {\n        removeView(loadingProgressBar);\n        loadingProgressBar = null;\n        this.configuration = configuration;\n        if (configuration != null && configuration.hasPasswordlessConnections()) {\n            init();\n        } else {\n            showConfigurationMissingLayout(configuration == null);\n        }\n    }\n\n    private void showConfigurationMissingLayout(final boolean showRetry) {\n        final View errorLayout = LayoutInflater.from(getContext()).inflate(R.layout.com_auth0_lock_error_layout, this, false);\n        TextView tvTitle = errorLayout.findViewById(R.id.com_auth0_lock_error_title);\n        TextView tvError = errorLayout.findViewById(R.id.com_auth0_lock_error_subtitle);\n        TextView tvAction = errorLayout.findViewById(R.id.com_auth0_lock_error_action);\n\n        if (showRetry) {\n            tvTitle.setText(R.string.com_auth0_lock_recoverable_error_title);\n            tvError.setText(R.string.com_auth0_lock_recoverable_error_subtitle);\n            tvAction.setText(R.string.com_auth0_lock_recoverable_error_action);\n            tvAction.setOnClickListener(v -> {\n                bus.post(new FetchApplicationEvent());\n                removeView(errorLayout);\n                showWaitForConfigurationLayout();\n            });\n        } else if (configuration.getSupportURL() == null) {\n            tvTitle.setText(R.string.com_auth0_lock_unrecoverable_error_title);\n            tvError.setText(R.string.com_auth0_lock_unrecoverable_error_subtitle_without_action);\n            tvAction.setVisibility(GONE);\n        } else {\n            tvTitle.setText(R.string.com_auth0_lock_unrecoverable_error_title);\n            tvError.setText(R.string.com_auth0_lock_unrecoverable_error_subtitle);\n            tvAction.setText(R.string.com_auth0_lock_unrecoverable_error_action);\n            tvAction.setOnClickListener(v -> getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(configuration.getSupportURL()))));\n        }\n        addView(errorLayout);\n    }\n\n    @Override\n    public void updateHeaderTitle(@StringRes int titleRes) {\n        headerView.setTitle(getContext().getString(titleRes));\n        headerView.showTitle(true);\n    }\n\n    @Override\n    public void resetHeaderTitle() {\n        headerView.setTitle(lockTheme.getHeaderTitle(getContext()));\n        headerView.showTitle(!configuration.hideMainScreenTitle());\n    }\n\n    /**\n     * Triggers the back action on the form.\n     *\n     * @return true if it was handled, false otherwise\n     */\n    public boolean onBackPressed() {\n        return formLayout != null && formLayout.onBackPressed();\n    }\n\n    /**\n     * Displays a progress bar on top of the action button. This will also\n     * enable or disable the action button.\n     *\n     * @param show whether to show or hide the action bar.\n     */\n    public void showProgress(boolean show) {\n        if (actionButton != null) {\n            actionButton.showProgress(show);\n        }\n        if (formLayout != null) {\n            formLayout.setEnabled(!show);\n        }\n    }\n\n    /**\n     * Notifies the form that the code was correctly sent and it should now wait\n     * for the user to input the valid code.\n     */\n    @Override\n    public void onPasswordlessCodeSent(@NonNull String emailOrNumber) {\n        formLayout.codeSent(emailOrNumber);\n    }\n\n    @NonNull\n    @Override\n    public Configuration getConfiguration() {\n        return configuration;\n    }\n\n    @Override\n    public void onFormSubmit() {\n        actionButton.callOnClick();\n    }\n\n    @Override\n    public void onOAuthLoginRequest(@NonNull OAuthLoginEvent event) {\n        Log.d(TAG, \"Social login triggered for connection \" + event.getConnection());\n        bus.post(event);\n    }\n\n    @Override\n    public void onClick(@NonNull View v) {\n        Object event = formLayout.onActionPressed();\n        if (event != null) {\n            bus.post(event);\n            actionButton.showProgress(true);\n        }\n    }\n\n    @Override\n    public void onCountryCodeChangeRequest() {\n        bus.post(new CountryCodeChangeEvent());\n    }\n\n    /**\n     * Notifies the form that a new country code was selected by the user.\n     *\n     * @param country  the selected country iso code (2 chars).\n     * @param dialCode the dial code for this country\n     */\n    public void onCountryCodeSelected(@NonNull String country, @NonNull String dialCode) {\n        formLayout.onCountryCodeSelected(country, dialCode);\n    }\n\n    public void loadPasswordlessData(@NonNull String input, @Nullable Country country) {\n        formLayout.loadPasswordlessData(input, country);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/PasswordlessRequestCodeFormView.java",
    "content": "/*\n * PasswordlessSendCodeFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.util.Log;\nimport android.view.KeyEvent;\nimport android.view.View;\nimport android.view.inputmethod.EditorInfo;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.events.PasswordlessLoginEvent;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.lock.views.interfaces.LockWidgetPasswordless;\n\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.DISABLED;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.EMAIL_LINK;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_CODE;\nimport static com.auth0.android.lock.internal.configuration.PasswordlessMode.SMS_LINK;\n\n@SuppressLint(\"ViewConstructor\")\npublic class PasswordlessRequestCodeFormView extends FormView implements View.OnClickListener, TextView.OnEditorActionListener {\n\n    private static final String TAG = PasswordlessRequestCodeFormView.class.getSimpleName();\n\n    private final LockWidgetPasswordless lockWidget;\n    private ValidatedInputView passwordlessInput;\n    @PasswordlessMode\n    private final int passwordlessMode;\n    private TextView topMessage;\n    private CountryCodeSelectorView countryCodeSelector;\n\n    public PasswordlessRequestCodeFormView(@NonNull LockWidgetPasswordless lockWidget) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        passwordlessMode = lockWidget.getConfiguration().getPasswordlessMode();\n        boolean showTitle = lockWidget.getConfiguration().getSocialConnections().isEmpty();\n        Log.v(TAG, \"New instance with mode \" + passwordlessMode);\n        init(showTitle);\n    }\n\n    private void init(boolean showTitle) {\n        inflate(getContext(), R.layout.com_auth0_lock_passwordless_request_code_form_view, this);\n        topMessage = findViewById(R.id.com_auth0_lock_text);\n        passwordlessInput = findViewById(R.id.com_auth0_lock_input_passwordless);\n        passwordlessInput.setOnEditorActionListener(this);\n        countryCodeSelector = findViewById(R.id.com_auth0_lock_country_code_selector);\n        countryCodeSelector.setOnClickListener(this);\n\n        selectPasswordlessMode(showTitle);\n    }\n\n    private void selectPasswordlessMode(boolean showTitle) {\n        int titleMessage = 0;\n        switch (passwordlessMode) {\n            case EMAIL_CODE:\n                titleMessage = R.string.com_auth0_lock_title_passwordless_email;\n                passwordlessInput.setDataType(ValidatedInputView.DataType.EMAIL);\n                countryCodeSelector.setVisibility(GONE);\n                break;\n            case EMAIL_LINK:\n                titleMessage = R.string.com_auth0_lock_title_passwordless_email;\n                passwordlessInput.setDataType(ValidatedInputView.DataType.EMAIL);\n                countryCodeSelector.setVisibility(GONE);\n                break;\n            case SMS_CODE:\n                titleMessage = R.string.com_auth0_lock_title_passwordless_sms;\n                passwordlessInput.setDataType(ValidatedInputView.DataType.MOBILE_PHONE);\n                countryCodeSelector.setVisibility(VISIBLE);\n                break;\n            case SMS_LINK:\n                titleMessage = R.string.com_auth0_lock_title_passwordless_sms;\n                passwordlessInput.setDataType(ValidatedInputView.DataType.MOBILE_PHONE);\n                countryCodeSelector.setVisibility(VISIBLE);\n                break;\n            case DISABLED:\n                break;\n        }\n        passwordlessInput.setVisibility(VISIBLE);\n        passwordlessInput.clearInput();\n        topMessage.setVisibility(showTitle ? VISIBLE : GONE);\n        topMessage.setText(showTitle ? getResources().getString(titleMessage) : null);\n    }\n\n    @NonNull\n    @Override\n    public Object getActionEvent() {\n        String emailOrNumber = getInputText();\n        if (passwordlessMode == SMS_CODE || passwordlessMode == SMS_LINK) {\n            Log.d(TAG, \"Starting a SMS Passwordless flow\");\n            return PasswordlessLoginEvent.requestCode(passwordlessMode, emailOrNumber, countryCodeSelector.getSelectedCountry());\n        } else {\n            Log.d(TAG, \"Starting an Email Passwordless flow\");\n            return PasswordlessLoginEvent.requestCode(passwordlessMode, emailOrNumber);\n        }\n    }\n\n    @SuppressLint(\"KotlinPropertyAccess\")\n    private String getInputText() {\n        return passwordlessInput.getText().replace(\" \", \"\");\n    }\n\n    @Override\n    public boolean validateForm() {\n        return passwordlessInput.validate();\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        return validateForm() ? getActionEvent() : null;\n    }\n\n    /**\n     * Notifies the form that a new country code was selected by the user.\n     *\n     * @param isoCode  the selected country iso code (2 chars).\n     * @param dialCode the dial code for this country\n     */\n    public void onCountryCodeSelected(@NonNull String isoCode, @NonNull String dialCode) {\n        Country selectedCountry = new Country(isoCode, dialCode);\n        countryCodeSelector.setSelectedCountry(selectedCountry);\n    }\n\n    @Override\n    public void onClick(@NonNull View v) {\n        int id = v.getId();\n        if (id == R.id.com_auth0_lock_country_code_selector) {\n            lockWidget.onCountryCodeChangeRequest();\n        }\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n\n    public void setInputText(@NonNull String text) {\n        passwordlessInput.setText(text);\n    }\n\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/SignUpFormView.java",
    "content": "/*\n * SignUpFormView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.KeyEvent;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.inputmethod.EditorInfo;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.UsernameStyle;\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.utils.CustomField;\nimport com.auth0.android.lock.utils.HiddenField;\nimport com.auth0.android.lock.views.interfaces.IdentityListener;\nimport com.auth0.android.lock.views.interfaces.LockWidgetForm;\n\nimport java.util.List;\n\nimport static com.auth0.android.lock.views.CustomFieldsFormView.setEventRootProfileAttributes;\n\npublic class SignUpFormView extends FormView implements TextView.OnEditorActionListener, IdentityListener {\n\n    private static final String TAG = SignUpFormView.class.getSimpleName();\n\n    private final LockWidgetForm lockWidget;\n    private ValidatedUsernameInputView usernameInput;\n    private ValidatedInputView emailInput;\n    private ValidatedPasswordInputView passwordInput;\n    private LinearLayout fieldContainer;\n    private boolean displayCustomFieldsHere;\n\n    public SignUpFormView(@NonNull Context context) {\n        super(context);\n        this.lockWidget = null;\n    }\n\n    public SignUpFormView(@NonNull LockWidgetForm lockWidget) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        init();\n    }\n\n    private void init() {\n        Configuration configuration = lockWidget.getConfiguration();\n        inflate(getContext(), R.layout.com_auth0_lock_signup_form_view, this);\n        fieldContainer = findViewById(R.id.com_auth0_lock_custom_fields_container);\n\n        usernameInput = findViewById(R.id.com_auth0_lock_input_username);\n        usernameInput.configureFrom(configuration.getDatabaseConnection());\n        usernameInput.setUsernameStyle(UsernameStyle.USERNAME);\n        usernameInput.setOnEditorActionListener(this);\n        emailInput = findViewById(R.id.com_auth0_lock_input_email);\n        emailInput.setDataType(ValidatedInputView.DataType.EMAIL);\n        emailInput.setIdentityListener(this);\n        emailInput.setOnEditorActionListener(this);\n        passwordInput = findViewById(R.id.com_auth0_lock_input_password);\n        passwordInput.setPasswordComplexity(configuration.getPasswordComplexity());\n        passwordInput.setAllowShowPassword(configuration.allowShowPassword());\n        passwordInput.setOnEditorActionListener(this);\n\n        usernameInput.setVisibility(configuration.isUsernameRequired() ? View.VISIBLE : View.GONE);\n\n        displayCustomFieldsHere = lockWidget.getConfiguration().getVisibleSignUpFields().size() <= configuration.getVisibleSignUpFieldsThreshold();\n        if (displayCustomFieldsHere) {\n            addCustomFields(configuration.getVisibleSignUpFields());\n        }\n    }\n\n    private void addCustomFields(List<CustomField> customFields) {\n        Log.d(TAG, String.format(\"Adding %d custom fields.\", customFields.size()));\n        ViewGroup.LayoutParams fieldParams = defineFieldParams();\n\n        for (CustomField data : customFields) {\n            ValidatedInputView field = new ValidatedInputView(getContext());\n            data.configureField(field);\n            field.setLayoutParams(fieldParams);\n            field.setOnEditorActionListener(this);\n            fieldContainer.addView(field);\n        }\n    }\n\n\n    private LinearLayout.LayoutParams defineFieldParams() {\n        int verticalMargin = getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_field);\n        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        params.gravity = Gravity.CENTER_HORIZONTAL;\n        params.setMargins(0, verticalMargin, 0, 0);\n        params.setMarginStart(0);\n        params.setMarginEnd(0);\n        return params;\n    }\n\n    @Override\n    @NonNull\n    public Object getActionEvent() {\n        Log.d(TAG, String.format(\"Triggered sign up with email %s and username %s\", getEmail(), getUsername()));\n        return new DatabaseSignUpEvent(getEmail(), getPassword(), getUsername());\n    }\n\n    @Nullable\n    private String getUsername() {\n        return usernameInput.getVisibility() == VISIBLE ? usernameInput.getText().trim() : null;\n    }\n\n    @NonNull\n    private String getEmail() {\n        return emailInput.getText().trim();\n    }\n\n    @NonNull\n    private String getPassword() {\n        return passwordInput.getText();\n    }\n\n    @Override\n    public boolean validateForm() {\n        boolean valid = true;\n        if (usernameInput.getVisibility() == VISIBLE) {\n            valid = usernameInput.validate();\n        }\n        if (emailInput.getVisibility() == VISIBLE) {\n            valid = emailInput.validate() && valid;\n        }\n        if (passwordInput.getVisibility() == VISIBLE) {\n            valid = passwordInput.validate() && valid;\n        }\n        for (int i = 0; displayCustomFieldsHere && i < fieldContainer.getChildCount(); i++) {\n            ValidatedInputView input = (ValidatedInputView) fieldContainer.getChildAt(i);\n            valid = input.validate() && valid;\n        }\n        return valid;\n    }\n\n    @Nullable\n    @Override\n    public Object submitForm() {\n        if (validateForm()) {\n            DatabaseSignUpEvent event = (DatabaseSignUpEvent) getActionEvent();\n            List<CustomField> visibleFields = lockWidget.getConfiguration().getVisibleSignUpFields();\n            if (displayCustomFieldsHere) {\n                List<HiddenField> hiddenFields = lockWidget.getConfiguration().getHiddenSignUpFields();\n                setEventRootProfileAttributes(event, visibleFields, hiddenFields, fieldContainer);\n                return event;\n            }\n            if (!visibleFields.isEmpty()) {\n                lockWidget.showCustomFieldsForm(event);\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public boolean onEditorAction(@NonNull TextView v, int actionId, @NonNull KeyEvent event) {\n        if (actionId == EditorInfo.IME_ACTION_DONE) {\n            lockWidget.onFormSubmit();\n        }\n        return false;\n    }\n\n    public void setLastEmail(@Nullable String email) {\n        emailInput.setText(email);\n        passwordInput.clearInput();\n    }\n\n    @Override\n    public void onEmailChanged(@NonNull String email) {\n        lockWidget.onEmailChanged(email);\n    }\n\n    public void clearEmptyFieldsError() {\n        if (usernameInput.getText().isEmpty()) {\n            usernameInput.clearInput();\n        }\n        if (emailInput.getText().isEmpty()) {\n            emailInput.clearInput();\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/SocialButton.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.graphics.drawable.Drawable;\nimport android.graphics.drawable.ShapeDrawable;\nimport android.graphics.drawable.StateListDrawable;\nimport androidx.annotation.ColorInt;\nimport android.util.AttributeSet;\nimport android.widget.ImageView;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.AuthMode;\n\n@SuppressLint(\"Instantiatable\")\nclass SocialButton extends RelativeLayout {\n\n    private static final int NORMAL_STATE_ALPHA = 230;\n    private static final float FOCUSED_STATE_ALPHA = 0.64f;\n\n    private ImageView icon;\n    private TextView title;\n\n    public SocialButton(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public SocialButton(Context context) {\n        super(context);\n        init();\n    }\n\n    private void init() {\n        inflate(getContext(), R.layout.com_auth0_lock_btn_social_large, this);\n        icon = findViewById(R.id.com_auth0_lock_icon);\n        title = findViewById(R.id.com_auth0_lock_text);\n        setFocusableInTouchMode(false);\n        setFocusable(true);\n        setOnFocusChangeListener((v, hasFocus) -> v.setAlpha(hasFocus ? FOCUSED_STATE_ALPHA : 1f));\n    }\n\n    private StateListDrawable getTouchFeedbackBackground(@ColorInt int pressedColor) {\n        final Drawable normalBackground;\n        final ShapeDrawable pressedBackground;\n\n        boolean shouldDrawOutline = pressedColor == Color.WHITE;\n        if (shouldDrawOutline) {\n            int outlineColor = getResources().getColor(R.color.com_auth0_lock_social_light_background_focused);\n            normalBackground = ViewUtils.getOpaqueRoundedOutlineBackground(getResources(), pressedColor, outlineColor);\n            pressedBackground = ViewUtils.getRoundedBackground(this, outlineColor, ViewUtils.Corners.ALL);\n        } else {\n            normalBackground = ViewUtils.getRoundedBackground(this, pressedColor, ViewUtils.Corners.ALL);\n            pressedBackground = ViewUtils.getRoundedBackground(this, pressedColor, ViewUtils.Corners.ALL);\n        }\n\n        pressedBackground.getPaint().setAlpha(NORMAL_STATE_ALPHA);\n\n        StateListDrawable states = new StateListDrawable();\n        states.addState(new int[]{android.R.attr.state_pressed}, pressedBackground);\n        states.addState(new int[]{}, normalBackground);\n        return states;\n    }\n\n    /**\n     * Configures the button with the given connection information.\n     *\n     * @param config contains the connection information.\n     * @param mode   the current button mode. Used to prefix the title with \"Log In\" or \"Sign Up\".\n     */\n    public void setStyle(AuthConfig config, @AuthMode int mode) {\n        final Drawable logo = config.getLogo(getContext());\n        final int backgroundColor = config.getBackgroundColor(getContext());\n        Drawable touchBackground = getTouchFeedbackBackground(backgroundColor);\n\n        // When background is white, change default text color\n        boolean shouldUseDarkText = backgroundColor == Color.WHITE;\n        if (shouldUseDarkText) {\n            int textColor = getResources().getColor(R.color.com_auth0_lock_social_text_light);\n            title.setTextColor(textColor);\n        }\n        icon.setImageDrawable(logo);\n        final String name = config.getName(getContext());\n        final String prefixFormat = getResources().getString(mode == AuthMode.LOG_IN ? R.string.com_auth0_lock_social_log_in : R.string.com_auth0_lock_social_sign_up);\n        title.setText(String.format(prefixFormat, name));\n        ViewUtils.setBackground(this, touchBackground);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/SocialView.java",
    "content": "/*\n * SocialView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\n\nimport androidx.annotation.NonNull;\nimport androidx.appcompat.widget.LinearLayoutCompat;\nimport androidx.recyclerview.widget.GridLayoutManager;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.internal.configuration.AuthMode;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\nimport com.auth0.android.lock.views.interfaces.LockWidgetOAuth;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static androidx.recyclerview.widget.RecyclerView.LayoutManager;\n\n@SuppressLint(\"ViewConstructor\")\npublic class SocialView extends LinearLayout implements SocialViewAdapter.OAuthListener {\n\n    private static final String TAG = SocialView.class.getSimpleName();\n    private final LockWidgetOAuth lockWidget;\n    private SocialViewAdapter adapter;\n\n    /**\n     * Creates a new SocialView widget\n     *\n     * @param lockWidget   the main widget context\n     * @param smallButtons Deprecated and no longer used. All SocialView widgets will display using large buttons.\n     */\n    @SuppressLint(\"LambdaLast\")\n    public SocialView(@NonNull LockWidgetOAuth lockWidget, boolean smallButtons) {\n        super(lockWidget.getContext());\n        this.lockWidget = lockWidget;\n        Log.v(TAG, \"New instance created. Using small buttons: \" + smallButtons);\n        init();\n    }\n\n    private void init() {\n        setOrientation(VERTICAL);\n        setGravity(Gravity.CENTER);\n        RecyclerView recycler = new RecyclerView(getContext());\n        List<OAuthConnection> connections = lockWidget.getConfiguration().getSocialConnections();\n        adapter = new SocialViewAdapter(getContext(), generateAuthConfigs(connections));\n        adapter.setCallback(this);\n        LayoutManager lm = new GridLayoutManager(getContext(), 1, GridLayoutManager.VERTICAL, false);\n        recycler.setLayoutManager(lm);\n        recycler.setHasFixedSize(true);\n        recycler.setAdapter(adapter);\n        recycler.setOverScrollMode(OVER_SCROLL_NEVER);\n        final SpacesItemDecoration spaceDecoration = new SpacesItemDecoration(getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_vertical_margin_social), LinearLayoutCompat.VERTICAL);\n        recycler.addItemDecoration(spaceDecoration);\n        LayoutParams recyclerParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        addView(recycler, recyclerParams);\n        setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));\n    }\n\n    private List<AuthConfig> generateAuthConfigs(List<OAuthConnection> connections) {\n        List<AuthConfig> configs = new ArrayList<>();\n        for (OAuthConnection c : connections) {\n            int style = lockWidget.getConfiguration().authStyleForConnection(c.getStrategy(), c.getName());\n            configs.add(new AuthConfig(c, style));\n        }\n        return configs;\n    }\n\n    @Override\n    public void onAuthenticationRequest(@NonNull OAuthConnection connection) {\n        lockWidget.onOAuthLoginRequest(new OAuthLoginEvent(connection));\n    }\n\n    /**\n     * Updates the Authentication mode for all the SocialButtons on this view.\n     *\n     * @param mode the new AuthMode.\n     */\n    public void setCurrentMode(@AuthMode int mode) {\n        adapter.setButtonMode(mode);\n        adapter.notifyDataSetChanged();\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/SocialViewAdapter.java",
    "content": "/*\n * SocialViewAdapter.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.auth0.android.lock.internal.configuration.AuthMode;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\n\nimport java.util.List;\n\nclass SocialViewAdapter extends RecyclerView.Adapter<SocialViewAdapter.ViewHolder> {\n    private static final String TAG = SocialViewAdapter.class.getSimpleName();\n\n    private final Context context;\n    private final List<AuthConfig> authConfigs;\n    private OAuthListener callback;\n    @AuthMode\n    private int buttonMode;\n\n    public SocialViewAdapter(Context context, @NonNull List<AuthConfig> authConfigs) {\n        this.context = context;\n        this.authConfigs = authConfigs;\n    }\n\n    @Override\n    @NonNull\n    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {\n        View view = new SocialButton(context);\n        return new ViewHolder(view);\n    }\n\n    @Override\n    public void onBindViewHolder(ViewHolder viewHolder, int i) {\n        viewHolder.socialButton.setStyle(authConfigs.get(i), buttonMode);\n    }\n\n    @Override\n    public int getItemCount() {\n        return authConfigs.size();\n    }\n\n    /**\n     * Sets the button mode to Sign Up or Log In. This will prefix the mode text before the title.\n     *\n     * @param mode the mode to use on the current button list.\n     */\n    public void setButtonMode(@AuthMode int mode) {\n        this.buttonMode = mode;\n    }\n\n    /**\n     * Sets the callback to notify when the user clicks a SocialButton.\n     *\n     * @param callback the callback\n     */\n    public void setCallback(OAuthListener callback) {\n        this.callback = callback;\n    }\n\n    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {\n        final SocialButton socialButton;\n\n        public ViewHolder(@NonNull View v) {\n            super(v);\n            socialButton = (SocialButton) v;\n            socialButton.setOnClickListener(this);\n        }\n\n        @Override\n        public void onClick(@NonNull View view) {\n            if (callback != null) {\n                final AuthConfig item = authConfigs.get(getAdapterPosition());\n                callback.onAuthenticationRequest(item.getConnection());\n            } else {\n                Log.w(TAG, \"No callback was configured\");\n            }\n        }\n\n    }\n\n    public interface OAuthListener {\n        /**\n         * Called when a SocialButton is clicked.\n         *\n         * @param connection the connection associated to the button.\n         */\n        void onAuthenticationRequest(@NonNull OAuthConnection connection);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/SpacesItemDecoration.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.graphics.Rect;\nimport androidx.annotation.NonNull;\nimport androidx.appcompat.widget.LinearLayoutCompat;\nimport androidx.recyclerview.widget.RecyclerView;\nimport android.view.View;\n\nclass SpacesItemDecoration extends RecyclerView.ItemDecoration {\n    private final int orientation;\n    private final int space;\n\n    public SpacesItemDecoration(int space, @LinearLayoutCompat.OrientationMode int orientation) {\n        this.space = space;\n        this.orientation = orientation;\n    }\n\n    @Override\n    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {\n        if (orientation == RecyclerView.HORIZONTAL) {\n            outRect.left = space;\n            outRect.right = space;\n        } else {\n            boolean firstItem = parent.getChildAdapterPosition(view) == 0;\n            boolean lastItem = parent.getChildAdapterPosition(view) == parent.getChildCount() - 1;\n            outRect.top = firstItem ? 0 : space;\n            outRect.bottom = lastItem ? 0 : space;\n        }\n    }\n}"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ValidatedInputView.java",
    "content": "/*\n * EmailAndPasswordView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Typeface;\nimport android.graphics.drawable.Drawable;\nimport android.graphics.drawable.ShapeDrawable;\nimport android.os.Handler;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.DrawableRes;\nimport androidx.annotation.IntDef;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StringRes;\nimport androidx.core.content.ContextCompat;\nimport android.text.Editable;\nimport android.text.InputType;\nimport android.text.TextWatcher;\nimport android.text.method.PasswordTransformationMethod;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.EditText;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.views.interfaces.IdentityListener;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\nimport static com.auth0.android.lock.internal.configuration.DatabaseConnection.MAX_USERNAME_LENGTH;\nimport static com.auth0.android.lock.internal.configuration.DatabaseConnection.MIN_USERNAME_LENGTH;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.EMAIL;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.MFA_CODE;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.MOBILE_PHONE;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.NON_EMPTY_USERNAME;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.NUMBER;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.PASSWORD;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.PHONE_NUMBER;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.TEXT_NAME;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.USERNAME;\nimport static com.auth0.android.lock.views.ValidatedInputView.DataType.USERNAME_OR_EMAIL;\n\npublic class ValidatedInputView extends LinearLayout {\n\n    public static final String USERNAME_REGEX = \"^[a-zA-Z0-9_@^$.#!`+\\\\-'~]+$\";\n    public static final String PHONE_NUMBER_REGEX = \"^[0-9]{6,14}$\";\n    public static final String CODE_REGEX = \"^[0-9]{4,12}$\";\n    public static final String EMAIL_REGEX = \"[a-zA-Z0-9-.!#$%&'*+–/=?^_`{|}~]{1,64}@[a-z0-9-.]{1,255}\";\n    private static final String TAG = ValidatedInputView.class.getSimpleName();\n    private static final int VALIDATION_DELAY = 500;\n\n    private TextView errorDescription;\n    private EditText input;\n    private ImageView icon;\n    private ImageCheckbox showPasswordToggle;\n    private IdentityListener identityListener;\n    private int inputIcon;\n    private boolean hasValidInput = true;\n    private boolean allowShowPassword = true;\n    private View outline;\n    private ShapeDrawable focusedOutlineBackground;\n    private ShapeDrawable normalOutlineBackground;\n    private ShapeDrawable errorOutlineBackground;\n\n    @IntDef({USERNAME, EMAIL, USERNAME_OR_EMAIL, MFA_CODE, PHONE_NUMBER, PASSWORD, MOBILE_PHONE, TEXT_NAME, NUMBER, NON_EMPTY_USERNAME})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface DataType {\n        int USERNAME = 0;\n        int EMAIL = 1;\n        int USERNAME_OR_EMAIL = 2;\n        int MFA_CODE = 3;\n        int PHONE_NUMBER = 4;\n        int PASSWORD = 5;\n        int MOBILE_PHONE = 6;\n        int TEXT_NAME = 7;\n        int NUMBER = 8;\n        int NON_EMPTY_USERNAME = 9;\n    }\n\n    @DataType\n    private int dataType;\n\n    public ValidatedInputView(@NonNull Context context) {\n        super(context);\n        init(null);\n    }\n\n    public ValidatedInputView(@NonNull Context context, @NonNull AttributeSet attrs) {\n        super(context, attrs);\n        init(attrs);\n    }\n\n    public ValidatedInputView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(attrs);\n    }\n\n    private void init(AttributeSet attrs) {\n        inflate(getContext(), R.layout.com_auth0_lock_validated_input_view, this);\n\n        outline = findViewById(R.id.com_auth0_lock_outline);\n        errorDescription = findViewById(R.id.errorDescription);\n        icon = findViewById(R.id.com_auth0_lock_icon);\n        input = findViewById(R.id.com_auth0_lock_input);\n        showPasswordToggle = findViewById(R.id.com_auth0_lock_show_password_toggle);\n        setOrientation(VERTICAL);\n\n        if (isInEditMode()) {\n            return;\n        }\n\n        if (attrs != null) {\n            @SuppressLint(\"CustomViewStyleable\") TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.Lock_ValidatedInput);\n            //noinspection WrongConstant\n            dataType = a.getInt(R.styleable.Lock_ValidatedInput_Auth0_InputDataType, 0);\n            a.recycle();\n        }\n\n        createBackground();\n\n        setupInputValidation();\n        focusedOutlineBackground = ViewUtils.getRoundedOutlineBackground(getResources(), ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_focused));\n        normalOutlineBackground = ViewUtils.getRoundedOutlineBackground(getResources(), ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_normal));\n        errorOutlineBackground = ViewUtils.getRoundedOutlineBackground(getResources(), ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_error));\n        updateBorder();\n\n        setNextFocusRightId(R.id.com_auth0_lock_show_password_toggle);\n        showPasswordToggle.setOnCheckedChangeListener((view, isChecked) -> {\n            if (dataType != PASSWORD) {\n                return;\n            }\n            String passwordValue = input.getText().toString();\n            if (isChecked) {\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);\n                view.setImageResource(R.drawable.com_auth0_lock_ic_password_visible);\n            } else {\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);\n                input.setTransformationMethod(PasswordTransformationMethod.getInstance());\n                view.setImageResource(R.drawable.com_auth0_lock_ic_password_hidden);\n            }\n            setText(passwordValue);\n            input.setTypeface(Typeface.DEFAULT);\n        });\n        input.setOnFocusChangeListener((v, hasFocus) -> updateBorder());\n    }\n\n    @Override\n    protected void onAttachedToWindow() {\n        super.onAttachedToWindow();\n        input.addTextChangedListener(inputWatcher);\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        input.removeTextChangedListener(inputWatcher);\n    }\n\n    private final TextWatcher inputWatcher = new TextWatcher() {\n        @Override\n        public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n        }\n\n        @Override\n        public void onTextChanged(CharSequence s, int start, int before, int count) {\n        }\n\n        @Override\n        public void afterTextChanged(Editable s) {\n            runValidation();\n            if (dataType == EMAIL || dataType == USERNAME_OR_EMAIL) {\n                notifyEmailChanged(s.toString());\n            }\n        }\n\n        private void runValidation() {\n            hasValidInput = validate(false);\n            Handler handler = getHandler();\n            handler.removeCallbacks(uiUpdater);\n            handler.postDelayed(uiUpdater, VALIDATION_DELAY);\n        }\n\n        private void notifyEmailChanged(String emailInput) {\n            boolean validOrEmptyEmail = emailInput.isEmpty() || emailInput.matches(EMAIL_REGEX);\n            if (identityListener != null && validOrEmptyEmail) {\n                identityListener.onEmailChanged(emailInput);\n            }\n        }\n    };\n\n    private final Runnable uiUpdater = this::updateBorder;\n\n    @SuppressLint(\"StringFormatInvalid\")\n    private void setupInputValidation() {\n        String hint = \"\";\n        String error = \"\";\n        input.setTransformationMethod(null);\n        Log.v(TAG, \"Setting up validation for field of type \" + dataType);\n        switch (dataType) {\n            case EMAIL:\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);\n                inputIcon = R.drawable.com_auth0_lock_ic_email;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_email);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_email);\n                break;\n            case PASSWORD:\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);\n                input.setTransformationMethod(PasswordTransformationMethod.getInstance());\n                input.setTypeface(Typeface.DEFAULT);\n                inputIcon = R.drawable.com_auth0_lock_ic_password;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_password);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_password);\n                break;\n            case USERNAME_OR_EMAIL:\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);\n                inputIcon = R.drawable.com_auth0_lock_ic_username;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_username_or_email);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_username_email);\n                break;\n            case TEXT_NAME:\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME);\n                inputIcon = R.drawable.com_auth0_lock_ic_username;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_username);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_empty);\n                break;\n            case NON_EMPTY_USERNAME:\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);\n                inputIcon = R.drawable.com_auth0_lock_ic_username;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_username);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_username_empty);\n                break;\n            case USERNAME:\n                input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);\n                inputIcon = R.drawable.com_auth0_lock_ic_username;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_username);\n                error = String.format(getResources().getString(R.string.com_auth0_lock_input_error_username), MIN_USERNAME_LENGTH, MAX_USERNAME_LENGTH);\n                break;\n            case NUMBER:\n                input.setInputType(InputType.TYPE_CLASS_NUMBER);\n                inputIcon = R.drawable.com_auth0_lock_ic_password;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_code);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_empty);\n                break;\n            case MFA_CODE:\n                input.setInputType(InputType.TYPE_CLASS_NUMBER);\n                inputIcon = R.drawable.com_auth0_lock_ic_password;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_code);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_code);\n                break;\n            case MOBILE_PHONE:\n                input.setInputType(InputType.TYPE_CLASS_NUMBER);\n                inputIcon = R.drawable.com_auth0_lock_ic_mobile;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_phone_number);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_phone_number);\n                break;\n            case PHONE_NUMBER:\n                input.setInputType(InputType.TYPE_CLASS_PHONE);\n                inputIcon = R.drawable.com_auth0_lock_ic_phone;\n                hint = getResources().getString(R.string.com_auth0_lock_hint_phone_number);\n                error = getResources().getString(R.string.com_auth0_lock_input_error_phone_number);\n                break;\n        }\n        showPasswordToggle.setVisibility(dataType == PASSWORD && allowShowPassword ? ViewGroup.VISIBLE : ViewGroup.GONE);\n        showPasswordToggle.setChecked(false);\n        input.setHint(hint);\n        errorDescription.setText(error);\n        icon.setImageResource(inputIcon);\n    }\n\n    /**\n     * Updates the view knowing if the input is valid or not.\n     */\n    @CallSuper\n    protected void updateBorder() {\n        boolean isFocused = input.hasFocus() && !input.isInTouchMode();\n        ViewUtils.setBackground(outline, hasValidInput ? (isFocused ? focusedOutlineBackground : normalOutlineBackground) : errorOutlineBackground);\n        errorDescription.setVisibility(hasValidInput ? GONE : VISIBLE);\n        requestLayout();\n    }\n\n    private void createBackground() {\n        int inputBackgroundColor = ContextCompat.getColor(getContext(), isEnabled() ? R.color.com_auth0_lock_input_field_background : R.color.com_auth0_lock_input_field_background_disabled);\n        Drawable leftBackground = ViewUtils.getRoundedBackground(this, ContextCompat.getColor(getContext(), R.color.com_auth0_lock_input_field_border_normal), ViewUtils.Corners.ONLY_LEFT);\n        Drawable rightBackground = ViewUtils.getRoundedBackground(this, inputBackgroundColor, ViewUtils.Corners.ONLY_RIGHT);\n        ViewUtils.setBackground(icon, leftBackground);\n        ViewUtils.setBackground((ViewGroup) input.getParent(), rightBackground);\n    }\n\n    /**\n     * Changes the type of input this view will validate.\n     *\n     * @param type a valid DataType\n     */\n    public void setDataType(@DataType int type) {\n        dataType = type;\n        hasValidInput = true;\n        updateBorder();\n        setupInputValidation();\n    }\n\n    /**\n     * Getter for the DataType associated to this field.\n     *\n     * @return the DataType associated to this view.\n     */\n    @SuppressLint(\"KotlinPropertyAccess\")\n    @DataType\n    protected int getDataType() {\n        return dataType;\n    }\n\n    /**\n     * Validates the input data and updates the border. DataType must be set.\n     * Empty fields are considered valid.\n     *\n     * @return whether the data is valid or not.\n     */\n    public boolean validate() {\n        hasValidInput = validate(true);\n        updateBorder();\n        return hasValidInput;\n    }\n\n    /**\n     * Validates the input data and updates the icon. DataType must be set.\n     *\n     * @param validateEmptyFields if an empty input should be considered invalid.\n     * @return whether the data is valid or not.\n     */\n    protected boolean validate(boolean validateEmptyFields) {\n        boolean isValid = false;\n        String value = dataType == PASSWORD ? getText() : getText().trim();\n        if (!validateEmptyFields && value.isEmpty()) {\n            return true;\n        }\n\n        switch (dataType) {\n            case TEXT_NAME:\n            case NUMBER:\n            case PASSWORD:\n            case NON_EMPTY_USERNAME:\n                isValid = !value.isEmpty();\n                break;\n            case EMAIL:\n                isValid = value.matches(EMAIL_REGEX);\n                break;\n            case USERNAME:\n                isValid = value.matches(USERNAME_REGEX) && value.length() >= 1 && value.length() <= 15;\n                break;\n            case USERNAME_OR_EMAIL:\n                final boolean validEmail = value.matches(EMAIL_REGEX);\n                final boolean validUsername = value.matches(USERNAME_REGEX) && value.length() >= 1 && value.length() <= 15;\n                isValid = validEmail || validUsername;\n                break;\n            case MOBILE_PHONE:\n            case PHONE_NUMBER:\n                isValid = value.matches(PHONE_NUMBER_REGEX);\n                break;\n            case MFA_CODE:\n                isValid = value.matches(CODE_REGEX);\n                break;\n        }\n\n        Log.v(TAG, \"Field validation results: Is valid? \" + isValid);\n        return isValid;\n    }\n\n    /**\n     * Gets the current text from the input field.\n     *\n     * @return the current text\n     */\n    @NonNull\n    public String getText() {\n        return input.getText().toString();\n    }\n\n    /**\n     * Updates the input field text.\n     *\n     * @param text the new text to set.\n     */\n    public void setText(@Nullable String text) {\n        input.setText(\"\");\n        if (text != null) {\n            input.append(text);\n        }\n    }\n\n    @Override\n    public void setEnabled(boolean enabled) {\n        super.setEnabled(enabled);\n        input.setEnabled(enabled);\n        showPasswordToggle.setEnabled(enabled);\n        createBackground();\n    }\n\n    @Override\n    public boolean isEnabled() {\n        return input.isEnabled();\n    }\n\n    /**\n     * Whether to display the Show Password toggle or not.\n     * Only available for Password data type. Defaults to true.\n     *\n     * @param allow whether to display a button to toggle between showing or hiding the password or not.\n     */\n    public void setAllowShowPassword(boolean allow) {\n        this.allowShowPassword = allow;\n        setupInputValidation();\n    }\n\n    /**\n     * Updates the input field hint.\n     *\n     * @param hint the new hint to set.\n     */\n    public void setHint(@StringRes int hint) {\n        input.setHint(hint);\n    }\n\n    /**\n     * Updates the validation error description.\n     *\n     * @param error the new error description to set.\n     */\n    public void setErrorDescription(@Nullable String error) {\n        errorDescription.setText(error);\n    }\n\n    /**\n     * Updates the input Icon.\n     *\n     * @param icon the new icon to set.\n     */\n    public void setIcon(@DrawableRes int icon) {\n        this.icon.setImageResource(icon);\n    }\n\n    /**\n     * Removes any text present on the input field and clears any validation error, if present.\n     */\n    public void clearInput() {\n        Log.v(TAG, \"Input cleared and validation errors removed\");\n        input.setText(\"\");\n        hasValidInput = true;\n        updateBorder();\n        showPasswordToggle.setChecked(false);\n    }\n\n    /**\n     * Adds the given TextWatcher to this view EditText.\n     *\n     * @param watcher to add to the EditText.\n     */\n    public void addTextChangedListener(@NonNull TextWatcher watcher) {\n        input.addTextChangedListener(watcher);\n    }\n\n    /**\n     * Sets the given OnEditorActionListener to this view EditText.\n     *\n     * @param listener to set to the EditText.\n     */\n    public void setOnEditorActionListener(@NonNull TextView.OnEditorActionListener listener) {\n        input.setOnEditorActionListener(listener);\n    }\n\n    /**\n     * Sets the given IdentityListener to this view EditText.\n     *\n     * @param listener to set to this view.\n     */\n    public void setIdentityListener(@NonNull IdentityListener listener) {\n        this.identityListener = listener;\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ValidatedPasswordInputView.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport android.util.AttributeSet;\nimport android.util.Log;\n\nimport com.auth0.android.lock.internal.configuration.PasswordComplexity;\nimport com.auth0.android.lock.internal.configuration.PasswordStrength;\n\n\npublic class ValidatedPasswordInputView extends ValidatedInputView {\n    private static final String TAG = ValidatedPasswordInputView.class.getSimpleName();\n    private PasswordStrengthView strengthView;\n    private boolean hasValidInput = true;\n\n    public ValidatedPasswordInputView(@NonNull Context context) {\n        super(context);\n        init();\n    }\n\n    public ValidatedPasswordInputView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init();\n    }\n\n    public ValidatedPasswordInputView(@NonNull Context context, @NonNull AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public void init() {\n        strengthView = new PasswordStrengthView(getContext());\n        addView(strengthView, 0);  //Add it above the field\n    }\n\n    @Override\n    protected boolean validate(boolean validateEmptyFields) {\n        String value = getText();\n        //Run strength validation to update ui\n        hasValidInput = strengthView.isValid(value) || !validateEmptyFields && value.isEmpty();\n        Log.v(TAG, \"Field validation results: Is valid? \" + hasValidInput);\n        return hasValidInput;\n    }\n\n    @Override\n    protected void updateBorder() {\n        super.updateBorder();\n        if (strengthView != null && strengthView.isEnabled()) {\n            strengthView.setVisibility(!hasValidInput || !getText().isEmpty() ? VISIBLE : GONE);\n        }\n    }\n\n    /**\n     * Sets the Password Strength Policy level for this view.\n     *\n     * @param strength the new Policy level.\n     * @deprecated use {@link #setPasswordComplexity(PasswordComplexity)} method\n     */\n    @Deprecated\n    public void setPasswordPolicy(@PasswordStrength int strength) {\n        //noinspection deprecation\n        strengthView.setStrength(strength);\n    }\n\n    /**\n     * Sets the Password Complexity for this view.\n     *\n     * @param complexity the new Password complexity to use\n     */\n    public void setPasswordComplexity(@NonNull PasswordComplexity complexity) {\n        strengthView.setPasswordComplexity(complexity);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ValidatedUsernameInputView.java",
    "content": "/*\n * ValidatedUserInputView.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.util.AttributeSet;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.UsernameStyle;\nimport com.auth0.android.lock.internal.configuration.DatabaseConnection;\n\nimport static com.auth0.android.lock.UsernameStyle.DEFAULT;\nimport static com.auth0.android.lock.UsernameStyle.EMAIL;\nimport static com.auth0.android.lock.UsernameStyle.USERNAME;\nimport static com.auth0.android.lock.internal.configuration.DatabaseConnection.MAX_USERNAME_LENGTH;\nimport static com.auth0.android.lock.internal.configuration.DatabaseConnection.MIN_USERNAME_LENGTH;\n\npublic class ValidatedUsernameInputView extends ValidatedInputView {\n\n    private int minUsernameLength = MIN_USERNAME_LENGTH;\n    private int maxUsernameLength = MAX_USERNAME_LENGTH;\n\n    private boolean usernameRequired;\n    private boolean isCustomDatabase;\n\n    public ValidatedUsernameInputView(@NonNull Context context) {\n        super(context);\n        init();\n    }\n\n    public ValidatedUsernameInputView(@NonNull Context context, @NonNull AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public ValidatedUsernameInputView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init();\n    }\n\n    private void init() {\n        setUsernameStyle(DEFAULT);\n    }\n\n    /**\n     * Extract the required values from this Database connection to use later in this widget.\n     *\n     * @param connection used with this widget\n     */\n    public void configureFrom(@Nullable DatabaseConnection connection) {\n        if (connection == null) {\n            return;\n        }\n        minUsernameLength = connection.getMinUsernameLength();\n        maxUsernameLength = connection.getMaxUsernameLength();\n        usernameRequired = connection.requiresUsername();\n        isCustomDatabase = connection.isCustomDatabase();\n    }\n\n    /**\n     * Choose username or email DataType, according to the Username Style.\n     *\n     * @param style to use in this username field\n     */\n    @SuppressLint(\"StringFormatInvalid\")\n    public void setUsernameStyle(@UsernameStyle int style) {\n        if (style == EMAIL || !usernameRequired) {\n            setDataType(DataType.EMAIL);\n        } else if (style == USERNAME) {\n            setDataType(DataType.USERNAME);\n            String errorDescription = isCustomDatabase ? getResources().getString(R.string.com_auth0_lock_input_error_username_empty) :\n                    getResources().getString(R.string.com_auth0_lock_input_error_username, minUsernameLength, maxUsernameLength);\n            setErrorDescription(errorDescription);\n        } else if (style == DEFAULT) {\n            setDataType(DataType.USERNAME_OR_EMAIL);\n        }\n    }\n\n    @Override\n    protected boolean validate(boolean validateEmptyFields) {\n        final String value = getText().trim();\n        if (!validateEmptyFields && value.isEmpty()) {\n            return true;\n        }\n        boolean validUsernameLength = value.length() >= minUsernameLength && value.length() <= maxUsernameLength;\n\n        if (getDataType() == DataType.USERNAME) {\n            return validUsernameLength && !isCustomDatabase ? value.matches(USERNAME_REGEX) : validUsernameLength;\n        }\n        if (getDataType() == DataType.USERNAME_OR_EMAIL) {\n            //This case is only used in the LogInFormView, avoid validating against username regex\n            final boolean validEmail = value.matches(EMAIL_REGEX);\n            return validEmail || validUsernameLength;\n        }\n        return super.validate(validateEmptyFields);\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/ViewUtils.java",
    "content": "/*\n * ViewUtils.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views;\n\nimport android.content.res.ColorStateList;\nimport android.content.res.Resources;\nimport android.graphics.RectF;\nimport android.graphics.drawable.Drawable;\nimport android.graphics.drawable.GradientDrawable;\nimport android.graphics.drawable.ShapeDrawable;\nimport android.graphics.drawable.shapes.RoundRectShape;\nimport android.os.Build;\nimport androidx.annotation.ColorInt;\nimport androidx.annotation.IntDef;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport android.text.TextUtils;\nimport android.util.TypedValue;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ProgressBar;\n\nimport com.auth0.android.lock.R;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.util.Locale;\n\nimport static com.auth0.android.lock.views.ViewUtils.Corners.ALL;\nimport static com.auth0.android.lock.views.ViewUtils.Corners.ONLY_LEFT;\nimport static com.auth0.android.lock.views.ViewUtils.Corners.ONLY_RIGHT;\n\nabstract class ViewUtils {\n\n    /**\n     * Used by the getRoundedBackground method. It defines which corners to set as rounded\n     * in the drawable.\n     */\n    @IntDef({ALL, ONLY_LEFT, ONLY_RIGHT})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface Corners {\n        int ALL = 0;\n        int ONLY_LEFT = -1;\n        int ONLY_RIGHT = 1;\n    }\n\n    /**\n     * Converts dp into px.\n     *\n     * @param resources the context's current resources.\n     * @param dip       the dp value to convert to px.\n     * @return the result px value.\n     */\n    static float dipToPixels(Resources resources, int dip) {\n        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, resources.getDisplayMetrics());\n    }\n\n    /**\n     * Generates a rounded drawable with the given background color and the specified corners.\n     *\n     * @param view    a valid View context\n     * @param color   the color to use as background.\n     * @param corners the rounded corners this drawable will have. Can be one of ONLY_LEFT, ONLY_RIGHT, ALL\n     * @return the rounded drawable.\n     */\n    static ShapeDrawable getRoundedBackground(@NonNull View view, @ColorInt int color, @Corners int corners) {\n        int r = view.getResources().getDimensionPixelSize(R.dimen.com_auth0_lock_widget_corner_radius);\n        float[] outerR = new float[0];\n        boolean languageRTL = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;\n        if (languageRTL) {\n            //noinspection WrongConstant\n            corners = -corners;\n        }\n        switch (corners) {\n            case ONLY_LEFT:\n                outerR = new float[]{r, r, 0, 0, 0, 0, r, r};\n                break;\n            case ONLY_RIGHT:\n                outerR = new float[]{0, 0, r, r, r, r, 0, 0};\n                break;\n            case ALL:\n                outerR = new float[]{r, r, r, r, r, r, r, r};\n                break;\n        }\n\n        RoundRectShape rr = new RoundRectShape(outerR, null, null);\n        ShapeDrawable drawable = new ShapeDrawable(rr);\n        drawable.getPaint().setColor(color);\n        return drawable;\n    }\n\n    /**\n     * Generates a rounded outline drawable with a transparent background.\n     *\n     * @param resources the context's current resources.\n     * @param color     the color to use for the outline.\n     * @return the rounded drawable.\n     */\n    static ShapeDrawable getRoundedOutlineBackground(Resources resources, @ColorInt int color) {\n        int r = resources.getDimensionPixelSize(R.dimen.com_auth0_lock_widget_corner_radius);\n        int t = resources.getDimensionPixelSize(R.dimen.com_auth0_lock_input_field_stroke_width);\n        RoundRectShape rr = new RoundRectShape(new float[]{r, r, r, r, r, r, r, r}, new RectF(t, t, t, t), new float[]{r, r, r, r, r, r, r, r});\n        ShapeDrawable drawable = new ShapeDrawable(rr);\n        drawable.getPaint().setColor(color);\n        return drawable;\n    }\n\n    /**\n     * Generates a rounded outline drawable with the given background color.\n     *\n     * @param resources       the context's current resources.\n     * @param backgroundColor the color to use for the background.\n     * @param outlineColor    the color to use for the outline\n     * @return the opaque rounded drawable.\n     */\n    static Drawable getOpaqueRoundedOutlineBackground(\n            Resources resources,\n            @ColorInt int backgroundColor,\n            @ColorInt int outlineColor\n    ) {\n        int cornerRadius = resources.getDimensionPixelSize(R.dimen.com_auth0_lock_widget_corner_radius);\n        int stroke = resources.getDimensionPixelSize(R.dimen.com_auth0_lock_input_field_stroke_width);\n        GradientDrawable drawable = new GradientDrawable();\n        drawable.setCornerRadius(cornerRadius);\n        drawable.setColor(backgroundColor);\n        drawable.setStroke(stroke, outlineColor);\n        return drawable;\n    }\n\n    /**\n     * Sets a background drawable to a view, safely using the latest available sdk method.\n     *\n     * @param view       the view to set the background drawable to.\n     * @param background the drawable to use as background.\n     */\n    static void setBackground(@NonNull View view, @Nullable Drawable background) {\n        view.setBackground(background);\n    }\n\n    /**\n     * Measures the height of a view considering the margins and its visibility.\n     *\n     * @param view to measure the height.\n     */\n    static int measureViewHeight(@Nullable View view) {\n        int height = 0;\n        if (view != null && view.isShown()) {\n            ViewGroup.MarginLayoutParams modeSelectionParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();\n            height = view.getMeasuredHeight() + modeSelectionParams.topMargin + modeSelectionParams.bottomMargin + view.getPaddingTop() + view.getPaddingBottom();\n        }\n        return height;\n    }\n\n    /**\n     * Tints the progress bar drawable to the given color. Only for devices running Lollipop or greater.\n     *\n     * @param progressBar the view to tint\n     * @param color       the color to use\n     */\n    static void tintWidget(@NonNull ProgressBar progressBar, @ColorInt int color) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            ColorStateList tint = ColorStateList.valueOf(color);\n            progressBar.setIndeterminateTintList(tint);\n        }\n    }\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/interfaces/IdentityListener.java",
    "content": "/*\n * IdentityListener.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views.interfaces;\n\nimport androidx.annotation.NonNull;\n\npublic interface IdentityListener {\n\n    void onEmailChanged(@NonNull String currentValue);\n\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/interfaces/LockWidget.java",
    "content": "/*\n * LockWidgets.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views.interfaces;\n\nimport android.content.Context;\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.lock.internal.configuration.Configuration;\n\npublic interface LockWidget {\n\n    @NonNull\n    Context getContext();\n\n    @NonNull\n    Configuration getConfiguration();\n\n    void onFormSubmit();\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/interfaces/LockWidgetForm.java",
    "content": "/*\n * LockWidgetDatabase.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views.interfaces;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.StringRes;\n\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\n\npublic interface LockWidgetForm extends LockWidgetOAuth, IdentityListener {\n\n    void showChangePasswordForm(boolean show);\n\n    void showCustomFieldsForm(@NonNull DatabaseSignUpEvent event);\n\n    void showBottomBanner(boolean show);\n\n    void showTopBanner(boolean show);\n\n    void updateButtonLabel(@StringRes int stringRes);\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/interfaces/LockWidgetOAuth.java",
    "content": "/*\n * LockWidgetSocial.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views.interfaces;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.lock.events.OAuthLoginEvent;\n\npublic interface LockWidgetOAuth extends LockWidget {\n\n    void onOAuthLoginRequest(@NonNull OAuthLoginEvent event);\n}\n"
  },
  {
    "path": "lib/src/main/java/com/auth0/android/lock/views/interfaces/LockWidgetPasswordless.java",
    "content": "/*\n * LockWidgetPasswordless.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.views.interfaces;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.StringRes;\n\npublic interface LockWidgetPasswordless extends LockWidgetOAuth {\n\n    void onCountryCodeChangeRequest();\n\n    void onPasswordlessCodeSent(@NonNull String emailOrNumber);\n\n    /**\n     * Change the Header Title to the given value and update the visibility depending on the Contextual Header Title flag.\n     *\n     * @param titleRes the string resource to use as title.\n     */\n    void updateHeaderTitle(@StringRes int titleRes);\n\n    /**\n     * Return the Header Title to the default text and visibility depending on the Contextual Header Title flag.\n     */\n    void resetHeaderTitle();\n}\n"
  },
  {
    "path": "lib/src/main/res/color/com_auth0_lock_text.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_normal_text.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/com_auth0_lock_disabled_text\" android:state_enabled=\"false\" />\n    <item android:color=\"@color/com_auth0_lock_normal_text\" />\n</selector>"
  },
  {
    "path": "lib/src/main/res/drawable/com_auth0_lock_link_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_link_background.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <solid android:color=\"@color/com_auth0_lock_link_focused\" />\n    <corners android:radius=\"@dimen/com_auth0_lock_widget_corner_radius\" />\n</shape>"
  },
  {
    "path": "lib/src/main/res/drawable/com_auth0_lock_tab.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_normal_text.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@color/com_auth0_lock_tab_focused\" android:state_focused=\"true\"/>\n    <item android:drawable=\"@android:color/transparent\" />\n</selector>"
  },
  {
    "path": "lib/src/main/res/drawable/com_auth0_lock_terms.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_normal_text.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@color/com_auth0_lock_terms_background_focused\" android:state_focused=\"true\"/>\n    <item android:drawable=\"@color/com_auth0_lock_terms_background\" />\n</selector>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_action_button.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_action_button.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    style=\"@style/Lock.Theme.Widget.SubmitButton\">\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_icon\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:paddingBottom=\"@dimen/com_auth0_lock_action_button_vertical_margin\"\n        android:paddingTop=\"@dimen/com_auth0_lock_action_button_vertical_margin\"\n        android:scaleType=\"center\"\n        android:src=\"@drawable/com_auth0_lock_ic_submit\" />\n\n    <LinearLayout\n        android:id=\"@+id/com_auth0_lock_labeled\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:gravity=\"center\"\n        android:paddingBottom=\"@dimen/com_auth0_lock_action_button_labeled_vertical_margin\"\n        android:paddingTop=\"@dimen/com_auth0_lock_action_button_labeled_vertical_margin\">\n\n        <TextView\n            android:id=\"@+id/com_auth0_lock_title\"\n            style=\"@style/Lock.Theme.Text.SubmitButton\"\n            android:text=\"@string/com_auth0_lock_action_log_in\" />\n\n        <ImageView\n            android:id=\"@+id/com_auth0_lock_chevron\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center_vertical\"\n            android:scaleType=\"fitCenter\"\n            android:src=\"@drawable/com_auth0_lock_ic_chevron_submit\"\n            tools:ignore=\"MissingPrefix\" />\n    </LinearLayout>\n\n    <ProgressBar\n        android:id=\"@+id/com_auth0_lock_progress\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:indeterminate=\"true\" />\n\n</RelativeLayout>\n"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_activity_lock.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/com_auth0_lock_container\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ScrollView\n        android:id=\"@+id/com_auth0_lock_content\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:fillViewport=\"true\"\n        android:isScrollContainer=\"true\" />\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_result_message\"\n        style=\"@style/Lock.Theme.Text.ResultMessage\"\n        android:visibility=\"gone\"\n        tools:background=\"@color/com_auth0_lock_result_message_error_background\"\n        tools:text=\"There was an error\"\n        tools:visibility=\"visible\" />\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_activity_lock_passwordless.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_activity_lock_passwordless.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/com_auth0_lock_container\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ScrollView\n        android:id=\"@+id/com_auth0_lock_content\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:fillViewport=\"true\"\n        android:isScrollContainer=\"true\" />\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_result_message\"\n        style=\"@style/Lock.Theme.Text.ResultMessage\"\n        android:visibility=\"gone\"\n        tools:background=\"@color/com_auth0_lock_result_message_error_background\"\n        tools:text=\"There was an error\"\n        tools:visibility=\"visible\" />\n\n    <LinearLayout\n        android:id=\"@+id/com_auth0_lock_link_sent_cover\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_alignParentStart=\"true\"\n        android:layout_alignParentTop=\"true\"\n        android:background=\"@android:color/white\"\n        android:gravity=\"center\"\n        android:orientation=\"vertical\"\n        android:visibility=\"gone\"\n        tools:background=\"@null\"\n        tools:visibility=\"visible\">\n\n        <ImageView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_passwordless_sent\"\n            android:src=\"@drawable/com_auth0_lock_link_sent\" />\n\n        <androidx.appcompat.widget.AppCompatTextView\n            android:id=\"@+id/com_auth0_lock_passwordless_message\"\n            style=\"@style/Lock.Theme.Text.LinkSent\"\n            android:text=\"@string/com_auth0_lock_title_passwordless_link_sent\" />\n\n        <com.auth0.android.lock.views.LinkTextView\n            android:id=\"@+id/com_auth0_lock_got_code\"\n            style=\"@style/Lock.Theme.Text.Link\"\n            android:nextFocusDown=\"@+id/com_auth0_lock_resend\"\n            android:text=\"@string/com_auth0_lock_title_passwordless_got_code\" />\n\n        <com.auth0.android.lock.views.LinkTextView\n            android:id=\"@+id/com_auth0_lock_resend\"\n            style=\"@style/Lock.Theme.Text.Link\"\n            android:nextFocusUp=\"@+id/com_auth0_lock_got_code\"\n            android:text=\"@string/com_auth0_lock_title_passwordless_code_retry\"\n            android:visibility=\"invisible\"\n            tools:visibility=\"visible\" />\n\n    </LinearLayout>\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_btn_social_large.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_btn_social_large.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/com_auth0_lock_container\"\n    style=\"@style/Lock.Theme.Widget.SocialButton\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"@dimen/com_auth0_lock_input_field_stroke_width\"\n        android:orientation=\"horizontal\"\n        tools:ignore=\"UseCompoundDrawables\">\n\n        <ImageView\n            android:id=\"@+id/com_auth0_lock_icon\"\n            style=\"@style/Lock.Theme.Widget.Icon.Social\"\n            tools:background=\"#FF3333\"\n            tools:src=\"@drawable/com_auth0_lock_ic_social_auth0\" />\n\n        <TextView\n            android:id=\"@+id/com_auth0_lock_text\"\n            style=\"@style/Lock.Theme.Text.SocialButton\"\n            tools:background=\"#FF3333\"\n            tools:text=\"Sign in with App\"\n            tools:ignore=\"SelectableText\" />\n\n    </LinearLayout>\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_changepwd_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_changepwd_form_view.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_gravity=\"center\"\n    android:paddingBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n    android:paddingTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\">\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_text\"\n        style=\"@style/Lock.Theme.Text.Subtitle.ResetPassword\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_passwordless\"\n        android:text=\"@string/com_auth0_lock_description_change_password\"\n        android:textSize=\"@dimen/com_auth0_lock_title_text\" />\n\n    <com.auth0.android.lock.views.ValidatedInputView\n        android:id=\"@+id/com_auth0_lock_input_email\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n        android:layout_marginRight=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n        android:layout_marginStart=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n        android:layout_marginEnd=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n        lock:Auth0.InputDataType=\"email\" />\n\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_checkable_option.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_checkable_optionon.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_checkable_option\"\n    android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_checkable_option\"\n    android:orientation=\"horizontal\"\n    tools:ignore=\"UseCompoundDrawables\">\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_checkable_text_icon\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center_vertical\"\n        android:src=\"@drawable/com_auth0_lock_ic_check_success\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_checkable_text_description\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:layout_marginStart=\"@dimen/com_auth0_lock_widget_with_text_horizontal_padding\"\n        android:gravity=\"center_vertical\"\n        tools:text=\"Option value or description\"\n        tools:ignore=\"SelectableText\" />\n</LinearLayout>\n"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_custom_fields_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_custom_fields_form_view.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fadeScrollbars=\"false\"\n    android:scrollbarStyle=\"outsideInset\">\n\n    <LinearLayout\n        android:id=\"@+id/com_auth0_lock_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        android:layout_gravity=\"center_vertical\"\n        android:orientation=\"vertical\" />\n</ScrollView>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_error_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <androidx.legacy.widget.Space\n        android:id=\"@+id/com_auth0_lock_space\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\" />\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_icon\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_above=\"@+id/com_auth0_lock_space\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_error_title\"\n        android:src=\"@drawable/com_auth0_lock_load_error\" />\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_error_title\"\n        style=\"@style/Lock.Theme.Text.Title.Error\"\n        android:layout_below=\"@+id/com_auth0_lock_space\"\n        tools:text=\"@string/com_auth0_lock_unrecoverable_error_title\" />\n\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_error_subtitle\"\n        style=\"@style/Lock.Theme.Text.Subtitle.Error\"\n        android:layout_below=\"@+id/com_auth0_lock_error_title\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_password_strength\"\n        tools:text=\"@string/com_auth0_lock_unrecoverable_error_subtitle_without_action\" />\n\n    <com.auth0.android.lock.views.LinkTextView\n        android:id=\"@+id/com_auth0_lock_error_action\"\n        style=\"@style/Lock.Theme.Text.ErrorLink\"\n        android:layout_below=\"@+id/com_auth0_lock_error_subtitle\"\n        tools:text=\"@string/com_auth0_lock_unrecoverable_error_action\" />\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_header.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_header.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/com_auth0_lock_header_background\"\n    style=\"@style/Lock.Theme.Widget.Header\"\n    tools:background=\"#40000000\"\n    tools:context=\".LockActivity\">\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_header_logo\"\n        style=\"@style/Lock.Theme.Widget.Logo\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_header_vertical_margin\"\n        android:fitsSystemWindows=\"false\"\n        lock:srcCompat=\"?attr/Auth0.HeaderLogo\"\n        tools:ignore=\"MissingPrefix\"\n        tools:srcCompat=\"@drawable/com_auth0_lock_header_logo\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_header_text\"\n        style=\"@style/Lock.Theme.Text.Header\"\n        android:layout_below=\"@id/com_auth0_lock_header_logo\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_header_vertical_margin\"\n        tools:ignore=\"SelectableText\"\n        tools:text=\"Auth0\" />\n</RelativeLayout>\n"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_login_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_login_form_view.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_text\"\n        style=\"@style/Lock.Theme.Text.Title\"\n        android:layout_alignParentTop=\"true\"\n        android:visibility=\"gone\" />\n\n    <com.auth0.android.lock.views.ValidatedUsernameInputView\n        android:id=\"@+id/com_auth0_lock_input_username_email\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/com_auth0_lock_text\"\n        lock:Auth0.InputDataType=\"username_or_email\" />\n\n    <com.auth0.android.lock.views.ValidatedUsernameInputView\n        android:id=\"@+id/com_auth0_lock_input_username\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/com_auth0_lock_input_username_email\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        android:visibility=\"gone\"\n        lock:Auth0.InputDataType=\"username\" />\n\n    <com.auth0.android.lock.views.ValidatedInputView\n        android:id=\"@+id/com_auth0_lock_input_password\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/com_auth0_lock_input_username\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        android:visibility=\"gone\"\n        lock:Auth0.InputDataType=\"password\" />\n\n    <com.auth0.android.lock.views.SocialButton\n        android:id=\"@+id/com_auth0_lock_enterprise_button\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@id/com_auth0_lock_input_password\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        android:visibility=\"gone\" />\n\n    <com.auth0.android.lock.views.LinkTextView\n        android:id=\"@+id/com_auth0_lock_change_password_btn\"\n        style=\"@style/Lock.Theme.Text.Link\"\n        android:layout_below=\"@id/com_auth0_lock_input_password\"\n        android:text=\"@string/com_auth0_lock_action_forgot_password\" />\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_mfa_input_code_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_mfa_input_code_form_view.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_gravity=\"center\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\"\n    android:paddingBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n    android:paddingEnd=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n    android:paddingLeft=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n    android:paddingRight=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n    android:paddingStart=\"@dimen/com_auth0_lock_widget_horizontal_margin\"\n    android:paddingTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\">\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_text\"\n        style=\"@style/Lock.Theme.Text.Subtitle.ResetPassword\"\n        android:text=\"@string/com_auth0_lock_description_mfa_input_code\"\n        android:textSize=\"@dimen/com_auth0_lock_title_text\" />\n\n    <com.auth0.android.lock.views.ValidatedInputView\n        android:id=\"@+id/com_auth0_lock_input_code\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_passwordless\"\n        lock:Auth0.InputDataType=\"number\" />\n\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_password_strength.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_password_strength.xmlength.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n    android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_password_strength\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_password_strength_title_must_have\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_title_must_have\" />\n\n    <com.auth0.android.lock.views.CheckableOptionView\n        android:id=\"@+id/com_auth0_lock_password_strength_option_length\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_chars_length\" />\n\n    <com.auth0.android.lock.views.CheckableOptionView\n        android:id=\"@+id/com_auth0_lock_password_strength_option_identical_characters\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_identical_chars\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_password_strength_title_at_least\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        android:text=\"@string/com_auth0_lock_password_strength_title_at_least\" />\n\n    <com.auth0.android.lock.views.CheckableOptionView\n        android:id=\"@+id/com_auth0_lock_password_strength_option_lowercase\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_lowercase_letters\" />\n\n    <com.auth0.android.lock.views.CheckableOptionView\n        android:id=\"@+id/com_auth0_lock_password_strength_option_uppercase\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_uppercase_letters\" />\n\n    <com.auth0.android.lock.views.CheckableOptionView\n        android:id=\"@+id/com_auth0_lock_password_strength_option_numeric\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_numbers\" />\n\n    <com.auth0.android.lock.views.CheckableOptionView\n        android:id=\"@+id/com_auth0_lock_password_strength_option_special_characters\"\n        style=\"@style/Lock.Theme.Text.PasswordPolicy\"\n        android:text=\"@string/com_auth0_lock_password_strength_special_chars\" />\n</LinearLayout>\n"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_passwordless_activity_country_code.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_passwordless_activity_country_code.xml\n  ~\n  ~ Copyright (c) 2015 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fitsSystemWindows=\"true\"\n    tools:context=\".CountryCodeActivity\">\n\n    <EditText\n        android:id=\"@+id/com_auth0_lock_passwordless_sms_search_country\"\n        style=\"@style/Lock.Theme.Widget.Field.Search\"\n        tools:ignore=\"Autofill,LabelFor\" />\n\n    <ListView\n        android:id=\"@+id/com_auth0_lock_passwordless_sms_country_code_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_below=\"@id/com_auth0_lock_passwordless_sms_search_country\" />\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_passwordless_country_code_selector.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_passwordless_country_code_selector.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_icon\"\n        style=\"@style/Lock.Theme.Widget.Icon\"\n        android:layout_alignParentStart=\"true\"\n        android:src=\"@drawable/com_auth0_lock_ic_world\"\n        tools:ignore=\"MissingPrefix\" />\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_chevron\"\n        style=\"@style/Lock.Theme.Widget.Icon\"\n        android:layout_alignParentEnd=\"true\"\n        android:src=\"@drawable/com_auth0_lock_ic_chevron\"\n        tools:ignore=\"MissingPrefix\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_country_code\"\n        style=\"@style/Lock.Theme.Widget.CountryCodeSelector.CountryCode\"\n        android:layout_width=\"wrap_content\"\n        android:layout_toStartOf=\"@+id/com_auth0_lock_chevron\"\n        tools:ignore=\"SelectableText\"\n        tools:text=\"+1234\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_country_name\"\n        style=\"@style/Lock.Theme.Widget.CountryCodeSelector.CountryName\"\n        android:layout_toStartOf=\"@+id/com_auth0_lock_country_code\"\n        android:layout_toEndOf=\"@id/com_auth0_lock_icon\"\n        tools:ignore=\"SelectableText\"\n        tools:text=\"Antigua and Barbuda and United States\" />\n\n    <FrameLayout\n        android:id=\"@+id/com_auth0_lock_outline\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/com_auth0_lock_widget_height\"\n        android:layout_alignParentTop=\"true\"\n        tools:visibility=\"gone\" />\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_passwordless_input_code_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_passwordless_input_code_form_view.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_text\"\n        style=\"@style/Lock.Theme.Text.Title\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_passwordless_sent\"\n        tools:text=\"@string/com_auth0_lock_title_passwordless_code_email_sent\" />\n\n    <com.auth0.android.lock.views.ValidatedInputView\n        android:id=\"@+id/com_auth0_lock_input_passwordless\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        lock:Auth0.InputDataType=\"number\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_resend\"\n        style=\"@style/Lock.Theme.Text.Link\"\n        android:text=\"@string/com_auth0_lock_title_passwordless_code_retry\" />\n\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_passwordless_item_country_code.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_passwordless_item_country_code.xml\n  ~\n  ~ Copyright (c) 2015 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"horizontal\">\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_passwordless_sms_country_name_text_view\"\n        style=\"@style/Lock.Theme.Text.ListItem\"\n        tools:text=\"US\"\n        android:layout_width=\"wrap_content\"\n        android:gravity=\"center_vertical\"\n        tools:ignore=\"SelectableText\" />\n\n    <TextView\n        android:id=\"@+id/com_auth0_lock_passwordless_sms_country_code_text_view\"\n        style=\"@style/Lock.Theme.Text.ListItem\"\n        tools:text=\"+1\"\n        android:layout_width=\"0dp\"\n        android:layout_weight=\"1\"\n        android:gravity=\"center_vertical|start\"\n        tools:ignore=\"SelectableText\" />\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_passwordless_request_code_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_login_form_view.xmlew.xml\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <androidx.appcompat.widget.AppCompatTextView\n        android:id=\"@+id/com_auth0_lock_text\"\n        style=\"@style/Lock.Theme.Text.Title\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_passwordless_sent\"\n        android:visibility=\"gone\"\n        tools:text=\"@string/com_auth0_lock_title_passwordless_email\" />\n\n    <com.auth0.android.lock.views.CountryCodeSelectorView\n        android:id=\"@+id/com_auth0_lock_country_code_selector\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center_horizontal\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        android:focusable=\"true\"\n        android:focusableInTouchMode=\"false\"\n        android:nextFocusDown=\"@+id/com_auth0_lock_input_passwordless\" />\n\n    <com.auth0.android.lock.views.ValidatedInputView\n        android:id=\"@+id/com_auth0_lock_input_passwordless\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:nextFocusUp=\"@+id/com_auth0_lock_input_passwordless\"\n        lock:Auth0.InputDataType=\"username_or_email\" />\n\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_signup_form_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_signup_form_view.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:lock=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <com.auth0.android.lock.views.ValidatedUsernameInputView\n        android:id=\"@+id/com_auth0_lock_input_username\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        lock:Auth0.InputDataType=\"username\" />\n\n    <com.auth0.android.lock.views.ValidatedInputView\n        android:id=\"@+id/com_auth0_lock_input_email\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        lock:Auth0.InputDataType=\"email\" />\n\n    <com.auth0.android.lock.views.ValidatedPasswordInputView\n        android:id=\"@+id/com_auth0_lock_input_password\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"@dimen/com_auth0_lock_widget_vertical_margin_field\"\n        lock:Auth0.InputDataType=\"password\" />\n\n    <LinearLayout\n        android:id=\"@+id/com_auth0_lock_custom_fields_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\" />\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_sso_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_sso_layout.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/com_auth0_lock_sso_message\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_alignParentTop=\"true\"\n    android:background=\"@color/com_auth0_lock_sso_background\"\n    android:gravity=\"center\"\n    android:orientation=\"horizontal\"\n    android:paddingBottom=\"@dimen/com_auth0_lock_top_banner_vertical_margin\"\n    android:paddingTop=\"@dimen/com_auth0_lock_top_banner_vertical_margin\"\n    tools:ignore=\"Overdraw\">\n\n    <ImageView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:src=\"@drawable/com_auth0_lock_ic_sso\"\n        tools:ignore=\"MissingPrefix\" />\n\n    <TextView\n        style=\"@style/Lock.Theme.Text.SSO\"\n        android:text=\"@string/com_auth0_lock_single_sign_on_enabled\" />\n\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_tab.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <TextView\n        android:id=\"@android:id/text1\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:gravity=\"center\"\n        android:lines=\"1\"\n        android:textAppearance=\"@style/Lock.Theme.TextAppearance.Tab\"\n        tools:ignore=\"SelectableText\" />\n\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_tab_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <com.google.android.material.tabs.TabLayout xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/com_auth0_lock_tab_layout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        app:tabBackground=\"@drawable/com_auth0_lock_tab\"\n        app:tabMode=\"fixed\"\n        app:tabIndicatorColor=\"@color/com_auth0_lock_text\"\n        app:tabIndicatorHeight=\"@dimen/com_auth0_lock_widget_tab_strip_height\"\n        app:tabPaddingEnd=\"0dp\"\n        app:tabPaddingStart=\"0dp\"/>\n\n    <FrameLayout\n            android:layout_width=\"match_parent\"\n            android:layout_gravity=\"bottom\"\n            android:layout_height=\"@dimen/com_auth0_lock_widget_tab_strip_height\"\n            android:background=\"@color/com_auth0_lock_tab_underline\" />\n\n</FrameLayout>\n"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_terms_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_terms_layout.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"@drawable/com_auth0_lock_terms\"\n    android:focusable=\"true\"\n    android:focusableInTouchMode=\"false\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\"\n    android:paddingBottom=\"@dimen/com_auth0_lock_bottom_banner_vertical_margin\"\n    android:paddingTop=\"@dimen/com_auth0_lock_bottom_banner_vertical_margin\">\n\n    <androidx.appcompat.widget.AppCompatTextView\n        style=\"@style/Lock.Theme.Text.Terms\"\n        android:text=\"@string/com_auth0_lock_sign_up_terms\" />\n\n</LinearLayout>"
  },
  {
    "path": "lib/src/main/res/layout/com_auth0_lock_validated_input_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ com_auth0_lock_validated_field.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <ImageView\n        android:id=\"@+id/com_auth0_lock_icon\"\n        style=\"@style/Lock.Theme.Widget.Icon\"\n        android:layout_alignParentStart=\"true\"\n        tools:ignore=\"MissingPrefix\"\n        tools:src=\"@drawable/com_auth0_lock_ic_email\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignWithParentIfMissing=\"true\"\n        android:layout_toEndOf=\"@+id/com_auth0_lock_icon\">\n\n        <EditText\n            android:id=\"@+id/com_auth0_lock_input\"\n            style=\"@style/Lock.Theme.Widget.Field\"\n            android:layout_width=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@null\"\n            tools:ignore=\"Autofill,TextFields,LabelFor\"\n            tools:text=\"email@domain.com\" />\n\n        <com.auth0.android.lock.views.ImageCheckbox\n            android:id=\"@+id/com_auth0_lock_show_password_toggle\"\n            style=\"@style/Lock.Theme.Widget.Icon.PasswordVisibilityToggle\"\n            android:checked=\"true\" />\n    </LinearLayout>\n\n    <TextView\n        android:id=\"@+id/errorDescription\"\n        style=\"@style/Lock.Theme.Text.ValidationError\"\n        android:layout_below=\"@+id/com_auth0_lock_icon\"\n        tools:ignore=\"SelectableText\"\n        tools:text=\"Invalid Email Address \" />\n\n    <FrameLayout\n        android:id=\"@+id/com_auth0_lock_outline\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/com_auth0_lock_widget_height\"\n        android:layout_alignParentTop=\"true\" />\n</RelativeLayout>"
  },
  {
    "path": "lib/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ attrs.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources>\n    <declare-styleable name=\"Lock.Theme\">\n        <attr name=\"Auth0.HeaderLogo\" format=\"reference\" />\n        <attr name=\"Auth0.HeaderTitle\" format=\"string|reference\" />\n        <attr name=\"Auth0.HeaderBackground\" format=\"color|reference\" />\n        <attr name=\"Auth0.HeaderTitleColor\" format=\"color|reference\" />\n        <attr name=\"Auth0.PrimaryColor\" format=\"color|reference\" />\n        <attr name=\"Auth0.DarkPrimaryColor\" format=\"color|reference\" />\n        <attr name=\"Auth0.DefaultSocialStyle\" format=\"reference\" />\n    </declare-styleable>\n\n    <declare-styleable name=\"Lock.ValidatedInput\">\n        <attr name=\"Auth0.InputDataType\" format=\"enum\">\n            <enum name=\"username\" value=\"0\" />\n            <enum name=\"email\" value=\"1\" />\n            <enum name=\"username_or_email\" value=\"2\" />\n            <enum name=\"number\" value=\"3\" />\n            <enum name=\"phone_number\" value=\"4\" />\n            <enum name=\"password\" value=\"5\" />\n        </attr>\n    </declare-styleable>\n\n    <declare-styleable name=\"Lock.SocialConfig\">\n        <attr name=\"Auth0.BackgroundColor\" format=\"color|reference\" />\n        <attr name=\"Auth0.Name\" format=\"string|reference\" />\n        <attr name=\"Auth0.Logo\" format=\"reference\" />\n    </declare-styleable>\n</resources>"
  },
  {
    "path": "lib/src/main/res/values/auth_styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"Lock.Theme.AuthStyle.Apple\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_apple</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_apple</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_apple</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Dropbox\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_dropbox</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_dropbox</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_dropbox</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.BitBucket\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_bitbucket</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_bitbucket</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_bitbucket</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Yahoo\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_yahoo</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_yahoo</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_yahoo</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.LinkedIn\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_linkedin</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_linkedin</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_linkedin</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.GoogleOAuth2\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_google_oauth2</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_google_oauth2</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_google_oauth2</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Twitter\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_twitter</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_twitter</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_twitter</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Facebook\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_facebook</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_facebook</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_facebook</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Amazon\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_amazon</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_amazon</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_amazon</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.AOL\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_aol</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_aol</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_aol</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Box\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_box</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_box</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_box</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Evernote\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_evernote</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_evernote</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_evernote</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.EvernoteSandbox\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_evernote_sandbox</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_evernote_sandbox</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_evernote_sandbox</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Exact\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_exact</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_exact</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_exact</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.GitHub\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_github</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_github</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_github</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Instagram\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_instagram</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_instagram</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_instagram</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.MiiCard\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_miicard</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_miicard</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_miicard</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Paypal\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_paypal</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_paypal</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_paypal</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.PaypalSandbox\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_paypal</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_paypal_sandbox</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_paypal</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Salesforce\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_salesforce</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_salesforce</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_salesforce</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.SalesforceCommunity\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_salesforce_community</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_salesforce_community</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_salesforce_community</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.SalesforceSandbox\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_salesforce_sandbox</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_salesforce_sandbox</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_salesforce_sandbox</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.SoundCloud\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_soundcloud</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_soundcloud</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_soundcloud</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.WindowsLive\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_windowslive</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_windowslive</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_windowslive</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Yammer\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_yammer</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_yammer</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_yammer</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Baidu\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_baidu</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_baidu</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_baidu</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Fitbit\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_fitbit</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_fitbit</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_fitbit</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.PlanningCenter\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_planningcenter</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_planningcenter</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_planningcenter</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.RenRen\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_renren</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_renren</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_renren</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.TheCity\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_thecity</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_thecity</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_thecity</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.TheCitySandbox\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_thecity_sandbox</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_thecity_sandbox</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_thecity_sandbox</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.ThirtySevenSignals\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_thirtysevensignals</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_thirtysevensignals</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_thirtysevensignals</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Vkontakte\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_vkontakte</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_vkontakte</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_vkontakte</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Weibo\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_weibo</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_weibo</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_weibo</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Wordpress\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_wordpress</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_wordpress</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_wordpress</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Yandex\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_yandex</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_yandex</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_yandex</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Shopify\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_shopify</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_shopify</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_shopify</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle.Dwolla\" parent=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_dwolla</item>\n        <item name=\"Auth0.Name\">@string/com_auth0_lock_social_dwolla</item>\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_dwolla</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "lib/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ colors.xml\n  ~\n  ~ Copyright (c) 2015 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n<resources xmlns:tools=\"http://schemas.android.com/tools\" tools:keep=\"@color/com_auth0_lock_social_*\">\n    <color name=\"com_auth0_lock_social_unknown\">#E33B1B</color>\n    <color name=\"com_auth0_lock_social_yahoo\">#410093</color>\n    <color name=\"com_auth0_lock_social_linkedin\">#0077B5</color>\n    <color name=\"com_auth0_lock_social_google_oauth2\">#FFFFFF</color>\n    <color name=\"com_auth0_lock_social_twitter\">#55ACEE</color>\n    <color name=\"com_auth0_lock_social_facebook\">#3B5998</color>\n    <color name=\"com_auth0_lock_social_amazon\">#FF9900</color>\n    <color name=\"com_auth0_lock_social_aol\">#E60E04</color>\n    <color name=\"com_auth0_lock_social_box\">#267BB6</color>\n    <color name=\"com_auth0_lock_social_apple\">#000000</color>\n    <color name=\"com_auth0_lock_social_dropbox\">#007ee5</color>\n    <color name=\"com_auth0_lock_social_bitbucket\">#205081</color>\n    <color name=\"com_auth0_lock_social_evernote\">#82B137</color>\n    <color name=\"com_auth0_lock_social_evernote_sandbox\">#82B137</color>\n    <color name=\"com_auth0_lock_social_exact\">#ED1C24</color>\n    <color name=\"com_auth0_lock_social_github\">#333333</color>\n    <color name=\"com_auth0_lock_social_instagram\">#3F729B</color>\n    <color name=\"com_auth0_lock_social_miicard\">#3FB7FF</color>\n    <color name=\"com_auth0_lock_social_paypal\">#009CDE</color>\n    <color name=\"com_auth0_lock_social_salesforce\">#1798C1</color>\n    <color name=\"com_auth0_lock_social_salesforce_community\">#1798C1</color>\n    <color name=\"com_auth0_lock_social_salesforce_sandbox\">#1798C1</color>\n    <color name=\"com_auth0_lock_social_soundcloud\">#FF8800</color>\n    <color name=\"com_auth0_lock_social_windowslive\">#00A1F1</color>\n    <color name=\"com_auth0_lock_social_yammer\">#0072C6</color>\n    <color name=\"com_auth0_lock_social_baidu\">#2529D8</color>\n    <color name=\"com_auth0_lock_social_fitbit\">#4CC2C4</color>\n    <color name=\"com_auth0_lock_social_planningcenter\">#4E4E4E</color>\n    <color name=\"com_auth0_lock_social_renren\">#0056B5</color>\n    <color name=\"com_auth0_lock_social_thecity\">#767571</color>\n    <color name=\"com_auth0_lock_social_thecity_sandbox\">#767571</color>\n    <color name=\"com_auth0_lock_social_thirtysevensignals\">#6AC071</color>\n    <color name=\"com_auth0_lock_social_vkontakte\">#45668E</color>\n    <color name=\"com_auth0_lock_social_weibo\">#DA4A38</color>\n    <color name=\"com_auth0_lock_social_wordpress\">#21759B</color>\n    <color name=\"com_auth0_lock_social_yandex\">#FFCC00</color>\n    <color name=\"com_auth0_lock_social_shopify\">#96BF48</color>\n    <color name=\"com_auth0_lock_social_dwolla\">#F5891F</color>\n    <color name=\"com_auth0_lock_social_text\">#FFFFFF</color>\n    <color name=\"com_auth0_lock_social_text_light\">#333333</color>\n\n    <color name=\"com_auth0_lock_validation_error_text\">#ff0000</color>\n\n    <color name=\"com_auth0_lock_header_background\">#E5E5E5</color>\n    <color name=\"com_auth0_lock_form_background\">#ffffff</color>\n    <color name=\"com_auth0_lock_terms_background\">#EEEEEE</color>\n    <color name=\"com_auth0_lock_terms_text\">#666666</color>\n    <color name=\"com_auth0_lock_sso_text\">#8e000000</color>\n    <color name=\"com_auth0_lock_sso_background\">#F5F7F9</color>\n    <color name=\"com_auth0_lock_tab_underline\">#325C666F</color>\n    <color name=\"com_auth0_lock_tab_text\">#5C666F</color>\n\n    <color name=\"com_auth0_lock_input_field_border_normal\">#f1f1f1</color>\n    <color name=\"com_auth0_lock_input_field_border_error\">#ff0000</color>\n    <color name=\"com_auth0_lock_input_field_background\">#ffffff</color>\n    <color name=\"com_auth0_lock_input_field_background_disabled\">#f9f9f9</color>\n    <color name=\"com_auth0_lock_input_country_code_background\">#FAFAFA</color>\n    <color name=\"com_auth0_lock_submit_normal\">#EC5210</color>\n    <color name=\"com_auth0_lock_submit_pressed\">#8C3215</color>\n    <color name=\"com_auth0_lock_submit_disabled\">#e3e5e7</color>\n    <color name=\"com_auth0_lock_result_message_error_background\">#FF3E00</color>\n    <color name=\"com_auth0_lock_result_message_success_background\">#7ED321</color>\n    <color name=\"com_auth0_lock_result_message\">#ffffff</color>\n    <color name=\"com_auth0_lock_normal_text\">#a6000000</color>\n    <color name=\"com_auth0_lock_disabled_text\">#4d000000</color>\n    <color name=\"com_auth0_lock_passwordless_link_sent_text\">#c8000000</color>\n    <color name=\"com_auth0_lock_hint_text\">#999999</color>\n    <color name=\"com_auth0_lock_error_link\">#0A86B1</color>\n\n    <color name=\"com_auth0_lock_checkable_option_success\">#518C11</color>\n    <color name=\"com_auth0_lock_checkable_option_error\">#FF511A</color>\n\n\n    <!-- Focus State Colors -->\n    <color name=\"com_auth0_lock_terms_background_focused\">#d7d7d7</color>\n    <color name=\"com_auth0_lock_input_field_border_focused\">#a4000000</color>\n    <color name=\"com_auth0_lock_link_focused\">#D8D8D8</color>\n    <color name=\"com_auth0_lock_tab_focused\">#F9F9F9</color>\n    <color name=\"com_auth0_lock_social_light_background_focused\">#f0f0f0</color>\n\n</resources>"
  },
  {
    "path": "lib/src/main/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ dimens.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources>\n    <dimen name=\"com_auth0_lock_widget_corner_radius\">3dp</dimen>\n    <dimen name=\"com_auth0_lock_list_item_height\">52dp</dimen>\n    <dimen name=\"com_auth0_lock_header_logo_size\">72dp</dimen>\n    <dimen name=\"com_auth0_lock_header_height\">116dp</dimen>\n\n    <dimen name=\"com_auth0_lock_input_field_stroke_width\">1dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_with_text_horizontal_padding\">13dp</dimen>\n\n    <dimen name=\"com_auth0_lock_widget_tab_strip_height\">2dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_height\">47dp</dimen>\n    <dimen name=\"com_auth0_lock_field_icon_height\">30dp</dimen>\n    <dimen name=\"com_auth0_lock_form_selector_height\">33dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_small_margin\">6dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_field_icon_padding\">13dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_social_icon_padding\">10dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_passwordless_sent\">26dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_link\">25dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_mode_selection\">15dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_error_title\">32dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_field\">7dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_field_with_error\">3dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_password_strength\">10dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_social\">7dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_passwordless\">30dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_horizontal_margin_small\">9dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_horizontal_margin\">25dp</dimen>\n\n    <dimen name=\"com_auth0_lock_header_vertical_margin\">4dp</dimen>\n    <dimen name=\"com_auth0_lock_header_logo_vertical_margin\">2dp</dimen>\n    <dimen name=\"com_auth0_lock_action_button_vertical_margin\">16dp</dimen>\n    <dimen name=\"com_auth0_lock_action_button_labeled_vertical_margin\">31dp</dimen>\n    <dimen name=\"com_auth0_lock_bottom_banner_vertical_margin\">7dp</dimen>\n    <dimen name=\"com_auth0_lock_top_banner_vertical_margin\">12dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_checkable_option\">2.6dp</dimen>\n\n    <!-- TEXTS -->\n    <dimen name=\"com_auth0_lock_tab_text\">14sp</dimen>\n    <dimen name=\"com_auth0_lock_header_text\">23sp</dimen>\n    <dimen name=\"com_auth0_lock_title_text\">17sp</dimen>\n    <dimen name=\"com_auth0_lock_change_password_title_text\">25sp</dimen>\n    <dimen name=\"com_auth0_lock_sign_up_custom_fields_title_text\">24.4sp</dimen>\n\n    <dimen name=\"com_auth0_lock_small_clickable_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_terms_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_social_button_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_sso_text\">14sp</dimen>\n    <dimen name=\"com_auth0_lock_switcher_text\">12sp</dimen>\n    <dimen name=\"com_auth0_lock_field_text\">15dp</dimen>\n    <dimen name=\"com_auth0_lock_field_error_text\">13sp</dimen>\n    <dimen name=\"com_auth0_lock_password_policy_text\">14sp</dimen>\n    <dimen name=\"com_auth0_lock_list_item_text\">17sp</dimen>\n    <dimen name=\"com_auth0_lock_result_message_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_labeled_submit_button_text\">19sp</dimen>\n    <dimen name=\"com_auth0_lock_title_error_text\">21sp</dimen>\n    <dimen name=\"com_auth0_lock_subtitle_error_text\">15sp</dimen>\n\n    <dimen name=\"com_auth0_lock_title_text_spacing\">10dp</dimen>\n    <dimen name=\"com_auth0_lock_subtitle_text_spacing\">8dp</dimen>\n    <dimen name=\"com_auth0_lock_terms_text_spacing\">8dp</dimen>\n    <dimen name=\"com_auth0_lock_separator_text_spacing\">6dp</dimen>\n    <dimen name=\"com_auth0_lock_link_sent_text_spacing\">13dp</dimen>\n    <dimen name=\"com_auth0_lock_result_message_text_spacing\">5dp</dimen>\n\n</resources>"
  },
  {
    "path": "lib/src/main/res/values/ids.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ ids.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources>\n    <item name=\"com_auth0_lock_form_selector\" type=\"id\" />\n</resources>"
  },
  {
    "path": "lib/src/main/res/values/strings.xml",
    "content": "<!--\n  ~ strings.xml\n  ~\n  ~ Copyright (c) 2015 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources xmlns:tools=\"http://schemas.android.com/tools\" tools:keep=\"@string/com_auth0_lock_social_*\">\n    <!-- Social Buttons -->\n    <string name=\"com_auth0_lock_social_log_in\">Sign in with %s</string>\n    <string name=\"com_auth0_lock_social_sign_up\">Sign up with %s</string>\n    <string name=\"com_auth0_lock_social_apple\">Apple</string>\n    <string name=\"com_auth0_lock_social_dropbox\">Dropbox</string>\n    <string name=\"com_auth0_lock_social_bitbucket\">Bitbucket</string>\n    <string name=\"com_auth0_lock_social_yahoo\">Yahoo!</string>\n    <string name=\"com_auth0_lock_social_linkedin\">LinkedIn</string>\n    <string name=\"com_auth0_lock_social_google_oauth2\">Google</string>\n    <string name=\"com_auth0_lock_social_twitter\">Twitter</string>\n    <string name=\"com_auth0_lock_social_facebook\">Facebook</string>\n    <string name=\"com_auth0_lock_social_amazon\">Amazon</string>\n    <string name=\"com_auth0_lock_social_aol\">AOL</string>\n    <string name=\"com_auth0_lock_social_box\">BOX</string>\n    <string name=\"com_auth0_lock_social_evernote\">Evernote</string>\n    <string name=\"com_auth0_lock_social_evernote_sandbox\">Evernote (Sandbox)</string>\n    <string name=\"com_auth0_lock_social_exact\">Exact</string>\n    <string name=\"com_auth0_lock_social_github\">Github</string>\n    <string name=\"com_auth0_lock_social_instagram\">Instagram</string>\n    <string name=\"com_auth0_lock_social_miicard\">miiCard</string>\n    <string name=\"com_auth0_lock_social_paypal\">PayPal</string>\n    <string name=\"com_auth0_lock_social_paypal_sandbox\">PayPal (Sandbox)</string>\n    <string name=\"com_auth0_lock_social_salesforce\">Salesforce</string>\n    <string name=\"com_auth0_lock_social_salesforce_community\">Salesforce (Community)</string>\n    <string name=\"com_auth0_lock_social_salesforce_sandbox\">Salesforce (Sandbox)</string>\n    <string name=\"com_auth0_lock_social_soundcloud\">SoundCloud</string>\n    <string name=\"com_auth0_lock_social_windowslive\">Microsoft</string>\n    <string name=\"com_auth0_lock_social_yammer\">Yammer</string>\n    <string name=\"com_auth0_lock_social_baidu\">百度</string>\n    <string name=\"com_auth0_lock_social_fitbit\">Fitbit</string>\n    <string name=\"com_auth0_lock_social_planningcenter\">Planning Center</string>\n    <string name=\"com_auth0_lock_social_renren\">人人</string>\n    <string name=\"com_auth0_lock_social_thecity\">The City</string>\n    <string name=\"com_auth0_lock_social_thecity_sandbox\">The City (Sandbox)</string>\n    <string name=\"com_auth0_lock_social_thirtysevensignals\">Basecamp</string>\n    <string name=\"com_auth0_lock_social_vkontakte\">VKontakte</string>\n    <string name=\"com_auth0_lock_social_weibo\">新浪微博</string>\n    <string name=\"com_auth0_lock_social_wordpress\">WordPress</string>\n    <string name=\"com_auth0_lock_social_yandex\">Yandex</string>\n    <string name=\"com_auth0_lock_social_shopify\">Shopify</string>\n    <string name=\"com_auth0_lock_social_dwolla\">Dwolla</string>\n\n    <!-- Lock General -->\n    <string name=\"com_auth0_lock_default_country_name_fallback\">US</string>\n    <string name=\"com_auth0_lock_default_country_code_fallback\">+1</string>\n    <string name=\"com_auth0_lock_header_title\">Auth0</string>\n    <string name=\"com_auth0_lock_input_error_email\">Invalid Email Address</string>\n    <string name=\"com_auth0_lock_input_error_password\">Invalid Password</string>\n    <string name=\"com_auth0_lock_input_error_username_email\">Invalid Username or Email Address</string>\n    <string name=\"com_auth0_lock_input_error_username\" formatted=\"false\" tools:ignore=\"StringFormatInvalid,TypographyQuotes\">Invalid Username. Can only contain between %d to %d alphanumeric characters and \\'_\\'.</string>\n    <string name=\"com_auth0_lock_input_error_username_empty\" formatted=\"false\">Invalid Username</string>\n    <string name=\"com_auth0_lock_input_error_code\">Invalid Code</string>\n    <string name=\"com_auth0_lock_input_error_phone_number\">Invalid Phone Number</string>\n    <string name=\"com_auth0_lock_input_error_empty\">The value cannot be empty</string>\n    <string name=\"com_auth0_lock_hint_email\">Email</string>\n    <string name=\"com_auth0_lock_hint_password\">Password</string>\n    <string name=\"com_auth0_lock_hint_username\">Username</string>\n    <string name=\"com_auth0_lock_hint_username_or_email\">Username/Email</string>\n    <string name=\"com_auth0_lock_hint_code\">Code</string>\n    <string name=\"com_auth0_lock_hint_mfa_code\">Verification Code</string>\n    <string name=\"com_auth0_lock_hint_phone_number\">Phone Number</string>\n    <string name=\"com_auth0_lock_hint_search_country\">Search your country</string>\n    <string name=\"com_auth0_lock_action_sign_up\">SIGN UP</string>\n    <string name=\"com_auth0_lock_action_log_in\">LOG IN</string>\n    <string name=\"com_auth0_lock_mode_sign_up\">Sign Up</string>\n    <string name=\"com_auth0_lock_mode_log_in\">Log In</string>\n    <string name=\"com_auth0_lock_action_send_email\">SEND EMAIL</string>\n    <string name=\"com_auth0_lock_action_forgot_password\">Don\\'t remember your password?</string>\n    <string name=\"com_auth0_lock_action_single_login_with_corporate\">Login with your corporate credentials.</string>\n    <string name=\"com_auth0_lock_action_login_with_corporate\">Please enter your corporate credentials at %s</string>\n    <string name=\"com_auth0_lock_action_accept\">Accept</string>\n    <string name=\"com_auth0_lock_action_cancel\">Cancel</string>\n    <string name=\"com_auth0_lock_action_ok\">OK</string>\n    <string name=\"com_auth0_lock_single_sign_on_enabled\">SINGLE SIGN ON ENABLED</string>\n    <string name=\"com_auth0_lock_forms_separator\">OR</string>\n    <string name=\"com_auth0_lock_passwordless_sms_forms_separator\">Otherwise, enter your phone to sign in or create an account</string>\n    <string name=\"com_auth0_lock_passwordless_email_forms_separator\">Otherwise, enter your email to sign in or create an account</string>\n    <string name=\"com_auth0_lock_title_change_password\">Reset Password</string>\n    <string name=\"com_auth0_lock_title_sign_up_custom_fields\">Complete the sign up process</string>\n    <string name=\"com_auth0_lock_description_change_password\">Please enter your email address. We will send you an email to reset your password.</string>\n    <string name=\"com_auth0_lock_title_passwordless\">Code Sent</string>\n    <string name=\"com_auth0_lock_title_passwordless_code_email_sent\">An email with the code has been sent to %s</string>\n    <string name=\"com_auth0_lock_title_passwordless_code_sms_sent\">An SMS with the code has been sent to %s</string>\n    <string name=\"com_auth0_lock_title_passwordless_link_sent\">We sent you a link to sign in to\\n %s</string>\n    <string name=\"com_auth0_lock_title_passwordless_code_retry\">Did not get the code?</string>\n    <string name=\"com_auth0_lock_title_passwordless_got_code\">I have a code</string>\n    <string name=\"com_auth0_lock_title_social_progress_dialog\">Logging in</string>\n    <string name=\"com_auth0_lock_message_social_progress_dialog\">Logging in to Auth0</string>\n    <string name=\"com_auth0_lock_sign_up_terms\">By signing up, you agree to our terms of\\n service and privacy policy</string>\n    <string name=\"com_auth0_lock_title_passwordless_email\">Enter your email address to sign in\\n or create an account</string>\n    <string name=\"com_auth0_lock_title_passwordless_sms\">Enter your phone to sign in\\n or create an account</string>\n    <string name=\"com_auth0_lock_sign_up_terms_dialog_title\">Terms &amp; Policy</string>\n    <string name=\"com_auth0_lock_sign_up_terms_dialog_message\" formatted=\"false\" tools:ignore=\"StringFormatInvalid\"><![CDATA[\n    By signing up, you agree to our <a href=\\'%s\\'>terms of service</a> and <a href=\\'%s\\'>privacy policy</a>\n    ]]></string>\n\n    <!-- Custom Error Messages -->\n    <string name=\"com_auth0_lock_recoverable_error_title\">Can\\'t load the login box</string>\n    <string name=\"com_auth0_lock_recoverable_error_subtitle\">Please check your internet\\n connection.</string>\n    <string name=\"com_auth0_lock_recoverable_error_action\">Retry</string>\n    <string name=\"com_auth0_lock_unrecoverable_error_title\">Can\\'t resolve your request</string>\n    <string name=\"com_auth0_lock_unrecoverable_error_subtitle\">There was an unexpected error while resolving the login box configuration.</string>\n    <string name=\"com_auth0_lock_unrecoverable_error_subtitle_without_action\">There was an unexpected error while resolving the login box configuration, please contact support.</string>\n    <string name=\"com_auth0_lock_unrecoverable_error_action\">Contact support</string>\n    <string name=\"com_auth0_lock_missing_connections_message\">There isn\\'t any connection configured for this Application. Check your dashboard configuration on http://auth0.com</string>\n    <string name=\"com_auth0_lock_configuration_retrieving_error\">Error retrieving the Dashboard configuration</string>\n    <string name=\"com_auth0_lock_enterprise_no_connection_message\">THERE WAS NO CONNECTION CONFIGURED FOR THE DOMAIN</string>\n    <string name=\"com_auth0_lock_db_login_error_message\">THERE WAS AN ERROR PROCESSING THE SIGN IN</string>\n    <string name=\"com_auth0_lock_db_login_error_invalid_credentials_message\">WRONG EMAIL OR PASSWORD</string>\n    <string name=\"com_auth0_lock_db_login_error_mfa_enroll_required\">THE USER HAS NOT ENROLLED MULTIFACTOR AUTHENTICATION</string>\n    <string name=\"com_auth0_lock_db_login_error_invalid_mfa_code_message\">THE CODE IS INVALID OR HAS EXPIRED</string>\n    <string name=\"com_auth0_lock_db_login_error_unauthorized_message\">USER IS BLOCKED</string>\n    <string name=\"com_auth0_lock_db_sign_up_error_message\">THERE WAS AN ERROR PROCESSING THE SIGN UP</string>\n    <string name=\"com_auth0_lock_db_change_password_message_success\">WE\\'VE JUST SENT YOU AN EMAIL TO RESET YOUR PASSWORD</string>\n    <string name=\"com_auth0_lock_db_message_change_password_error\">COULDN\\'T RESET YOUR PASSWORD</string>\n    <string name=\"com_auth0_lock_db_signup_user_already_exists_error_message\">THE USER ALREADY EXISTS</string>\n    <string name=\"com_auth0_lock_db_signup_password_already_used_error_message\">THE PASSWORD WAS USED PREVIOUSLY</string>\n    <string name=\"com_auth0_lock_db_signup_password_not_strong_error_message\">THE PASSWORD IS NOT STRONG ENOUGH</string>\n    <string name=\"com_auth0_lock_db_too_many_attempts_error_message\">YOUR ACCOUNT HAS BEEN BLOCKED AFTER MULTIPLE CONSECUTIVE LOGIN ATTEMPTS</string>\n    <string name=\"com_auth0_lock_db_password_leaked_error_message\">THIS PASSWORD WAS FOUND IN A 3RD PARTY DATA BREACH. PLEASE CHANGE YOUR PASSWORD.</string>\n    <string name=\"com_auth0_lock_passwordless_code_request_error_message\">THERE WAS AN ERROR SENDING THE CODE</string>\n    <string name=\"com_auth0_lock_passwordless_link_request_error_message\">THERE WAS AN ERROR SENDING THE LINK</string>\n    <string name=\"com_auth0_lock_passwordless_login_error_invalid_credentials_message\">WRONG IDENTITY OR PASSCODE</string>\n    <string name=\"com_auth0_lock_title_mfa_input_code\">Two Step Verification</string>\n    <string name=\"com_auth0_lock_description_mfa_input_code\">Please enter a verification code from\\n your code generator application.</string>\n\n    <!-- Password Strength/Policies -->\n    <string name=\"com_auth0_lock_password_strength_identical_chars\">No more than 2 identical characters in a row (e.g., “111” not allowed)</string>\n    <string name=\"com_auth0_lock_password_strength_chars_length\" formatted=\"false\" tools:ignore=\"StringFormatInvalid\">At least %d characters in length</string>\n    <string name=\"com_auth0_lock_password_strength_lowercase_letters\">Lower case letters (a-z)</string>\n    <string name=\"com_auth0_lock_password_strength_uppercase_letters\">Upper case letters (A-Z)</string>\n    <string name=\"com_auth0_lock_password_strength_numbers\">Numbers (i.e. 0–9)</string>\n    <string name=\"com_auth0_lock_password_strength_special_chars\">Special characters (e.g. !@#$%^&amp;* )</string>\n    <string name=\"com_auth0_lock_password_strength_title_at_least\">And contain at least 3 of the following 4 types of characters:</string>\n    <string name=\"com_auth0_lock_password_strength_title_must_have\">Must have:</string>\n</resources>\n"
  },
  {
    "path": "lib/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ styles.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources>\n\n    <style name=\"Lock.Theme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"colorAccent\">?attr/Auth0.PrimaryColor</item>\n        <item name=\"colorPrimaryDark\">?attr/Auth0.HeaderBackground</item>\n        <item name=\"android:textColorHighlight\">@color/com_auth0_lock_link_focused</item>\n        <item name=\"android:windowBackground\">@color/com_auth0_lock_form_background</item>\n        <item name=\"Auth0.HeaderLogo\">@drawable/com_auth0_lock_header_logo</item>\n        <item name=\"Auth0.HeaderTitle\">@string/com_auth0_lock_header_title</item>\n        <item name=\"Auth0.HeaderTitleColor\">@color/com_auth0_lock_text</item>\n        <item name=\"Auth0.HeaderBackground\">@color/com_auth0_lock_header_background</item>\n        <item name=\"Auth0.PrimaryColor\">@color/com_auth0_lock_submit_normal</item>\n        <item name=\"Auth0.DarkPrimaryColor\">@color/com_auth0_lock_submit_pressed</item>\n    </style>\n\n    <style name=\"Lock.Theme.AuthStyle\">\n        <item name=\"Auth0.BackgroundColor\">@color/com_auth0_lock_social_unknown</item>\n        <item name=\"Auth0.Name\" />\n        <item name=\"Auth0.Logo\">@drawable/com_auth0_lock_ic_social_auth0</item>\n    </style>\n\n    <style name=\"Lock.Theme.ActionBar\" parent=\"Theme.AppCompat.Light.DarkActionBar\" />\n\n    <style name=\"Lock.Theme.Text\">\n        <item name=\"android:textStyle\">normal</item>\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_text</item>\n        <item name=\"android:fontFamily\">sans-serif</item>\n    </style>\n\n    <style name=\"Lock.Theme.TextAppearance.Tab\" parent=\"TextAppearance.AppCompat.Button\">\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_tab_text</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_tab_text</item>\n        <item name=\"android:textAllCaps\">false</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.PasswordPolicy\">\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_field_error_text</item>\n        <item name=\"android:layout_gravity\">start</item>\n        <item name=\"android:textAlignment\">viewStart</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.ValidationError\">\n        <item name=\"android:textColor\">@color/com_auth0_lock_validation_error_text</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_field_error_text</item>\n        <item name=\"android:maxLines\">2</item>\n        <item name=\"android:layout_gravity\">start</item>\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_marginTop\">\n            @dimen/com_auth0_lock_widget_vertical_margin_field_with_error\n        </item>\n        <item name=\"android:textAlignment\">viewStart</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Terms\">\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:lineSpacingExtra\">@dimen/com_auth0_lock_terms_text_spacing</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_terms_text</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_terms_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.SSO\">\n        <item name=\"android:layout_marginLeft\">\n            @dimen/com_auth0_lock_widget_horizontal_margin_small\n        </item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_sso_text</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_sso_text</item>\n        <item name=\"android:layout_marginStart\">\n            @dimen/com_auth0_lock_widget_horizontal_margin_small\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.ListItem\">\n        <item name=\"android:layout_marginLeft\">\n            @dimen/com_auth0_lock_widget_horizontal_margin_small\n        </item>\n        <item name=\"android:layout_height\">@dimen/com_auth0_lock_list_item_height</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_list_item_text</item>\n        <item name=\"android:layout_marginStart\">\n            @dimen/com_auth0_lock_widget_horizontal_margin_small\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Link\">\n        <item name=\"android:layout_gravity\">center_horizontal</item>\n        <item name=\"android:layout_centerHorizontal\">true</item>\n        <item name=\"android:layout_marginTop\">@dimen/com_auth0_lock_widget_vertical_margin_link\n        </item>\n        <item name=\"android:gravity\">center_horizontal</item>\n        <item name=\"android:padding\">@dimen/com_auth0_lock_widget_vertical_margin_field</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_small_clickable_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.ErrorLink\" parent=\"Lock.Theme.Text.Link\">\n        <item name=\"android:layout_marginTop\">0dp</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_error_link</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_subtitle_error_text</item>\n        <item name=\"android:layout_marginLeft\">@dimen/com_auth0_lock_widget_horizontal_margin</item>\n        <item name=\"android:layout_marginRight\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginStart\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginEnd\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Title\">\n        <item name=\"android:layout_gravity\">center_horizontal</item>\n        <item name=\"android:layout_centerHorizontal\">true</item>\n        <item name=\"android:gravity\">center_horizontal</item>\n        <item name=\"android:layout_marginBottom\">\n            @dimen/com_auth0_lock_widget_vertical_margin_field\n        </item>\n        <item name=\"android:lineSpacingExtra\">@dimen/com_auth0_lock_title_text_spacing</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_title_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Title.ResetPassword\">\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_change_password_title_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Title.SignUpCustomFields\">\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_sign_up_custom_fields_title_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Subtitle.ResetPassword\" parent=\"Lock.Theme.Text.Title\">\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_title_text</item>\n        <item name=\"android:lineSpacingExtra\">@dimen/com_auth0_lock_subtitle_text_spacing</item>\n        <item name=\"android:layout_marginLeft\">@dimen/com_auth0_lock_widget_horizontal_margin</item>\n        <item name=\"android:layout_marginRight\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginStart\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginEnd\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Title.Error\">\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_title_error_text</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_passwordless_link_sent_text</item>\n        <item name=\"android:layout_marginLeft\">@dimen/com_auth0_lock_widget_horizontal_margin</item>\n        <item name=\"android:layout_marginRight\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginStart\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginEnd\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Subtitle.Error\" parent=\"Lock.Theme.Text.Title\">\n        <item name=\"android:lineSpacingExtra\">@dimen/com_auth0_lock_subtitle_text_spacing</item>\n        <item name=\"android:layout_marginBottom\">\n            @dimen/com_auth0_lock_widget_vertical_margin_passwordless\n        </item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_subtitle_error_text</item>\n        <item name=\"android:layout_marginLeft\">@dimen/com_auth0_lock_widget_horizontal_margin</item>\n        <item name=\"android:layout_marginRight\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginStart\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n        <item name=\"android:layout_marginEnd\">@dimen/com_auth0_lock_widget_horizontal_margin\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.SocialButton\">\n        <item name=\"android:gravity\">center|start</item>\n        <item name=\"android:layout_height\">match_parent</item>\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:maxLines\">1</item>\n        <item name=\"android:paddingLeft\">@dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:paddingRight\">\n            @dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:singleLine\">true</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_social_button_text</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_social_text</item>\n        <item name=\"android:layout_gravity\">start</item>\n        <item name=\"android:fontFamily\">sans-serif-medium</item>\n        <item name=\"android:paddingStart\">@dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:paddingEnd\">\n            @dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:textAlignment\">viewStart</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.ResultMessage\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_alignParentTop\">true</item>\n        <item name=\"android:maxLines\">2</item>\n        <item name=\"android:singleLine\">false</item>\n        <item name=\"android:lineSpacingExtra\">@dimen/com_auth0_lock_result_message_text_spacing\n        </item>\n        <item name=\"android:textStyle\">bold</item>\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:paddingBottom\">@dimen/com_auth0_lock_widget_small_margin</item>\n        <item name=\"android:paddingTop\">@dimen/com_auth0_lock_widget_small_margin</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_result_message</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_result_message_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget\">\n        <item name=\"android:layout_height\">@dimen/com_auth0_lock_widget_height</item>\n        <item name=\"android:layout_width\">match_parent</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Icon\">\n        <item name=\"android:layout_gravity\">center</item>\n        <item name=\"android:scaleType\">fitCenter</item>\n        <item name=\"android:padding\">@dimen/com_auth0_lock_widget_field_icon_padding</item>\n        <item name=\"android:layout_width\">@dimen/com_auth0_lock_widget_height</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Icon.Social\">\n        <item name=\"android:layout_width\">@dimen/com_auth0_lock_widget_height</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Icon.PasswordVisibilityToggle\">\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:layout_gravity\">center_vertical</item>\n        <item name=\"android:padding\">@dimen/com_auth0_lock_input_field_stroke_width</item>\n        <item name=\"android:tint\">@color/com_auth0_lock_hint_text</item>\n        <item name=\"android:src\">@drawable/com_auth0_lock_ic_password_hidden</item>\n        <item name=\"android:layout_marginRight\">@dimen/com_auth0_lock_widget_horizontal_margin_small\n        </item>\n        <item name=\"android:focusable\">true</item>\n        <item name=\"android:focusableInTouchMode\">false</item>\n        <item name=\"android:layout_marginEnd\">@dimen/com_auth0_lock_widget_horizontal_margin_small\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Field\" parent=\"Lock.Theme.Text\">\n        <item name=\"android:gravity\">center_vertical</item>\n        <item name=\"android:textColorHint\">@color/com_auth0_lock_hint_text</item>\n        <item name=\"android:layout_height\">@dimen/com_auth0_lock_widget_height</item>\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_text</item>\n        <item name=\"android:paddingLeft\">@dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:paddingRight\">\n            @dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:layout_marginRight\">@dimen/com_auth0_lock_input_field_stroke_width\n        </item>\n        <item name=\"android:layout_gravity\">start</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_field_text</item>\n        <item name=\"android:paddingStart\">@dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:paddingEnd\">\n            @dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:layout_marginEnd\">@dimen/com_auth0_lock_input_field_stroke_width</item>\n        <item name=\"android:textAlignment\">viewStart</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Field.Search\">\n        <item name=\"android:layout_height\">?android:attr/actionBarSize</item>\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:hint\">@string/com_auth0_lock_hint_search_country</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_title_text</item>\n        <item name=\"android:theme\">@style/Lock.Theme</item>\n        <item name=\"android:singleLine\">true</item>\n        <item name=\"android:maxLines\">1</item>\n        <item name=\"android:imeOptions\">actionDone</item>\n        <item name=\"android:inputType\">textAutoCorrect</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.CountryCodeSelector\" parent=\"Lock.Theme.Widget.Field\">\n        <item name=\"android:background\">@color/com_auth0_lock_input_country_code_background</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_hint_text</item>\n        <item name=\"android:layout_marginRight\">0dp</item>\n        <item name=\"android:paddingLeft\">0dp</item>\n        <item name=\"android:paddingRight\">0dp</item>\n        <item name=\"android:paddingStart\">0dp</item>\n        <item name=\"android:paddingEnd\">0dp</item>\n        <item name=\"android:layout_marginEnd\">0dp</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.CountryCodeSelector.CountryName\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:maxLines\">1</item>\n        <item name=\"android:singleLine\">true</item>\n        <item name=\"android:ellipsize\">end</item>\n        <item name=\"android:paddingLeft\">@dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:paddingStart\">@dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.CountryCodeSelector.CountryCode\">\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:maxLines\">1</item>\n        <item name=\"android:singleLine\">true</item>\n        <item name=\"android:ellipsize\">none</item>\n        <item name=\"android:paddingLeft\">\n            @dimen/com_auth0_lock_widget_small_margin\n        </item>\n        <item name=\"android:paddingRight\">\n            @dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n        <item name=\"android:paddingStart\">\n            @dimen/com_auth0_lock_widget_small_margin\n        </item>\n        <item name=\"android:paddingEnd\">\n            @dimen/com_auth0_lock_widget_with_text_horizontal_padding\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.SocialButton\">\n        <item name=\"android:layout_height\">wrap_content</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.SubmitButton\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:background\">@color/com_auth0_lock_submit_disabled</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.SubmitButton\">\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:maxLines\">1</item>\n        <item name=\"android:paddingRight\">@dimen/com_auth0_lock_widget_small_margin\n        </item>\n        <item name=\"android:singleLine\">true</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_labeled_submit_button_text</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_social_text</item>\n        <item name=\"android:paddingEnd\">@dimen/com_auth0_lock_widget_small_margin\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.LinkSent\">\n        <item name=\"android:layout_gravity\">center_horizontal</item>\n        <item name=\"android:gravity\">center_horizontal</item>\n        <item name=\"android:lineSpacingExtra\">@dimen/com_auth0_lock_link_sent_text_spacing</item>\n        <item name=\"android:textColor\">@color/com_auth0_lock_passwordless_link_sent_text</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_title_text</item>\n    </style>\n\n    <style name=\"Lock.Theme.Text.Header\">\n        <item name=\"android:layout_centerHorizontal\">true</item>\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:textSize\">@dimen/com_auth0_lock_header_text</item>\n        <item name=\"android:text\">?attr/Auth0.HeaderTitle</item>\n        <item name=\"android:lines\">1</item>\n        <item name=\"android:maxLines\">1</item>\n        <item name=\"android:singleLine\">true</item>\n        <item name=\"android:layout_marginTop\">@dimen/com_auth0_lock_header_logo_vertical_margin\n        </item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Logo\">\n        <item name=\"android:src\">?attr/Auth0.HeaderLogo</item>\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">@dimen/com_auth0_lock_header_logo_size</item>\n        <item name=\"android:layout_centerHorizontal\">true</item>\n        <item name=\"android:scaleType\">centerInside</item>\n    </style>\n\n    <style name=\"Lock.Theme.Widget.Header\">\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:layout_height\">@dimen/com_auth0_lock_header_height</item>\n        <item name=\"android:background\">?attr/Auth0.HeaderBackground</item>\n    </style>\n</resources>"
  },
  {
    "path": "lib/src/main/res/values-sw400dp/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ dimens.xml\n  ~\n  ~ Copyright (c) 2016 Auth0 (http://auth0.com)\n  ~\n  ~ Permission is hereby granted, free of charge, to any person obtaining a copy\n  ~ of this software and associated documentation files (the \"Software\"), to deal\n  ~ in the Software without restriction, including without limitation the rights\n  ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  ~ copies of the Software, and to permit persons to whom the Software is\n  ~ furnished to do so, subject to the following conditions:\n  ~\n  ~ The above copyright notice and this permission notice shall be included in\n  ~ all copies or substantial portions of the Software.\n  ~\n  ~ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  ~ THE SOFTWARE.\n  -->\n\n<resources>\n    <dimen name=\"com_auth0_lock_widget_corner_radius\">4dp</dimen>\n    <dimen name=\"com_auth0_lock_list_item_height\">55dp</dimen>\n    <dimen name=\"com_auth0_lock_header_logo_size\">80dp</dimen>\n    <dimen name=\"com_auth0_lock_header_height\">138dp</dimen>\n\n    <dimen name=\"com_auth0_lock_input_field_stroke_width\">2dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_with_text_horizontal_padding\">15dp</dimen>\n\n    <dimen name=\"com_auth0_lock_widget_tab_strip_height\">2dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_height\">54dp</dimen>\n    <dimen name=\"com_auth0_lock_field_icon_height\">35dp</dimen>\n    <dimen name=\"com_auth0_lock_form_selector_height\">40dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_small_margin\">7dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_field_icon_padding\">15dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_social_icon_padding\">13dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_passwordless_sent\">29dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_link\">33dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_mode_selection\">20dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_error_title\">40dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_field\">10dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_field_with_error\">5dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_password_strength\">15dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_social\">10dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_passwordless\">36dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_horizontal_margin_small\">11dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_horizontal_margin\">30dp</dimen>\n\n    <dimen name=\"com_auth0_lock_header_vertical_margin\">8dp</dimen>\n    <dimen name=\"com_auth0_lock_header_logo_vertical_margin\">4dp</dimen>\n    <dimen name=\"com_auth0_lock_action_button_vertical_margin\">19dp</dimen>\n    <dimen name=\"com_auth0_lock_action_button_labeled_vertical_margin\">33dp</dimen>\n    <dimen name=\"com_auth0_lock_bottom_banner_vertical_margin\">9dp</dimen>\n    <dimen name=\"com_auth0_lock_top_banner_vertical_margin\">15dp</dimen>\n    <dimen name=\"com_auth0_lock_widget_vertical_margin_checkable_option\">3.4dp</dimen>\n\n    <!-- TEXTS -->\n    <dimen name=\"com_auth0_lock_tab_text\">16sp</dimen>\n    <dimen name=\"com_auth0_lock_header_text\">25sp</dimen>\n    <dimen name=\"com_auth0_lock_title_text\">19sp</dimen>\n    <dimen name=\"com_auth0_lock_change_password_title_text\">27sp</dimen>\n    <dimen name=\"com_auth0_lock_sign_up_custom_fields_title_text\">26sp</dimen>\n\n    <dimen name=\"com_auth0_lock_small_clickable_text\">16sp</dimen>\n    <dimen name=\"com_auth0_lock_terms_text\">16sp</dimen>\n    <dimen name=\"com_auth0_lock_social_button_text\">17sp</dimen>\n    <dimen name=\"com_auth0_lock_sso_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_switcher_text\">13.5sp</dimen>\n    <dimen name=\"com_auth0_lock_field_text\">17dp</dimen>\n    <dimen name=\"com_auth0_lock_field_error_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_password_policy_text\">15sp</dimen>\n    <dimen name=\"com_auth0_lock_list_item_text\">18sp</dimen>\n    <dimen name=\"com_auth0_lock_result_message_text\">16sp</dimen>\n    <dimen name=\"com_auth0_lock_labeled_submit_button_text\">20sp</dimen>\n    <dimen name=\"com_auth0_lock_title_error_text\">26sp</dimen>\n    <dimen name=\"com_auth0_lock_subtitle_error_text\">16sp</dimen>\n\n    <dimen name=\"com_auth0_lock_title_text_spacing\">14dp</dimen>\n    <dimen name=\"com_auth0_lock_subtitle_text_spacing\">11dp</dimen>\n    <dimen name=\"com_auth0_lock_terms_text_spacing\">12dp</dimen>\n    <dimen name=\"com_auth0_lock_separator_text_spacing\">10dp</dimen>\n    <dimen name=\"com_auth0_lock_link_sent_text_spacing\">18dp</dimen>\n    <dimen name=\"com_auth0_lock_result_message_text_spacing\">7dp</dimen>\n\n</resources>"
  },
  {
    "path": "lib/src/test/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.auth0.android.lock\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application>\n        <!--Auth0 WebAuthProvider-->\n        <activity\n            android:name=\"com.auth0.android.provider.RedirectActivity\"\n            tools:node=\"remove\">\n        </activity>\n        <!--Auth0 WebAuthProvider End-->\n\n        <!--Auth0 Lock-->\n        <activity\n            android:name=\"com.auth0.android.lock.LockActivity\"\n            tools:node=\"remove\"/>\n        <!--Auth0 Lock End-->\n\n        <!--Auth0 PasswordlessLock-->\n        <activity\n            android:name=\"com.auth0.android.lock.PasswordlessLockActivity\"\n            tools:node=\"remove\">\n        </activity>\n        <!--Auth0 PasswordlessLock End-->\n\n        <!--Auth0 Lock Passwordless SMS Country Code Selection-->\n        <activity\n            android:name=\"com.auth0.android.lock.CountryCodeActivity\"\n            tools:node=\"remove\"/>\n        <!--Auth0 Lock Passwordless SMS Country Code Selection-->\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/Auth0ParcelableTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.os.Parcel;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.util.Auth0UserAgent;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport okhttp3.HttpUrl;\n\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.junit.Assert.assertThat;\n\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class Auth0ParcelableTest {\n\n    private static final String CLIENT_ID = \"CLIENT_ID\";\n    private static final String DOMAIN = \"https://my-domain.auth0.com\";\n    private static final String CONFIG_DOMAIN = \"https://my-cdn.auth0.com\";\n\n    @Test\n    public void shouldSaveClientId() {\n        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN, CONFIG_DOMAIN);\n        Auth0Parcelable auth0Parcelable = new Auth0Parcelable(auth0);\n        Parcel parcel = Parcel.obtain();\n        auth0Parcelable.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Auth0Parcelable parceledAuth0 = Auth0Parcelable.CREATOR.createFromParcel(parcel);\n        assertThat(auth0.getClientId(), is(equalTo(CLIENT_ID)));\n        assertThat(parceledAuth0.getAuth0().getClientId(), is(equalTo(CLIENT_ID)));\n    }\n\n    @Test\n    public void shouldSaveDomainUrl() {\n        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN, CONFIG_DOMAIN);\n        Auth0Parcelable auth0Parcelable = new Auth0Parcelable(auth0);\n        Parcel parcel = Parcel.obtain();\n        auth0Parcelable.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Auth0Parcelable parceledAuth0 = Auth0Parcelable.CREATOR.createFromParcel(parcel);\n        assertThat(HttpUrl.parse(auth0.getDomainUrl()), is(equalTo(HttpUrl.parse(DOMAIN))));\n        assertThat(HttpUrl.parse(parceledAuth0.getAuth0().getDomainUrl()), is(equalTo(HttpUrl.parse(DOMAIN))));\n    }\n\n    @Test\n    public void shouldSaveConfigurationUrl() {\n        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN, CONFIG_DOMAIN);\n        Auth0Parcelable auth0Parcelable = new Auth0Parcelable(auth0);\n        Parcel parcel = Parcel.obtain();\n        auth0Parcelable.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Auth0Parcelable parceledAuth0 = Auth0Parcelable.CREATOR.createFromParcel(parcel);\n        assertThat(HttpUrl.parse(auth0.getConfigurationUrl()), is(equalTo(HttpUrl.parse(CONFIG_DOMAIN))));\n        assertThat(HttpUrl.parse(parceledAuth0.getAuth0().getConfigurationUrl()), is(equalTo(HttpUrl.parse(CONFIG_DOMAIN))));\n    }\n\n    @Test\n    public void shouldSaveUserAgent() {\n        Auth0UserAgent userAgent = new Auth0UserAgent(\"name\", \"version\", \"libraryVersion\");\n        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN, CONFIG_DOMAIN);\n        auth0.setAuth0UserAgent(userAgent);\n        Auth0Parcelable auth0Parcelable = new Auth0Parcelable(auth0);\n        Parcel parcel = Parcel.obtain();\n        auth0Parcelable.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Auth0Parcelable parceledAuth0 = Auth0Parcelable.CREATOR.createFromParcel(parcel);\n        assertThat(userAgent.getValue(), is(notNullValue()));\n        assertThat(auth0.getAuth0UserAgent().getValue(), is(equalTo(userAgent.getValue())));\n        assertThat(parceledAuth0.getAuth0().getAuth0UserAgent().getValue(), is(equalTo(userAgent.getValue())));\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/AuthenticationCallbackTest.java",
    "content": "/*\n * AuthenticationCallbackTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock;\n\nimport android.content.Intent;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.LockCallback.LockEvent;\nimport com.auth0.android.lock.utils.MockLockCallback;\nimport com.auth0.android.result.Credentials;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.Date;\n\nimport static com.auth0.android.lock.utils.AuthenticationCallbackMatcher.hasAuthentication;\nimport static com.auth0.android.lock.utils.AuthenticationCallbackMatcher.hasError;\nimport static com.auth0.android.lock.utils.AuthenticationCallbackMatcher.hasNoError;\nimport static com.auth0.android.lock.utils.AuthenticationCallbackMatcher.isCanceled;\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.not;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class AuthenticationCallbackTest {\n\n    private MockLockCallback callback;\n\n    @Before\n    public void setUp() {\n        callback = new MockLockCallback();\n    }\n\n    @Test\n    public void shouldCallOnAuthentication() {\n        Intent data = getAuthenticationData();\n        callback.onEvent(LockEvent.AUTHENTICATION, data);\n\n        assertThat(callback, hasAuthentication());\n        assertThat(callback, hasNoError());\n    }\n\n    @Test\n    public void shouldReturnAuthentication() {\n        Intent data = getAuthenticationData();\n        callback.onEvent(LockEvent.AUTHENTICATION, data);\n        Credentials credentials = credentialsFromData(data);\n\n        assertThat(callback.getCredentials().getAccessToken(), equalTo(credentials.getAccessToken()));\n        assertThat(callback.getCredentials().getIdToken(), equalTo(credentials.getIdToken()));\n        assertThat(callback.getCredentials().getRefreshToken(), equalTo(credentials.getRefreshToken()));\n        assertThat(callback.getCredentials().getType(), equalTo(credentials.getType()));\n        assertThat(callback.getCredentials().getExpiresAt(), equalTo(credentials.getExpiresAt()));\n        assertThat(callback.getCredentials().getScope(), equalTo(credentials.getScope()));\n        assertThat(callback, hasNoError());\n    }\n\n    @Test\n    public void shouldReturnAuthenticationError() {\n        Intent data = new Intent();\n        AuthenticationException error = new AuthenticationException(\"err_code\", \"err description\");\n        data.putExtra(Constants.EXCEPTION_EXTRA, error);\n        callback.onEvent(LockEvent.AUTHENTICATION, data);\n\n        assertThat(callback, hasError());\n    }\n\n    @Test\n    public void shouldCallOnCanceled() {\n        Intent data = new Intent();\n        callback.onEvent(LockEvent.CANCELED, data);\n\n        assertThat(callback, isCanceled());\n        assertThat(callback, hasError());\n    }\n\n    @Test\n    public void shouldNotAuthenticateOrCancelWhenSignUp() {\n        Intent data = new Intent();\n        callback.onEvent(LockEvent.SIGN_UP, data);\n\n        assertThat(callback, not(hasAuthentication()));\n        assertThat(callback, not(isCanceled()));\n        assertThat(callback, hasNoError());\n    }\n\n    @Test\n    public void shouldNotAuthenticateOrCancelWhenResetPassword() {\n        Intent data = new Intent();\n        callback.onEvent(LockEvent.RESET_PASSWORD, data);\n\n        assertThat(callback, not(hasAuthentication()));\n        assertThat(callback, not(isCanceled()));\n        assertThat(callback, hasNoError());\n    }\n\n    public Intent getAuthenticationData() {\n        Intent i = new Intent(Constants.AUTHENTICATION_ACTION);\n        i.putExtra(Constants.ID_TOKEN_EXTRA, \"idToken\");\n        i.putExtra(Constants.ACCESS_TOKEN_EXTRA, \"accessToken\");\n        i.putExtra(Constants.TOKEN_TYPE_EXTRA, \"tokenType\");\n        i.putExtra(Constants.REFRESH_TOKEN_EXTRA, \"refreshToken\");\n        i.putExtra(Constants.EXPIRES_AT_EXTRA, new Date());\n        i.putExtra(Constants.SCOPE_EXTRA, \"openid profile\");\n        return i;\n    }\n\n    public Credentials credentialsFromData(Intent data) {\n        String idToken = data.getStringExtra(Constants.ID_TOKEN_EXTRA);\n        String accessToken = data.getStringExtra(Constants.ACCESS_TOKEN_EXTRA);\n        String tokenType = data.getStringExtra(Constants.TOKEN_TYPE_EXTRA);\n        String refreshToken = data.getStringExtra(Constants.REFRESH_TOKEN_EXTRA);\n        Date expiresAt = (Date) data.getSerializableExtra(Constants.EXPIRES_AT_EXTRA);\n        String scope = data.getStringExtra(Constants.SCOPE_EXTRA);\n\n        return new Credentials(idToken, accessToken, tokenType, refreshToken, expiresAt, scope);\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/ClassicBuilderTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.app.Activity;\nimport android.content.BroadcastReceiver;\nimport android.content.IntentFilter;\nimport android.content.res.Resources;\n\nimport com.auth0.android.Auth0;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.Robolectric;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.anyString;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 23)\npublic class ClassicBuilderTest {\n\n    @Rule\n    public ExpectedException expectedException = ExpectedException.none();\n    @Mock\n    Auth0 account;\n    @Mock\n    LockCallback callback;\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.initMocks(this);\n    }\n\n    @Test\n    public void shouldThrowIfCallbackIsMissing() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"Missing callback.\");\n\n        final Activity activity = Robolectric.buildActivity(Activity.class).create().get();\n        Lock.Builder builder = Lock.newBuilder(account, null);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldThrowIfAccountIsMissing() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"Missing Auth0 account information.\");\n\n        final Activity activity = Robolectric.buildActivity(Activity.class).create().get();\n        Lock.Builder builder = Lock.newBuilder(null, callback);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldThrowIfAccountIsMissingAlsoFromResources() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"Missing Auth0 account information.\");\n\n        Activity activity = Mockito.mock(Activity.class);\n        Resources resources= Mockito.mock(Resources.class);\n        Mockito.when(activity.getResources()).thenReturn(resources);\n        Mockito.when(resources.getIdentifier(anyString(), anyString(), anyString())).thenReturn(0);\n\n        Lock.Builder builder = Lock.newBuilder(callback);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldCreateAccountFromResources() {\n        Activity activity = Mockito.mock(Activity.class);\n        Resources resources= Mockito.mock(Resources.class);\n        Mockito.when(activity.getApplicationContext()).thenReturn(RuntimeEnvironment.application);\n        Mockito.when(activity.registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class))).thenReturn(null);\n        Mockito.when(activity.getResources()).thenReturn(resources);\n        Mockito.when(activity.getPackageName()).thenReturn(\"test.app\");\n        Mockito.when(resources.getIdentifier(eq(\"com_auth0_client_id\"), eq(\"string\"), eq(\"test.app\"))).thenReturn(1);\n        Mockito.when(resources.getIdentifier(eq(\"com_auth0_domain\"), eq(\"string\"), eq(\"test.app\"))).thenReturn(2);\n        Mockito.when(activity.getString(1)).thenReturn(\"clientId\");\n        Mockito.when(activity.getString(2)).thenReturn(\"domain\");\n\n        Lock.Builder builder = Lock.newBuilder(callback);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldThrowIfAllScreensAreDisabled() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"You disabled all the Lock screens (LogIn/SignUp/ForgotPassword). Please enable at least one.\");\n\n        Lock.Builder builder = Lock.newBuilder(account, callback);\n        builder.allowSignUp(false);\n        builder.allowLogIn(false);\n        builder.allowForgotPassword(false);\n        builder.build(new Activity());\n    }\n\n    @Test\n    public void shouldThrowIfInitialScreenIsLogInButIsDisabled() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"You chose LOG_IN as the initial screen but you have also disabled that screen.\");\n\n        Lock.Builder builder = Lock.newBuilder(account, callback);\n        builder.allowLogIn(false);\n        builder.initialScreen(InitialScreen.LOG_IN);\n        builder.build(new Activity());\n    }\n\n    @Test\n    public void shouldThrowIfInitialScreenIsSignUpButIsDisabled() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"You chose SIGN_UP as the initial screen but you have also disabled that screen.\");\n\n        Lock.Builder builder = Lock.newBuilder(account, callback);\n        builder.allowSignUp(false);\n        builder.initialScreen(InitialScreen.SIGN_UP);\n        builder.build(new Activity());\n    }\n\n    @Test\n    public void shouldThrowIfInitialScreenIsForgotPasswordButIsDisabled() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"You chose FORGOT_PASSWORD as the initial screen but you have also disabled that screen.\");\n\n        Lock.Builder builder = Lock.newBuilder(account, callback);\n        builder.allowForgotPassword(false);\n        builder.initialScreen(InitialScreen.FORGOT_PASSWORD);\n        builder.build(new Activity());\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/LockActivityTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.app.Activity;\nimport android.content.Intent;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.lock.events.DatabaseChangePasswordEvent;\nimport com.auth0.android.lock.events.DatabaseLoginEvent;\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.Connection;\nimport com.auth0.android.lock.internal.configuration.DatabaseConnection;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.lock.provider.AuthResolver;\nimport com.auth0.android.lock.views.ClassicLockView;\nimport com.auth0.android.provider.AuthCallback;\nimport com.auth0.android.provider.AuthHandler;\nimport com.auth0.android.provider.AuthProvider;\nimport com.auth0.android.request.AuthenticationRequest;\nimport com.auth0.android.request.Request;\nimport com.auth0.android.request.SignUpRequest;\nimport com.auth0.android.result.Challenge;\nimport com.auth0.android.result.Credentials;\nimport com.auth0.android.result.DatabaseUser;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Captor;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static android.os.Looper.getMainLooper;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.hasEntry;\nimport static org.hamcrest.Matchers.hasKey;\nimport static org.hamcrest.Matchers.not;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.anyMapOf;\nimport static org.mockito.Matchers.anyString;\nimport static org.mockito.Matchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyZeroInteractions;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.internal.verification.VerificationModeFactory.atLeastOnce;\nimport static org.robolectric.Shadows.shadowOf;\n\n@SuppressWarnings(\"ResultOfMethodCallIgnored\")\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class LockActivityTest {\n\n    private static final int REQ_CODE_WEB_PROVIDER = 200;\n    private static final int REQ_CODE_CUSTOM_PROVIDER = 201;\n    private static final int REQ_CODE_PERMISSIONS = 202;\n    @Mock\n    Options options;\n    @Mock\n    AuthenticationAPIClient client;\n    @Mock\n    WebProvider webProvider;\n    @Mock\n    AuthenticationRequest authRequest;\n    @Mock\n    SignUpRequest signUpRequest;\n    @Mock\n    Request<DatabaseUser, AuthenticationException> dbRequest;\n    @Mock\n    Request<Challenge, AuthenticationException> challengeRequest;\n    @Mock\n    Request<Void, AuthenticationException> voidRequest;\n    @Mock\n    ClassicLockView lockView;\n    @Captor\n    ArgumentCaptor<Map> mapCaptor;\n    @Captor\n    ArgumentCaptor<Callback<Credentials, AuthenticationException>> callbackCaptor;\n    @Captor\n    ArgumentCaptor<Callback<Challenge, AuthenticationException>> challengeCallbackCaptor;\n    @Captor\n    ArgumentCaptor<DatabaseLoginEvent> dbEventCaptor;\n    @Captor\n    ArgumentCaptor<Callback<DatabaseUser, AuthenticationException>> dbCallbackCaptor;\n    Configuration configuration;\n    LockActivity activity;\n    HashMap basicParameters;\n    HashMap connectionScope;\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.openMocks(this);\n        basicParameters = new HashMap<>(Collections.singletonMap(\"extra\", \"value\"));\n        connectionScope = new HashMap<>(Collections.singletonMap(\"custom-connection\", \"the connection scope\"));\n        when(options.getAccount()).thenReturn(new Auth0(\"cliendId\", \"domain\"));\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getConnectionsScope()).thenReturn(connectionScope);\n\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        when(client.login(anyString(), anyString(), anyString())).thenReturn(authRequest);\n        when(client.loginWithOTP(anyString(), anyString())).thenReturn(authRequest);\n        when(client.loginWithOOB(anyString(), anyString(), anyString())).thenReturn(authRequest);\n        when(client.multifactorChallenge(anyString(), any(), any())).thenReturn(challengeRequest);\n        when(client.createUser(anyString(), anyString(), anyString())).thenReturn(dbRequest);\n        when(client.createUser(anyString(), anyString(), any(), anyString())).thenReturn(dbRequest);\n        when(client.createUser(anyString(), anyString(), any(), anyString(), anyMap())).thenReturn(dbRequest);\n        when(client.signUp(anyString(), anyString(), anyString())).thenReturn(signUpRequest);\n        when(client.signUp(anyString(), anyString(), any(), anyString())).thenReturn(signUpRequest);\n        when(client.signUp(anyString(), anyString(), any(), anyString(), anyMap())).thenReturn(signUpRequest);\n        when(client.resetPassword(anyString(), anyString())).thenReturn(voidRequest);\n        when(authRequest.addParameters(anyMapOf(String.class, String.class))).thenReturn(authRequest);\n        when(signUpRequest.addParameters(anyMapOf(String.class, String.class))).thenReturn(signUpRequest);\n        when(dbRequest.addParameters(anyMapOf(String.class, String.class))).thenReturn(dbRequest);\n\n        DatabaseConnection connection = mock(DatabaseConnection.class);\n        when(connection.getName()).thenReturn(\"connection\");\n        configuration = spy(new Configuration(java.util.Collections.<Connection>emptyList(), options));\n        when(configuration.getDatabaseConnection()).thenReturn(connection);\n\n        activity = new LockActivity(configuration, options, lockView, webProvider);\n    }\n\n    @Test\n    public void shouldFailDatabaseLoginOnNullConnection() {\n        when(configuration.getDatabaseConnection()).thenReturn(null);\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"username\", \"password\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(options, never()).getAuthenticationAPIClient();\n        verify(authRequest, never()).addParameters(anyMapOf(String.class, String.class));\n        verify(authRequest, never()).start(any(Callback.class));\n        verify(client, never()).login(anyString(), anyString(), anyString());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n    }\n\n    @Test\n    public void shouldCallOIDCDatabaseLoginWithOTPCodeAndMFAToken() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"username\", \"password\");\n        event.setMultifactorOTP(\"123456\");\n        event.setMultifactorToken(\"mfaToken\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).loginWithOTP(\"mfaToken\", \"123456\");\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).start(any(Callback.class));\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).setAudience(\"aud\");\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, not(hasKey(\"mfa_code\")));\n    }\n\n    @Test\n    public void shouldCallOIDCDatabaseLoginWithOOBCodeAndMFAToken() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"username\", \"password\");\n        event.setMultifactorOTP(\"123456\");\n        event.setMultifactorOOBCode(\"abcdef\");\n        event.setMultifactorToken(\"mfaToken\");\n        event.setMultifactorChallengeType(\"oob\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).loginWithOOB(\"mfaToken\", \"abcdef\", \"123456\");\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).start(any(Callback.class));\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).setAudience(\"aud\");\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, not(hasKey(\"mfa_code\")));\n    }\n\n    @Test\n    public void shouldSuccessfullyRequestMFAChallengeWhenMFAIsRequired() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"john@doe.com\", \"123456\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).login(\"john@doe.com\", \"123456\", \"connection\");\n        verify(authRequest).start(callbackCaptor.capture());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Callback<Credentials, AuthenticationException> callback = callbackCaptor.getValue();\n        AuthenticationException mfaRequiredErr = mock(AuthenticationException.class);\n        when(mfaRequiredErr.isMultifactorRequired()).thenReturn(true);\n        when(mfaRequiredErr.getValue(\"mfa_token\")).thenReturn(\"mfaToken\");\n        callback.onFailure(mfaRequiredErr);\n\n        verify(client).multifactorChallenge(eq(\"mfaToken\"), isNull(), isNull());\n        verify(challengeRequest).start(challengeCallbackCaptor.capture());\n\n        assertThat(challengeCallbackCaptor.getValue(), is(notNullValue()));\n        Challenge challenge = new Challenge(\"oob\", \"abcdef\", \"prompt\");\n        // Trigger success callback\n        challengeCallbackCaptor.getValue().onSuccess(challenge);\n\n        shadowOf(getMainLooper()).idle();\n        verify(lockView).showProgress(false);\n        verify(lockView).showMFACodeForm(dbEventCaptor.capture());\n\n        DatabaseLoginEvent mfaEvent = dbEventCaptor.getValue();\n        assertThat(mfaEvent, is(notNullValue()));\n        assertThat(mfaEvent.getMultifactorOOBCode(), is(\"abcdef\"));\n        assertThat(mfaEvent.getMultifactorChallengeType(), is(\"oob\"));\n        assertThat(mfaEvent.getMultifactorToken(), is(\"mfaToken\"));\n        assertThat(mfaEvent.getMultifactorOTP(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldFailToRequestMFAChallengeWhenMFAIsRequired() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"john@doe.com\", \"123456\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).login(\"john@doe.com\", \"123456\", \"connection\");\n        verify(authRequest).start(callbackCaptor.capture());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Callback<Credentials, AuthenticationException> callback = callbackCaptor.getValue();\n        AuthenticationException mfaRequiredErr = mock(AuthenticationException.class);\n        when(mfaRequiredErr.isMultifactorRequired()).thenReturn(true);\n        when(mfaRequiredErr.getValue(\"mfa_token\")).thenReturn(\"mfaToken\");\n        callback.onFailure(mfaRequiredErr);\n\n        verify(client).multifactorChallenge(eq(\"mfaToken\"), isNull(), isNull());\n        verify(challengeRequest).start(challengeCallbackCaptor.capture());\n\n        assertThat(challengeCallbackCaptor.getValue(), is(notNullValue()));\n        // Trigger failure callback\n        challengeCallbackCaptor.getValue().onFailure(mock(AuthenticationException.class));\n\n        shadowOf(getMainLooper()).idle();\n        verify(lockView).showProgress(false);\n        verify(lockView).showMFACodeForm(dbEventCaptor.capture());\n\n        DatabaseLoginEvent mfaEvent = dbEventCaptor.getValue();\n        assertThat(mfaEvent, is(notNullValue()));\n        assertThat(mfaEvent.getMultifactorOOBCode(), is(nullValue()));\n        assertThat(mfaEvent.getMultifactorChallengeType(), is(nullValue()));\n        assertThat(mfaEvent.getMultifactorToken(), is(\"mfaToken\"));\n        assertThat(mfaEvent.getMultifactorOTP(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldCallDatabaseLoginThatWillRequireVerification() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"john@doe.com\", \"123456\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).login(\"john@doe.com\", \"123456\", \"connection\");\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).start(callbackCaptor.capture());\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).setAudience(\"aud\");\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Callback<Credentials, AuthenticationException> callback = callbackCaptor.getValue();\n        AuthenticationException flaggedRequestErr = mock(AuthenticationException.class);\n        when(flaggedRequestErr.isVerificationRequired()).thenReturn(true);\n        callback.onFailure(flaggedRequestErr);\n\n        Map<String, String> firstAuthValues = mapCaptor.getValue();\n        assertThat(firstAuthValues, hasEntry(\"extra\", \"value\"));\n\n        verify(webProvider).start(eq(activity), eq(\"connection\"), mapCaptor.capture(), any(Callback.class));\n\n        Map<String, String> secondAuthValues = mapCaptor.getValue();\n        assertThat(secondAuthValues, hasEntry(\"login_hint\", \"john@doe.com\"));\n        assertThat(secondAuthValues, hasEntry(\"screen_hint\", \"login\"));\n    }\n\n    @Test\n    public void shouldCallDatabaseSignUpThatWillRequireVerification() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        //set sign in behavior\n        when(options.loginAfterSignUp()).thenReturn(true);\n        when(configuration.loginAfterSignUp()).thenReturn(true);\n\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(\"john@doe.com\", \"123456\", \"johncito\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).signUp(\"john@doe.com\", \"123456\", \"johncito\", \"connection\", Collections.emptyMap());\n        verify(signUpRequest).setScope(\"openid user photos\");\n        verify(signUpRequest).setAudience(\"aud\");\n        verify(signUpRequest).addParameters(mapCaptor.capture());\n        verify(signUpRequest).start(callbackCaptor.capture());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Callback<Credentials, AuthenticationException> callback = callbackCaptor.getValue();\n        AuthenticationException flaggedRequestErr = mock(AuthenticationException.class);\n        when(flaggedRequestErr.isVerificationRequired()).thenReturn(true);\n        callback.onFailure(flaggedRequestErr);\n\n        Map<String, String> firstAuthValues = mapCaptor.getValue();\n        assertThat(firstAuthValues, hasEntry(\"extra\", \"value\"));\n\n        verify(webProvider).start(eq(activity), eq(\"connection\"), mapCaptor.capture(), any(Callback.class));\n\n        Map<String, String> secondAuthValues = mapCaptor.getValue();\n        assertThat(secondAuthValues, hasEntry(\"login_hint\", \"john@doe.com\"));\n        assertThat(secondAuthValues, hasEntry(\"screen_hint\", \"signup\"));\n    }\n\n    @Test\n    public void shouldCallDatabaseCreateUserThatWillRequireVerification() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        //set create user behavior\n        when(options.loginAfterSignUp()).thenReturn(false);\n        when(configuration.loginAfterSignUp()).thenReturn(false);\n\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(\"john@doe.com\", \"123456\", \"johncito\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).createUser(\"john@doe.com\", \"123456\", \"johncito\", \"connection\", Collections.emptyMap());\n        verifyZeroInteractions(authRequest);\n        verify(dbRequest).start(dbCallbackCaptor.capture());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Callback<DatabaseUser, AuthenticationException> callback = dbCallbackCaptor.getValue();\n        AuthenticationException flaggedRequestErr = mock(AuthenticationException.class);\n        when(flaggedRequestErr.isVerificationRequired()).thenReturn(true);\n        callback.onFailure(flaggedRequestErr);\n\n        verify(webProvider).start(eq(activity), eq(\"connection\"), mapCaptor.capture(), any(Callback.class));\n\n        Map<String, String> extraAuthValues = mapCaptor.getValue();\n        assertThat(extraAuthValues, hasEntry(\"login_hint\", \"john@doe.com\"));\n        assertThat(extraAuthValues, hasEntry(\"screen_hint\", \"signup\"));\n    }\n\n    @Test\n    public void shouldCallOIDCDatabaseLoginWithCustomAudience() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n\n        DatabaseLoginEvent event = new DatabaseLoginEvent(\"username\", \"password\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).login(\"username\", \"password\", \"connection\");\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).setAudience(\"aud\");\n        verify(authRequest).start(any(Callback.class));\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n    }\n\n\n    @Test\n    public void shouldFailDatabaseSignUpOnNullConnection() {\n        when(configuration.getDatabaseConnection()).thenReturn(null);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(\"email@domain.com\", \"password\", \"username\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(options, never()).getAuthenticationAPIClient();\n        verify(dbRequest, never()).start(any(Callback.class));\n        verify(authRequest, never()).addParameters(anyMapOf(String.class, String.class));\n        verify(client, never()).login(anyString(), anyString(), anyString());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n    }\n\n    @Test\n    public void shouldCallDatabaseSignUpWithUsername() {\n        when(configuration.loginAfterSignUp()).thenReturn(false);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(\"email@domain.com\", \"password\", \"username\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(dbRequest).start(any(Callback.class));\n        verify(client).createUser(\"email@domain.com\", \"password\", \"username\", \"connection\", Collections.emptyMap());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n    }\n\n    @Test\n    public void shouldCallDatabaseSignUp() {\n        when(configuration.loginAfterSignUp()).thenReturn(false);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(\"email@domain.com\", \"password\", null);\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(dbRequest).start(any(Callback.class));\n        verify(client).createUser(\"email@domain.com\", \"password\", null, \"connection\", Collections.emptyMap());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n    }\n\n    @Test\n    public void shouldCallOIDCDatabaseSignInWithCustomAudience() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n\n        when(configuration.loginAfterSignUp()).thenReturn(true);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(\"email@domain.com\", \"password\", \"username\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(signUpRequest).addParameters(mapCaptor.capture());\n        verify(signUpRequest).start(any(Callback.class));\n        verify(signUpRequest).setScope(\"openid user photos\");\n        verify(signUpRequest).setAudience(\"aud\");\n        verify(client).signUp(\"email@domain.com\", \"password\", \"username\", \"connection\", Collections.emptyMap());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n    }\n\n    @Test\n    public void shouldFailDatabasePasswordResetOnNullConnection() {\n        when(configuration.getDatabaseConnection()).thenReturn(null);\n        DatabaseChangePasswordEvent event = new DatabaseChangePasswordEvent(\"email@domain.com\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(options, never()).getAuthenticationAPIClient();\n        verify(dbRequest, never()).start(any(Callback.class));\n        verify(authRequest, never()).addParameters(anyMapOf(String.class, String.class));\n        verify(client, never()).resetPassword(anyString(), anyString());\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n    }\n\n    @Test\n    public void shouldCallDatabasePasswordReset() {\n        DatabaseChangePasswordEvent event = new DatabaseChangePasswordEvent(\"email@domain.com\");\n        activity.onDatabaseAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(voidRequest, never()).addParameters(any(Map.class));\n        verify(voidRequest).start(any(Callback.class));\n        verify(client).resetPassword(\"email@domain.com\", \"connection\");\n        verify(configuration, atLeastOnce()).getDatabaseConnection();\n    }\n\n    @Test\n    public void shouldCallEnterpriseOAuthAuthenticationWithActiveFlow() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        when(connection.isActiveFlowEnabled()).thenReturn(true);\n        OAuthLoginEvent event = new OAuthLoginEvent(connection, \"email@domain.com\", \"password\");\n        activity.onOAuthAuthenticationRequest(event);\n\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).start(any(Callback.class));\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).setAudience(\"aud\");\n        verify(client).login(\"email@domain.com\", \"password\", \"my-connection\");\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n    }\n\n    @Test\n    public void shouldCallOAuthAuthenticationWithCustomProvider() {\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n\n        verify(lockView, never()).showProgress(true);\n        verify(customProvider).setParameters(mapCaptor.capture());\n        verify(customProvider).start(eq(activity), any(AuthCallback.class), eq(REQ_CODE_PERMISSIONS), eq(REQ_CODE_CUSTOM_PROVIDER));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, hasEntry(\"scope\", \"openid user photos\"));\n        assertThat(reqParams, hasEntry(\"connection_scope\", \"the connection scope\"));\n        assertThat(reqParams, hasKey(\"audience\"));\n    }\n\n    @Test\n    public void shouldCallOAuthAuthenticationWithCustomProviderAndAudience() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getConnectionsScope()).thenReturn(connectionScope);\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n\n\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n\n        verify(lockView, never()).showProgress(true);\n        verify(customProvider).setParameters(mapCaptor.capture());\n        verify(customProvider).start(eq(activity), any(AuthCallback.class), eq(REQ_CODE_PERMISSIONS), eq(REQ_CODE_CUSTOM_PROVIDER));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, hasEntry(\"scope\", \"openid user photos\"));\n        assertThat(reqParams, hasEntry(\"connection_scope\", \"the connection scope\"));\n        assertThat(reqParams, hasEntry(\"audience\", \"aud\"));\n    }\n\n    @Test\n    public void shouldCallEnterpriseOAuthAuthenticationWithCustomProvider() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getConnectionsScope()).thenReturn(connectionScope);\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        LockActivity activity = new LockActivity(configuration, options, lockView, webProvider);\n\n\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        when(connection.isActiveFlowEnabled()).thenReturn(false);\n        OAuthLoginEvent event = new OAuthLoginEvent(connection, \"user@domain.com\", null);\n        activity.onOAuthAuthenticationRequest(event);\n\n\n        verify(lockView, never()).showProgress(true);\n        verify(customProvider).setParameters(mapCaptor.capture());\n        verify(customProvider).start(eq(activity), any(AuthCallback.class), eq(REQ_CODE_PERMISSIONS), eq(REQ_CODE_CUSTOM_PROVIDER));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, hasEntry(\"scope\", \"openid user photos\"));\n        assertThat(reqParams, hasEntry(\"connection_scope\", \"the connection scope\"));\n        assertThat(reqParams, hasEntry(\"login_hint\", \"user@domain.com\"));\n    }\n\n    @Test\n    public void shouldCallEnterpriseOAuthAuthenticationWithWebProvider() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        when(connection.isActiveFlowEnabled()).thenReturn(false);\n        OAuthLoginEvent event = new OAuthLoginEvent(connection, \"user@domain.com\", null);\n        activity.onOAuthAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(webProvider).start(eq(activity), eq(\"my-connection\"), mapCaptor.capture(), any(Callback.class));\n\n        Map<String, String> extraParams = mapCaptor.getValue();\n        assertThat(extraParams, is(notNullValue()));\n        assertThat(extraParams.size(), is(1));\n        assertThat(extraParams, hasEntry(\"login_hint\", \"user@domain.com\"));\n    }\n\n    @Test\n    public void shouldResumeEnterpriseOAuthAuthenticationWithWebProviderOnActivityResult() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        when(connection.isActiveFlowEnabled()).thenReturn(false);\n        OAuthLoginEvent event = new OAuthLoginEvent(connection, \"user@domain.com\", null);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onActivityResult(REQ_CODE_WEB_PROVIDER, Activity.RESULT_OK, intent);\n\n        verify(lockView).showProgress(false);\n        verify(webProvider).resume(intent);\n    }\n\n    @Test\n    public void shouldCallOAuthAuthenticationWithWebProvider() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(webProvider).start(eq(activity), eq(\"my-connection\"), mapCaptor.capture(), any(Callback.class));\n\n        Map<String, String> extraParams = mapCaptor.getValue();\n        assertThat(extraParams, is(nullValue()));\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithWebProviderOnActivityResult() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onActivityResult(REQ_CODE_WEB_PROVIDER, Activity.RESULT_OK, intent);\n\n        verify(lockView).showProgress(false);\n        verify(webProvider).resume(intent);\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithCustomProviderOnActivityResult() {\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onActivityResult(REQ_CODE_CUSTOM_PROVIDER, Activity.RESULT_OK, intent);\n\n        verify(lockView).showProgress(false);\n        verify(customProvider).authorize(REQ_CODE_CUSTOM_PROVIDER, Activity.RESULT_OK, intent);\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithWebProviderOnNewIntent() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onNewIntent(intent);\n\n        verify(lockView).showProgress(false);\n        verify(webProvider).resume(intent);\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithCustomProviderOnNewIntent() {\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onNewIntent(intent);\n\n        verify(lockView).showProgress(false);\n        verify(customProvider).authorize(intent);\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n    }\n\n    @Test\n    public void shouldResumeEnterpriseOAuthAuthenticationWithWebProviderOnNewIntent() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection, \"user@domain.com\", null);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onNewIntent(intent);\n\n        verify(lockView).showProgress(false);\n        verify(webProvider).resume(intent);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/PasswordlessBuilderTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.app.Activity;\nimport android.content.BroadcastReceiver;\nimport android.content.IntentFilter;\nimport android.content.res.Resources;\n\nimport androidx.test.core.app.ApplicationProvider;\n\nimport com.auth0.android.Auth0;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.Robolectric;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.anyString;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 23)\npublic class PasswordlessBuilderTest {\n\n    @Rule\n    public ExpectedException expectedException = ExpectedException.none();\n    @Mock\n    Auth0 account;\n    @Mock\n    LockCallback callback;\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.initMocks(this);\n    }\n\n    @Test\n    public void shouldThrowIfCallbackIsMissing() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"Missing callback.\");\n\n        final Activity activity = Robolectric.buildActivity(Activity.class).create().get();\n        PasswordlessLock.Builder builder = PasswordlessLock.newBuilder(account, null);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldThrowIfAccountIsMissing() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"Missing Auth0 account information.\");\n\n        final Activity activity = Robolectric.buildActivity(Activity.class).create().get();\n        PasswordlessLock.Builder builder = PasswordlessLock.newBuilder(null, callback);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldThrowIfAccountIsMissingAlsoFromResources() {\n        expectedException.expect(IllegalStateException.class);\n        expectedException.expectMessage(\"Missing Auth0 account information.\");\n\n        Activity activity = Mockito.mock(Activity.class);\n        Resources resources = Mockito.mock(Resources.class);\n        Mockito.when(activity.getResources()).thenReturn(resources);\n        Mockito.when(resources.getIdentifier(anyString(), anyString(), anyString())).thenReturn(0);\n\n        PasswordlessLock.Builder builder = PasswordlessLock.newBuilder(callback);\n        builder.build(activity);\n    }\n\n    @Test\n    public void shouldCreateAccountFromResources() {\n        Activity activity = Mockito.mock(Activity.class);\n        Resources resources = Mockito.mock(Resources.class);\n        Mockito.when(activity.getApplicationContext()).thenReturn(ApplicationProvider.getApplicationContext());\n        Mockito.when(activity.registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class))).thenReturn(null);\n        Mockito.when(activity.getResources()).thenReturn(resources);\n        Mockito.when(activity.getPackageName()).thenReturn(\"test.app\");\n        Mockito.when(resources.getIdentifier(eq(\"com_auth0_client_id\"), eq(\"string\"), eq(\"test.app\"))).thenReturn(1);\n        Mockito.when(resources.getIdentifier(eq(\"com_auth0_domain\"), eq(\"string\"), eq(\"test.app\"))).thenReturn(2);\n        Mockito.when(activity.getString(1)).thenReturn(\"clientId\");\n        Mockito.when(activity.getString(2)).thenReturn(\"domain\");\n\n        PasswordlessLock.Builder builder = PasswordlessLock.newBuilder(callback);\n        builder.build(activity);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/PasswordlessIdentityHelperTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.SharedPreferences;\n\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.Mockito;\n\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Matchers.anyInt;\nimport static org.mockito.Matchers.anyString;\nimport static org.mockito.Matchers.eq;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\npublic class PasswordlessIdentityHelperTest {\n\n    private Context context;\n    private SharedPreferences sp;\n    private SharedPreferences.Editor editor;\n\n    @SuppressLint(\"CommitPrefEdits\")\n    @Before\n    public void setUp() {\n        context = Mockito.mock(Context.class);\n        sp = Mockito.mock(SharedPreferences.class);\n        editor = Mockito.mock(SharedPreferences.Editor.class);\n        when(context.getSharedPreferences(eq(\"Lock\"), eq(Context.MODE_PRIVATE))).thenReturn(sp);\n        when(sp.edit()).thenReturn(editor);\n        when(editor.putString(anyString(), anyString())).thenReturn(editor);\n        when(editor.putString(anyString(), (String) isNull())).thenReturn(editor);\n        when(editor.putInt(anyString(), anyInt())).thenReturn(editor);\n    }\n\n    @Test\n    public void shouldSaveIdentity() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        helper.saveIdentity(\"me@auth0.com\", null);\n\n        verify(editor).putString(\"last_passwordless_identity\", \"me@auth0.com\");\n        verify(editor).putString(\"last_passwordless_country\", null);\n        verify(editor).putInt(\"last_passwordless_mode\", PasswordlessMode.SMS_CODE);\n    }\n\n    @Test\n    public void shouldSaveIdentityWithCountry() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        helper.saveIdentity(\"1234567890\", new Country(\"ar\", \"54\"));\n\n        verify(editor).putString(\"last_passwordless_identity\", \"1234567890\");\n        verify(editor).putString(\"last_passwordless_country\", \"ar@54\");\n        verify(editor).putInt(\"last_passwordless_mode\", PasswordlessMode.SMS_CODE);\n    }\n\n    @Test\n    public void shouldGetSavedIdentity() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        when(sp.getString(eq(\"last_passwordless_identity\"), anyString())).thenReturn(\"me@auth0.com\");\n\n        String identity = helper.getLastIdentity();\n        assertThat(identity, is(\"me@auth0.com\"));\n    }\n\n    @Test\n    public void shouldGetSavedCountry() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        when(sp.getString(eq(\"last_passwordless_country\"), (String) isNull())).thenReturn(\"ar@54\");\n\n        Country country = helper.getLastCountry();\n        assertThat(country, is(notNullValue()));\n        assertThat(country.getDialCode(), is(\"54\"));\n        assertThat(country.getIsoCode(), is(\"ar\"));\n    }\n\n    @Test\n    public void shouldNotHaveLoggedInBeforeIfCurrentPasswordlessModeIsDisabled() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.DISABLED);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n    }\n\n    @Test\n    public void shouldNotHaveLoggedInBeforeIfLastPasswordlessModeIsDisabled() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.DISABLED);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n    }\n\n    @Test\n    public void shouldNotHaveLoggedInBeforeOnDifferentConnections() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n\n        helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_LINK);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n\n        helper = new PasswordlessIdentityHelper(context, PasswordlessMode.EMAIL_CODE);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n\n        helper = new PasswordlessIdentityHelper(context, PasswordlessMode.EMAIL_LINK);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(false));\n    }\n\n    @Test\n    public void shouldHaveLoggedInBeforeOnSameConnections() {\n        PasswordlessIdentityHelper helper = new PasswordlessIdentityHelper(context, PasswordlessMode.EMAIL_CODE);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n\n        helper = new PasswordlessIdentityHelper(context, PasswordlessMode.EMAIL_LINK);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.EMAIL_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n\n        helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_CODE);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n\n        helper = new PasswordlessIdentityHelper(context, PasswordlessMode.SMS_LINK);\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_CODE);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n        when(sp.getInt(eq(\"last_passwordless_mode\"), anyInt())).thenReturn(PasswordlessMode.SMS_LINK);\n        assertThat(helper.hasLoggedInBefore(), is(true));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/PasswordlessLockActivityTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.app.Activity;\nimport android.content.Intent;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.PasswordlessType;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.events.OAuthLoginEvent;\nimport com.auth0.android.lock.events.PasswordlessLoginEvent;\nimport com.auth0.android.lock.internal.configuration.Configuration;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.lock.internal.configuration.PasswordlessConnection;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.lock.provider.AuthResolver;\nimport com.auth0.android.lock.views.PasswordlessLockView;\nimport com.auth0.android.provider.AuthCallback;\nimport com.auth0.android.provider.AuthHandler;\nimport com.auth0.android.provider.AuthProvider;\nimport com.auth0.android.request.AuthenticationRequest;\nimport com.auth0.android.request.Request;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.hamcrest.Matchers.hasEntry;\nimport static org.hamcrest.Matchers.hasKey;\nimport static org.hamcrest.Matchers.not;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.anyMapOf;\nimport static org.mockito.Matchers.anyString;\nimport static org.mockito.Matchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.internal.verification.VerificationModeFactory.atLeastOnce;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class PasswordlessLockActivityTest {\n\n    private static final int REQ_CODE_WEB_PROVIDER = 200;\n    private static final int REQ_CODE_CUSTOM_PROVIDER = 201;\n    private static final int REQ_CODE_PERMISSIONS = 202;\n\n    @Mock\n    Options options;\n    @Mock\n    AuthenticationAPIClient client;\n    @Mock\n    WebProvider webProvider;\n    @Mock\n    Request codeRequest;\n    @Mock\n    AuthenticationRequest authRequest;\n    @Mock\n    Configuration configuration;\n    @Mock\n    PasswordlessLockView lockView;\n    Map<String, String> connectionScope;\n    PasswordlessLockActivity activity;\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.openMocks(this);\n        HashMap basicParameters = new HashMap<>(Collections.singletonMap(\"extra\", \"value\"));\n        connectionScope = new HashMap<>(Collections.singletonMap(\"my-connection\", \"the connection scope\"));\n        when(options.getAccount()).thenReturn(new Auth0(\"cliendId\", \"domain\"));\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getConnectionsScope()).thenReturn(connectionScope);\n\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        when(client.passwordlessWithEmail(anyString(), any(PasswordlessType.class))).thenReturn(codeRequest);\n        when(client.passwordlessWithSMS(anyString(), any(PasswordlessType.class))).thenReturn(codeRequest);\n        when(client.loginWithEmail(anyString(), anyString())).thenReturn(authRequest);\n        when(client.loginWithPhoneNumber(anyString(), anyString())).thenReturn(authRequest);\n        when(codeRequest.addParameters(anyMapOf(String.class, Object.class))).thenReturn(codeRequest);\n        when(codeRequest.addParameter(anyString(), any(String.class))).thenReturn(codeRequest);\n        when(authRequest.addParameters(anyMapOf(String.class, String.class))).thenReturn(authRequest);\n        when(authRequest.setConnection(anyString())).thenReturn(authRequest);\n\n        PasswordlessConnection connection = mock(PasswordlessConnection.class);\n        when(connection.getName()).thenReturn(\"connection\");\n        when(configuration.getPasswordlessConnection()).thenReturn(connection);\n\n        activity = new PasswordlessLockActivity(configuration, options, lockView, webProvider, null);\n    }\n\n    @Test\n    public void shouldFailPasswordlessCodeRequestWithEmailOnNullConnection() {\n        activity = new PasswordlessLockActivity(configuration, options, lockView, webProvider, \"user@domain.com\");\n\n        when(configuration.getPasswordlessConnection()).thenReturn(null);\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_CODE, \"email@domain.com\");\n        activity.onPasswordlessAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(options, never()).getAuthenticationAPIClient();\n        verify(authRequest, never()).start(any(Callback.class));\n        verify(client, never()).passwordlessWithEmail(anyString(), eq(PasswordlessType.CODE));\n        verify(configuration, atLeastOnce()).getPasswordlessConnection();\n    }\n\n    @Test\n    public void shouldCallPasswordlessCodeRequestWithEmail() {\n        activity = new PasswordlessLockActivity(configuration, options, lockView, webProvider, \"user@domain.com\");\n\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_CODE, \"email@domain.com\");\n        activity.onPasswordlessAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).passwordlessWithEmail(eq(\"email@domain.com\"), eq(PasswordlessType.CODE));\n        verify(codeRequest).addParameter(eq(\"connection\"), eq(\"connection\"));\n        verify(codeRequest).start(any(Callback.class));\n        verify(configuration, atLeastOnce()).getPasswordlessConnection();\n    }\n\n    @Test\n    public void shouldDoPasswordlessLoginWithEmail() {\n        activity = new PasswordlessLockActivity(configuration, options, lockView, webProvider, \"user@domain.com\");\n\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.submitCode(PasswordlessMode.EMAIL_CODE, \"1234\");\n        activity.onPasswordlessAuthenticationRequest(event);\n\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).loginWithEmail(eq(\"user@domain.com\"), eq(\"1234\"));\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).setConnection(eq(\"connection\"));\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).start(any(Callback.class));\n        verify(configuration, atLeastOnce()).getPasswordlessConnection();\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n    }\n\n    @Test\n    public void shouldFailPasswordlessCodeRequestWithPhoneOnNullConnection() {\n        Country country = Mockito.mock(Country.class);\n        when(configuration.getPasswordlessConnection()).thenReturn(null);\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_CODE, \"1234567890\", country);\n        activity.onPasswordlessAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(true);\n        verify(options, never()).getAuthenticationAPIClient();\n        verify(authRequest, never()).start(any(Callback.class));\n        verify(client, never()).passwordlessWithSMS(anyString(), eq(PasswordlessType.CODE));\n        verify(configuration, atLeastOnce()).getPasswordlessConnection();\n    }\n\n    @Test\n    public void shouldCallPasswordlessCodeRequestWithPhone() {\n        Country country = Mockito.mock(Country.class);\n        when(country.getDialCode()).thenReturn(\"+54\");\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_CODE, \"1234567890\", country);\n        activity.onPasswordlessAuthenticationRequest(event);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).passwordlessWithSMS(eq(\"+541234567890\"), eq(PasswordlessType.CODE));\n        verify(codeRequest).addParameter(eq(\"connection\"), eq(\"connection\"));\n        verify(codeRequest).start(any(Callback.class));\n        verify(configuration, atLeastOnce()).getPasswordlessConnection();\n    }\n\n    @Test\n    public void shouldDoPasswordlessLoginWithPhone() {\n        activity = new PasswordlessLockActivity(configuration, options, lockView, webProvider, \"+541234567890\");\n\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.submitCode(PasswordlessMode.SMS_CODE, \"1234\");\n        activity.onPasswordlessAuthenticationRequest(event);\n\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        verify(lockView).showProgress(true);\n        verify(options).getAuthenticationAPIClient();\n        verify(client).loginWithPhoneNumber(eq(\"+541234567890\"), eq(\"1234\"));\n        verify(authRequest).addParameters(mapCaptor.capture());\n        verify(authRequest).setConnection(eq(\"connection\"));\n        verify(authRequest).setScope(\"openid user photos\");\n        verify(authRequest).start(any(Callback.class));\n        verify(configuration, atLeastOnce()).getPasswordlessConnection();\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n    }\n\n    @Test\n    public void shouldCallOAuthAuthenticationWithCustomProvider() {\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"my-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        verify(lockView, never()).showProgress(true);\n        verify(customProvider).setParameters(mapCaptor.capture());\n        verify(customProvider).start(eq(activity), any(AuthCallback.class), eq(REQ_CODE_PERMISSIONS), eq(REQ_CODE_CUSTOM_PROVIDER));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, hasEntry(\"scope\", \"openid user photos\"));\n        assertThat(reqParams, hasEntry(\"connection_scope\", \"the connection scope\"));\n        assertThat(reqParams, not(hasKey(\"audience\")));\n    }\n\n    @Test\n    public void shouldCallOAuthAuthenticationWithCustomProviderAndAudience() {\n        Auth0 account = new Auth0(\"cliendId\", \"domain\");\n        Options options = mock(Options.class);\n        when(options.getAccount()).thenReturn(account);\n        when(options.getAuthenticationAPIClient()).thenReturn(client);\n        when(options.getAudience()).thenReturn(\"aud\");\n        when(options.getScope()).thenReturn(\"openid user photos\");\n        when(options.getConnectionsScope()).thenReturn(connectionScope);\n        HashMap basicParameters = new HashMap<>(Collections.singletonMap(\"extra\", \"value\"));\n        when(options.getAuthenticationParameters()).thenReturn(basicParameters);\n        PasswordlessLockActivity activity = new PasswordlessLockActivity(configuration, options, lockView, webProvider, null);\n\n\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"my-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        verify(lockView, never()).showProgress(true);\n        verify(customProvider).setParameters(mapCaptor.capture());\n        verify(customProvider).start(eq(activity), any(AuthCallback.class), eq(REQ_CODE_PERMISSIONS), eq(REQ_CODE_CUSTOM_PROVIDER));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(notNullValue()));\n        assertThat(reqParams, hasEntry(\"extra\", \"value\"));\n        assertThat(reqParams, hasEntry(\"scope\", \"openid user photos\"));\n        assertThat(reqParams, hasEntry(\"connection_scope\", \"the connection scope\"));\n        assertThat(reqParams, hasEntry(\"audience\", \"aud\"));\n    }\n\n    @Test\n    public void shouldCallOAuthAuthenticationWithWebProvider() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        verify(lockView, never()).showProgress(eq(true));\n\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n        verify(webProvider).start(eq(activity), eq(\"my-connection\"), mapCaptor.capture(), any(Callback.class));\n\n        Map<String, String> reqParams = mapCaptor.getValue();\n        assertThat(reqParams, is(nullValue()));\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithWebProviderOnActivityResult() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onActivityResult(REQ_CODE_WEB_PROVIDER, Activity.RESULT_OK, intent);\n\n        verify(lockView).showProgress(false);\n        verify(webProvider).resume(eq(intent));\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithCustomProviderOnActivityResult() {\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onActivityResult(REQ_CODE_CUSTOM_PROVIDER, Activity.RESULT_OK, intent);\n\n        verify(lockView).showProgress(false);\n        verify(customProvider).authorize(eq(REQ_CODE_CUSTOM_PROVIDER), eq(Activity.RESULT_OK), eq(intent));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithWebProviderOnNewIntent() {\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"my-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onNewIntent(intent);\n\n        verify(lockView).showProgress(false);\n        verify(webProvider).resume(eq(intent));\n    }\n\n    @Test\n    public void shouldResumeOAuthAuthenticationWithCustomProviderOnNewIntent() {\n        AuthProvider customProvider = mock(AuthProvider.class);\n        AuthHandler handler = mock(AuthHandler.class);\n        when(handler.providerFor((String) isNull(), eq(\"custom-connection\"))).thenReturn(customProvider);\n        AuthResolver.setAuthHandlers(Collections.singletonList(handler));\n\n        OAuthConnection connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"custom-connection\");\n        OAuthLoginEvent event = new OAuthLoginEvent(connection);\n        activity.onOAuthAuthenticationRequest(event);\n\n        Intent intent = mock(Intent.class);\n        activity.onNewIntent(intent);\n\n        verify(lockView).showProgress(false);\n        verify(customProvider).authorize(eq(intent));\n        AuthResolver.setAuthHandlers(Collections.<AuthHandler>emptyList());\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/WebProviderTest.java",
    "content": "package com.auth0.android.lock;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.pm.ActivityInfo;\nimport android.content.pm.PackageManager;\nimport android.content.pm.ResolveInfo;\nimport android.net.Uri;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.Callback;\nimport com.auth0.android.lock.internal.configuration.Options;\nimport com.auth0.android.provider.AuthenticationActivity;\nimport com.auth0.android.provider.CustomTabsOptions;\nimport com.auth0.android.result.Credentials;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.mockito.ArgumentCaptor;\nimport org.robolectric.Robolectric;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;\nimport static androidx.test.espresso.intent.matcher.UriMatchers.hasHost;\nimport static androidx.test.espresso.intent.matcher.UriMatchers.hasParamWithValue;\nimport static androidx.test.espresso.intent.matcher.UriMatchers.hasScheme;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.Matchers.isOneOf;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.Matchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.hamcrest.MockitoHamcrest.intThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class WebProviderTest {\n\n    @Rule\n    public ExpectedException exception = ExpectedException.none();\n\n    private Activity activity;\n\n    @Before\n    public void setUp() {\n        activity = spy(Robolectric.buildActivity(Activity.class)\n                .create()\n                .start()\n                .resume()\n                .get());\n        setupBrowserContext(activity, Collections.singletonList(\"com.auth0.browser\"));\n    }\n\n    @Test\n    public void shouldStart() {\n        Options options = new Options();\n        options.setAccount(new Auth0(\"clientId\", \"domain.auth0.com\"));\n        Callback<Credentials, AuthenticationException> callback = mock(Callback.class);\n        WebProvider webProvider = new WebProvider(options);\n\n        webProvider.start(activity, \"my-connection\", null, callback);\n        verify(callback, never()).onFailure(any(AuthenticationException.class));\n    }\n\n    @Test\n    public void shouldFailWhenBrowserAppIsMissing() {\n        setupBrowserContext(activity, Collections.<String>emptyList());\n\n        Options options = new Options();\n        options.setAccount(new Auth0(\"clientId\", \"domain.auth0.com\"));\n        Callback<Credentials, AuthenticationException> callback = mock(Callback.class);\n        WebProvider webProvider = new WebProvider(options);\n        webProvider.start(activity, \"my-connection\", null, callback);\n\n        ArgumentCaptor<AuthenticationException> exceptionCaptor = ArgumentCaptor.forClass(AuthenticationException.class);\n        verify(callback).onFailure(exceptionCaptor.capture());\n        assertThat(exceptionCaptor.getValue(), is(notNullValue()));\n        assertThat(exceptionCaptor.getValue().isBrowserAppNotAvailable(), is(true));\n    }\n\n    @Test\n    public void shouldStartWithCustomAuthenticationParameters() {\n        Auth0 account = new Auth0(\"clientId\", \"domain.auth0.com\");\n        Options options = new Options();\n        options.setAccount(account);\n\n        options.withAudience(\"https://me.auth0.com/myapi\");\n\n        Callback<Credentials, AuthenticationException> callback = mock(Callback.class);\n        WebProvider webProvider = new WebProvider(options);\n\n        Map<String, String> parameters = new HashMap<>();\n        parameters.put(\"custom-param-1\", \"value-1\");\n        parameters.put(\"custom-param-2\", \"value-2\");\n\n        webProvider.start(activity, \"my-connection\", parameters, callback);\n        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);\n        verify(activity).startActivity(intentCaptor.capture());\n        verify(callback, never()).onFailure(any(AuthenticationException.class));\n\n        Intent intent = intentCaptor.getValue();\n        assertThat(intent, is(notNullValue()));\n\n        assertThat(intent.hasExtra(\"com.auth0.android.EXTRA_AUTHORIZE_URI\"), is(true));\n        Uri authorizeUri = intent.getParcelableExtra(\"com.auth0.android.EXTRA_AUTHORIZE_URI\");\n        assertThat(authorizeUri, hasHost(\"domain.auth0.com\"));\n        assertThat(authorizeUri, hasParamWithValue(\"custom-param-1\", \"value-1\"));\n        assertThat(authorizeUri, hasParamWithValue(\"custom-param-2\", \"value-2\"));\n        assertThat(authorizeUri, hasParamWithValue(\"client_id\", \"clientId\"));\n        assertThat(authorizeUri, hasParamWithValue(\"connection\", \"my-connection\"));\n        assertThat(authorizeUri, hasParamWithValue(\"audience\", \"https://me.auth0.com/myapi\"));\n        assertThat(intent, hasComponent(AuthenticationActivity.class.getName()));\n    }\n\n    @Test\n    public void shouldStartWithCustomAudience() {\n        Auth0 account = new Auth0(\"clientId\", \"domain.auth0.com\");\n        Options options = new Options();\n        options.setAccount(account);\n\n        options.withAudience(\"https://me.auth0.com/myapi\");\n\n        Callback<Credentials, AuthenticationException> callback = mock(Callback.class);\n        WebProvider webProvider = new WebProvider(options);\n\n        webProvider.start(activity, \"my-connection\", null, callback);\n        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);\n        verify(activity).startActivity(intentCaptor.capture());\n        verify(callback, never()).onFailure(any(AuthenticationException.class));\n\n        Intent intent = intentCaptor.getValue();\n        assertThat(intent, is(notNullValue()));\n\n        assertThat(intent.hasExtra(\"com.auth0.android.EXTRA_AUTHORIZE_URI\"), is(true));\n        Uri authorizeUri = intent.getParcelableExtra(\"com.auth0.android.EXTRA_AUTHORIZE_URI\");\n        assertThat(authorizeUri, hasHost(\"domain.auth0.com\"));\n        assertThat(authorizeUri, hasParamWithValue(\"client_id\", \"clientId\"));\n        assertThat(authorizeUri, hasParamWithValue(\"connection\", \"my-connection\"));\n        assertThat(authorizeUri, hasParamWithValue(\"audience\", \"https://me.auth0.com/myapi\"));\n        assertThat(intent, hasComponent(AuthenticationActivity.class.getName()));\n    }\n\n    @Test\n    public void shouldStartBrowserWithOptions() {\n        Auth0 account = new Auth0(\"clientId\", \"domain.auth0.com\");\n        Options options = new Options();\n        options.setAccount(account);\n\n        HashMap<String, String> parameters = new HashMap<>();\n        parameters.put(\"custom-param-1\", \"value-1\");\n        parameters.put(\"custom-param-2\", \"value-2\");\n        options.setAuthenticationParameters(parameters);\n        options.withScope(\"email profile photos\");\n        options.withConnectionScope(\"my-connection\", \"the connection scope\");\n        options.withScheme(\"auth0\");\n        CustomTabsOptions customTabsOptions = CustomTabsOptions.newBuilder().build();\n        options.withCustomTabsOptions(customTabsOptions);\n\n        Callback<Credentials, AuthenticationException> callback = mock(Callback.class);\n        WebProvider webProvider = new WebProvider(options);\n\n        webProvider.start(activity, \"my-connection\", null, callback);\n        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);\n        verify(activity).startActivity(intentCaptor.capture());\n        verify(callback, never()).onFailure(any(AuthenticationException.class));\n\n        Intent intent = intentCaptor.getValue();\n        assertThat(intent, is(notNullValue()));\n        assertThat(intent.hasExtra(\"com.auth0.android.EXTRA_AUTHORIZE_URI\"), is(true));\n        Uri authorizeUri = intent.getParcelableExtra(\"com.auth0.android.EXTRA_AUTHORIZE_URI\");\n\n        assertThat(authorizeUri.getQueryParameter(\"redirect_uri\"), is(notNullValue()));\n        Uri redirectUri = Uri.parse(authorizeUri.getQueryParameter(\"redirect_uri\"));\n        assertThat(redirectUri, hasScheme(\"auth0\"));\n\n        assertThat(authorizeUri, hasHost(\"domain.auth0.com\"));\n        assertThat(authorizeUri, hasParamWithValue(\"client_id\", \"clientId\"));\n        assertThat(authorizeUri, hasParamWithValue(\"connection\", \"my-connection\"));\n        assertThat(authorizeUri, hasParamWithValue(\"custom-param-1\", \"value-1\"));\n        assertThat(authorizeUri, hasParamWithValue(\"custom-param-2\", \"value-2\"));\n        assertThat(authorizeUri, hasParamWithValue(\"scope\", \"email profile photos openid\"));\n        assertThat(authorizeUri, hasParamWithValue(\"connection_scope\", \"the connection scope\"));\n        assertThat(intent.getParcelableExtra(\"com.auth0.android.EXTRA_CT_OPTIONS\"), is(notNullValue()));\n        assertThat(intent, hasComponent(AuthenticationActivity.class.getName()));\n    }\n\n    @Test\n    public void shouldResumeWithIntent() {\n        Intent intent = mock(Intent.class);\n        Options options = mock(Options.class);\n        WebProvider webProvider = new WebProvider(options);\n        assertThat(webProvider.resume(intent), is(false));\n    }\n\n    /**\n     * Sets up a given context for using browsers.\n     * If the list passed is empty, then no browser packages would be available.\n     */\n    static void setupBrowserContext(@NonNull Context context, @NonNull List<String> browserPackages) {\n        PackageManager pm = mock(PackageManager.class);\n        when(context.getPackageManager()).thenReturn(pm);\n\n        List<ResolveInfo> allBrowsers = new ArrayList<>();\n        for (String browser : browserPackages) {\n            ResolveInfo info = resolveInfoForPackageName(browser);\n            allBrowsers.add(info);\n        }\n        when(pm.queryIntentActivities(any(Intent.class), intThat(isOneOf(0, PackageManager.MATCH_ALL)))).thenReturn(allBrowsers);\n    }\n\n    private static ResolveInfo resolveInfoForPackageName(@Nullable String packageName) {\n        if (packageName == null) {\n            return null;\n        }\n        ResolveInfo resInfo = mock(ResolveInfo.class);\n        resInfo.activityInfo = new ActivityInfo();\n        resInfo.activityInfo.packageName = packageName;\n        return resInfo;\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/errors/LoginErrorMessageBuilderTest.java",
    "content": "package com.auth0.android.lock.errors;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.R;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class LoginErrorMessageBuilderTest {\n\n    @Mock\n    AuthenticationException exception;\n    LoginErrorMessageBuilder builder;\n\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.openMocks(this);\n        builder = new LoginErrorMessageBuilder();\n    }\n\n    @Test\n    public void shouldHaveDefaultMessageIfAccessDenied() {\n        Mockito.when(exception.isAccessDenied()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfInvalidCredentials() {\n        Mockito.when(exception.isInvalidCredentials()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_invalid_credentials_message)));\n    }\n\n    @Test\n    public void shouldHaveDescriptionIfRuleError() {\n        Mockito.when(exception.isRuleError()).thenReturn(true);\n        Mockito.when(exception.getDescription()).thenReturn(\"Description\");\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(R.string.com_auth0_lock_db_login_error_unauthorized_message));\n        assertThat(error.getCustomMessage(), is(equalTo(\"Description\")));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfPasswordLeaked() {\n        Mockito.when(exception.isPasswordLeaked()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_password_leaked_error_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfMultifactorCodeInvalid() {\n        Mockito.when(exception.isMultifactorCodeInvalid()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_invalid_mfa_code_message)));\n    }\n\n    @Test\n    public void shouldHaveDefaultMessageIfMultifactorRequired() {\n        Mockito.when(exception.isMultifactorRequired()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_message)));\n    }\n\n    @Test\n    public void shouldHaveDefaultMessageIfMultifactorEnrollRequired() {\n        Mockito.when(exception.isMultifactorEnrollRequired()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_mfa_enroll_required)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfUsernameExists() {\n        Mockito.when(exception.getCode()).thenReturn(\"user_exists\");\n        final AuthenticationError error1 = builder.buildFrom(exception);\n        assertThat(error1.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_signup_user_already_exists_error_message)));\n\n        Mockito.when(exception.getCode()).thenReturn(\"username_exists\");\n        final AuthenticationError error2 = builder.buildFrom(exception);\n        assertThat(error2.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_signup_user_already_exists_error_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfUserIsBlocked() {\n        Mockito.when(exception.isRuleError()).thenReturn(true);\n        Mockito.when(exception.getDescription()).thenReturn(\"user is blocked\");\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_unauthorized_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfIsTooManyAttempts() {\n        Mockito.when(exception.getCode()).thenReturn(\"too_many_attempts\");\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_too_many_attempts_error_message)));\n    }\n\n    @Test\n    public void shouldHaveDefaultMessageIfIsWrongClientType() {\n        Mockito.when(exception.getDescription()).thenReturn(\"Unauthorized\");\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_login_error_message)));\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/errors/SignUpErrorMessageBuilderTest.java",
    "content": "package com.auth0.android.lock.errors;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.R;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class SignUpErrorMessageBuilderTest {\n\n    @Mock\n    AuthenticationException exception;\n    SignUpErrorMessageBuilder builder;\n\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.openMocks(this);\n        builder = new SignUpErrorMessageBuilder();\n    }\n\n    @Test\n    public void shouldHaveDefaultMessageIfAccessDenied() {\n        Mockito.when(exception.isAccessDenied()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_sign_up_error_message)));\n    }\n\n    @Test\n    public void shouldHaveDescriptionIfRuleError() {\n        Mockito.when(exception.isRuleError()).thenReturn(true);\n        Mockito.when(exception.getDescription()).thenReturn(\"Description\");\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(R.string.com_auth0_lock_db_sign_up_error_message));\n        assertThat(error.getCustomMessage(), is(equalTo(\"Description\")));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfUsernameExists() {\n        Mockito.when(exception.getCode()).thenReturn(\"user_exists\");\n        final AuthenticationError error1 = builder.buildFrom(exception);\n        assertThat(error1.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_signup_user_already_exists_error_message)));\n\n        Mockito.when(exception.getCode()).thenReturn(\"username_exists\");\n        final AuthenticationError error2 = builder.buildFrom(exception);\n        assertThat(error2.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_signup_user_already_exists_error_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfIsTooManyAttempts() {\n        Mockito.when(exception.getCode()).thenReturn(\"too_many_attempts\");\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_too_many_attempts_error_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfPasswordNotStrongEnough() {\n        Mockito.when(exception.isPasswordNotStrongEnough()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_signup_password_not_strong_error_message)));\n    }\n\n    @Test\n    public void shouldHaveCustomMessageIfPasswordAlreadyUsed() {\n        Mockito.when(exception.isPasswordAlreadyUsed()).thenReturn(true);\n        final AuthenticationError error = builder.buildFrom(exception);\n        assertThat(error.getMessageRes(), is(equalTo(R.string.com_auth0_lock_db_signup_password_already_used_error_message)));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/events/DatabaseEventTest.java",
    "content": "package com.auth0.android.lock.events;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class DatabaseEventTest {\n\n    @Test\n    public void shouldSetEmailIdentity() {\n        final DatabaseEvent event = new DatabaseEvent(\"email@me.com\");\n        assertThat(event.getEmail(), is(\"email@me.com\"));\n        assertThat(event.getUsername(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldSetUsernameIdentity() {\n        final DatabaseEvent event = new DatabaseEvent(\"this_is_me\");\n        assertThat(event.getEmail(), is(nullValue()));\n        assertThat(event.getUsername(), is(\"this_is_me\"));\n    }\n\n    @Test\n    public void shouldSetUsername() {\n        final DatabaseEvent event = new DatabaseEvent(\"email@me.com\");\n        event.setUsername(\"this_is_me\");\n        assertThat(event.getUsername(), is(\"this_is_me\"));\n    }\n\n    @Test\n    public void shouldSetBothEmailAndUsername() {\n        final DatabaseEvent event = new DatabaseEvent(\"email@me.com\", \"this_is_me\");\n        assertThat(event.getEmail(), is(\"email@me.com\"));\n        assertThat(event.getUsername(), is(\"this_is_me\"));\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/events/DatabaseLoginEventTest.java",
    "content": "package com.auth0.android.lock.events;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.core.Is.is;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class DatabaseLoginEventTest {\n\n    private DatabaseLoginEvent event;\n\n    @Before\n    public void setUp() {\n        event = new DatabaseLoginEvent(\"username\", \"password\");\n    }\n\n    @Test\n    public void shouldGetUsername() {\n        assertThat(event.getUsernameOrEmail(), is(\"username\"));\n    }\n\n    @Test\n    public void shouldGetPassword() {\n        assertThat(event.getPassword(), is(\"password\"));\n    }\n\n    @Test\n    public void shouldNotHaveOTP() {\n        assertThat(event.getMultifactorOTP(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldSetOTP() {\n        event.setMultifactorOTP(\"otp\");\n        assertThat(event.getMultifactorOTP(), is(\"otp\"));\n    }\n\n    @Test\n    public void shouldNotHaveOOBCode() {\n        assertThat(event.getMultifactorOOBCode(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldSetOOBCode() {\n        event.setMultifactorOOBCode(\"oob\");\n        assertThat(event.getMultifactorOOBCode(), is(\"oob\"));\n    }\n\n    @Test\n    public void shouldNotHaveMFAToken() {\n        assertThat(event.getMultifactorToken(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldSetMFAToken() {\n        event.setMultifactorToken(\"mfa-challenge\");\n        assertThat(event.getMultifactorToken(), is(\"mfa-challenge\"));\n    }\n\n    @Test\n    public void shouldNotHaveMFAChallengeType() {\n        assertThat(event.getMultifactorChallengeType(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldSetMFAChallengeType() {\n        event.setMultifactorChallengeType(\"mfa-challenge\");\n        assertThat(event.getMultifactorChallengeType(), is(\"mfa-challenge\"));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/events/DatabaseSignUpEventTest.java",
    "content": "/*\n * DatabaseSignUpEventTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.request.Request;\nimport com.auth0.android.request.SignUpRequest;\nimport com.auth0.android.result.DatabaseUser;\n\nimport org.hamcrest.collection.IsMapContaining;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mockito;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class DatabaseSignUpEventTest {\n\n    private static final String EMAIL = \"email\";\n    private static final String PASSWORD = \"password\";\n    private static final String USERNAME = \"username\";\n    private static final String CONNECTION = \"connection\";\n\n    @Test\n    public void shouldSetAllValues() {\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n\n        assertThat(event.getEmail(), is(equalTo(EMAIL)));\n        assertThat(event.getPassword(), is(equalTo(PASSWORD)));\n        assertThat(event.getUsername(), is(equalTo(USERNAME)));\n    }\n\n    @Test\n    public void shouldSetNullUsername() {\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n\n        assertThat(event.getEmail(), is(equalTo(EMAIL)));\n        assertThat(event.getPassword(), is(equalTo(PASSWORD)));\n        assertThat(event.getUsername(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldGetSignUpRequestWithUsername() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n        event.getSignUpRequest(client, CONNECTION);\n        Mockito.verify(client).signUp(EMAIL, PASSWORD, USERNAME, CONNECTION, Collections.emptyMap());\n    }\n\n    @Test\n    public void shouldGetSignUpRequestWithoutUsername() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n        event.getSignUpRequest(client, CONNECTION);\n        Mockito.verify(client).signUp(EMAIL, PASSWORD, null, CONNECTION, Collections.emptyMap());\n    }\n\n    @Test\n    public void shouldGetSignUpRequestWithUserMetadata() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        final Map<String, String> metadata = createMetadata();\n        ArgumentCaptor<Map<String, String>> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        SignUpRequest requestMock = mock(SignUpRequest.class);\n        Mockito.when(client.signUp(eq(EMAIL), eq(PASSWORD), eq(null), eq(CONNECTION), mapCaptor.capture())).thenReturn(requestMock);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n        event.setExtraFields(metadata);\n        event.getSignUpRequest(client, CONNECTION);\n        Map<String, String> metadataMap = mapCaptor.getValue();\n        assertValidMetadata(metadataMap);\n\n        SignUpRequest usernameRequestMock = mock(SignUpRequest.class);\n        Mockito.when(client.signUp(eq(EMAIL), eq(PASSWORD), eq(USERNAME), eq(CONNECTION), mapCaptor.capture())).thenReturn(usernameRequestMock);\n        DatabaseSignUpEvent usernameEvent = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n        usernameEvent.setExtraFields(metadata);\n        usernameEvent.getSignUpRequest(client, CONNECTION);\n        metadataMap = mapCaptor.getValue();\n        assertValidMetadata(metadataMap);\n    }\n\n    @Test\n    public void shouldGetSignUpRequestWithRootProfileAttributes() throws Exception {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        final Map<String, String> attrs = createRootProfileAttributes();\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        SignUpRequest requestMock = mock(SignUpRequest.class);\n        Mockito.when(client.signUp(eq(EMAIL), eq(PASSWORD), eq(null), eq(CONNECTION), anyMap())).thenReturn(requestMock);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n        event.setRootAttributes(attrs);\n        event.getSignUpRequest(client, CONNECTION);\n        Mockito.verify(requestMock).addSignUpParameters(mapCaptor.capture());\n        assertValidRootProfileAttributes(mapCaptor.getValue());\n\n        SignUpRequest usernameRequestMock = mock(SignUpRequest.class);\n        Mockito.when(client.signUp(eq(EMAIL), eq(PASSWORD), eq(USERNAME), eq(CONNECTION), anyMap())).thenReturn(usernameRequestMock);\n        DatabaseSignUpEvent usernameEvent = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n        usernameEvent.setRootAttributes(attrs);\n        usernameEvent.getSignUpRequest(client, CONNECTION);\n        Mockito.verify(usernameRequestMock).addSignUpParameters(mapCaptor.capture());\n        assertValidRootProfileAttributes(mapCaptor.getValue());\n    }\n\n    @Test\n    public void shouldGetCreateUserRequestWithoutRootProfileAttributes() throws Exception {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n\n        SignUpRequest signUpRequestMock = mock(SignUpRequest.class);\n        Mockito.when(client.signUp(EMAIL, PASSWORD, USERNAME, CONNECTION)).thenReturn(signUpRequestMock);\n        event.getSignUpRequest(client, CONNECTION);\n        Mockito.verify(signUpRequestMock, never()).addSignUpParameters(anyMap());\n\n        SignUpRequest createRequestMock = mock(SignUpRequest.class);\n        Mockito.when(client.signUp(EMAIL, PASSWORD, USERNAME, CONNECTION)).thenReturn(createRequestMock);\n        event.getCreateUserRequest(client, CONNECTION);\n        Mockito.verify(createRequestMock, never()).addSignUpParameters(anyMap());\n    }\n\n    @Test\n    public void shouldGetCreateUserRequestWithUsername() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n        event.getCreateUserRequest(client, CONNECTION);\n        Mockito.verify(client).createUser(EMAIL, PASSWORD, USERNAME, CONNECTION, Collections.emptyMap());\n    }\n\n    @Test\n    public void shouldGetCreateUserRequestWithoutUsername() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n        event.getCreateUserRequest(client, CONNECTION);\n        Mockito.verify(client).createUser(EMAIL, PASSWORD, null, CONNECTION, Collections.emptyMap());\n    }\n\n    @Test\n    public void shouldGetCreateUserRequestWithUserMetadata() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        final Map<String, String> metadata = createMetadata();\n\n        ArgumentCaptor<Map<String, String>> mapCaptor = ArgumentCaptor.forClass(Map.class);\n        Request<DatabaseUser, AuthenticationException> requestMock = mock(Request.class);\n        Mockito.when(client.createUser(eq(EMAIL), eq(PASSWORD), eq(null), eq(CONNECTION), mapCaptor.capture())).thenReturn(requestMock);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n        event.setExtraFields(metadata);\n        event.getCreateUserRequest(client, CONNECTION);\n        Mockito.verify(requestMock, never()).addParameters(anyMap());\n        Map<String, String> metadataMap = mapCaptor.getValue();\n        assertValidMetadata(metadataMap);\n\n        Request<DatabaseUser, AuthenticationException> usernameRequestMock = mock(Request.class);\n        Mockito.when(client.createUser(eq(EMAIL), eq(PASSWORD), eq(USERNAME), eq(CONNECTION), mapCaptor.capture())).thenReturn(usernameRequestMock);\n        DatabaseSignUpEvent eventUsername = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n        eventUsername.setExtraFields(metadata);\n        eventUsername.getCreateUserRequest(client, CONNECTION);\n        Mockito.verify(usernameRequestMock, never()).addParameters(anyMap());\n        metadataMap = mapCaptor.getValue();\n        assertValidMetadata(metadataMap);\n    }\n\n    @Test\n    public void shouldGetCreateUserRequestWithRootProfileAttributes() throws Exception {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        final Map<String, String> attrs = createRootProfileAttributes();\n\n        Request<DatabaseUser, AuthenticationException> requestMock = mock(Request.class);\n        Mockito.when(client.createUser(eq(EMAIL), eq(PASSWORD), eq(null), eq(CONNECTION), anyMap())).thenReturn(requestMock);\n        DatabaseSignUpEvent event = new DatabaseSignUpEvent(EMAIL, PASSWORD, null);\n        event.setRootAttributes(attrs);\n        event.getCreateUserRequest(client, CONNECTION);\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n        Mockito.verify(requestMock).addParameters(mapCaptor.capture());\n        assertValidRootProfileAttributes(mapCaptor.getValue());\n\n        Request<DatabaseUser, AuthenticationException> usernameRequestMock = mock(Request.class);\n        Mockito.when(client.createUser(eq(EMAIL), eq(PASSWORD), eq(USERNAME), eq(CONNECTION), anyMap())).thenReturn(usernameRequestMock);\n        DatabaseSignUpEvent eventUsername = new DatabaseSignUpEvent(EMAIL, PASSWORD, USERNAME);\n        eventUsername.setRootAttributes(attrs);\n        eventUsername.getCreateUserRequest(client, CONNECTION);\n        Mockito.verify(usernameRequestMock).addParameters(mapCaptor.capture());\n        assertValidRootProfileAttributes(mapCaptor.getValue());\n    }\n\n    private Map<String, String> createRootProfileAttributes() {\n        Map<String, String> map = new HashMap<>();\n        map.put(\"name\", \"Nicholas\");\n        map.put(\"nickname\", \"Nick\");\n        map.put(\"lastname\", \"Fury\");\n        return map;\n    }\n\n    private Map<String, String> createMetadata() {\n        Map<String, String> map = new HashMap<>();\n        map.put(\"country\", \"Argentina\");\n        map.put(\"preferred_color\", \"blue\");\n        return map;\n    }\n\n    private void assertValidRootProfileAttributes(Map<String, Object> map) {\n        assertThat(map, is(notNullValue()));\n        assertThat(map, IsMapContaining.hasEntry(\"name\", \"Nicholas\"));\n        assertThat(map, IsMapContaining.hasEntry(\"nickname\", \"Nick\"));\n        assertThat(map, IsMapContaining.hasEntry(\"lastname\", \"Fury\"));\n    }\n\n    private void assertValidMetadata(Map<String, String> map) {\n        assertThat(map, is(notNullValue()));\n        assertThat(map, IsMapContaining.hasEntry(\"country\", \"Argentina\"));\n        assertThat(map, IsMapContaining.hasEntry(\"preferred_color\", \"blue\"));\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/events/ErrorMessageEventTest.java",
    "content": "package com.auth0.android.lock.events;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class ErrorMessageEventTest {\n\n    @Test\n    public void shouldSetMessageResource() {\n        //noinspection ResourceType\n        final LockMessageEvent event = new LockMessageEvent(23);\n        assertThat(event.getMessageRes(), is(23));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/events/OAuthLoginEventTest.java",
    "content": "package com.auth0.android.lock.events;\n\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class OAuthLoginEventTest {\n\n    private OAuthConnection connection;\n\n    @Before\n    public void setUp() {\n        connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"connectionName\");\n        when(connection.getStrategy()).thenReturn(\"strategyName\");\n    }\n\n    @Test\n    public void shouldGetStrategyName() {\n        OAuthLoginEvent roEvent = new OAuthLoginEvent(connection, \"username\", \"password\");\n        assertThat(roEvent.getStrategy(), is(\"strategyName\"));\n\n        OAuthLoginEvent webEvent = new OAuthLoginEvent(connection);\n        assertThat(webEvent.getStrategy(), is(\"strategyName\"));\n    }\n\n    @Test\n    public void shouldGetConnectionName() {\n        OAuthLoginEvent roEvent = new OAuthLoginEvent(connection, \"username\", \"password\");\n        assertThat(roEvent.getConnection(), is(\"connectionName\"));\n\n        OAuthLoginEvent webEvent = new OAuthLoginEvent(connection);\n        assertThat(webEvent.getConnection(), is(\"connectionName\"));\n    }\n\n    @Test\n    public void shouldUseActiveFlow() {\n        OAuthLoginEvent roEvent = new OAuthLoginEvent(connection, \"username\", \"password\");\n        assertTrue(roEvent.useActiveFlow());\n    }\n\n    @Test\n    public void shouldHaveUsernameOnActiveFlow() {\n        OAuthLoginEvent roEvent = new OAuthLoginEvent(connection, \"username\", \"password\");\n        assertThat(roEvent.getUsername(), is(\"username\"));\n    }\n\n    @Test\n    public void shouldHavePasswordOnActiveFlow() {\n        OAuthLoginEvent roEvent = new OAuthLoginEvent(connection, \"username\", \"password\");\n        assertThat(roEvent.getPassword(), is(\"password\"));\n    }\n\n    @Test\n    public void shouldUseWebAuth() {\n        OAuthLoginEvent webEvent = new OAuthLoginEvent(connection);\n        assertFalse(webEvent.useActiveFlow());\n    }\n\n    @Test\n    public void shouldNotHaveUsernameOnWebAuth() {\n        OAuthLoginEvent webEvent = new OAuthLoginEvent(connection);\n        assertThat(webEvent.getUsername(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldNotHavePasswordOnWebAuth() {\n        OAuthLoginEvent webEvent = new OAuthLoginEvent(connection);\n        assertThat(webEvent.getPassword(), is(nullValue()));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/events/PasswordlessLoginEventTest.java",
    "content": "/*\n * PasswordlessLoginEventTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.events;\n\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.authentication.PasswordlessType;\nimport com.auth0.android.lock.adapters.Country;\nimport com.auth0.android.lock.internal.configuration.PasswordlessMode;\nimport com.auth0.android.request.AuthenticationRequest;\nimport com.auth0.android.request.Request;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class PasswordlessLoginEventTest {\n\n    private static final String CONNECTION_NAME = \"connectionName\";\n    private static final String EMAIL = \"an@email.com\";\n    private static final String PHONE_NUMBER_WITH_CODE = \"+11234567890\";\n    private static final String PHONE_NUMBER_WITHOUT_CODE = \"1234567890\";\n    private static final String CODE = \"123456\";\n    private static final String CONNECTION_KEY = \"connection\";\n\n    private Country country;\n\n    @Before\n    public void setUp() {\n        MockitoAnnotations.initMocks(this);\n        country = new Country(\"US\", \"+1\");\n    }\n\n    @Test\n    public void shouldHaveNullCodeByDefault() {\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_LINK, EMAIL);\n\n        Assert.assertThat(event.getEmailOrNumber(), is(equalTo(EMAIL)));\n        Assert.assertThat(event.getMode(), is(equalTo(PasswordlessMode.EMAIL_LINK)));\n        Assert.assertThat(event.getCode(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldSetTheCode() {\n        PasswordlessLoginEvent event = PasswordlessLoginEvent.submitCode(PasswordlessMode.EMAIL_CODE, CODE);\n\n        Assert.assertThat(event.getMode(), is(equalTo(PasswordlessMode.EMAIL_CODE)));\n        Assert.assertThat(event.getCode(), is(equalTo(CODE)));\n    }\n\n    @Test\n    public void shouldGetValidCodeRequestWhenUsingEmailAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithEmail(EMAIL, PasswordlessType.CODE)).thenReturn(request);\n        when(request.addParameter(CONNECTION_KEY, CONNECTION_NAME)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_CODE, EMAIL);\n        Request<Void, AuthenticationException> resultRequest = emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(request));\n    }\n\n    @Test\n    public void shouldGetValidCodeRequestWhenUsingEmailAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithEmail(EMAIL, PasswordlessType.ANDROID_LINK)).thenReturn(request);\n        when(request.addParameter(CONNECTION_KEY, CONNECTION_NAME)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_LINK, EMAIL);\n        Request<Void, AuthenticationException> resultRequest = emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(request));\n    }\n\n    @Test\n    public void shouldGetValidCodeRequestWhenUsingSMSAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.CODE)).thenReturn(request);\n        when(request.addParameter(CONNECTION_KEY, CONNECTION_NAME)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_CODE, PHONE_NUMBER_WITHOUT_CODE, country);\n        Request<Void, AuthenticationException> resultRequest = emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(request));\n    }\n\n    @Test\n    public void shouldGetValidCodeRequestWhenUsingSMSAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.ANDROID_LINK)).thenReturn(request);\n        when(request.addParameter(CONNECTION_KEY, CONNECTION_NAME)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_LINK, PHONE_NUMBER_WITHOUT_CODE, country);\n        Request<Void, AuthenticationException> resultRequest = emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(request));\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessStartWhenUsingSMSAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.ANDROID_LINK)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_LINK, PHONE_NUMBER_WITHOUT_CODE, country);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(client).passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.ANDROID_LINK);\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessStartWhenUsingSMSAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.CODE)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_CODE, PHONE_NUMBER_WITHOUT_CODE, country);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(client).passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.CODE);\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessStartWhenUsingEmailAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithEmail(EMAIL, PasswordlessType.ANDROID_LINK)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_LINK, EMAIL);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(client).passwordlessWithEmail(EMAIL, PasswordlessType.ANDROID_LINK);\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessStartWhenUsingEmailAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithEmail(EMAIL, PasswordlessType.CODE)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_CODE, EMAIL);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(client).passwordlessWithEmail(EMAIL, PasswordlessType.CODE);\n    }\n\n    @Test\n    public void shouldSetConnectionWhenUsingSMSAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.ANDROID_LINK)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_LINK, PHONE_NUMBER_WITHOUT_CODE, country);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(request).addParameter(CONNECTION_KEY, CONNECTION_NAME);\n    }\n\n    @Test\n    public void shouldSetConnectionWhenWhenUsingSMSAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithSMS(PHONE_NUMBER_WITH_CODE, PasswordlessType.CODE)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.SMS_CODE, PHONE_NUMBER_WITHOUT_CODE, country);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(request).addParameter(CONNECTION_KEY, CONNECTION_NAME);\n    }\n\n    @Test\n    public void shouldSetConnectionWhenWhenUsingEmailAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithEmail(EMAIL, PasswordlessType.ANDROID_LINK)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_LINK, EMAIL);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(request).addParameter(CONNECTION_KEY, CONNECTION_NAME);\n    }\n\n    @Test\n    public void shouldSetConnectionWhenWhenUsingEmailAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        Request<Void, AuthenticationException> request = mock(Request.class);\n        when(client.passwordlessWithEmail(EMAIL, PasswordlessType.CODE)).thenReturn(request);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.requestCode(PasswordlessMode.EMAIL_CODE, EMAIL);\n        emailCodeEvent.getCodeRequest(client, CONNECTION_NAME);\n\n        verify(request).addParameter(CONNECTION_KEY, CONNECTION_NAME);\n    }\n\n    @Test\n    public void shouldGetValidLoginRequestWhenUsingEmailAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithEmail(EMAIL, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.EMAIL_CODE, CODE);\n        AuthenticationRequest resultRequest = emailCodeEvent.getLoginRequest(client, EMAIL);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(authRequest));\n    }\n\n    @Test\n    public void shouldGetValidLoginRequestWhenUsingEmailAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithEmail(EMAIL, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.EMAIL_LINK, CODE);\n        AuthenticationRequest resultRequest = emailCodeEvent.getLoginRequest(client, EMAIL);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(authRequest));\n    }\n\n    @Test\n    public void shouldGetValidLoginRequestWhenUsingSMSAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithPhoneNumber(PHONE_NUMBER_WITH_CODE, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.SMS_CODE, CODE);\n        AuthenticationRequest resultRequest = emailCodeEvent.getLoginRequest(client, PHONE_NUMBER_WITH_CODE);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(authRequest));\n    }\n\n    @Test\n    public void shouldGetValidLoginRequestWhenUsingSMSAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithPhoneNumber(PHONE_NUMBER_WITH_CODE, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.SMS_LINK, CODE);\n        AuthenticationRequest resultRequest = emailCodeEvent.getLoginRequest(client, PHONE_NUMBER_WITH_CODE);\n\n        Assert.assertThat(resultRequest, notNullValue());\n        Assert.assertThat(resultRequest, equalTo(authRequest));\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessLoginWhenUsingEmailAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithEmail(EMAIL, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.EMAIL_CODE, CODE);\n        emailCodeEvent.getLoginRequest(client, EMAIL);\n\n        verify(client).loginWithEmail(EMAIL, CODE);\n        verify(client, never()).getProfileAfter(authRequest);\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessLoginWhenUsingEmailAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithEmail(EMAIL, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.EMAIL_LINK, CODE);\n        emailCodeEvent.getLoginRequest(client, EMAIL);\n\n        verify(client).loginWithEmail(EMAIL, CODE);\n        verify(client, never()).getProfileAfter(authRequest);\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessLoginWhenUsingSMSAndCode() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithPhoneNumber(PHONE_NUMBER_WITH_CODE, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.SMS_CODE, CODE);\n        emailCodeEvent.getLoginRequest(client, PHONE_NUMBER_WITH_CODE);\n\n        verify(client).loginWithPhoneNumber(PHONE_NUMBER_WITH_CODE, CODE);\n        verify(client, never()).getProfileAfter(authRequest);\n    }\n\n    @Test\n    public void shouldCallApiClientPasswordlessLoginWhenUsingSMSAndLink() {\n        AuthenticationAPIClient client = mock(AuthenticationAPIClient.class);\n        AuthenticationRequest authRequest = mock(AuthenticationRequest.class);\n        when(client.loginWithPhoneNumber(PHONE_NUMBER_WITH_CODE, CODE)).thenReturn(authRequest);\n\n        PasswordlessLoginEvent emailCodeEvent = PasswordlessLoginEvent.submitCode(PasswordlessMode.SMS_LINK, CODE);\n        emailCodeEvent.getLoginRequest(client, PHONE_NUMBER_WITH_CODE);\n\n        verify(client).loginWithPhoneNumber(PHONE_NUMBER_WITH_CODE, CODE);\n        verify(client, never()).getProfileAfter(authRequest);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ApplicationFetcherTest.java",
    "content": "/*\n * ApplicationFetcherTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.Auth0Exception;\nimport com.auth0.android.lock.utils.ApplicationAPI;\nimport com.auth0.android.lock.utils.CallbackMatcher;\nimport com.auth0.android.lock.utils.MockCallback;\nimport com.auth0.android.lock.utils.SSLTestUtils;\nimport com.google.gson.reflect.TypeToken;\n\nimport org.hamcrest.CoreMatchers;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.List;\n\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class ApplicationFetcherTest {\n\n    private ApplicationFetcher appFetcher;\n    private ApplicationAPI mockAPI;\n\n    @Before\n    public void setUp() throws Exception {\n        SSLTestUtils sslUtils = new SSLTestUtils();\n        mockAPI = new ApplicationAPI(sslUtils);\n\n        final Options options = Mockito.mock(Options.class);\n        Auth0 account = new Auth0(\"client_id\", mockAPI.getDomain());\n        account.setNetworkingClient(sslUtils.testClient);\n        Mockito.when(options.getAccount()).thenReturn(account);\n        appFetcher = new ApplicationFetcher(account);\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        mockAPI.shutdown();\n    }\n\n    @Test\n    public void shouldReturnApplicationOnValidJSONPResponse() throws Exception {\n        mockAPI.willReturnValidJSONPResponse();\n        final MockCallback<List<Connection>, Auth0Exception> callback = new MockCallback<>();\n        appFetcher.fetch(callback);\n        mockAPI.takeRequest();\n\n        TypeToken<List<Connection>> applicationType = new TypeToken<List<Connection>>(){};\n        TypeToken<Auth0Exception> errorType = new TypeToken<Auth0Exception>() {};\n        assertThat(callback, CallbackMatcher.hasPayloadOfType(applicationType, errorType));\n    }\n\n    @Test\n    public void shouldReturnExceptionOnInvalidJSONPResponse() throws Exception {\n        mockAPI.willReturnInvalidJSONPLengthResponse();\n        final MockCallback<List<Connection>, Auth0Exception> callback = new MockCallback<>();\n        appFetcher.fetch(callback);\n        mockAPI.takeRequest();\n\n        TypeToken<List<Connection>> applicationType = new TypeToken<List<Connection>>(){};\n        TypeToken<Auth0Exception> errorType = new TypeToken<Auth0Exception>() {};\n        assertThat(callback, CallbackMatcher.hasErrorOfType(applicationType, errorType));\n        assertThat(callback.getError(), CoreMatchers.instanceOf(Auth0Exception.class));\n        assertThat(callback.getError().getCause().getCause().getMessage(), CoreMatchers.containsString(\"Invalid App Info JSONP\"));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ApplicationGsonTest.java",
    "content": "/*\n * ApplicationGsonTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.google.gson.JsonParseException;\nimport com.google.gson.reflect.TypeToken;\n\nimport org.hamcrest.collection.IsCollectionWithSize;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\n\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.util.List;\n\nimport static org.hamcrest.Matchers.instanceOf;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.junit.Assert.assertThat;\n\npublic class ApplicationGsonTest extends GsonBaseTest {\n    private static final String APPLICATION = \"src/test/resources/application.json\";\n\n    @Rule\n    public ExpectedException expectedException = ExpectedException.none();\n\n    @Before\n    public void setUp() {\n        gson = createGson();\n    }\n\n    @Test\n    public void shouldFailWithEmptyJson() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        buildApplicationFrom(json(EMPTY_OBJECT));\n    }\n\n    @Test\n    public void shouldFailWithInvalidJson() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        buildApplicationFrom(json(INVALID));\n    }\n\n    @Test\n    public void shouldRequireId() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        expectedException.expectMessage(\"Missing required attribute id\");\n        buildApplicationFrom(new StringReader(\"{\\\"tenant\\\":\\\"samples\\\",\\\"authorize\\\":\\\"https://samples.auth0.com/authorize\\\",\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]}\"));\n    }\n\n    @Test\n    public void shouldRequireTenant() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        expectedException.expectMessage(\"Missing required attribute tenant\");\n        buildApplicationFrom(new StringReader(\"{\\\"id\\\":\\\"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\\\",\\\"authorize\\\":\\\"https://samples.auth0.com/authorize\\\",\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]}\"));\n    }\n\n    @Test\n    public void shouldRequireAuthorize() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        expectedException.expectMessage(\"Missing required attribute authorize\");\n        buildApplicationFrom(new StringReader(\"{\\\"id\\\":\\\"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\\\",\\\"tenant\\\":\\\"samples\\\",\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]}\"));\n    }\n\n    @Test\n    public void shouldAllowEmptyAuthorize() throws Exception {\n        buildApplicationFrom(new StringReader(\"{\\\"id\\\":\\\"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\\\",\\\"callback\\\":\\\"https://samples.auth0.com/callback\\\",\\\"tenant\\\":\\\"samples\\\",\\\"authorize\\\":\\\"\\\",\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]}\"));\n    }\n\n    @Test\n    public void shouldRequireCallback() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        expectedException.expectMessage(\"Missing required attribute callback\");\n        buildApplicationFrom(new StringReader(\"{\\\"id\\\":\\\"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\\\",\\\"authorize\\\":\\\"https://samples.auth0.com/authorize\\\",\\\"tenant\\\":\\\"samples\\\",\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]}\"));\n    }\n\n    @Test\n    public void shouldAllowEmptyCallback() throws Exception {\n        buildApplicationFrom(new StringReader(\"{\\\"id\\\":\\\"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\\\",\\\"tenant\\\":\\\"samples\\\",\\\"authorize\\\":\\\"https://samples.auth0.com/authorize\\\",\\\"callback\\\":\\\"\\\",\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]}\"));\n    }\n\n    @Test\n    public void shouldRequireStrategies() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        expectedException.expectMessage(\"Missing required attribute strategies\");\n        buildApplicationFrom(new StringReader(\"{\\\"id\\\":\\\"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\\\",\\\"tenant\\\":\\\"samples\\\",\\\"authorize\\\":\\\"https://samples.auth0.com/authorize\\\",\\\"callback\\\":\\\"https://samples.auth0.com/callback\\\"}\"));\n    }\n\n    @Test\n    public void shouldReturnApplication() throws Exception {\n        final List<Connection> connections = buildApplicationFrom(json(APPLICATION));\n        assertThat(connections, is(notNullValue()));\n        assertThat(connections, is(notNullValue()));\n        assertThat(connections, IsCollectionWithSize.hasSize(1));\n        assertThat(connections.get(0), instanceOf(Connection.class));\n    }\n\n    private List<Connection> buildApplicationFrom(Reader json) throws IOException {\n        TypeToken<List<Connection>> applicationType = new TypeToken<List<Connection>>() {};\n        return pojoFrom(json, applicationType);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ConfigurationTest.java",
    "content": "/*\n * ConfigurationTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.auth0.android.lock.InitialScreen;\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.UsernameStyle;\nimport com.auth0.android.lock.utils.CustomField;\nimport com.auth0.android.lock.utils.CustomField.FieldType;\nimport com.auth0.android.lock.utils.HiddenField;\nimport com.auth0.android.lock.utils.SignUpField;\nimport com.google.gson.reflect.TypeToken;\nimport com.google.gson.stream.JsonReader;\n\nimport org.hamcrest.Matchers;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.MockitoAnnotations;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.io.FileReader;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasConnection;\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasName;\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasStrategy;\nimport static org.hamcrest.Matchers.contains;\nimport static org.hamcrest.Matchers.containsInAnyOrder;\nimport static org.hamcrest.Matchers.emptyIterable;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.hasItem;\nimport static org.hamcrest.Matchers.hasSize;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.not;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class ConfigurationTest extends GsonBaseTest {\n\n    private static final String RESTRICTIVE_DATABASE = \"RestrictiveDatabase\";\n    private static final String CUSTOM_DATABASE = \"CustomDatabase\";\n    private static final String USERNAME_PASSWORD_AUTHENTICATION = \"Username-Password-Authentication\";\n    private static final String TWITTER = \"twitter\";\n    private static final String EMAIL = \"email\";\n    private static final String MY_AD = \"MyAD\";\n    private static final String UNKNOWN_CONNECTION = \"UnknownConnection\";\n    private static final String CUSTOM_PASSWORDLESS_CONNECTION = \"my-sms-connection\";\n\n    private Configuration configuration;\n    private List<Connection> connections;\n    private Options options;\n\n    @Before\n    public void setUp() throws Exception {\n        MockitoAnnotations.initMocks(this);\n        final FileReader fr = new FileReader(\"src/test/resources/appinfo.json\");\n        Type applicationType = new TypeToken<List<Connection>>() {\n        }.getType();\n        connections = createGson().fromJson(new JsonReader(fr), applicationType);\n        options = new Options();\n    }\n\n    @Test\n    public void shouldKeepApplicationDefaultsIfOptionsAreNotModified() {\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.isUsernameRequired(), is(false));\n        assertThat(configuration.allowLogIn(), is(true));\n        assertThat(configuration.allowSignUp(), is(true));\n        assertThat(configuration.allowForgotPassword(), is(true));\n        assertThat(configuration.allowShowPassword(), is(true));\n        assertThat(configuration.loginAfterSignUp(), is(true));\n        assertThat(configuration.getUsernameStyle(), is(equalTo(UsernameStyle.DEFAULT)));\n        assertThat(configuration.getInitialScreen(), is(equalTo(InitialScreen.LOG_IN)));\n        assertThat(configuration.getVisibleSignUpFieldsThreshold(), is(equalTo(2)));\n        assertThat(configuration.getPasswordComplexity(), is(notNullValue()));\n        assertThat(configuration.getPasswordComplexity().getPasswordPolicy(), is(PasswordStrength.NONE));\n        assertThat(configuration.mustAcceptTerms(), is(false));\n        assertThat(configuration.showTerms(), is(true));\n        assertThat(configuration.useLabeledSubmitButton(), is(true));\n        assertThat(configuration.hideMainScreenTitle(), is(false));\n        assertThat(configuration.usePasswordlessAutoSubmit(), is(false));\n    }\n\n    @Test\n    public void shouldGetValidStyleForNotOverriddenStrategy() {\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.authStyleForConnection(\"facebook\", \"facebook-prod\"), Matchers.is(R.style.Lock_Theme_AuthStyle_Facebook));\n    }\n\n    @Test\n    public void shouldGetVisibleSignUpFieldsThreshold() {\n        options.setVisibleSignUpFieldsThreshold(6);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getVisibleSignUpFieldsThreshold(), is(6));\n    }\n\n    @Test\n    public void shouldGetStyleForOverriddenStrategy() {\n        //noinspection ResourceType\n        options.withAuthStyle(\"facebook-prod\", 123456);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.authStyleForConnection(\"facebook\", \"facebook-prod\"), is(123456));\n    }\n\n    @Test\n    public void shouldMergeApplicationWithOptionsIfDefaultDatabaseExists() {\n        options.setConnections(Collections.singletonList(USERNAME_PASSWORD_AUTHENTICATION));\n        options.setAllowLogIn(false);\n        options.setAllowSignUp(false);\n        options.setAllowForgotPassword(false);\n        options.setAllowShowPassword(false);\n        options.setLoginAfterSignUp(false);\n        options.setUsernameStyle(UsernameStyle.USERNAME);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.isUsernameRequired(), is(false));\n        assertThat(configuration.allowLogIn(), is(false));\n        assertThat(configuration.allowSignUp(), is(false));\n        assertThat(configuration.allowForgotPassword(), is(false));\n        assertThat(configuration.allowShowPassword(), is(false));\n        assertThat(configuration.loginAfterSignUp(), is(false));\n        assertThat(configuration.getUsernameStyle(), is(equalTo(UsernameStyle.USERNAME)));\n    }\n\n    @Test\n    public void shouldNotMergeApplicationWithOptionsIfApplicationIsRestrictive() {\n        options.setConnections(Collections.singletonList(RESTRICTIVE_DATABASE));\n        options.setAllowSignUp(true);\n        options.setAllowForgotPassword(true);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.allowSignUp(), is(false));\n        assertThat(configuration.allowForgotPassword(), is(false));\n    }\n\n    @Test\n    public void shouldNotUseClassicLockIfNoConnectionsAreAvailable() {\n        configuration = filteredConfigBy(\"\");\n        assertThat(configuration.hasClassicConnections(), is(false));\n    }\n\n    @Test\n    public void shouldUseClassicLockWithEnterpriseConnections() {\n        configuration = filteredConfigBy(MY_AD);\n        assertThat(configuration.hasClassicConnections(), is(true));\n    }\n\n    @Test\n    public void shouldUseClassicLockWithSocialConnections() {\n        configuration = filteredConfigBy(TWITTER);\n        assertThat(configuration.hasClassicConnections(), is(true));\n    }\n\n    @Test\n    public void shouldUseClassicLockWithDatabaseConnections() {\n        configuration = filteredConfigBy(RESTRICTIVE_DATABASE);\n        assertThat(configuration.hasClassicConnections(), is(true));\n    }\n\n    @Test\n    public void shouldNotUsePasswordlessIfNoConnectionsAreAvailable() {\n        configuration = filteredConfigBy(\"\");\n        assertThat(configuration.hasPasswordlessConnections(), is(false));\n    }\n\n    @Test\n    public void shouldIgnoreAllowedScreenSettingsIfDatabaseConnectionsAreAvailable() {\n        options.setAllowLogIn(false);\n        options.setAllowSignUp(false);\n        options.setAllowForgotPassword(false);\n        configuration = filteredConfigBy(USERNAME_PASSWORD_AUTHENTICATION);\n        assertThat(configuration.hasClassicConnections(), is(true));\n    }\n\n    @Test\n    public void shouldUsePasswordlessLockWithSocialConnections() {\n        configuration = filteredConfigBy(TWITTER);\n        assertThat(configuration.hasPasswordlessConnections(), is(true));\n    }\n\n    @Test\n    public void shouldUsePasswordlessLockWithPasswordlessConnections() {\n        configuration = filteredConfigBy(EMAIL);\n        assertThat(configuration.hasPasswordlessConnections(), is(true));\n    }\n\n    @Test\n    public void shouldPasswordlessLockNotBeAffectedByClassicLockScreenFlags() {\n        options.setAllowLogIn(false);\n        options.setAllowSignUp(false);\n        options.setAllowForgotPassword(false);\n        configuration = filteredConfigBy(EMAIL, TWITTER);\n        assertThat(configuration.hasPasswordlessConnections(), is(true));\n    }\n\n    @Test\n    public void shouldSetExtraSignUpFields() {\n        List<SignUpField> fields = new ArrayList<>();\n        List<SignUpField> hiddenSignUpFields = createHiddenSignUpFields();\n        List<SignUpField> visibleSignUpFields = createVisibleSignUpFields();\n        fields.addAll(hiddenSignUpFields);\n        fields.addAll(visibleSignUpFields);\n\n        options.setSignUpFields(fields);\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getHiddenSignUpFields(), contains(hiddenSignUpFields.toArray()));\n        assertThat(configuration.getVisibleSignUpFields(), contains(visibleSignUpFields.toArray()));\n    }\n\n    @Test\n    public void shouldSetInitialScreenWhenDatabaseConnectionAvailable() {\n        options.setConnections(Collections.singletonList(USERNAME_PASSWORD_AUTHENTICATION));\n\n        options.setInitialScreen(InitialScreen.SIGN_UP);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getInitialScreen(), is(InitialScreen.SIGN_UP));\n\n        options.setInitialScreen(InitialScreen.LOG_IN);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getInitialScreen(), is(InitialScreen.LOG_IN));\n\n        options.setInitialScreen(InitialScreen.FORGOT_PASSWORD);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getInitialScreen(), is(InitialScreen.FORGOT_PASSWORD));\n    }\n\n    @Test\n    public void shouldNotChangeInitialScreenWhenNoDatabaseConnectionAvailable() {\n        options.setConnections(Collections.singletonList(\"\"));\n\n        //InitialScreen.LOG_IN is the default InitialScreen.\n        options.setInitialScreen(InitialScreen.SIGN_UP);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getInitialScreen(), is(InitialScreen.LOG_IN));\n\n        options.setInitialScreen(InitialScreen.FORGOT_PASSWORD);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getInitialScreen(), is(InitialScreen.LOG_IN));\n    }\n\n    @Test\n    public void shouldPreferPasswordlessEmailOverSMSWhenBothAvailable() {\n        options.setUseCodePasswordless(true);\n        options.setConnections(Arrays.asList(\"sms\", \"email\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.EMAIL_CODE));\n\n        options.setUseCodePasswordless(false);\n        options.setConnections(Arrays.asList(\"sms\", \"email\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.EMAIL_LINK));\n    }\n\n    @Test\n    public void shouldSetCorrectPasswordlessTypeWhenUsingEmail() {\n        options.setUseCodePasswordless(true);\n        options.setConnections(Collections.singletonList(\"email\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.EMAIL_CODE));\n\n        options.setUseCodePasswordless(false);\n        options.setConnections(Collections.singletonList(\"email\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.EMAIL_LINK));\n    }\n\n    @Test\n    public void shouldSetCorrectPasswordlessTypeWhenUsingSMS() {\n        options.setUseCodePasswordless(true);\n        options.setConnections(Collections.singletonList(\"sms\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.SMS_CODE));\n\n        options.setUseCodePasswordless(false);\n        options.setConnections(Collections.singletonList(\"sms\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.SMS_LINK));\n    }\n\n    @Test\n    public void shouldNotHavePasswordlessModeWithoutConnections() {\n        options.setUseCodePasswordless(true);\n        options.setConnections(Collections.singletonList(\"facebook\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.DISABLED));\n    }\n\n    @Test\n    public void shouldDefaultToCodePasswordlessWhenTypeMissingFromOptions() {\n        options.setConnections(Collections.singletonList(\"sms\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getPasswordlessMode(), is(PasswordlessMode.SMS_CODE));\n    }\n\n    @Test\n    public void shouldNotFilterDefaultDBConnection() {\n        configuration = unfilteredConfig();\n        assertThat(configuration.getDatabaseConnection(), hasName(USERNAME_PASSWORD_AUTHENTICATION));\n    }\n\n    @Test\n    public void shouldHandleNoDBConnections() {\n        options.useDatabaseConnection(null);\n        configuration = new Configuration(new ArrayList<Connection>(), options);\n        final DatabaseConnection connection = configuration.getDatabaseConnection();\n        assertThat(connection, nullValue());\n    }\n\n    @Test\n    public void shouldFilterDBConnection() {\n        configuration = filteredConfigBy(CUSTOM_DATABASE);\n        assertThat(configuration.getDatabaseConnection(), hasName(CUSTOM_DATABASE));\n    }\n\n    @Test\n    public void shouldReturnNullDBConnectionWhenNoneMatch() {\n        configuration = filteredConfigBy(UNKNOWN_CONNECTION);\n        assertThat(configuration.getDatabaseConnection(), nullValue());\n    }\n\n    @Test\n    public void shouldReturnSpecifiedDBConnectionWhenMoreThanOneDBConnectionIsAvailable() {\n        options.setConnections(Arrays.asList(CUSTOM_DATABASE, USERNAME_PASSWORD_AUTHENTICATION, RESTRICTIVE_DATABASE, UNKNOWN_CONNECTION));\n        options.useDatabaseConnection(RESTRICTIVE_DATABASE);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getDatabaseConnection(), hasName(RESTRICTIVE_DATABASE));\n    }\n\n    @Test\n    public void shouldReturnSpecifiedDBConnectionIfAvailable() {\n        options.setConnections(null);\n\n        options.useDatabaseConnection(CUSTOM_DATABASE);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getDatabaseConnection(), hasName(CUSTOM_DATABASE));\n    }\n\n    @Test\n    public void shouldIgnoreSpecifiedDBConnectionIfNotAvailable() {\n        options.setConnections(null);\n\n        options.useDatabaseConnection(\"non-existing-db-connection\");\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getDatabaseConnection(), hasName(USERNAME_PASSWORD_AUTHENTICATION));\n    }\n\n    @Test\n    public void shouldIgnoreSpecifiedDBConnectionIfFiltered() {\n        options.setConnections(Collections.singletonList(USERNAME_PASSWORD_AUTHENTICATION));\n\n        options.useDatabaseConnection(\"non-existing-db-connection\");\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getDatabaseConnection(), hasName(USERNAME_PASSWORD_AUTHENTICATION));\n    }\n\n    @Test\n    public void shouldReturnUnfilteredPasswordlessConnections() {\n        configuration = unfilteredConfig();\n        List<PasswordlessConnection> connections = configuration.getPasswordlessConnections();\n        assertThat(connections, is(notNullValue()));\n        assertThat(connections, containsInAnyOrder(hasConnection(\"email\", \"email\"),\n                hasConnection(\"sms\", \"sms\"), hasConnection(\"sms\", CUSTOM_PASSWORDLESS_CONNECTION)));\n    }\n\n    @Test\n    public void shouldReturnFilteredPasswordlessConnections() {\n        configuration = filteredConfigBy(CUSTOM_PASSWORDLESS_CONNECTION);\n        PasswordlessConnection connection = configuration.getPasswordlessConnection();\n        assertThat(connection, is(notNullValue()));\n        assertThat(connection, hasConnection(\"sms\", CUSTOM_PASSWORDLESS_CONNECTION));\n    }\n\n    @Test\n    public void shouldPreferEmailPasswordlessConnection() {\n        configuration = unfilteredConfig();\n        PasswordlessConnection defaultConnection = configuration.getPasswordlessConnection();\n        assertThat(defaultConnection, is(notNullValue()));\n        assertThat(defaultConnection.getName(), equalTo(\"email\"));\n    }\n\n    @Test\n    public void shouldReturnEmptyPasswordlessConnectionIfNoneMatch() {\n        configuration = filteredConfigBy(\"facebook\");\n        PasswordlessConnection connection = configuration.getPasswordlessConnection();\n        assertThat(connection, is(nullValue()));\n    }\n\n    @Test\n    public void shouldIgnoreStrategyNameAndReturnFilteredConnections() {\n        configuration = filteredConfigBy(\"twitter\", \"twitter-dev\");\n        final List<OAuthConnection> strategies = configuration.getSocialConnections();\n        assertThat(strategies, containsInAnyOrder(hasConnection(\"twitter\", \"twitter\"), hasConnection(\"twitter\", \"twitter-dev\")));\n        assertThat(strategies, hasSize(2));\n    }\n\n    @Test\n    public void shouldNotReturnFilteredSocialStrategiesWithoutConnections() {\n        configuration = filteredConfigBy(\"facebook\", \"linkedin\");\n        final List<OAuthConnection> connections = configuration.getSocialConnections();\n        assertThat(connections, hasItem(hasStrategy(\"facebook\")));\n        assertThat(connections, not(hasItem(hasStrategy(\"linkedin\"))));\n    }\n\n    @Test\n    public void shouldReturnUnfilteredSocialConnections() {\n        configuration = unfilteredConfig();\n        final List<OAuthConnection> connections = configuration.getSocialConnections();\n        assertThat(connections, containsInAnyOrder(hasConnection(\"facebook\", \"facebook\"),\n                hasConnection(\"twitter\", \"twitter\"), hasConnection(\"twitter\", \"twitter-dev\"), hasConnection(\"instagram\", \"instagram\"),\n                hasConnection(\"google-oauth2\", \"google-oauth2\")));\n    }\n\n    @Test\n    public void shouldReturnFilteredSocialConnections() {\n        configuration = filteredConfigBy(\"facebook\", \"instagram\");\n        assertThat(configuration.getSocialConnections(), containsInAnyOrder(hasConnection(\"facebook\", \"facebook\"),\n                hasConnection(\"instagram\", \"instagram\")));\n    }\n\n    @Test\n    public void shouldReturnEmptySocialConnectionsIfNoneMatch() {\n        configuration = filteredConfigBy(\"yammer\", \"yahoo\");\n        assertThat(configuration.getSocialConnections(), emptyIterable());\n    }\n\n    @Test\n    public void shouldReturnUnfilteredEnterpriseConnections() {\n        configuration = unfilteredConfig();\n        assertThat(configuration.getEnterpriseConnections(), containsInAnyOrder(\n                hasConnection(\"ad\", \"MyAD\"),\n                hasConnection(\"ad\", \"mySecondAD\"),\n                hasConnection(\"google-apps\", \"auth0.com\")\n        ));\n    }\n\n    @Test\n    public void shouldAllowEnterpriseActiveFlowByDefault() {\n        configuration = unfilteredConfig();\n        for (OAuthConnection c : configuration.getEnterpriseConnections()) {\n            if (Arrays.asList(\"ad\", \"waad\", \"adfs\").contains(c.getStrategy())) {\n                assertThat(c.isActiveFlowEnabled(), is(true));\n            } else {\n                //Strategies not included above should not allow ActiveFlow\n                assertThat(c.isActiveFlowEnabled(), is(false));\n            }\n        }\n    }\n\n    @Test\n    public void shouldDisableEnterpriseActiveFlowOnGivenConnections() {\n        List<String> webAuthEnabledConnections = Collections.singletonList(\"MyAD\");\n        options.setEnterpriseConnectionsUsingWebForm(webAuthEnabledConnections);\n        configuration = new Configuration(connections, options);\n\n        //Connections include 2 'ad' enterprise connections: \"MyAD\" and \"mySecondAD\"\n        //'MyAD' is tell above to use Web Authentication instead of its default behavior\n        for (OAuthConnection c : configuration.getEnterpriseConnections()) {\n            if (c.getName().equals(\"mySecondAD\")) {\n                assertThat(c.isActiveFlowEnabled(), is(true));\n            } else if (c.getName().equals(\"MyAD\")) {\n                assertThat(c.isActiveFlowEnabled(), is(false));\n            }\n        }\n    }\n\n    @Test\n    public void shouldNotFilterEnterpriseConnectionsByWebAuthEnabled() {\n        options.setConnections(Arrays.asList(\"auth0.com\", \"MyAD\"));\n        options.setEnterpriseConnectionsUsingWebForm(Arrays.asList(\"mySecondAD\", \"MyAD\"));\n        configuration = new Configuration(connections, options);\n\n        assertThat(configuration.getEnterpriseConnections(), containsInAnyOrder(\n                hasConnection(\"ad\", \"MyAD\"),\n                hasConnection(\"google-apps\", \"auth0.com\")\n        ));\n    }\n\n    @Test\n    public void shouldReturnFilteredEnterpriseConnections() {\n        configuration = filteredConfigBy(\"auth0.com\");\n        assertThat(configuration.getEnterpriseConnections(), contains(hasConnection(\"google-apps\", \"auth0.com\")));\n    }\n\n    @Test\n    public void shouldReturnEmptyEnterpriseConnectionsIfNoneMatch() {\n        configuration = filteredConfigBy(\"yandex\");\n        assertThat(configuration.getEnterpriseConnections(), emptyIterable());\n    }\n\n    @Test\n    public void shouldHaveDefaultPrivacyPolicyURL() {\n        configuration = unfilteredConfig();\n        assertThat(configuration.getPrivacyURL(), is(notNullValue()));\n        assertThat(configuration.getPrivacyURL(), is(equalTo(\"https://auth0.com/privacy\")));\n    }\n\n    @Test\n    public void shouldHaveCustomPrivacyPolicyURL() {\n        options.setPrivacyURL(\"https://google.com/privacy\");\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getPrivacyURL(), is(notNullValue()));\n        assertThat(configuration.getPrivacyURL(), is(equalTo(\"https://google.com/privacy\")));\n    }\n\n    @Test\n    public void shouldHaveDefaultTermsOfServiceURL() {\n        configuration = unfilteredConfig();\n        assertThat(configuration.getTermsURL(), is(notNullValue()));\n        assertThat(configuration.getTermsURL(), is(equalTo(\"https://auth0.com/terms\")));\n    }\n\n    @Test\n    public void shouldHaveCustomTermsOfServiceURL() {\n        options.setTermsURL(\"https://google.com/terms\");\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getTermsURL(), is(notNullValue()));\n        assertThat(configuration.getTermsURL(), is(equalTo(\"https://google.com/terms\")));\n    }\n\n    @Test\n    public void shouldNotHaveDefaultSupportURL() {\n        configuration = unfilteredConfig();\n        assertThat(configuration.getSupportURL(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldHaveCustomSupportURL() {\n        options.setSupportURL(\"https://google.com/support\");\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.getSupportURL(), is(notNullValue()));\n        assertThat(configuration.getSupportURL(), is(equalTo(\"https://google.com/support\")));\n    }\n\n    @Test\n    public void shouldHaveMustAcceptTermsEnabled() {\n        options.setMustAcceptTerms(true);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.mustAcceptTerms(), is(true));\n    }\n\n    @Test\n    public void shouldHaveShowTermsDisabled() {\n        options.setShowTerms(false);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.showTerms(), is(false));\n    }\n\n    @Test\n    public void shouldNotUseLabeledSubmitButton() {\n        options.setUseLabeledSubmitButton(false);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.useLabeledSubmitButton(), is(false));\n    }\n\n    @Test\n    public void shouldGetPasswordPolicy() {\n        options.useDatabaseConnection(\"with-strength\");\n        configuration = new Configuration(connections, options);\n        PasswordComplexity passwordComplexity = configuration.getPasswordComplexity();\n        assertThat(passwordComplexity, is(notNullValue()));\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.EXCELLENT));\n    }\n\n    @Test\n    public void shouldHideMainScreenTitle() {\n        options.setHideMainScreenTitle(true);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.hideMainScreenTitle(), is(true));\n    }\n\n    @Test\n    public void shouldUsePasswordlessAutoSubmit() {\n        options.setRememberLastPasswordlessLogin(true);\n        configuration = new Configuration(connections, options);\n        assertThat(configuration.usePasswordlessAutoSubmit(), is(true));\n    }\n\n    private Configuration unfilteredConfig() {\n        return new Configuration(connections, options);\n    }\n\n    private Configuration filteredConfigBy(String... names) {\n        options.setConnections(Arrays.asList(names));\n        return new Configuration(connections, options);\n    }\n\n    private List<SignUpField> createVisibleSignUpFields() {\n        CustomField fieldNumber = new CustomField(R.drawable.com_auth0_lock_ic_phone, FieldType.TYPE_PHONE_NUMBER, \"number\", R.string.com_auth0_lock_hint_phone_number);\n        CustomField fieldSurname = new CustomField(R.drawable.com_auth0_lock_ic_username, FieldType.TYPE_NAME, \"surname\", R.string.com_auth0_lock_hint_username);\n\n        List<SignUpField> signUpFields = new ArrayList<>();\n        signUpFields.add(fieldNumber);\n        signUpFields.add(fieldSurname);\n        return signUpFields;\n    }\n\n    private List<SignUpField> createHiddenSignUpFields() {\n        HiddenField fieldHidden1 = new HiddenField(\"referral_id\", \"0009912BBA\", CustomField.Storage.PROFILE_ROOT);\n        HiddenField fieldHidden2 = new HiddenField(\"ad_reference\", \"mmmaba\", CustomField.Storage.PROFILE_ROOT);\n\n        List<SignUpField> signUpFields = new ArrayList<>();\n        signUpFields.add(fieldHidden1);\n        signUpFields.add(fieldHidden2);\n        return signUpFields;\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ConnectionGsonTest.java",
    "content": "/*\n * StrategyGsonTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.google.gson.JsonParseException;\nimport com.google.gson.reflect.TypeToken;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\n\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.util.List;\n\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasType;\nimport static org.hamcrest.Matchers.contains;\nimport static org.hamcrest.Matchers.hasItem;\nimport static org.hamcrest.Matchers.hasSize;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.junit.Assert.assertThat;\n\npublic class ConnectionGsonTest extends GsonBaseTest {\n    private static final String STRATEGY = \"src/test/resources/strategy.json\";\n    private static final String ENTERPRISE_CONNECTION = \"src/test/resources/enterprise_connection.json\";\n    private static final String DATABASE_CONNECTION = \"src/test/resources/db_connection.json\";\n    private static final String DATABASE_CONNECTION_WITH_COMPLEXITY = \"src/test/resources/db_connection_with_complexity.json\";\n    private static final String SOCIAL_CONNECTION = \"src/test/resources/social_connection.json\";\n\n    @Rule\n    public ExpectedException expectedException = ExpectedException.none();\n\n    @Before\n    public void setUp() {\n        gson = createGson();\n    }\n\n    @Test\n    public void shouldFailWithEmptyJson() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        buildConnectionsFrom(json(EMPTY_OBJECT));\n    }\n\n    @Test\n    public void shouldFailWithInvalidJson() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        buildConnectionsFrom(json(INVALID));\n    }\n\n    @Test\n    public void shouldRequireName() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        buildConnectionsFrom(new StringReader(\"{\\\"connections\\\": \\\"[]\\\"}\"));\n    }\n\n    @Test\n    public void shouldRequireConnections() throws Exception {\n        expectedException.expect(JsonParseException.class);\n        buildConnectionsFrom(new StringReader(\"{\\\"name\\\": \\\"auth0\\\"}\"));\n    }\n\n    @Test\n    public void shouldReturnStrategy() throws Exception {\n        final List<Connection> connections = buildConnectionsFrom(json(STRATEGY));\n        assertThat(connections, is(notNullValue()));\n        assertThat(connections, hasSize(1));\n        assertThat(connections.get(0).getName(), is(\"twitter\"));\n        assertThat(connections.get(0).getStrategy(), is(\"twitter\"));\n    }\n\n    @Test\n    public void shouldReturnConnectionName() throws Exception {\n        final List<Connection> connections = buildConnectionsFrom(json(STRATEGY));\n        assertThat(connections, hasSize(1));\n        assertThat(connections.get(0), is(notNullValue()));\n        assertThat(connections.get(0).getName(), is(\"twitter\"));\n    }\n\n    @Test\n    public void shouldReturnEnterpriseConnections() throws Exception {\n        final List<Connection> connections = buildConnectionsFrom(json(ENTERPRISE_CONNECTION));\n        assertThat(connections, hasSize(1));\n        assertThat(connections.get(0), is(notNullValue()));\n        assertThat(connections.get(0), hasType(AuthType.ENTERPRISE));\n        assertThat(connections.get(0).getName(), is(\"ad\"));\n        assertThat(connections.get(0).getDomainSet(), contains(\"auth10.com\"));\n        assertThat(connections.get(0).valueForKey(\"domain\", String.class), is(\"auth10.com\"));\n        assertThat((List<String>) connections.get(0).valueForKey(\"domain_aliases\", List.class), hasItem(\"auth10.com\"));\n    }\n\n    @Test\n    public void shouldReturnSocial() throws Exception {\n        final List<Connection> connections = buildConnectionsFrom(json(SOCIAL_CONNECTION));\n        assertThat(connections, hasSize(1));\n        assertThat(connections.get(0), is(notNullValue()));\n        assertThat(connections.get(0), hasType(AuthType.SOCIAL));\n        assertThat(connections.get(0).getName(), is(\"twitter\"));\n        assertThat(connections.get(0).getStrategy(), is(\"twitter\"));\n        assertThat(connections.get(0).valueForKey(\"scope\", String.class), is(\"public_profile\"));\n    }\n\n    @Test\n    public void shouldReturnDatabase() throws Exception {\n        final List<Connection> connections = buildConnectionsFrom(json(DATABASE_CONNECTION));\n        assertThat(connections.get(0), is(notNullValue()));\n        assertThat(connections.get(0), hasType(AuthType.DATABASE));\n        assertThat(connections.get(0).getName(), is(\"Username-Password-Authentication\"));\n        assertThat(connections.get(0).getStrategy(), is(\"auth0\"));\n        assertThat(connections.get(0).valueForKey(\"forgot_password_url\", String.class), is(\"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:Username-Password-Authentication\"));\n        assertThat(connections.get(0).valueForKey(\"signup_url\", String.class), is(\"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:Username-Password-Authentication\"));\n        assertThat(connections.get(0).showSignUp(), is(true));\n        assertThat(connections.get(0).showForgot(), is(true));\n        assertThat(connections.get(0).requiresUsername(), is(false));\n        PasswordComplexity passwordComplexity = connections.get(0).getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.GOOD));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldReturnDatabaseWithComplexity() throws Exception {\n        final List<Connection> connections = buildConnectionsFrom(json(DATABASE_CONNECTION_WITH_COMPLEXITY));\n        assertThat(connections.get(0), is(notNullValue()));\n        assertThat(connections.get(0), hasType(AuthType.DATABASE));\n        assertThat(connections.get(0).getName(), is(\"Username-Password-Authentication\"));\n        assertThat(connections.get(0).getStrategy(), is(\"auth0\"));\n        assertThat(connections.get(0).valueForKey(\"forgot_password_url\", String.class), is(\"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:Username-Password-Authentication\"));\n        assertThat(connections.get(0).valueForKey(\"signup_url\", String.class), is(\"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:Username-Password-Authentication\"));\n        assertThat(connections.get(0).showSignUp(), is(true));\n        assertThat(connections.get(0).showForgot(), is(true));\n        assertThat(connections.get(0).requiresUsername(), is(false));\n        PasswordComplexity passwordComplexity = connections.get(0).getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.FAIR));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(12));\n    }\n\n    private List<Connection> buildConnectionsFrom(Reader json) throws IOException {\n        final TypeToken<List<Connection>> strategyType = new TypeToken<List<Connection>>() {};\n        return pojoFrom(json, strategyType);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ConnectionMatcher.java",
    "content": "/*\n * ConnectionMatcher.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\n\nimport org.hamcrest.BaseMatcher;\nimport org.hamcrest.Description;\n\npublic class ConnectionMatcher<T extends BaseConnection> extends BaseMatcher<T> {\n\n    private final String strategy;\n    private final String name;\n    @AuthType\n    private final Integer type;\n\n    public ConnectionMatcher(String strategy, String name, @AuthType Integer type) {\n        this.strategy = strategy;\n        this.name = name;\n        this.type = type;\n    }\n\n    @Override\n    public boolean matches(Object o) {\n        if (!(o instanceof Connection)) {\n            return false;\n        }\n        Connection connection = (Connection) o;\n        if (type != null) {\n            return connection.getType() == type;\n        }\n        if (name != null && strategy != null) {\n            return strategy.equals(connection.getStrategy()) && name.equals(connection.getName());\n        }\n        if (name != null) {\n            return name.equals(connection.getName());\n        }\n        if (strategy != null) {\n            return strategy.equals(connection.getStrategy());\n        }\n        return false;\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        if (strategy != null) {\n            description.appendText(\"connection with strategy \").appendValue(this.strategy);\n        }\n        if (name != null) {\n            description.appendText(\"connection with name \").appendValue(this.name);\n        }\n    }\n\n    @Override\n    public void describeMismatch(Object item, Description description) {\n        if (!(item instanceof Connection)) {\n            super.describeMismatch(item, description);\n            return;\n        }\n\n        final Connection connection = (Connection) item;\n        description.appendText(\"strategy was \").appendValue(connection.getStrategy()).appendText(\" \");\n        description.appendText(\"connection was \").appendValue(connection.getName()).appendText(\" \");\n    }\n\n    public static ConnectionMatcher hasConnection(String strategy, String name) {\n        return new ConnectionMatcher(strategy, name, null);\n    }\n\n    public static ConnectionMatcher hasName(String name) {\n        return new ConnectionMatcher(null, name, null);\n    }\n\n    public static ConnectionMatcher hasStrategy(String name) {\n        return new ConnectionMatcher(name, null, null);\n    }\n\n    public static ConnectionMatcher hasType(@AuthType int type) {\n        return new ConnectionMatcher(null, null, type);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ConnectionTest.java",
    "content": "/*\n * StrategyTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.auth0.android.lock.internal.configuration.Connection.newConnectionFor;\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasType;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class ConnectionTest {\n\n    private static final String CONNECTION_NAME = \"Username-Password\";\n    private static final Object VALUE = \"value\";\n    private static final String KEY = \"key\";\n\n    @Rule\n    public ExpectedException expectedException = ExpectedException.none();\n\n    @Test\n    public void shouldBuildConnectionWithName() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        assertNotNull(connection);\n        assertThat(connection.getStrategy(), equalTo(\"strategy\"));\n        assertThat(connection.getName(), equalTo(CONNECTION_NAME));\n    }\n\n    @Test\n    public void shouldBuildConnectionWithValues() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        values.put(KEY, VALUE);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        assertThat(connection.valueForKey(KEY, String.class), is(VALUE));\n    }\n\n    @Test\n    public void shouldNotStoreNameInValues() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        assertThat(connection.valueForKey(\"name\", String.class), is(nullValue()));\n    }\n\n    @Test\n    public void shouldRaiseExceptionWhenNameIsNull() {\n        expectedException.expect(IllegalArgumentException.class);\n        Map<String, Object> values = null;\n        newConnectionFor(\"strategy\", values);\n    }\n\n    @Test\n    public void shouldReturnValueFromKey() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        values.put(KEY, VALUE);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        String value = connection.valueForKey(KEY, String.class);\n        assertThat(value, equalTo(VALUE));\n    }\n\n    @Test\n    public void shouldReturnNullValueFromMissingKey() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        String value = connection.valueForKey(KEY, String.class);\n        assertThat(value, is(nullValue()));\n    }\n\n    @Test\n    public void shouldReturnNullValueOnWrongClassType() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        values.put(KEY, \"3\");\n        Connection connection = newConnectionFor(\"strategy\", values);\n        Integer value = connection.valueForKey(KEY, Integer.class);\n        assertThat(value, is(nullValue()));\n    }\n\n    @Test\n    public void shouldReturnBooleanFromKey() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        values.put(KEY, true);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        boolean value = connection.booleanForKey(KEY);\n        assertThat(value, is(true));\n    }\n\n    @Test\n    public void shouldReturnBooleanFromMissingKey() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        boolean value = connection.booleanForKey(KEY);\n        assertThat(value, is(false));\n    }\n\n    @Test\n    public void shouldReturnBooleanFromNullValue() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", CONNECTION_NAME);\n        values.put(KEY, null);\n        Connection connection = newConnectionFor(\"strategy\", values);\n        boolean value = connection.booleanForKey(KEY);\n        assertThat(value, is(false));\n    }\n\n    @Test\n    public void shouldReturnUnknownSocial() {\n        final Connection unknownSocial = connectionForStrategy(\"this-strategy-does-not-exist\");\n        assertThat(unknownSocial, hasType(AuthType.SOCIAL));\n    }\n\n    @Test\n    public void shouldReturnSocial() {\n        final Connection amazon = connectionForStrategy(\"amazon\");\n        final Connection aol = connectionForStrategy(\"aol\");\n        final Connection baidu = connectionForStrategy(\"baidu\");\n        final Connection bitbucket = connectionForStrategy(\"bitbucket\");\n        final Connection box = connectionForStrategy(\"box\");\n        final Connection dropbox = connectionForStrategy(\"dropbox\");\n        final Connection dwolla = connectionForStrategy(\"dwolla\");\n        final Connection ebay = connectionForStrategy(\"ebay\");\n        final Connection evernote = connectionForStrategy(\"evernote\");\n        final Connection evernoteSandbox = connectionForStrategy(\"evernote-sandbox\");\n        final Connection exact = connectionForStrategy(\"exact\");\n        final Connection facebook = connectionForStrategy(\"facebook\");\n        final Connection fitbit = connectionForStrategy(\"fitbit\");\n        final Connection github = connectionForStrategy(\"github\");\n        final Connection googleOauth2 = connectionForStrategy(\"google-oauth2\");\n        final Connection instagram = connectionForStrategy(\"instagram\");\n        final Connection linkedin = connectionForStrategy(\"linkedin\");\n        final Connection miicard = connectionForStrategy(\"miicard\");\n        final Connection paypal = connectionForStrategy(\"paypal\");\n        final Connection paypalSandbox = connectionForStrategy(\"paypal-sandbox\");\n        final Connection planningcenter = connectionForStrategy(\"planningcenter\");\n        final Connection renren = connectionForStrategy(\"renren\");\n        final Connection salesforce = connectionForStrategy(\"salesforce\");\n        final Connection salesforceSandbox = connectionForStrategy(\"salesforce-sandbox\");\n        final Connection shopify = connectionForStrategy(\"shopify\");\n        final Connection soundcloud = connectionForStrategy(\"soundcloud\");\n        final Connection thecity = connectionForStrategy(\"thecity\");\n        final Connection thecitySandbox = connectionForStrategy(\"thecity-sandbox\");\n        final Connection thirtysevensignals = connectionForStrategy(\"thirtysevensignals\");\n        final Connection twitter = connectionForStrategy(\"twitter\");\n        final Connection vkontakte = connectionForStrategy(\"vkontakte\");\n        final Connection weibo = connectionForStrategy(\"weibo\");\n        final Connection windowslive = connectionForStrategy(\"windowslive\");\n        final Connection wordpress = connectionForStrategy(\"wordpress\");\n        final Connection yahoo = connectionForStrategy(\"yahoo\");\n        final Connection yammer = connectionForStrategy(\"yammer\");\n        final Connection yandex = connectionForStrategy(\"yandex\");\n\n        assertThat(amazon, hasType(AuthType.SOCIAL));\n        assertThat(aol, hasType(AuthType.SOCIAL));\n        assertThat(baidu, hasType(AuthType.SOCIAL));\n        assertThat(bitbucket, hasType(AuthType.SOCIAL));\n        assertThat(box, hasType(AuthType.SOCIAL));\n        assertThat(dropbox, hasType(AuthType.SOCIAL));\n        assertThat(dwolla, hasType(AuthType.SOCIAL));\n        assertThat(ebay, hasType(AuthType.SOCIAL));\n        assertThat(evernote, hasType(AuthType.SOCIAL));\n        assertThat(evernoteSandbox, hasType(AuthType.SOCIAL));\n        assertThat(exact, hasType(AuthType.SOCIAL));\n        assertThat(facebook, hasType(AuthType.SOCIAL));\n        assertThat(fitbit, hasType(AuthType.SOCIAL));\n        assertThat(github, hasType(AuthType.SOCIAL));\n        assertThat(googleOauth2, hasType(AuthType.SOCIAL));\n        assertThat(instagram, hasType(AuthType.SOCIAL));\n        assertThat(linkedin, hasType(AuthType.SOCIAL));\n        assertThat(miicard, hasType(AuthType.SOCIAL));\n        assertThat(paypal, hasType(AuthType.SOCIAL));\n        assertThat(paypalSandbox, hasType(AuthType.SOCIAL));\n        assertThat(planningcenter, hasType(AuthType.SOCIAL));\n        assertThat(renren, hasType(AuthType.SOCIAL));\n        assertThat(salesforce, hasType(AuthType.SOCIAL));\n        assertThat(salesforceSandbox, hasType(AuthType.SOCIAL));\n        assertThat(shopify, hasType(AuthType.SOCIAL));\n        assertThat(soundcloud, hasType(AuthType.SOCIAL));\n        assertThat(thecity, hasType(AuthType.SOCIAL));\n        assertThat(thecitySandbox, hasType(AuthType.SOCIAL));\n        assertThat(thirtysevensignals, hasType(AuthType.SOCIAL));\n        assertThat(twitter, hasType(AuthType.SOCIAL));\n        assertThat(vkontakte, hasType(AuthType.SOCIAL));\n        assertThat(weibo, hasType(AuthType.SOCIAL));\n        assertThat(windowslive, hasType(AuthType.SOCIAL));\n        assertThat(wordpress, hasType(AuthType.SOCIAL));\n        assertThat(yahoo, hasType(AuthType.SOCIAL));\n        assertThat(yammer, hasType(AuthType.SOCIAL));\n        assertThat(yandex, hasType(AuthType.SOCIAL));\n    }\n\n    @Test\n    public void shouldReturnValidDatabaseStrategy() {\n        final Connection unknownSocial = connectionForStrategy(\"auth0\");\n        assertThat(unknownSocial, hasType(AuthType.DATABASE));\n    }\n\n    @Test\n    public void shouldReturnValidPasswordlessStrategy() {\n        final Connection sms = connectionForStrategy(\"sms\");\n        final Connection email = connectionForStrategy(\"email\");\n\n        assertThat(sms, hasType(AuthType.PASSWORDLESS));\n        assertThat(email, hasType(AuthType.PASSWORDLESS));\n    }\n\n    @Test\n    public void shouldReturnEnterprise() {\n        final Connection ad = connectionForStrategy(\"ad\");\n        final Connection adfs = connectionForStrategy(\"adfs\");\n        final Connection auth0Adldap = connectionForStrategy(\"auth0-adldap\");\n        final Connection custom = connectionForStrategy(\"custom\");\n        final Connection googleApps = connectionForStrategy(\"google-apps\");\n        final Connection googleOpenid = connectionForStrategy(\"google-openid\");\n        final Connection ip = connectionForStrategy(\"ip\");\n        final Connection mscrm = connectionForStrategy(\"mscrm\");\n        final Connection office365 = connectionForStrategy(\"office365\");\n        final Connection pingfederate = connectionForStrategy(\"pingfederate\");\n        final Connection samlp = connectionForStrategy(\"samlp\");\n        final Connection sharepoint = connectionForStrategy(\"sharepoint\");\n        final Connection waad = connectionForStrategy(\"waad\");\n\n        assertThat(ad, hasType(AuthType.ENTERPRISE));\n        assertThat(ad.isActiveFlowEnabled(), is(true));\n        assertThat(adfs, hasType(AuthType.ENTERPRISE));\n        assertThat(adfs.isActiveFlowEnabled(), is(true));\n        assertThat(auth0Adldap, hasType(AuthType.ENTERPRISE));\n        assertThat(auth0Adldap.isActiveFlowEnabled(), is(false));\n        assertThat(custom, hasType(AuthType.ENTERPRISE));\n        assertThat(custom.isActiveFlowEnabled(), is(false));\n        assertThat(googleApps, hasType(AuthType.ENTERPRISE));\n        assertThat(googleApps.isActiveFlowEnabled(), is(false));\n        assertThat(googleOpenid, hasType(AuthType.ENTERPRISE));\n        assertThat(googleOpenid.isActiveFlowEnabled(), is(false));\n        assertThat(ip, hasType(AuthType.ENTERPRISE));\n        assertThat(ip.isActiveFlowEnabled(), is(false));\n        assertThat(mscrm, hasType(AuthType.ENTERPRISE));\n        assertThat(mscrm.isActiveFlowEnabled(), is(false));\n        assertThat(office365, hasType(AuthType.ENTERPRISE));\n        assertThat(office365.isActiveFlowEnabled(), is(false));\n        assertThat(pingfederate, hasType(AuthType.ENTERPRISE));\n        assertThat(pingfederate.isActiveFlowEnabled(), is(false));\n        assertThat(samlp, hasType(AuthType.ENTERPRISE));\n        assertThat(samlp.isActiveFlowEnabled(), is(false));\n        assertThat(sharepoint, hasType(AuthType.ENTERPRISE));\n        assertThat(sharepoint.isActiveFlowEnabled(), is(false));\n        assertThat(waad, hasType(AuthType.ENTERPRISE));\n        assertThat(waad.isActiveFlowEnabled(), is(true));\n    }\n\n    @Test\n    public void shouldDisableActiveFlowOnDemand() {\n        final Connection waad = connectionForStrategy(\"waad\");\n        assertThat(waad.isActiveFlowEnabled(), is(true));\n        waad.disableActiveFlow();\n        assertThat(waad.isActiveFlowEnabled(), is(false));\n    }\n\n    private Connection connectionForStrategy(String connectionName) {\n        Map<String, Object> map = new HashMap<>();\n        map.put(\"name\", \"my-connection\");\n        return newConnectionFor(connectionName, map);\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/DatabaseConnectionTest.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport org.junit.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasType;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\n\npublic class DatabaseConnectionTest {\n\n    @Test\n    public void shouldRequireUsername() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"requires_username\", true);\n        final DatabaseConnection connection = connectionFor(values);\n\n        assertTrue(connection.requiresUsername());\n    }\n\n    @Test\n    public void shouldNotRequireUsername() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"requires_username\", false);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertFalse(connection.requiresUsername());\n    }\n\n    @Test\n    public void shouldShowSignup() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"showSignup\", true);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertTrue(connection.showSignUp());\n    }\n\n    @Test\n    public void shouldNotShowSignup() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"showSignup\", false);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertFalse(connection.showSignUp());\n    }\n\n    @Test\n    public void shouldShowForgot() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"showForgot\", true);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertTrue(connection.showForgot());\n    }\n\n    @Test\n    public void shouldNotShowForgot() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"showForgot\", false);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertFalse(connection.showForgot());\n    }\n\n    @Test\n    public void shouldGetExcellentPasswordPolicy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"passwordPolicy\", \"excellent\");\n        DatabaseConnection connection = connectionFor(values);\n        PasswordComplexity passwordComplexity = connection.getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.EXCELLENT));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldGetFairPasswordPolicy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"passwordPolicy\", \"fair\");\n        DatabaseConnection connection = connectionFor(values);\n\n        PasswordComplexity passwordComplexity = connection.getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.FAIR));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldGetGoodPasswordPolicy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"passwordPolicy\", \"good\");\n        DatabaseConnection connection = connectionFor(values);\n\n        PasswordComplexity passwordComplexity = connection.getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.GOOD));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldGetLowPasswordPolicy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        values.put(\"passwordPolicy\", \"low\");\n        DatabaseConnection connection = connectionFor(values);\n\n        PasswordComplexity passwordComplexity = connection.getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.LOW));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldGetNonePasswordPolicy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        DatabaseConnection connection = connectionFor(values);\n\n        PasswordComplexity passwordComplexity = connection.getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.NONE));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(nullValue()));\n    }\n\n    @Test\n    public void shouldGetMinPasswordLength() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> options = new HashMap<>();\n        options.put(\"min_length\", 123);\n        values.put(\"password_complexity_options\", options);\n        DatabaseConnection connection = connectionFor(values);\n\n        PasswordComplexity passwordComplexity = connection.getPasswordComplexity();\n        assertThat(passwordComplexity.getPasswordPolicy(), is(PasswordStrength.NONE));\n        assertThat(passwordComplexity.getMinLengthOverride(), is(123));\n    }\n\n    @Test\n    public void shouldGetMinMaxUsernameLength() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        Map<String, Object> usernameValidation = new HashMap<>();\n        usernameValidation.put(\"min\", \"10\");\n        usernameValidation.put(\"max\", \"60\");\n        validation.put(\"username\", usernameValidation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(10));\n        assertThat(connection.getMaxUsernameLength(), is(60));\n    }\n\n    @Test\n    public void shouldGetNonEmptyMinMaxUsernameLengthIfMissingMinMaxValues() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        Map<String, Object> usernameValidation = new HashMap<>();\n        validation.put(\"username\", usernameValidation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(1));\n        assertThat(connection.getMaxUsernameLength(), is(Integer.MAX_VALUE));\n    }\n\n    @Test\n    public void shouldGetNonEmptyMinMaxUsernameLengthIfMissingUsernameValidation() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(1));\n        assertThat(connection.getMaxUsernameLength(), is(Integer.MAX_VALUE));\n    }\n\n    @Test\n    public void shouldGetNonEmptyMinMaxUsernameLengthIfMissingValidation() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(1));\n        assertThat(connection.getMaxUsernameLength(), is(Integer.MAX_VALUE));\n    }\n\n    @Test\n    public void shouldGetNonEmptyMinMaxUsernameLengthIfMaxIsLowerThanMin() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        Map<String, Object> usernameValidation = new HashMap<>();\n        usernameValidation.put(\"min\", 60);\n        usernameValidation.put(\"max\", 10);\n        validation.put(\"username\", usernameValidation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(1));\n        assertThat(connection.getMaxUsernameLength(), is(Integer.MAX_VALUE));\n    }\n\n    @Test\n    public void shouldGetNonEmptyMinMaxUsernameLengthIfMaxIsMissing() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        Map<String, Object> usernameValidation = new HashMap<>();\n        usernameValidation.put(\"min\", 10);\n        validation.put(\"username\", usernameValidation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(1));\n        assertThat(connection.getMaxUsernameLength(), is(Integer.MAX_VALUE));\n    }\n\n    @Test\n    public void shouldGetNonEmptyMinMaxUsernameLengthIfMinIsMissing() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        Map<String, Object> usernameValidation = new HashMap<>();\n        usernameValidation.put(\"max\", 60);\n        validation.put(\"username\", usernameValidation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertThat(connection.getMinUsernameLength(), is(1));\n        assertThat(connection.getMaxUsernameLength(), is(Integer.MAX_VALUE));\n    }\n\n    @Test\n    public void shouldBeCustomDatabaseIfMissingValidation() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        DatabaseConnection connection = connectionFor(values);\n\n        assertTrue(connection.isCustomDatabase());\n    }\n\n    @Test\n    public void shouldBeCustomDatabaseIfMissingUsernameValidation() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertTrue(connection.isCustomDatabase());\n    }\n\n    @Test\n    public void shouldNotBeCustomDatabaseIfContainsUsernameValidation() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        Map<String, Object> validation = new HashMap<>();\n        values.put(\"validation\", validation);\n        Map<String, Object> username = new HashMap<>();\n        validation.put(\"username\", username);\n        DatabaseConnection connection = connectionFor(values);\n\n        assertFalse(connection.isCustomDatabase());\n    }\n\n    @Test\n    public void shouldHaveName() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"name\");\n        DatabaseConnection connection = connectionFor(values);\n        assertThat(connection.getName(), is(\"name\"));\n    }\n\n    @Test\n    public void shouldHaveStrategy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"name\");\n        DatabaseConnection connection = connectionFor(values);\n        assertThat(connection.getStrategy(), is(\"auth0\"));\n    }\n\n    @Test\n    public void shouldBeDatabaseType() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"Username-Password-Authentication\");\n        DatabaseConnection connection = connectionFor(values);\n        assertThat(connection, hasType(AuthType.DATABASE));\n    }\n\n    private DatabaseConnection connectionFor(Map<String, Object> values) {\n        return Connection.newConnectionFor(\"auth0\", values);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/EnterpriseConnectionMatcherTest.java",
    "content": "/*\n * EnterpriseConnectionMatcherTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.auth0.android.lock.utils.EnterpriseConnectionMatcher;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.auth0.android.lock.internal.configuration.Connection.newConnectionFor;\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.junit.Assert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class EnterpriseConnectionMatcherTest {\n\n    private static final String ENTERPRISE_STRATEGY = \"adfs\";\n    private static final String NAME_KEY = \"name\";\n    private static final String DOMAIN_KEY = \"domain\";\n    private static final String DOMAIN_ALIASES_KEY = \"domain_aliases\";\n    private static final String SAMPLE_VALID_EMAIL = \"username@pep.com\";\n    private static final String SAMPLE_UNKNOWN_EMAIL = \"username@unknown.net\";\n    private static final String SAMPLE_INVALID_EMAIL = \"usern!p_epom\";\n    private static final String NAME_VALUE = \"default\";\n    private static final String DOMAIN_VALUE = \"pepe.com\";\n    private final List<String> DOMAIN_ALIASES_VALUE = new ArrayList<>(Arrays.asList(DOMAIN_VALUE, \"pep.com\", \"pe.pe\"));\n\n    private EnterpriseConnectionMatcher parser;\n\n    @Before\n    public void setUp() {\n        List<OAuthConnection> connections = new ArrayList<>();\n        OAuthConnection connection = createConnection();\n        connections.add(connection);\n        parser = new EnterpriseConnectionMatcher(connections);\n    }\n\n    @Test\n    public void shouldExtractTheUsername() {\n        String username = parser.extractUsername(SAMPLE_VALID_EMAIL);\n        assertThat(username, is(equalTo(\"username\")));\n    }\n\n    @Test\n    public void shouldParseTheConnection() {\n        OAuthConnection connection = parser.parse(SAMPLE_VALID_EMAIL);\n        assertThat(connection, is(notNullValue()));\n        assertThat(connection.getName(), is(equalTo(NAME_VALUE)));\n        assertThat(connection.valueForKey(DOMAIN_KEY, String.class), is(equalTo(DOMAIN_VALUE)));\n        assertThat((List<String>) connection.valueForKey(DOMAIN_ALIASES_KEY, List.class),\n                is(equalTo(DOMAIN_ALIASES_VALUE)));\n    }\n\n    @Test\n    public void shouldNotFindAnUnknownDomain() {\n        OAuthConnection connection = parser.parse(SAMPLE_UNKNOWN_EMAIL);\n        assertThat(connection, is(nullValue()));\n    }\n\n    @Test\n    public void shouldReturnTheMainDomain() {\n        OAuthConnection connection = parser.parse(SAMPLE_VALID_EMAIL);\n        assertThat(parser.domainForConnection(connection), is(equalTo(DOMAIN_VALUE)));\n    }\n\n    @Test\n    public void shouldFailToGetConnectionIfNotValidDomain() {\n        OAuthConnection connection = parser.parse(SAMPLE_INVALID_EMAIL);\n        assertThat(connection, is(nullValue()));\n    }\n\n    @Test\n    public void shouldFailToGetConnectionIfInstantiatedWithEmptyStrategies() {\n        EnterpriseConnectionMatcher parser = new EnterpriseConnectionMatcher(new ArrayList<OAuthConnection>());\n        OAuthConnection connection = parser.parse(SAMPLE_VALID_EMAIL);\n        assertThat(connection, is(nullValue()));\n    }\n\n    private Connection createConnection() {\n        Map<String, Object> map = new HashMap<>();\n        map.put(NAME_KEY, NAME_VALUE);\n        map.put(DOMAIN_KEY, DOMAIN_VALUE);\n        map.put(DOMAIN_ALIASES_KEY, DOMAIN_ALIASES_VALUE);\n\n        return newConnectionFor(ENTERPRISE_STRATEGY, map);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/GsonBaseTest.java",
    "content": "/*\n * GsonBaseTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\n\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.io.Reader;\n\npublic abstract class GsonBaseTest {\n\n    static final String EMPTY_OBJECT = \"src/test/resources/empty_object.json\";\n    static final String INVALID = \"src/test/resources/invalid.json\";\n\n    Gson gson;\n\n    <T> T pojoFrom(Reader json, Class<T> clazz) throws IOException {\n        return gson.getAdapter(clazz).fromJson(json);\n    }\n\n    <T> T pojoFrom(Reader json, TypeToken<T> type) throws IOException {\n        return gson.getAdapter(type).fromJson(json);\n    }\n\n    FileReader json(String name) throws FileNotFoundException {\n        return new FileReader(name);\n    }\n\n    public Gson createGson() {\n        return ApplicationFetcher.createGson();\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/OAuthConnectionTest.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport org.junit.Test;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasType;\nimport static org.hamcrest.Matchers.hasItem;\nimport static org.hamcrest.Matchers.hasItems;\nimport static org.hamcrest.Matchers.is;\nimport static org.junit.Assert.assertThat;\n\npublic class OAuthConnectionTest {\n\n    @Test\n    public void shouldHaveName() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"name\");\n        OAuthConnection connection = Connection.newConnectionFor(\"strategy\", values);\n        assertThat(connection.getName(), is(\"name\"));\n    }\n\n    @Test\n    public void shouldHaveStrategy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"name\");\n        OAuthConnection connection = Connection.newConnectionFor(\"strategy\", values);\n        assertThat(connection.getStrategy(), is(\"strategy\"));\n    }\n\n    @Test\n    public void shouldBeSocialType() {\n        OAuthConnection connection = connectionForStrategy(\"facebook\");\n        assertThat(connection, hasType(AuthType.SOCIAL));\n    }\n\n    @Test\n    public void shouldBeEnterpriseType() {\n        OAuthConnection connection = connectionForStrategy(\"ad\");\n        assertThat(connection, hasType(AuthType.ENTERPRISE));\n    }\n\n    @Test\n    public void shouldReturnDomainNameInSet() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"ad\");\n        values.put(\"domain\", \"domain.com\");\n        OAuthConnection connection = Connection.newConnectionFor(\"ad\", values);\n        assertThat(connection.getDomainSet(), hasItem(\"domain.com\"));\n    }\n\n    @Test\n    public void shouldReturnAllDomainNamesAsSet() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"ad\");\n        values.put(\"domain\", \"domain.com\");\n        values.put(\"domain_aliases\", Arrays.asList(\"domain2.com\", \"domain3.com\"));\n        OAuthConnection connection = Connection.newConnectionFor(\"ad\", values);\n        assertThat(connection.getDomainSet(), hasItems(\"domain.com\", \"domain2.com\", \"domain3.com\"));\n    }\n\n    @Test\n    public void shouldReturnEmptySetWithNoDomainName() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"ad\");\n        OAuthConnection connection = Connection.newConnectionFor(\"ad\", values);\n        assertThat(connection.getDomainSet().isEmpty(), is(true));\n    }\n\n    @Test\n    public void shouldHaveResourceOwnerEnabledIfADFS() {\n        OAuthConnection connection = connectionForStrategy(\"adfs\");\n        assertThat(connection.isActiveFlowEnabled(), is(true));\n    }\n\n    @Test\n    public void shouldHaveResourceOwnerEnabledIfWaad() {\n        OAuthConnection connection = connectionForStrategy(\"waad\");\n        assertThat(connection.isActiveFlowEnabled(), is(true));\n    }\n\n    @Test\n    public void shouldHaveResourceOwnerEnabledIfActiveDirectory() {\n        OAuthConnection connection = connectionForStrategy(\"ad\");\n        assertThat(connection.isActiveFlowEnabled(), is(true));\n    }\n\n    @Test\n    public void shouldNotHaveResourceOwnerEnabledByDefault() {\n        OAuthConnection connection = connectionForStrategy(\"strategy\");\n        assertThat(connection.isActiveFlowEnabled(), is(false));\n    }\n\n    @Test\n    public void shouldNotHaveResourceOwnerEnabledIfNotADFSWaadOrActiveDirectory() {\n        OAuthConnection connectionAuth0LDAP = connectionForStrategy(\"auth0-adldap\");\n        OAuthConnection connectionCustom = connectionForStrategy(\"custom\");\n        OAuthConnection connectionGoogleApps = connectionForStrategy(\"google-apps\");\n        OAuthConnection connectionGoogleOpenId = connectionForStrategy(\"google-openid\");\n        OAuthConnection connectionIp = connectionForStrategy(\"ip\");\n        OAuthConnection connectionOffice365 = connectionForStrategy(\"mscrm\");\n        OAuthConnection connectionPingFederate = connectionForStrategy(\"pingfederate\");\n        OAuthConnection connectionSAMLP = connectionForStrategy(\"samlp\");\n        OAuthConnection connectionSharepoint = connectionForStrategy(\"sharepoint\");\n\n        assertThat(connectionAuth0LDAP.isActiveFlowEnabled(), is(false));\n        assertThat(connectionCustom.isActiveFlowEnabled(), is(false));\n        assertThat(connectionGoogleApps.isActiveFlowEnabled(), is(false));\n        assertThat(connectionGoogleOpenId.isActiveFlowEnabled(), is(false));\n        assertThat(connectionIp.isActiveFlowEnabled(), is(false));\n        assertThat(connectionOffice365.isActiveFlowEnabled(), is(false));\n        assertThat(connectionPingFederate.isActiveFlowEnabled(), is(false));\n        assertThat(connectionSAMLP.isActiveFlowEnabled(), is(false));\n        assertThat(connectionSharepoint.isActiveFlowEnabled(), is(false));\n    }\n\n    private OAuthConnection connectionForStrategy(String name) {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", name);\n        return Connection.newConnectionFor(name, values);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/OptionsTest.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport android.os.Build;\nimport android.os.Parcel;\n\nimport com.auth0.android.Auth0;\nimport com.auth0.android.authentication.AuthenticationAPIClient;\nimport com.auth0.android.lock.InitialScreen;\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.UsernameStyle;\nimport com.auth0.android.lock.utils.CustomField;\nimport com.auth0.android.lock.utils.CustomField.FieldType;\nimport com.auth0.android.lock.utils.SignUpField;\nimport com.auth0.android.provider.CustomTabsOptions;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\n\nimport static org.hamcrest.Matchers.containsInAnyOrder;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.hasSize;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.not;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.hamcrest.Matchers.nullValue;\nimport static org.hamcrest.collection.IsMapContaining.hasEntry;\nimport static org.junit.Assert.assertThat;\n\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class OptionsTest {\n\n    private static final String CLIENT_ID = \"CLIENT_ID\";\n    private static final String DOMAIN = \"https://my-domain.auth0.com\";\n    private static final String CONFIG_DOMAIN = \"https://my-cdn.auth0.com\";\n    private static final String SCOPE_KEY = \"scope\";\n    private static final String DEVICE_KEY = \"device\";\n    private static final String SCOPE_OPENID_OFFLINE_ACCESS = \"openid offline_access\";\n\n    private Options options;\n\n    @Rule\n    public ExpectedException exception = ExpectedException.none();\n\n    @Before\n    public void setUp() {\n        options = new Options();\n        options.setAccount(new Auth0(CLIENT_ID, DOMAIN, CONFIG_DOMAIN));\n    }\n\n    @Test\n    public void shouldSetAccount() {\n        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN, CONFIG_DOMAIN);\n        Options options = new Options();\n        options.setAccount(auth0);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getAccount().getClientId(), is(equalTo(parceledOptions.getAccount().getClientId())));\n        assertThat(options.getAccount().getConfigurationUrl(), is(equalTo(parceledOptions.getAccount().getConfigurationUrl())));\n        assertThat(options.getAccount().getDomainUrl(), is(equalTo(parceledOptions.getAccount().getDomainUrl())));\n    }\n\n    @Test\n    public void shouldSetMustAcceptTerms() {\n        options.setMustAcceptTerms(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.mustAcceptTerms(), is(true));\n        assertThat(options.mustAcceptTerms(), is(equalTo(parceledOptions.mustAcceptTerms())));\n    }\n\n    @Test\n    public void shouldSetShowTerms() {\n        options.setShowTerms(false);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.showTerms(), is(false));\n        assertThat(options.showTerms(), is(equalTo(parceledOptions.showTerms())));\n    }\n\n    @Test\n    public void shouldSetPrivacyPolicyURL() {\n        options.setPrivacyURL(\"https://valid.url/privacy\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getPrivacyURL(), is(\"https://valid.url/privacy\"));\n        assertThat(options.getPrivacyURL(), is(equalTo(parceledOptions.getPrivacyURL())));\n    }\n\n    @Test\n    public void shouldThrowWhenSettingPrivacyPolicyURLWithInvalidURL() {\n        exception.expect(IllegalArgumentException.class);\n        exception.expectMessage(\"The given Policy Privacy URL doesn't have a valid URL format: an-invalid/url\");\n        options.setPrivacyURL(\"an-invalid/url\");\n    }\n\n    @Test\n    public void shouldSetTermsOfServiceURL() {\n        options.setTermsURL(\"https://valid.url/terms\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getTermsURL(), is(\"https://valid.url/terms\"));\n        assertThat(options.getTermsURL(), is(equalTo(parceledOptions.getTermsURL())));\n    }\n\n    @Test\n    public void shouldThrowWhenSettingTermsOfServiceURLWithInvalidURL() {\n        exception.expect(IllegalArgumentException.class);\n        exception.expectMessage(\"The given Terms of Service URL doesn't have a valid URL format: an-invalid/url\");\n        options.setTermsURL(\"an-invalid/url\");\n    }\n\n    @Test\n    public void shouldSetSupportURL() {\n        options.setSupportURL(\"https://valid.url/support\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getSupportURL(), is(\"https://valid.url/support\"));\n        assertThat(options.getSupportURL(), is(equalTo(parceledOptions.getSupportURL())));\n    }\n\n    @Test\n    public void shouldThrowWhenSettingSupportURLWithInvalidURL() {\n        exception.expect(IllegalArgumentException.class);\n        exception.expectMessage(\"The given Support URL doesn't have a valid URL format: an-invalid/url\");\n        options.setSupportURL(\"an-invalid/url\");\n    }\n\n    @Test\n    public void shouldUseLabeledSubmitButton() {\n        options.setUseLabeledSubmitButton(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.useLabeledSubmitButton(), is(true));\n        assertThat(options.useLabeledSubmitButton(), is(equalTo(parceledOptions.useLabeledSubmitButton())));\n    }\n\n    @Test\n    public void shouldHideMainScreenTitle() {\n        options.setHideMainScreenTitle(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.hideMainScreenTitle(), is(true));\n        assertThat(options.hideMainScreenTitle(), is(equalTo(parceledOptions.hideMainScreenTitle())));\n    }\n\n\n    @Test\n    public void shouldSetPasswordlessAutoSubmit() {\n        options.setRememberLastPasswordlessLogin(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.rememberLastPasswordlessAccount(), is(true));\n        assertThat(options.rememberLastPasswordlessAccount(), is(equalTo(parceledOptions.rememberLastPasswordlessAccount())));\n    }\n\n    @Test\n    public void shouldBeClosable() {\n        options.setClosable(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.isClosable(), is(equalTo(parceledOptions.isClosable())));\n        assertThat(options.isClosable(), is(true));\n    }\n\n    @Test\n    public void shouldNotLoginAfterSignUp() {\n        options.setLoginAfterSignUp(false);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.loginAfterSignUp(), is(equalTo(parceledOptions.loginAfterSignUp())));\n        assertThat(options.loginAfterSignUp(), is(false));\n    }\n\n    @Test\n    public void shouldSetVisibleSignUpFieldsThreshold() {\n        options.setVisibleSignUpFieldsThreshold(9);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.visibleSignUpFieldsThreshold(), is(equalTo(parceledOptions.visibleSignUpFieldsThreshold())));\n        assertThat(options.visibleSignUpFieldsThreshold(), is(9));\n    }\n\n    @Test\n    public void shouldChangeInitialScreenToLogIn() {\n        options.setInitialScreen(InitialScreen.LOG_IN);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.initialScreen(), is(equalTo(parceledOptions.initialScreen())));\n        assertThat(options.initialScreen(), is(InitialScreen.LOG_IN));\n    }\n\n    @Test\n    public void shouldUseDefaultVisibleSignUpFieldThreshold() {\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.visibleSignUpFieldsThreshold(), is(equalTo(parceledOptions.visibleSignUpFieldsThreshold())));\n        assertThat(options.visibleSignUpFieldsThreshold(), is(2));\n    }\n\n    @Test\n    public void shouldChangeInitialScreenToSignUp() {\n        options.setInitialScreen(InitialScreen.SIGN_UP);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.initialScreen(), is(equalTo(parceledOptions.initialScreen())));\n        assertThat(options.initialScreen(), is(InitialScreen.SIGN_UP));\n    }\n\n    @Test\n    public void shouldChangeInitialScreenToForgotPassword() {\n        options.setInitialScreen(InitialScreen.FORGOT_PASSWORD);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.initialScreen(), is(equalTo(parceledOptions.initialScreen())));\n        assertThat(options.initialScreen(), is(InitialScreen.FORGOT_PASSWORD));\n    }\n\n    @Test\n    public void shouldUseEmailUsernameStyle() {\n        options.setUsernameStyle(UsernameStyle.EMAIL);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.usernameStyle(), is(equalTo(parceledOptions.usernameStyle())));\n        assertThat(options.usernameStyle(), is(UsernameStyle.EMAIL));\n    }\n\n    @Test\n    public void shouldUseUsernameUsernameStyle() {\n        options.setUsernameStyle(UsernameStyle.USERNAME);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.usernameStyle(), is(equalTo(parceledOptions.usernameStyle())));\n        assertThat(options.usernameStyle(), is(UsernameStyle.USERNAME));\n    }\n\n    @Test\n    public void shouldUseDefaultUsernameStyle() {\n        options.setUsernameStyle(UsernameStyle.DEFAULT);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.usernameStyle(), is(equalTo(parceledOptions.usernameStyle())));\n        assertThat(options.usernameStyle(), is(UsernameStyle.DEFAULT));\n    }\n\n    @Test\n    public void shouldAllowLogIn() {\n        options.setAllowLogIn(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.allowLogIn(), is(equalTo(parceledOptions.allowLogIn())));\n        assertThat(options.allowLogIn(), is(true));\n    }\n\n    @Test\n    public void shouldAllowSignUp() {\n        options.setAllowSignUp(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.allowSignUp(), is(equalTo(parceledOptions.allowSignUp())));\n        assertThat(options.allowSignUp(), is(true));\n    }\n\n    @Test\n    public void shouldAllowForgotPassword() {\n        options.setAllowForgotPassword(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.allowForgotPassword(), is(equalTo(parceledOptions.allowForgotPassword())));\n        assertThat(options.allowForgotPassword(), is(true));\n    }\n\n    @Test\n    public void shouldAllowShowPassword() {\n        options.setAllowShowPassword(true);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.allowShowPassword(), is(equalTo(parceledOptions.allowShowPassword())));\n        assertThat(options.allowShowPassword(), is(true));\n    }\n\n    @Test\n    public void shouldUsePasswordlessCode() {\n        options.setUseCodePasswordless(false);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.useCodePasswordless(), is(equalTo(parceledOptions.useCodePasswordless())));\n        assertThat(options.useCodePasswordless(), is(false));\n    }\n\n    @Test\n    public void shouldHavePasswordlessCodeByDefault() {\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.useCodePasswordless(), is(equalTo(parceledOptions.useCodePasswordless())));\n        assertThat(options.useCodePasswordless(), is(true));\n        assertThat(parceledOptions.useCodePasswordless(), is(true));\n    }\n\n    @Test\n    public void shouldSetDefaultDatabaseConnection() {\n        options.useDatabaseConnection(\"default_db_connection\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getDefaultDatabaseConnection(), is(equalTo(parceledOptions.getDefaultDatabaseConnection())));\n        assertThat(options.getDefaultDatabaseConnection(), is(\"default_db_connection\"));\n    }\n\n    @Test\n    public void shouldSetDefaultTheme() {\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getTheme(), is(notNullValue()));\n        assertThat(parceledOptions.getTheme(), is(notNullValue()));\n    }\n\n\n    @Test\n    public void shouldSetCustomTheme() {\n        Theme theme = Theme.newBuilder()\n                .withHeaderTitle(R.string.com_auth0_lock_header_title)\n                .withHeaderLogo(R.drawable.com_auth0_lock_header_logo)\n                .withHeaderColor(R.color.com_auth0_lock_social_unknown)\n                .withHeaderTitleColor(R.color.com_auth0_lock_social_unknown)\n                .withPrimaryColor(R.color.com_auth0_lock_social_unknown)\n                .withDarkPrimaryColor(R.color.com_auth0_lock_social_unknown)\n                .build();\n        options.withTheme(theme);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getTheme().getCustomDarkPrimaryColorRes(), is(equalTo(parceledOptions.getTheme().getCustomDarkPrimaryColorRes())));\n        assertThat(options.getTheme().getCustomPrimaryColorRes(), is(equalTo(parceledOptions.getTheme().getCustomPrimaryColorRes())));\n        assertThat(options.getTheme().getCustomHeaderColorRes(), is(equalTo(parceledOptions.getTheme().getCustomHeaderColorRes())));\n        assertThat(options.getTheme().getCustomHeaderLogoRes(), is(equalTo(parceledOptions.getTheme().getCustomHeaderLogoRes())));\n        assertThat(options.getTheme().getCustomHeaderTitleRes(), is(equalTo(parceledOptions.getTheme().getCustomHeaderTitleRes())));\n        assertThat(options.getTheme().getCustomHeaderTitleColorRes(), is(equalTo(parceledOptions.getTheme().getCustomHeaderTitleColorRes())));\n    }\n\n    @Test\n    public void shouldSetConnections() {\n        options.setConnections(createConnections(\"twitter\", \"facebook\"));\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getConnections(), is(containsInAnyOrder(\"twitter\", \"facebook\")));\n        assertThat(options.getConnections(), is(equalTo(parceledOptions.getConnections())));\n    }\n\n\n    @Test\n    public void shouldSetEnterpriseConnectionsUsingWebForm() {\n        options.setEnterpriseConnectionsUsingWebForm(createEnterpriseConnectionsUsingWebForm(\"myAD\"));\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getEnterpriseConnectionsUsingWebForm(), containsInAnyOrder(\"myAD\"));\n        assertThat(options.getEnterpriseConnectionsUsingWebForm(), is(equalTo(parceledOptions.getEnterpriseConnectionsUsingWebForm())));\n    }\n\n    @Test\n    public void shouldSetAuthenticationParameters() {\n        options.setAuthenticationParameters(createAuthenticationParameters(654123));\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getAuthenticationParameters(), is(equalTo(parceledOptions.getAuthenticationParameters())));\n    }\n\n    @Test\n    public void shouldSetConnectionScope() {\n        options.withConnectionScope(\"some_connection\", \"scope for some connection\");\n        options.withConnectionScope(\"other_connection\", \"scope for other connection\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getConnectionsScope(), is(equalTo(parceledOptions.getConnectionsScope())));\n        assertThat(options.getConnectionsScope().size(), is(2));\n        assertThat(options.getConnectionsScope(), hasEntry(\"some_connection\", \"scope for some connection\"));\n        assertThat(options.getConnectionsScope(), hasEntry(\"other_connection\", \"scope for other connection\"));\n        assertThat(parceledOptions.getConnectionsScope().size(), is(2));\n        assertThat(parceledOptions.getConnectionsScope(), hasEntry(\"some_connection\", \"scope for some connection\"));\n        assertThat(parceledOptions.getConnectionsScope(), hasEntry(\"other_connection\", \"scope for other connection\"));\n    }\n\n    @Test\n    public void shouldSetScope() {\n        options.withScope(\"some connection scope\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getScope(), is(equalTo(\"some connection scope\")));\n        assertThat(parceledOptions.getScope(), is(\"some connection scope\"));\n    }\n\n    @Test\n    public void shouldSetAudience() {\n        options.withAudience(\"https://domain.auth0.com/users\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getAudience(), is(equalTo(\"https://domain.auth0.com/users\")));\n        assertThat(parceledOptions.getAudience(), is(\"https://domain.auth0.com/users\"));\n    }\n\n    @Test\n    public void shouldSetScheme() {\n        options.withScheme(\"auth0\");\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getScheme(), is(equalTo(\"auth0\")));\n        assertThat(parceledOptions.getScheme(), is(\"auth0\"));\n    }\n\n    @Test\n    public void shouldSetCustomTabsOptions() {\n        CustomTabsOptions ctOptions = CustomTabsOptions.newBuilder().build();\n        options.withCustomTabsOptions(ctOptions);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getCustomTabsOptions(), is(equalTo(ctOptions)));\n        assertThat(parceledOptions.getCustomTabsOptions(), is(notNullValue()));\n    }\n\n    @SuppressWarnings(\"ResourceType\")\n    @Test\n    public void shouldAddAuthStyles() {\n        options.withAuthStyle(\"firstConnection\", 1);\n        options.withAuthStyle(\"secondConnection\", 2);\n        options.withAuthStyle(\"thirdConnection\", 3);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getAuthStyles().size(), is(3));\n        assertThat(options.getAuthStyles(), is(hasEntry(\"firstConnection\", 1)));\n        assertThat(options.getAuthStyles(), is(hasEntry(\"secondConnection\", 2)));\n        assertThat(options.getAuthStyles(), is(hasEntry(\"thirdConnection\", 3)));\n        assertThat(parceledOptions.getAuthStyles().size(), is(3));\n        assertThat(parceledOptions.getAuthStyles(), is(hasEntry(\"firstConnection\", 1)));\n        assertThat(parceledOptions.getAuthStyles(), is(hasEntry(\"secondConnection\", 2)));\n        assertThat(parceledOptions.getAuthStyles(), is(hasEntry(\"thirdConnection\", 3)));\n    }\n\n    @Test\n    public void shouldSetCustomFields() {\n        options.setSignUpFields(createCustomFields());\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(parceledOptions.getSignUpFields(), hasSize(options.getSignUpFields().size()));\n        for (int i = 0; i < options.getSignUpFields().size(); i++) {\n            SignUpField fieldA = options.getSignUpFields().get(i);\n            SignUpField fieldB = parceledOptions.getSignUpFields().get(i);\n            assertThat(fieldA.getKey(), is(equalTo(fieldB.getKey())));\n        }\n    }\n\n    @Test\n    public void shouldGetEmptyCustomFieldsIfNotSet() {\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getSignUpFields(), is(notNullValue()));\n        assertThat(options.getSignUpFields().size(), is(0));\n        assertThat(parceledOptions.getSignUpFields(), is(notNullValue()));\n        assertThat(parceledOptions.getSignUpFields().size(), is(0));\n    }\n\n    @Test\n    public void shouldSetDeviceParameterIfUsingOfflineAccessScope() {\n        HashMap<String, String> params = new HashMap<>();\n        params.put(SCOPE_KEY, SCOPE_OPENID_OFFLINE_ACCESS);\n        options.setAuthenticationParameters(params);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getAuthenticationParameters().get(DEVICE_KEY), is(notNullValue()));\n        assertThat((String) options.getAuthenticationParameters().get(DEVICE_KEY), is(Build.MODEL));\n        assertThat(parceledOptions.getAuthenticationParameters().get(DEVICE_KEY), is(notNullValue()));\n        assertThat((String) parceledOptions.getAuthenticationParameters().get(DEVICE_KEY), is(Build.MODEL));\n    }\n\n    @Test\n    public void shouldNotOverrideDeviceParameterIfAlreadySet() {\n        HashMap<String, String> params = new HashMap<>();\n        params.put(SCOPE_KEY, SCOPE_OPENID_OFFLINE_ACCESS);\n        params.put(DEVICE_KEY, \"my_device 2016\");\n        options.setAuthenticationParameters(params);\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.getAuthenticationParameters().get(DEVICE_KEY), is(notNullValue()));\n        assertThat((String) options.getAuthenticationParameters().get(DEVICE_KEY), is(not(Build.MODEL)));\n        assertThat(parceledOptions.getAuthenticationParameters().get(DEVICE_KEY), is(notNullValue()));\n        assertThat((String) parceledOptions.getAuthenticationParameters().get(DEVICE_KEY), is(not(Build.MODEL)));\n    }\n\n    @Test\n    public void shouldSetDefaultValues() {\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options, is(not(parceledOptions))); //assure correct Parcelable object testing\n        assertThat(options.allowLogIn(), is(true));\n        assertThat(options.allowSignUp(), is(true));\n        assertThat(options.allowForgotPassword(), is(true));\n        assertThat(options.allowShowPassword(), is(true));\n        assertThat(options.loginAfterSignUp(), is(true));\n        assertThat(options.useCodePasswordless(), is(true));\n        assertThat(options.mustAcceptTerms(), is(false));\n        assertThat(options.showTerms(), is(true));\n        assertThat(options.useLabeledSubmitButton(), is(true));\n        assertThat(options.hideMainScreenTitle(), is(false));\n        assertThat(options.rememberLastPasswordlessAccount(), is(false));\n        assertThat(options.getScope(), is(nullValue()));\n        assertThat(options.getAudience(), is(nullValue()));\n        assertThat(options.getScheme(), is(nullValue()));\n        assertThat(options.getCustomTabsOptions(), is(nullValue()));\n        assertThat(options.usernameStyle(), is(equalTo(UsernameStyle.DEFAULT)));\n        assertThat(options.visibleSignUpFieldsThreshold(), is(equalTo(2)));\n        assertThat(options.getTheme(), is(notNullValue()));\n        assertThat(options.getAuthenticationParameters(), is(notNullValue()));\n        assertThat(options.getAuthStyles(), is(notNullValue()));\n    }\n\n\n    @Test\n    public void shouldSetAllTrueFields() {\n        options.setUsernameStyle(UsernameStyle.EMAIL);\n        options.setInitialScreen(InitialScreen.LOG_IN);\n        options.setAllowLogIn(true);\n        options.setAllowSignUp(true);\n        options.setAllowForgotPassword(true);\n        options.setAllowShowPassword(true);\n        options.setClosable(true);\n        options.setMustAcceptTerms(true);\n        options.setShowTerms(true);\n        options.setLoginAfterSignUp(true);\n        options.setUseLabeledSubmitButton(true);\n        options.setHideMainScreenTitle(true);\n        options.setRememberLastPasswordlessLogin(true);\n\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.mustAcceptTerms(), is(equalTo(parceledOptions.mustAcceptTerms())));\n        assertThat(options.showTerms(), is(equalTo(parceledOptions.showTerms())));\n        assertThat(options.isClosable(), is(equalTo(parceledOptions.isClosable())));\n        assertThat(options.usernameStyle(), is(equalTo(parceledOptions.usernameStyle())));\n        assertThat(options.initialScreen(), is(equalTo(parceledOptions.initialScreen())));\n        assertThat(options.allowLogIn(), is(equalTo(parceledOptions.allowLogIn())));\n        assertThat(options.allowSignUp(), is(equalTo(parceledOptions.allowSignUp())));\n        assertThat(options.allowForgotPassword(), is(equalTo(parceledOptions.allowForgotPassword())));\n        assertThat(options.allowShowPassword(), is(equalTo(parceledOptions.allowShowPassword())));\n        assertThat(options.loginAfterSignUp(), is(equalTo(parceledOptions.loginAfterSignUp())));\n        assertThat(options.useLabeledSubmitButton(), is(equalTo(parceledOptions.useLabeledSubmitButton())));\n        assertThat(options.hideMainScreenTitle(), is(equalTo(parceledOptions.hideMainScreenTitle())));\n        assertThat(options.rememberLastPasswordlessAccount(), is(equalTo(parceledOptions.rememberLastPasswordlessAccount())));\n    }\n\n    @Test\n    public void shouldSetAllFalseFields() {\n        options.setClosable(false);\n        options.setUsernameStyle(UsernameStyle.USERNAME);\n        options.setInitialScreen(InitialScreen.SIGN_UP);\n        options.setAllowLogIn(false);\n        options.setAllowSignUp(false);\n        options.setAllowForgotPassword(false);\n        options.setAllowShowPassword(false);\n        options.setMustAcceptTerms(false);\n        options.setShowTerms(false);\n        options.setLoginAfterSignUp(false);\n        options.setUseLabeledSubmitButton(false);\n        options.setHideMainScreenTitle(false);\n        options.setRememberLastPasswordlessLogin(false);\n\n\n        Parcel parcel = Parcel.obtain();\n        options.writeToParcel(parcel, 0);\n        parcel.setDataPosition(0);\n\n        Options parceledOptions = Options.CREATOR.createFromParcel(parcel);\n        assertThat(options.mustAcceptTerms(), is(equalTo(parceledOptions.mustAcceptTerms())));\n        assertThat(options.showTerms(), is(equalTo(parceledOptions.showTerms())));\n        assertThat(options.isClosable(), is(equalTo(parceledOptions.isClosable())));\n        assertThat(options.usernameStyle(), is(equalTo(parceledOptions.usernameStyle())));\n        assertThat(options.initialScreen(), is(equalTo(parceledOptions.initialScreen())));\n        assertThat(options.allowLogIn(), is(equalTo(parceledOptions.allowLogIn())));\n        assertThat(options.allowSignUp(), is(equalTo(parceledOptions.allowSignUp())));\n        assertThat(options.allowForgotPassword(), is(equalTo(parceledOptions.allowForgotPassword())));\n        assertThat(options.allowShowPassword(), is(equalTo(parceledOptions.allowShowPassword())));\n        assertThat(options.loginAfterSignUp(), is(equalTo(parceledOptions.loginAfterSignUp())));\n        assertThat(options.useLabeledSubmitButton(), is(equalTo(parceledOptions.useLabeledSubmitButton())));\n        assertThat(options.hideMainScreenTitle(), is(equalTo(parceledOptions.hideMainScreenTitle())));\n        assertThat(options.rememberLastPasswordlessAccount(), is(equalTo(parceledOptions.rememberLastPasswordlessAccount())));\n    }\n\n\n    private HashMap<String, String> createAuthenticationParameters(int innerIntParam) {\n        HashMap<String, String> authenticationParameters = new HashMap<>();\n        authenticationParameters.put(\"key_param_string\", \"value_param_string\");\n        authenticationParameters.put(\"key_param_int\", \"123456\");\n        return authenticationParameters;\n    }\n\n    @Test\n    public void shouldCreateAuthenticationAPIClientInstance() {\n        AuthenticationAPIClient client = options.getAuthenticationAPIClient();\n\n        assertThat(client, is(notNullValue()));\n    }\n\n    private List<SignUpField> createCustomFields() {\n        CustomField fieldNumber = new CustomField(R.drawable.com_auth0_lock_ic_phone, FieldType.TYPE_PHONE_NUMBER, \"number\", R.string.com_auth0_lock_hint_phone_number);\n        CustomField fieldSurname = new CustomField(R.drawable.com_auth0_lock_ic_username, FieldType.TYPE_NAME, \"surname\", R.string.com_auth0_lock_hint_username);\n\n        List<SignUpField> customFields = new ArrayList<>();\n        customFields.add(fieldNumber);\n        customFields.add(fieldSurname);\n        return customFields;\n    }\n\n    private List<String> createConnections(String... connections) {\n        return Arrays.asList(connections);\n    }\n\n    private List<String> createEnterpriseConnectionsUsingWebForm(String... connections) {\n        return Arrays.asList(connections);\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/PasswordlessConnectionTest.java",
    "content": "package com.auth0.android.lock.internal.configuration;\n\nimport org.junit.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.auth0.android.lock.internal.configuration.ConnectionMatcher.hasType;\nimport static org.hamcrest.Matchers.is;\nimport static org.junit.Assert.assertThat;\n\npublic class PasswordlessConnectionTest {\n\n    @Test\n    public void shouldHaveName() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"name\");\n        PasswordlessConnection connection = Connection.newConnectionFor(\"sms\", values);\n        assertThat(connection.getName(), is(\"name\"));\n    }\n\n    @Test\n    public void shouldHaveStrategy() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"name\");\n        PasswordlessConnection connection = Connection.newConnectionFor(\"sms\", values);\n        assertThat(connection.getStrategy(), is(\"sms\"));\n    }\n\n    @Test\n    public void shouldBePasswordlessType() {\n        Map<String, Object> values = new HashMap<>();\n        values.put(\"name\", \"sms\");\n        PasswordlessConnection connection = Connection.newConnectionFor(\"sms\", values);\n        assertThat(connection, hasType(AuthType.PASSWORDLESS));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/internal/configuration/ThemeTest.java",
    "content": "/*\n * ThemeTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.internal.configuration;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.ColorRes;\nimport androidx.annotation.DrawableRes;\nimport androidx.annotation.StringRes;\nimport androidx.core.content.ContextCompat;\nimport android.util.TypedValue;\n\nimport com.auth0.android.lock.R;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertThat;\nimport static org.robolectric.Shadows.shadowOf;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class ThemeTest {\n\n    @StringRes\n    static final int STRING_RES = R.string.com_auth0_lock_header_title;\n    @DrawableRes\n    static final int DRAWABLE_RES = R.drawable.com_auth0_lock_ic_social_auth0;\n    @ColorRes\n    static final int COLOR_RES = R.color.com_auth0_lock_social_unknown;\n    static final int NOT_SET_RES = 0;\n\n    Theme.Builder builder;\n\n    @Before\n    public void setUp() {\n        builder = Theme.newBuilder();\n    }\n\n    @Test\n    public void shouldResolveDefaultHeaderTitle() {\n        final Theme theme = builder.build();\n        final Context context = RuntimeEnvironment.application;\n        context.setTheme(R.style.Lock_Theme);\n\n        final String headerTitle = theme.getHeaderTitle(context);\n        assertThat(headerTitle, is(equalTo(context.getString(getLockThemeResourceId(context, R.attr.Auth0_HeaderTitle)))));\n    }\n\n    @Test\n    public void shouldResolveDefaultHeaderLogo() {\n        final Theme theme = builder.build();\n        final Context context = RuntimeEnvironment.application;\n        context.setTheme(R.style.Lock_Theme);\n        Drawable drawable1 = theme.getHeaderLogo(context);\n        Drawable drawable2 = ContextCompat.getDrawable(context, getLockThemeResourceId(context, R.attr.Auth0_HeaderLogo));\n        int d1 = shadowOf(drawable1).getCreatedFromResId();\n        int d2 = shadowOf(drawable2).getCreatedFromResId();\n        Assert.assertThat(d1, is(equalTo(d2)));\n    }\n\n    @Test\n    public void shouldResolveDefaultHeaderColor() {\n        final Theme theme = builder.build();\n        final Context context = RuntimeEnvironment.application;\n        context.setTheme(R.style.Lock_Theme);\n\n        final int headerColor = theme.getHeaderColor(context);\n        assertThat(headerColor, is(equalTo(ContextCompat.getColor(context, getLockThemeResourceId(context, R.attr.Auth0_HeaderBackground)))));\n    }\n\n    @Test\n    public void shouldResolveDefaultHeaderTitleColor() {\n        final Theme theme = builder.build();\n        final Context context = RuntimeEnvironment.application;\n        context.setTheme(R.style.Lock_Theme);\n\n        final int titleColor = theme.getHeaderTitleColor(context);\n        assertThat(titleColor, is(equalTo(ContextCompat.getColor(context, getLockThemeResourceId(context, R.attr.Auth0_HeaderTitleColor)))));\n    }\n\n    @Test\n    public void shouldResolveDefaultPrimaryColor() {\n        final Theme theme = builder.build();\n        final Context context = RuntimeEnvironment.application;\n        context.setTheme(R.style.Lock_Theme);\n\n        final int primaryColor = theme.getPrimaryColor(context);\n        assertThat(primaryColor, is(equalTo(ContextCompat.getColor(context, getLockThemeResourceId(context, R.attr.Auth0_PrimaryColor)))));\n    }\n\n    @Test\n    public void shouldResolveDefaultDarkPrimaryColor() {\n        final Theme theme = builder.build();\n        final Context context = RuntimeEnvironment.application;\n        context.setTheme(R.style.Lock_Theme);\n\n        final int darkPrimaryColor = theme.getDarkPrimaryColor(context);\n        assertThat(darkPrimaryColor, is(equalTo(ContextCompat.getColor(context, getLockThemeResourceId(context, R.attr.Auth0_DarkPrimaryColor)))));\n    }\n\n\n    @Test\n    public void shouldResolveCustomHeaderTitle() {\n        final Theme theme = builder.withHeaderTitle(STRING_RES).build();\n        final Context context = RuntimeEnvironment.application;\n\n        final String headerTitle = theme.getHeaderTitle(context);\n        final String actualTitle = context.getString(STRING_RES);\n        assertThat(headerTitle, is(equalTo(actualTitle)));\n    }\n\n    @Test\n    public void shouldResolveCustomHeaderLogo() {\n        final Theme theme = builder.withHeaderLogo(DRAWABLE_RES).build();\n        final Context context = RuntimeEnvironment.application;\n        Drawable drawable1 = theme.getHeaderLogo(context);\n        Drawable drawable2 = ContextCompat.getDrawable(context, DRAWABLE_RES);\n        int d1 = shadowOf(drawable1).getCreatedFromResId();\n        int d2 = shadowOf(drawable2).getCreatedFromResId();\n        Assert.assertThat(d1, is(equalTo(d2)));\n    }\n\n    @Test\n    public void shouldResolveCustomHeaderColor() {\n        final Theme theme = builder.withHeaderColor(COLOR_RES).build();\n        final Context context = RuntimeEnvironment.application;\n\n        final int headerColor = theme.getHeaderColor(context);\n        final int actualColor = ContextCompat.getColor(context, COLOR_RES);\n        assertThat(headerColor, is(equalTo(actualColor)));\n    }\n\n    @Test\n    public void shouldResolveCustomHeaderTitleColor() {\n        final Theme theme = builder.withHeaderTitleColor(COLOR_RES).build();\n        final Context context = RuntimeEnvironment.application;\n\n        final int titleColor = theme.getHeaderTitleColor(context);\n        final int actualColor = ContextCompat.getColor(context, COLOR_RES);\n        assertThat(titleColor, is(equalTo(actualColor)));\n    }\n\n    @Test\n    public void shouldResolveCustomPrimaryColor() {\n        final Theme theme = builder.withPrimaryColor(COLOR_RES).build();\n        final Context context = RuntimeEnvironment.application;\n\n        final int headerColor = theme.getPrimaryColor(context);\n        final int actualColor = ContextCompat.getColor(context, COLOR_RES);\n        assertThat(headerColor, is(equalTo(actualColor)));\n    }\n\n    @Test\n    public void shouldResolveCustomDarkPrimaryColor() {\n        final Theme theme = builder.withDarkPrimaryColor(COLOR_RES).build();\n        final Context context = RuntimeEnvironment.application;\n\n        final int headerColor = theme.getDarkPrimaryColor(context);\n        final int actualColor = ContextCompat.getColor(context, COLOR_RES);\n        assertThat(headerColor, is(equalTo(actualColor)));\n    }\n\n    @Test\n    public void shouldSetHeaderTitle() {\n        final Theme theme = builder.withHeaderTitle(STRING_RES)\n                .build();\n        assertThat(theme.getCustomHeaderTitleRes(), is(equalTo(STRING_RES)));\n    }\n\n    @Test\n    public void shouldSetHeaderLogo() {\n        final Theme theme = builder.withHeaderLogo(DRAWABLE_RES)\n                .build();\n        assertThat(theme.getCustomHeaderLogoRes(), is(equalTo(DRAWABLE_RES)));\n    }\n\n    @Test\n    public void shouldSetHeaderColor() {\n        final Theme theme = builder.withHeaderColor(COLOR_RES)\n                .build();\n        assertThat(theme.getCustomHeaderColorRes(), is(equalTo(COLOR_RES)));\n    }\n\n    @Test\n    public void shouldSetHeaderTitleColor() {\n        final Theme theme = builder.withHeaderTitleColor(COLOR_RES)\n                .build();\n        assertThat(theme.getCustomHeaderTitleColorRes(), is(equalTo(COLOR_RES)));\n    }\n\n    @Test\n    public void shouldSetPrimaryColor() {\n        final Theme theme = builder.withPrimaryColor(COLOR_RES)\n                .build();\n        assertThat(theme.getCustomPrimaryColorRes(), is(equalTo(COLOR_RES)));\n    }\n\n    @Test\n    public void shouldSetDarkPrimaryColor() {\n        final Theme theme = builder.withDarkPrimaryColor(COLOR_RES)\n                .build();\n        assertThat(theme.getCustomDarkPrimaryColorRes(), is(equalTo(COLOR_RES)));\n    }\n\n    @Test\n    public void shouldNotHaveCustomValues() {\n        final Theme theme = builder.build();\n        assertThat(theme.getCustomHeaderTitleRes(), is(equalTo(NOT_SET_RES)));\n        assertThat(theme.getCustomHeaderLogoRes(), is(equalTo(NOT_SET_RES)));\n        assertThat(theme.getCustomHeaderColorRes(), is(equalTo(NOT_SET_RES)));\n        assertThat(theme.getCustomHeaderTitleColorRes(), is(equalTo(NOT_SET_RES)));\n        assertThat(theme.getCustomPrimaryColorRes(), is(equalTo(NOT_SET_RES)));\n        assertThat(theme.getCustomDarkPrimaryColorRes(), is(equalTo(NOT_SET_RES)));\n    }\n\n    private int getLockThemeResourceId(Context context, @AttrRes int attrResId) {\n        TypedValue typedValue = new TypedValue();\n        context.getTheme().resolveAttribute(attrResId, typedValue, true);\n        return typedValue.resourceId;\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/provider/AuthResolverTest.java",
    "content": "/*\n * ProviderResolverManagerTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.provider;\n\nimport com.auth0.android.provider.AuthHandler;\nimport com.auth0.android.provider.AuthProvider;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class AuthResolverTest {\n\n    @Test\n    public void shouldHaveReturnNullWhenNoAuthHandlers() {\n        assertThat(AuthResolver.providerFor(\"\", \"\"), nullValue());\n    }\n\n    @Test\n    public void shouldKeepACopyOfTheList() {\n        AuthProvider aProvider = Mockito.mock(AuthProvider.class);\n        AuthProvider bProvider = Mockito.mock(AuthProvider.class);\n        AuthHandler aHandler = Mockito.mock(AuthHandler.class);\n        AuthHandler bHandler = Mockito.mock(AuthHandler.class);\n        Mockito.when(aHandler.providerFor(\"aStrategy\", \"aConnection\")).thenReturn(aProvider);\n        Mockito.when(bHandler.providerFor(\"bStrategy\", \"bConnection\")).thenReturn(bProvider);\n\n        List<AuthHandler> list = new ArrayList<>();\n        list.add(aHandler);\n        list.add(bHandler);\n        AuthResolver.setAuthHandlers(list);\n        list.clear();\n\n        assertThat(AuthResolver.providerFor(\"aStrategy\", \"aConnection\"), is(equalTo(aProvider)));\n        assertThat(AuthResolver.providerFor(\"bStrategy\", \"bConnection\"), is(equalTo(bProvider)));\n    }\n\n    @Test\n    public void shouldSetAuthHandlers() {\n        AuthProvider aProvider = Mockito.mock(AuthProvider.class);\n        AuthProvider bProvider = Mockito.mock(AuthProvider.class);\n        AuthProvider cProvider = Mockito.mock(AuthProvider.class);\n        AuthHandler abHandler = Mockito.mock(AuthHandler.class);\n        AuthHandler cHandler = Mockito.mock(AuthHandler.class);\n        Mockito.when(abHandler.providerFor(\"aStrategy\", \"aConnection\")).thenReturn(aProvider);\n        Mockito.when(abHandler.providerFor(\"bStrategy\", \"bConnection\")).thenReturn(bProvider);\n        Mockito.when(cHandler.providerFor(\"cStrategy\", \"cConnection\")).thenReturn(cProvider);\n        AuthResolver.setAuthHandlers(Arrays.asList(abHandler, cHandler));\n\n        assertThat(AuthResolver.providerFor(\"aStrategy\", \"aConnection\"), is(equalTo(aProvider)));\n        assertThat(AuthResolver.providerFor(\"bStrategy\", \"bConnection\"), is(equalTo(bProvider)));\n        assertThat(AuthResolver.providerFor(\"cStrategy\", \"cConnection\"), is(equalTo(cProvider)));\n    }\n\n    @Test\n    public void shouldRespectAuthHandlersOrder() {\n        AuthProvider aProvider = Mockito.mock(AuthProvider.class);\n        AuthProvider bProvider = Mockito.mock(AuthProvider.class);\n\n        AuthProvider cProvider = Mockito.mock(AuthProvider.class);\n        AuthHandler firstHandler = Mockito.mock(AuthHandler.class);\n        AuthHandler secondHandler = Mockito.mock(AuthHandler.class);\n        Mockito.when(firstHandler.providerFor(\"sameStrategy\", \"sameConnection\")).thenReturn(aProvider);\n        Mockito.when(firstHandler.providerFor(\"differentStrategy\", \"differentConnection\")).thenReturn(bProvider);\n        Mockito.when(secondHandler.providerFor(\"sameStrategy\", \"sameConnection\")).thenReturn(cProvider);\n        AuthResolver.setAuthHandlers(Arrays.asList(secondHandler, firstHandler));\n\n        assertThat(AuthResolver.providerFor(\"sameStrategy\", \"sameConnection\"), is(equalTo(cProvider)));\n        assertThat(AuthResolver.providerFor(\"differentStrategy\", \"differentConnection\"), is(equalTo(bProvider)));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/ApplicationAPI.java",
    "content": "/*\n * ApplicationAPI.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\n\nimport java.io.IOException;\n\nimport okhttp3.mockwebserver.MockResponse;\nimport okhttp3.mockwebserver.MockWebServer;\nimport okhttp3.mockwebserver.RecordedRequest;\n\npublic class ApplicationAPI {\n\n    private MockWebServer server;\n\n    public ApplicationAPI(SSLTestUtils sslUtils) throws IOException {\n        this.server = sslUtils.createMockWebServer();\n        this.server.start();\n    }\n\n    public String getDomain() {\n        return server.url(\"/\").toString();\n    }\n\n    public void shutdown() throws IOException {\n        this.server.shutdown();\n    }\n\n    public RecordedRequest takeRequest() throws InterruptedException {\n        return server.takeRequest();\n    }\n\n    public void willReturnValidJSONPResponse() {\n        willReturnApplicationResponseWithBody(\"Auth0.setClient({\\\"id\\\":\\\"CLIENTID\\\",\\\"tenant\\\":\\\"overmind\\\",\\\"subscription\\\":\\\"free\\\",\\\"authorize\\\":\\\"https://samples.auth0.com/authorize\\\",\\\"callback\\\":\\\"http://localhost:3000/\\\",\\\"hasAllowedOrigins\\\":true,\\\"strategies\\\":[{\\\"name\\\":\\\"twitter\\\",\\\"connections\\\":[{\\\"name\\\":\\\"twitter\\\"}]}]});\", 200);\n    }\n\n    public void willReturnInvalidJSONPLengthResponse() {\n        server.enqueue(responseWithJSON(\"SHORTJSON\", 200));\n    }\n\n    private void willReturnApplicationResponseWithBody(String body, int statusCode) {\n        MockResponse response = new MockResponse()\n                .setResponseCode(statusCode)\n                .addHeader(\"Content-Type\", \"application/x-javascript\")\n                .setBody(body);\n        server.enqueue(response);\n    }\n\n    private MockResponse responseWithJSON(String json, int statusCode) {\n        return new MockResponse()\n                .setResponseCode(statusCode)\n                .addHeader(\"Content-Type\", \"application/json\")\n                .setBody(json);\n    }\n\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/Auth0AuthenticationCallbackMatcher.java",
    "content": "/*\n * CallbackMatcher.java\n *\n * Copyright (c) 2015 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.AuthenticationCallback;\nimport com.google.gson.reflect.TypeToken;\nimport com.jayway.awaitility.core.ConditionTimeoutException;\n\nimport org.hamcrest.BaseMatcher;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\n\nimport static com.jayway.awaitility.Awaitility.await;\nimport static org.hamcrest.Matchers.allOf;\nimport static org.hamcrest.Matchers.equalTo;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.isA;\nimport static org.hamcrest.Matchers.not;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.hamcrest.Matchers.nullValue;\n\npublic class Auth0AuthenticationCallbackMatcher<T> extends BaseMatcher<AuthenticationCallback<T>> {\n    private final Matcher<T> payloadMatcher;\n    private final Matcher<AuthenticationException> errorMatcher;\n\n    public Auth0AuthenticationCallbackMatcher(Matcher<T> payloadMatcher, Matcher<AuthenticationException> errorMatcher) {\n        this.payloadMatcher = payloadMatcher;\n        this.errorMatcher = errorMatcher;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public boolean matches(Object item) {\n        MockAuthenticationCallback<T> callback = (MockAuthenticationCallback<T>) item;\n        try {\n            await().until(callback.payload(), payloadMatcher);\n            await().until(callback.error(), errorMatcher);\n            return true;\n        } catch (ConditionTimeoutException e) {\n            return false;\n        }\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description\n                .appendText(\"successful method be called\");\n    }\n\n    public static <T> Matcher<AuthenticationCallback<T>> hasPayloadOfType(TypeToken<T> tType) {\n        return new Auth0AuthenticationCallbackMatcher<>(TypeTokenMatcher.isA(tType), is(nullValue(AuthenticationException.class)));\n    }\n\n    public static <T> Matcher<AuthenticationCallback<T>> hasPayloadOfType(Class<T> tClazz) {\n        return new Auth0AuthenticationCallbackMatcher<>(isA(tClazz), is(nullValue(AuthenticationException.class)));\n    }\n\n    public static <T> Matcher<AuthenticationCallback<T>> hasPayload(T payload) {\n        return new Auth0AuthenticationCallbackMatcher<>(equalTo(payload), is(nullValue(AuthenticationException.class)));\n    }\n\n    public static <T> Matcher<AuthenticationCallback<T>> hasNoPayloadOfType(Class<T> tClazz) {\n        return new Auth0AuthenticationCallbackMatcher<>(is(nullValue(tClazz)), is(notNullValue(AuthenticationException.class)));\n    }\n\n    public static <T> Matcher<AuthenticationCallback<T>> hasNoPayloadOfType(TypeToken<T> tType) {\n        return new Auth0AuthenticationCallbackMatcher<>(allOf(nullValue(), not(TypeTokenMatcher.isA(tType))), is(notNullValue(AuthenticationException.class)));\n    }\n\n    public static Matcher<AuthenticationCallback<Void>> hasNoError() {\n        return new Auth0AuthenticationCallbackMatcher<>(is(nullValue(Void.class)), is(nullValue(AuthenticationException.class)));\n    }\n\n    public static Matcher<AuthenticationCallback<Void>> hasError() {\n        return new Auth0AuthenticationCallbackMatcher<>(is(nullValue(Void.class)), is(notNullValue(AuthenticationException.class)));\n    }\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/AuthenticationCallbackMatcher.java",
    "content": "/*\n * AuthenticationCallbackMatcher.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.result.Credentials;\nimport com.jayway.awaitility.Duration;\nimport com.jayway.awaitility.core.ConditionTimeoutException;\n\nimport org.hamcrest.BaseMatcher;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.Matchers;\n\nimport static com.jayway.awaitility.Awaitility.waitAtMost;\nimport static org.hamcrest.CoreMatchers.any;\nimport static org.hamcrest.CoreMatchers.anyOf;\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.CoreMatchers.nullValue;\nimport static org.hamcrest.Matchers.isA;\n\npublic class AuthenticationCallbackMatcher extends BaseMatcher<MockLockCallback> {\n    private final Matcher<Credentials> authenticationMatcher;\n    private final Matcher<Boolean> canceledMatcher;\n    private final Matcher<Throwable> errorMatcher;\n\n    public AuthenticationCallbackMatcher(Matcher<Credentials> authenticationMatcher, Matcher<Boolean> canceledMatcher, Matcher<Throwable> errorMatcher) {\n        this.authenticationMatcher = authenticationMatcher;\n        this.canceledMatcher = canceledMatcher;\n        this.errorMatcher = errorMatcher;\n    }\n\n    @Override\n    public boolean matches(Object item) {\n        MockLockCallback callback = (MockLockCallback) item;\n        try {\n            waitAtMost(Duration.ONE_SECOND).await().until(callback.authentication(), authenticationMatcher);\n            waitAtMost(Duration.ONE_SECOND).await().until(callback.canceled(), canceledMatcher);\n            waitAtMost(Duration.ONE_SECOND).await().until(callback.error(), errorMatcher);\n            return true;\n        } catch (ConditionTimeoutException e) {\n            return false;\n        }\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description\n                .appendText(\"successful method be called\");\n    }\n\n    public static AuthenticationCallbackMatcher isCanceled() {\n        return new AuthenticationCallbackMatcher(is(nullValue(Credentials.class)), equalTo(true), is(notNullValue(Throwable.class)));\n    }\n\n    public static AuthenticationCallbackMatcher hasAuthentication() {\n        return new AuthenticationCallbackMatcher(is(notNullValue(Credentials.class)), equalTo(false), is(nullValue(Throwable.class)));\n    }\n\n    public static AuthenticationCallbackMatcher hasError() {\n        return new AuthenticationCallbackMatcher(is(nullValue(Credentials.class)), any(Boolean.class), is(notNullValue(Throwable.class)));\n    }\n\n    public static AuthenticationCallbackMatcher hasNoError() {\n        return new AuthenticationCallbackMatcher(anyOf(nullValue(Credentials.class), notNullValue(Credentials.class)), any(Boolean.class), is(nullValue(Throwable.class)));\n    }\n\n    public static <T> CallbackMatcher<T, AuthenticationException> hasPayloadOfType(Class<T> clazz) {\n        return new CallbackMatcher<>(isA(clazz), Matchers.is(Matchers.nullValue(AuthenticationException.class)));\n    }\n\n    public static <T> CallbackMatcher<T, AuthenticationException> hasPayload(T payload) {\n        return new CallbackMatcher<>(Matchers.equalTo(payload), Matchers.is(Matchers.nullValue(AuthenticationException.class)));\n    }\n\n    public static <T> CallbackMatcher<T, AuthenticationException> hasNoPayloadOfType(Class<T> clazz) {\n        return new CallbackMatcher<>(Matchers.is(Matchers.nullValue(clazz)), Matchers.is(Matchers.notNullValue(AuthenticationException.class)));\n    }\n\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/CallbackMatcher.java",
    "content": "/*\n * CallbackMatcher.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport com.auth0.android.Auth0Exception;\nimport com.google.gson.reflect.TypeToken;\nimport com.jayway.awaitility.core.ConditionTimeoutException;\n\nimport org.hamcrest.BaseMatcher;\nimport org.hamcrest.Description;\nimport org.hamcrest.Matcher;\nimport org.hamcrest.Matchers;\n\nimport static com.jayway.awaitility.Awaitility.await;\nimport static org.hamcrest.Matchers.isA;\nimport static org.hamcrest.Matchers.not;\nimport static org.hamcrest.Matchers.notNullValue;\n\npublic class CallbackMatcher<T, U extends Auth0Exception> extends BaseMatcher<MockCallback<T, U>> {\n    private final Matcher<T> payloadMatcher;\n    private final Matcher<U> errorMatcher;\n\n    public CallbackMatcher(Matcher<T> payloadMatcher, Matcher<U> errorMatcher) {\n        this.payloadMatcher = payloadMatcher;\n        this.errorMatcher = errorMatcher;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public boolean matches(Object item) {\n        MockCallback<T, U> callback = (MockCallback<T, U>) item;\n        try {\n            await().until(callback.payload(), payloadMatcher);\n            await().until(callback.error(), errorMatcher);\n            return true;\n        } catch (ConditionTimeoutException e) {\n            return false;\n        }\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description\n                .appendText(\"successful method be called\");\n    }\n\n    public static <T, U extends Auth0Exception> Matcher<MockCallback<T, U>> hasPayloadOfType(Class<T> clazz, Class<U> uClazz) {\n        return new CallbackMatcher<>(isA(clazz), Matchers.is(Matchers.nullValue(uClazz)));\n    }\n\n    public static <T, U extends Auth0Exception> Matcher<MockCallback<T, U>> hasPayloadOfType(TypeToken<T> tType, TypeToken<U> uType) {\n        return new CallbackMatcher<>(TypeTokenMatcher.isA(tType), TypeTokenMatcher.isNull(uType));\n    }\n\n    public static <T, U extends Auth0Exception> Matcher<MockCallback<T, U>> hasErrorOfType(TypeToken<T> tType, TypeToken<U> uType) {\n        return new CallbackMatcher<>(TypeTokenMatcher.isNull(tType), TypeTokenMatcher.isA(uType));\n    }\n\n    public static <T, U extends Auth0Exception> Matcher<MockCallback<T, U>> hasPayload(T payload, Class<U> uClazz) {\n        return new CallbackMatcher<>(Matchers.equalTo(payload), Matchers.is(Matchers.nullValue(uClazz)));\n    }\n\n    public static <T, U extends Auth0Exception> Matcher<MockCallback<T, U>> hasNoPayloadOfType(Class<T> clazz, Class<U> uClazz) {\n        return new CallbackMatcher<>(Matchers.is(Matchers.nullValue(clazz)), Matchers.is(notNullValue(uClazz)));\n    }\n\n    public static <T, U extends Auth0Exception> Matcher<MockCallback<T, U>> hasNoPayloadOfType(TypeToken<T> tType, TypeToken<U> uType) {\n        return new CallbackMatcher<>(TypeTokenMatcher.isNull(tType), not(TypeTokenMatcher.isA(uType)));\n    }\n\n    public static <U extends Auth0Exception> Matcher<MockCallback<Void, U>> hasNoError(Class<U> uClazz) {\n        return new CallbackMatcher<>(Matchers.is(Matchers.nullValue(Void.class)), Matchers.is(Matchers.nullValue(uClazz)));\n    }\n\n    public static <U extends Auth0Exception> Matcher<MockCallback<Void, U>> hasError(Class<U> uClazz) {\n        return new CallbackMatcher<>(Matchers.is(Matchers.nullValue(Void.class)), Matchers.is(notNullValue(uClazz)));\n    }\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/CustomFieldTest.java",
    "content": "/*\n * CustomFieldTest.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport android.os.Bundle;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.utils.CustomField.FieldType;\nimport com.auth0.android.lock.views.ValidatedInputView;\nimport com.auth0.android.lock.views.ValidatedInputView.DataType;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mockito;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static com.auth0.android.lock.utils.CustomField.Storage;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.notNullValue;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.Matchers.eq;\nimport static org.mockito.Mockito.when;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class CustomFieldTest {\n\n    private static final int ICON = R.drawable.com_auth0_lock_ic_email;\n    private static final int TYPE = FieldType.TYPE_EMAIL;\n    private static final String KEY = \"key\";\n    private static final int HINT = R.string.com_auth0_lock_hint_email;\n    private static final String CUSTOM_FIELD_KEY = \"custom_field\";\n    private static final int STORAGE = Storage.PROFILE_ROOT;\n\n    @Rule\n    public ExpectedException exception = ExpectedException.none();\n\n    @Test\n    public void shouldThrowIfKeyIsEmpty() {\n        exception.expect(IllegalArgumentException.class);\n        exception.expectMessage(\"The key cannot be empty.\");\n        new CustomField(ICON, TYPE, \"\", HINT, STORAGE);\n    }\n\n    @Test\n    public void shouldThrowIfKeyIsUserMetadataAndStorageIsRoot() {\n        exception.expect(IllegalArgumentException.class);\n        exception.expectMessage(\"Update the user_metadata root profile attributes by using Storage.USER_METADATA as storage location.\");\n        new CustomField(ICON, TYPE, \"user_metadata\", HINT, Storage.PROFILE_ROOT);\n    }\n\n    @Test\n    public void shouldCreateWithDefaultValues() {\n        CustomField field = new CustomField(ICON, TYPE, KEY, HINT);\n        assertThat(field.getIcon(), is(ICON));\n        assertThat(field.getType(), is(TYPE));\n        assertThat(field.getKey(), is(KEY));\n        assertThat(field.getHint(), is(HINT));\n        //Default values\n        assertThat(field.getStorage(), is(Storage.USER_METADATA));\n    }\n\n    @Test\n    public void shouldCreate() {\n        CustomField field = new CustomField(ICON, TYPE, KEY, HINT, STORAGE);\n        assertThat(field.getIcon(), is(ICON));\n        assertThat(field.getType(), is(TYPE));\n        assertThat(field.getKey(), is(KEY));\n        assertThat(field.getHint(), is(HINT));\n        assertThat(field.getStorage(), is(STORAGE));\n    }\n\n    @Test\n    public void shouldBeParcelable() {\n        CustomField field = new CustomField(ICON, TYPE, KEY, HINT, STORAGE);\n        Bundle bundle = new Bundle();\n        bundle.putParcelable(CUSTOM_FIELD_KEY, field);\n\n        CustomField parcelableCustomField = bundle.getParcelable(CUSTOM_FIELD_KEY);\n        assertThat(parcelableCustomField, is(notNullValue()));\n        assertThat(parcelableCustomField.getIcon(), is(ICON));\n        assertThat(parcelableCustomField.getType(), is(TYPE));\n        assertThat(parcelableCustomField.getKey(), is(KEY));\n        assertThat(parcelableCustomField.getHint(), is(HINT));\n        assertThat(parcelableCustomField.getStorage(), is(STORAGE));\n    }\n\n    @Test\n    public void shouldConfigureTheEmailField() {\n        ValidatedInputView input = Mockito.mock(ValidatedInputView.class);\n\n        CustomField field = new CustomField(ICON, FieldType.TYPE_EMAIL, KEY, HINT);\n        field.configureField(input);\n\n        Mockito.verify(input).setIcon(ICON);\n        Mockito.verify(input).setDataType(DataType.EMAIL);\n        Mockito.verify(input).setHint(HINT);\n        Mockito.verify(input).setTag(KEY);\n    }\n\n    @Test\n    public void shouldConfigureTheNameField() {\n        ValidatedInputView input = Mockito.mock(ValidatedInputView.class);\n\n        CustomField field = new CustomField(ICON, FieldType.TYPE_NAME, KEY, HINT);\n        field.configureField(input);\n\n        Mockito.verify(input).setIcon(ICON);\n        Mockito.verify(input).setDataType(DataType.TEXT_NAME);\n        Mockito.verify(input).setHint(HINT);\n        Mockito.verify(input).setTag(KEY);\n    }\n\n    @Test\n    public void shouldConfigureThePhoneNumberField() {\n        ValidatedInputView input = Mockito.mock(ValidatedInputView.class);\n\n        CustomField field = new CustomField(ICON, FieldType.TYPE_PHONE_NUMBER, KEY, HINT);\n        field.configureField(input);\n\n        Mockito.verify(input).setIcon(ICON);\n        Mockito.verify(input).setDataType(DataType.PHONE_NUMBER);\n        Mockito.verify(input).setHint(HINT);\n        Mockito.verify(input).setTag(KEY);\n    }\n\n    @Test\n    public void shouldConfigureTheNumberField() {\n        ValidatedInputView input = Mockito.mock(ValidatedInputView.class);\n\n        CustomField field = new CustomField(ICON, FieldType.TYPE_NUMBER, KEY, HINT);\n        field.configureField(input);\n\n        Mockito.verify(input).setIcon(ICON);\n        Mockito.verify(input).setDataType(DataType.NUMBER);\n        Mockito.verify(input).setHint(HINT);\n        Mockito.verify(input).setTag(KEY);\n    }\n\n    @Test\n    public void shouldObtainTheValue() {\n        ViewGroup container = Mockito.mock(LinearLayout.class);\n        ValidatedInputView input = Mockito.mock(ValidatedInputView.class);\n\n        when(input.getText()).thenReturn(\"user defined value\");\n        when(container.findViewWithTag(eq(KEY))).thenReturn(input);\n\n        CustomField field = new CustomField(ICON, TYPE, KEY, HINT);\n        String value = field.findValue(container);\n\n        assertThat(value, is(\"user defined value\"));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/HiddenFieldTest.java",
    "content": "package com.auth0.android.lock.utils;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.hamcrest.core.Is.is;\nimport static org.junit.Assert.assertThat;\n\npublic class HiddenFieldTest {\n    private static final String KEY = \"key\";\n    private static final String VALUE = \"fixed value\";\n    private static final int STORAGE = CustomField.Storage.PROFILE_ROOT;\n    private HiddenField field;\n\n    @Before\n    public void setUp() throws Exception {\n        field = new HiddenField(KEY, VALUE, STORAGE);\n    }\n\n    @Test\n    public void shouldGetKey() {\n        assertThat(field.getKey(), is(KEY));\n    }\n\n    @Test\n    public void shouldGetStorage() {\n        assertThat(field.getStorage(), is(CustomField.Storage.PROFILE_ROOT));\n    }\n\n    @Test\n    public void shouldGetValue() {\n        assertThat(field.getValue(), is(VALUE));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/MockAuthenticationCallback.java",
    "content": "/*\n * MockBaseCallback.java\n *\n * Copyright (c) 2015 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.callback.AuthenticationCallback;\n\nimport java.util.concurrent.Callable;\n\npublic class MockAuthenticationCallback<T> implements AuthenticationCallback<T> {\n\n    private AuthenticationException error;\n    private T payload;\n\n    @Override\n    public void onFailure(AuthenticationException error) {\n        this.error = error;\n    }\n\n    @Override\n    public void onSuccess(T payload) {\n        this.payload = payload;\n    }\n\n    public Callable<AuthenticationException> error() {\n        return new Callable<AuthenticationException>() {\n            @Override\n            public AuthenticationException call() {\n                return error;\n            }\n        };\n    }\n\n    public Callable<T> payload() {\n        return new Callable<T>() {\n            @Override\n            public T call() {\n                return payload;\n            }\n        };\n    }\n\n    public AuthenticationException getError() {\n        return error;\n    }\n\n    public T getPayload() {\n        return payload;\n    }\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/MockCallback.java",
    "content": "/*\n * MockBaseCallback.java\n *\n * Copyright (c) 2015 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.Auth0Exception;\nimport com.auth0.android.callback.Callback;\n\nimport java.util.concurrent.Callable;\n\npublic class MockCallback<T, U extends Auth0Exception> implements Callback<T, U> {\n\n    private T payload;\n    private U error;\n\n    @Override\n    public void onSuccess(@NonNull T payload) {\n        this.payload = payload;\n    }\n\n    @Override\n    public void onFailure(@NonNull U error) {\n        this.error = error;\n    }\n\n    public Callable<T> payload() {\n        return new Callable<T>() {\n            @Override\n            public T call() {\n                return payload;\n            }\n        };\n    }\n\n    public Callable<U> error() {\n        return new Callable<U>() {\n            @Override\n            public U call() {\n                return error;\n            }\n        };\n    }\n\n    public T getPayload() {\n        return payload;\n    }\n\n    public U getError() {\n        return error;\n    }\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/MockLockCallback.java",
    "content": "/*\n * MockLockCallback.java\n *\n * Copyright (c) 2016 Auth0 (http://auth0.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.auth0.android.lock.utils;\n\nimport androidx.annotation.NonNull;\n\nimport com.auth0.android.authentication.AuthenticationException;\nimport com.auth0.android.lock.AuthenticationCallback;\nimport com.auth0.android.result.Credentials;\n\nimport java.util.concurrent.Callable;\n\npublic class MockLockCallback extends AuthenticationCallback {\n\n    private Credentials credentials;\n    private AuthenticationException error;\n\n    public Callable<Credentials> authentication() {\n        return () -> credentials;\n    }\n\n    public Callable<Boolean> canceled() {\n        return () -> error != null && error.isCanceled();\n    }\n\n    public Callable<AuthenticationException> error() {\n        return () -> error;\n    }\n\n    @Override\n    public void onAuthentication(@NonNull Credentials credentials) {\n        this.credentials = credentials;\n    }\n\n    @Override\n    public void onError(@NonNull AuthenticationException error) {\n        this.error = error;\n    }\n\n    public Credentials getCredentials() {\n        return this.credentials;\n    }\n\n    public AuthenticationException getError() {\n        return error;\n    }\n}\n"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/SSLTestUtils.java",
    "content": "package com.auth0.android.lock.utils;\n\nimport com.auth0.android.request.DefaultClient;\n\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.Collections;\n\nimport okhttp3.mockwebserver.MockWebServer;\nimport okhttp3.tls.HandshakeCertificates;\nimport okhttp3.tls.HeldCertificate;\n\n/**\n * Utility object for executing tests that use the networking client over HTTPS on localhost.\n */\npublic class SSLTestUtils {\n    private final HeldCertificate localhostCertificate;\n    private final HandshakeCertificates serverCertificates;\n    private final HandshakeCertificates clientCertificates;\n    public final DefaultClient testClient;\n\n    public SSLTestUtils() throws UnknownHostException {\n        String localhost = InetAddress.getByName(\"localhost\").getCanonicalHostName();\n\n        localhostCertificate = new HeldCertificate.Builder()\n                .addSubjectAlternativeName(localhost)\n                .build();\n\n        clientCertificates = new HandshakeCertificates.Builder()\n                .addTrustedCertificate(localhostCertificate.certificate())\n                .build();\n\n        serverCertificates = new HandshakeCertificates.Builder()\n                .heldCertificate(localhostCertificate)\n                .build();\n\n        testClient = new DefaultClient(\n                10,\n                10,\n                Collections.emptyMap(),\n                false,\n                clientCertificates.sslSocketFactory(),\n                clientCertificates.trustManager()\n        );\n    }\n\n    MockWebServer createMockWebServer() {\n        MockWebServer mockServer = new MockWebServer();\n        mockServer.useHttps(serverCertificates.sslSocketFactory(), false);\n        return mockServer;\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/utils/TypeTokenMatcher.java",
    "content": "package com.auth0.android.lock.utils;\n\nimport com.google.gson.reflect.TypeToken;\n\nimport org.hamcrest.BaseMatcher;\nimport org.hamcrest.Description;\n\npublic class TypeTokenMatcher<T> extends BaseMatcher<T> {\n    private final TypeToken<T> typeToken;\n    private final boolean shouldBeNull;\n\n    private TypeTokenMatcher(TypeToken<T> typeToken, boolean shouldBeNull) {\n        this.typeToken = typeToken;\n        this.shouldBeNull = shouldBeNull;\n    }\n\n    public static <T> TypeTokenMatcher<T> isA(TypeToken<T> typeToken) {\n        return new TypeTokenMatcher<>(typeToken, false);\n    }\n\n    public static <T> TypeTokenMatcher<T> isNull(TypeToken<T> typeToken) {\n        return new TypeTokenMatcher<>(typeToken, true);\n    }\n\n    @Override\n    public void describeTo(Description description) {\n        description.appendText(\"isA(\" + typeToken.toString() + \")\");\n    }\n\n    @Override\n    public boolean matches(Object item) {\n        if (shouldBeNull) {\n            return item == null;\n        }\n        return item != null && typeToken.getRawType().isAssignableFrom(item.getClass());\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/views/AuthConfigTest.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.graphics.drawable.Drawable;\nimport android.os.Build;\n\nimport com.auth0.android.lock.R;\nimport com.auth0.android.lock.internal.configuration.OAuthConnection;\n\nimport org.junit.Assert;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\nimport org.robolectric.util.ReflectionHelpers;\n\nimport static org.hamcrest.CoreMatchers.equalTo;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\nimport static org.robolectric.Shadows.shadowOf;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class AuthConfigTest {\n\n    private AuthConfig authConfig;\n    private OAuthConnection connection;\n\n    @Before\n    public void setUp() {\n        connection = mock(OAuthConnection.class);\n        when(connection.getName()).thenReturn(\"facebook-prod\");\n        when(connection.getStrategy()).thenReturn(\"facebook\");\n        authConfig = new AuthConfig(connection, R.style.Lock_Theme_AuthStyle_Facebook);\n    }\n\n    @Test\n    public void shouldGetConnection() {\n        Assert.assertThat(authConfig.getConnection(), is(connection));\n    }\n\n    @Test\n    public void shouldGetName() {\n        ReflectionHelpers.setStaticField(Build.VERSION.class, \"SDK_INT\", Build.VERSION_CODES.JELLY_BEAN);\n        final String string = RuntimeEnvironment.application.getResources().getString(R.string.com_auth0_lock_social_facebook);\n        Assert.assertThat(authConfig.getName(RuntimeEnvironment.application), is(equalTo(string)));\n    }\n\n    @Test\n    public void shouldGetLogo() {\n        ReflectionHelpers.setStaticField(Build.VERSION.class, \"SDK_INT\", Build.VERSION_CODES.JELLY_BEAN);\n        Drawable drawable1 = RuntimeEnvironment.application.getResources().getDrawable(R.drawable.com_auth0_lock_ic_social_facebook);\n        Drawable drawable2 = authConfig.getLogo(RuntimeEnvironment.application);\n        int d1 = shadowOf(drawable1).getCreatedFromResId();\n        int d2 = shadowOf(drawable2).getCreatedFromResId();\n        Assert.assertThat(d1, is(equalTo(d2)));\n    }\n\n    @Test\n    public void shouldGetBackgroundColor() {\n        ReflectionHelpers.setStaticField(Build.VERSION.class, \"SDK_INT\", Build.VERSION_CODES.JELLY_BEAN);\n        final int color = RuntimeEnvironment.application.getResources().getColor(R.color.com_auth0_lock_social_facebook);\n        Assert.assertThat(authConfig.getBackgroundColor(RuntimeEnvironment.application), is(equalTo(color)));\n    }\n\n    @Test\n    public void shouldHaveValidDefaultName() {\n        ReflectionHelpers.setStaticField(Build.VERSION.class, \"SDK_INT\", Build.VERSION_CODES.JELLY_BEAN);\n        AuthConfig defaultConfig = new AuthConfig(connection, R.style.Lock_Theme);\n        Assert.assertThat(defaultConfig.getName(RuntimeEnvironment.application), is(equalTo(\"facebook\")));\n    }\n\n    @Test\n    public void shouldHaveValidDefaultLogo() {\n        ReflectionHelpers.setStaticField(Build.VERSION.class, \"SDK_INT\", Build.VERSION_CODES.JELLY_BEAN);\n        AuthConfig defaultConfig = new AuthConfig(connection, R.style.Lock_Theme);\n        Drawable drawable1 = RuntimeEnvironment.application.getResources().getDrawable(R.drawable.com_auth0_lock_ic_social_auth0);\n        Drawable drawable2 = defaultConfig.getLogo(RuntimeEnvironment.application);\n        int d1 = shadowOf(drawable1).getCreatedFromResId();\n        int d2 = shadowOf(drawable2).getCreatedFromResId();\n        Assert.assertThat(d1, is(equalTo(d2)));\n    }\n\n    @Test\n    public void shouldHaveValidDefaultColor() {\n        ReflectionHelpers.setStaticField(Build.VERSION.class, \"SDK_INT\", Build.VERSION_CODES.JELLY_BEAN);\n        AuthConfig defaultConfig = new AuthConfig(connection, R.style.Lock_Theme);\n        final int color = RuntimeEnvironment.application.getResources().getColor(R.color.com_auth0_lock_social_unknown);\n        Assert.assertThat(defaultConfig.getBackgroundColor(RuntimeEnvironment.application), is(equalTo(color)));\n    }\n\n    @Test\n    public void shouldGetStyleForStrategy() {\n        Assert.assertThat(AuthConfig.styleForStrategy(\"amazon\"), is(R.style.Lock_Theme_AuthStyle_Amazon));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"aol\"), is(R.style.Lock_Theme_AuthStyle_AOL));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"bitbucket\"), is(R.style.Lock_Theme_AuthStyle_BitBucket));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"dropbox\"), is(R.style.Lock_Theme_AuthStyle_Dropbox));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"yahoo\"), is(R.style.Lock_Theme_AuthStyle_Yahoo));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"linkedin\"), is(R.style.Lock_Theme_AuthStyle_LinkedIn));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"google-oauth2\"), is(R.style.Lock_Theme_AuthStyle_GoogleOAuth2));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"twitter\"), is(R.style.Lock_Theme_AuthStyle_Twitter));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"facebook\"), is(R.style.Lock_Theme_AuthStyle_Facebook));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"box\"), is(R.style.Lock_Theme_AuthStyle_Box));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"evernote\"), is(R.style.Lock_Theme_AuthStyle_Evernote));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"evernote-sandbox\"), is(R.style.Lock_Theme_AuthStyle_EvernoteSandbox));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"exact\"), is(R.style.Lock_Theme_AuthStyle_Exact));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"github\"), is(R.style.Lock_Theme_AuthStyle_GitHub));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"instagram\"), is(R.style.Lock_Theme_AuthStyle_Instagram));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"miicard\"), is(R.style.Lock_Theme_AuthStyle_MiiCard));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"paypal\"), is(R.style.Lock_Theme_AuthStyle_Paypal));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"paypal-sandbox\"), is(R.style.Lock_Theme_AuthStyle_PaypalSandbox));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"salesforce\"), is(R.style.Lock_Theme_AuthStyle_Salesforce));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"salesforce-community\"), is(R.style.Lock_Theme_AuthStyle_SalesforceCommunity));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"salesforce-sandbox\"), is(R.style.Lock_Theme_AuthStyle_SalesforceSandbox));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"soundcloud\"), is(R.style.Lock_Theme_AuthStyle_SoundCloud));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"windowslive\"), is(R.style.Lock_Theme_AuthStyle_WindowsLive));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"yammer\"), is(R.style.Lock_Theme_AuthStyle_Yammer));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"baidu\"), is(R.style.Lock_Theme_AuthStyle_Baidu));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"fitbit\"), is(R.style.Lock_Theme_AuthStyle_Fitbit));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"planningcenter\"), is(R.style.Lock_Theme_AuthStyle_PlanningCenter));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"renren\"), is(R.style.Lock_Theme_AuthStyle_RenRen));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"thecity\"), is(R.style.Lock_Theme_AuthStyle_TheCity));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"thecity-sandbox\"), is(R.style.Lock_Theme_AuthStyle_TheCitySandbox));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"thirtysevensignals\"), is(R.style.Lock_Theme_AuthStyle_ThirtySevenSignals));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"vkontakte\"), is(R.style.Lock_Theme_AuthStyle_Vkontakte));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"weibo\"), is(R.style.Lock_Theme_AuthStyle_Weibo));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"wordpress\"), is(R.style.Lock_Theme_AuthStyle_Wordpress));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"yandex\"), is(R.style.Lock_Theme_AuthStyle_Yandex));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"shopify\"), is(R.style.Lock_Theme_AuthStyle_Shopify));\n        Assert.assertThat(AuthConfig.styleForStrategy(\"dwolla\"), is(R.style.Lock_Theme_AuthStyle_Dwolla));\n    }\n\n    @Test\n    public void shouldGetDefaultStyleForUnknownStrategy() {\n        Assert.assertThat(AuthConfig.styleForStrategy(\"unknown-strategy\"), is(R.style.Lock_Theme_AuthStyle));\n    }\n\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/views/CustomFieldsFormViewTest.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.view.ViewGroup;\n\nimport com.auth0.android.lock.events.DatabaseSignUpEvent;\nimport com.auth0.android.lock.utils.CustomField;\nimport com.auth0.android.lock.utils.HiddenField;\n\nimport org.junit.Test;\nimport org.mockito.ArgumentCaptor;\n\nimport java.util.ArrayList;\nimport java.util.Map;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.CoreMatchers.notNullValue;\nimport static org.hamcrest.collection.IsMapContaining.hasEntry;\nimport static org.junit.Assert.assertThat;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\npublic class CustomFieldsFormViewTest {\n\n    @Test\n    public void shouldConvertCustomFieldsToMap() {\n        DatabaseSignUpEvent event = mock(DatabaseSignUpEvent.class);\n        ViewGroup container = mock(ViewGroup.class);\n\n        //user_metadata attributes\n        CustomField fieldMetadata = mock(CustomField.class);\n        when(fieldMetadata.getKey()).thenReturn(\"company\");\n        when(fieldMetadata.findValue(container)).thenReturn(\"Auth0 INC\");\n        when(fieldMetadata.getStorage()).thenReturn(CustomField.Storage.USER_METADATA);\n\n        HiddenField fieldHidden1 = mock(HiddenField.class);\n        when(fieldHidden1.getKey()).thenReturn(\"referral_id\");\n        when(fieldHidden1.getValue()).thenReturn(\"123456789\");\n        when(fieldHidden1.getStorage()).thenReturn(CustomField.Storage.USER_METADATA);\n\n\n        //Root profile attributes\n        CustomField fieldFamilyName = mock(CustomField.class);\n        when(fieldFamilyName.getKey()).thenReturn(\"family_name\");\n        when(fieldFamilyName.findValue(container)).thenReturn(\"John\");\n        when(fieldFamilyName.getStorage()).thenReturn(CustomField.Storage.PROFILE_ROOT);\n\n        CustomField fieldNickname = mock(CustomField.class);\n        when(fieldNickname.getKey()).thenReturn(\"nickname\");\n        when(fieldNickname.findValue(container)).thenReturn(\"Johnnnny\");\n        when(fieldNickname.getStorage()).thenReturn(CustomField.Storage.PROFILE_ROOT);\n\n        HiddenField fieldHidden2 = mock(HiddenField.class);\n        when(fieldHidden2.getKey()).thenReturn(\"partnership\");\n        when(fieldHidden2.getValue()).thenReturn(\"bookar\");\n        when(fieldHidden2.getStorage()).thenReturn(CustomField.Storage.PROFILE_ROOT);\n\n\n        ArrayList<CustomField> visibleList = new ArrayList<>();\n        visibleList.add(fieldMetadata);\n        visibleList.add(fieldFamilyName);\n        visibleList.add(fieldNickname);\n\n        ArrayList<HiddenField> hiddenList = new ArrayList<>();\n        hiddenList.add(fieldHidden1);\n        hiddenList.add(fieldHidden2);\n\n        //Method under test\n        CustomFieldsFormView.setEventRootProfileAttributes(event, visibleList, hiddenList, container);\n\n\n        //Assertions\n        ArgumentCaptor<Map> mapCaptor = ArgumentCaptor.forClass(Map.class);\n\n        verify(event).setExtraFields(mapCaptor.capture());\n        Map<String, String> metadataFields = mapCaptor.getValue();\n        assertThat(metadataFields, is(notNullValue()));\n        assertThat(metadataFields, hasEntry(\"company\", \"Auth0 INC\"));\n        assertThat(metadataFields, hasEntry(\"referral_id\", \"123456789\"));\n\n        verify(event).setRootAttributes(mapCaptor.capture());\n        Map<String, Object> rootAttributes = mapCaptor.getValue();\n        assertThat(rootAttributes, is(notNullValue()));\n        assertThat(rootAttributes, hasEntry(\"family_name\", (Object) \"John\"));\n        assertThat(rootAttributes, hasEntry(\"nickname\", (Object) \"Johnnnny\"));\n        assertThat(rootAttributes, hasEntry(\"partnership\", (Object) \"bookar\"));\n    }\n}"
  },
  {
    "path": "lib/src/test/java/com/auth0/android/lock/views/PasswordStrengthViewTest.java",
    "content": "package com.auth0.android.lock.views;\n\nimport android.app.Activity;\n\nimport com.auth0.android.lock.internal.configuration.PasswordComplexity;\nimport com.auth0.android.lock.internal.configuration.PasswordStrength;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.robolectric.Robolectric;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n@RunWith(RobolectricTestRunner.class)\n@Config(sdk = 21)\npublic class PasswordStrengthViewTest {\n\n    public static final String PASSWORD_TOO_LONG = \"otPtgNsthiK98lw61BEwevHChF87YMNqVZDpvxgAWBESkBL\" +\n            \"ytrGRrG6JDhZjIyt2HqqxJDeyeKLlKnRG1pnOoA5xaZWKI6zK6tk37BocILDZESio107JZiHWbc4DlIFe0\";\n    public static final String PASSWORD_128_LONG = \"otPtgNsthiK98lw61BEwevHChF87YMNqVZDpvxgAWBESkBL\" +\n            \"ytrGRrG6JDhZjIyt2HqqxJDeyeKLlKnRG1pnOoA5xaZWKI6zK6tk37BocILDZESio107JZiHWbc4DlIFe\";\n    public static final String PASSWORD_10_LONG = \"123KImd$$.\";\n    public static final String PASSWORD_8_LONG = \"12KImd$.\";\n    public static final String PASSWORD_6_LONG = \"1Kd$$.\";\n    public static final String PASSWORD_1_LONG = \"1\";\n    public static final String PASSWORD_EMPTY = \"\";\n\n    public static final String PASSWORD_NUMERIC = \"1234567890\";\n    public static final String PASSWORD_ALPHA = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    public static final String PASSWORD_ALPHA_LOWER_CASE = \"abcdefghijklmnopqrstuvwxyz\";\n    public static final String PASSWORD_ALPHA_UPPER_CASE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    public static final String PASSWORD_SPECIAL = \" !\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\";\n    public static final String PASSWORD_IDENTICAL = \"AAAAaaaa1111$$$$\";\n\n    public static final String PASSWORD_NUMERIC_SPECIAL = \"12$#5!@321$314#%5667^&\";\n    public static final String PASSWORD_ALPHA_NUMERIC = \"ab12ab12ab12\";\n    public static final String PASSWORD_ALPHA_NUMERIC_SPECIAL = \"a!b1@ca2$bc1@bd2j$1j3\";\n    public static final String PASSWORD_ALPHA_CASE_NUMERIC_SPECIAL = \"a!B1@CA2$bc1@bd2j$1j3E\";\n    public static final String PASSWORD_ALPHA_CASE_NUMERIC = \"aB1aB1aB1aB1aB1\";\n\n    private PasswordStrengthView view;\n\n    @Before\n    public void setUp() {\n        Activity context = Robolectric.buildActivity(Activity.class).create().get();\n        view = new PasswordStrengthView(context);\n    }\n\n    @Test\n    public void shouldHandlePasswordStrengthNONE() {\n        view.setStrength(PasswordStrength.NONE);\n\n        assertTrue(view.isValid(PASSWORD_NUMERIC));\n        assertTrue(view.isValid(PASSWORD_ALPHA));\n        assertTrue(view.isValid(PASSWORD_ALPHA_LOWER_CASE));\n        assertTrue(view.isValid(PASSWORD_ALPHA_UPPER_CASE));\n        assertTrue(view.isValid(PASSWORD_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_IDENTICAL));\n\n        assertTrue(view.isValid(PASSWORD_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_NUMERIC));\n        assertTrue(view.isValid(PASSWORD_ALPHA_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC));\n\n        assertTrue(view.isValid(PASSWORD_128_LONG));\n        assertTrue(view.isValid(PASSWORD_10_LONG));\n        assertTrue(view.isValid(PASSWORD_8_LONG));\n        assertTrue(view.isValid(PASSWORD_6_LONG));\n        assertTrue(view.isValid(PASSWORD_1_LONG));\n\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n    }\n\n    @Test\n    public void shouldHandlePasswordStrengthLOW() {\n        view.setStrength(PasswordStrength.LOW);\n\n        assertTrue(view.isValid(PASSWORD_NUMERIC));\n        assertTrue(view.isValid(PASSWORD_ALPHA));\n        assertTrue(view.isValid(PASSWORD_ALPHA_LOWER_CASE));\n        assertTrue(view.isValid(PASSWORD_ALPHA_UPPER_CASE));\n        assertTrue(view.isValid(PASSWORD_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_IDENTICAL));\n\n        assertTrue(view.isValid(PASSWORD_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_NUMERIC));\n        assertTrue(view.isValid(PASSWORD_ALPHA_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC));\n\n        assertTrue(view.isValid(PASSWORD_128_LONG));\n        assertTrue(view.isValid(PASSWORD_10_LONG));\n        assertTrue(view.isValid(PASSWORD_8_LONG));\n        assertTrue(view.isValid(PASSWORD_6_LONG));\n        assertFalse(view.isValid(PASSWORD_1_LONG));\n\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n    }\n\n    @Test\n    public void shouldHandlePasswordStrengthFAIR() {\n        view.setStrength(PasswordStrength.FAIR);\n\n        assertFalse(view.isValid(PASSWORD_NUMERIC));\n        assertFalse(view.isValid(PASSWORD_ALPHA));\n        assertFalse(view.isValid(PASSWORD_ALPHA_LOWER_CASE));\n        assertFalse(view.isValid(PASSWORD_ALPHA_UPPER_CASE));\n        assertFalse(view.isValid(PASSWORD_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_IDENTICAL));\n\n        assertFalse(view.isValid(PASSWORD_NUMERIC_SPECIAL));\n        assertFalse(view.isValid(PASSWORD_ALPHA_NUMERIC));\n        assertFalse(view.isValid(PASSWORD_ALPHA_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC));\n\n        assertTrue(view.isValid(PASSWORD_128_LONG));\n        assertTrue(view.isValid(PASSWORD_10_LONG));\n        assertTrue(view.isValid(PASSWORD_8_LONG));\n        assertFalse(view.isValid(PASSWORD_6_LONG));\n        assertFalse(view.isValid(PASSWORD_1_LONG));\n\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n    }\n\n    @Test\n    public void shouldHandlePasswordStrengthGOOD() {\n        view.setStrength(PasswordStrength.GOOD);\n\n        assertFalse(view.isValid(PASSWORD_NUMERIC));\n        assertFalse(view.isValid(PASSWORD_ALPHA));\n        assertFalse(view.isValid(PASSWORD_ALPHA_LOWER_CASE));\n        assertFalse(view.isValid(PASSWORD_ALPHA_UPPER_CASE));\n        assertFalse(view.isValid(PASSWORD_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_IDENTICAL));\n\n        assertFalse(view.isValid(PASSWORD_NUMERIC_SPECIAL));\n        assertFalse(view.isValid(PASSWORD_ALPHA_NUMERIC));\n        assertTrue(view.isValid(PASSWORD_ALPHA_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC));\n\n        assertTrue(view.isValid(PASSWORD_128_LONG));\n        assertTrue(view.isValid(PASSWORD_10_LONG));\n        assertTrue(view.isValid(PASSWORD_8_LONG));\n        assertFalse(view.isValid(PASSWORD_6_LONG));\n        assertFalse(view.isValid(PASSWORD_1_LONG));\n\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n    }\n\n    @Test\n    public void shouldHandlePasswordStrengthEXCELLENT() {\n        view.setStrength(PasswordStrength.EXCELLENT);\n\n        assertFalse(view.isValid(PASSWORD_NUMERIC));\n        assertFalse(view.isValid(PASSWORD_ALPHA));\n        assertFalse(view.isValid(PASSWORD_ALPHA_LOWER_CASE));\n        assertFalse(view.isValid(PASSWORD_ALPHA_UPPER_CASE));\n        assertFalse(view.isValid(PASSWORD_SPECIAL));\n        assertFalse(view.isValid(PASSWORD_IDENTICAL));\n\n        assertFalse(view.isValid(PASSWORD_NUMERIC_SPECIAL));\n        assertFalse(view.isValid(PASSWORD_ALPHA_NUMERIC));\n        assertTrue(view.isValid(PASSWORD_ALPHA_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC_SPECIAL));\n        assertTrue(view.isValid(PASSWORD_ALPHA_CASE_NUMERIC));\n\n        assertTrue(view.isValid(PASSWORD_128_LONG));\n        assertTrue(view.isValid(PASSWORD_10_LONG));\n        assertFalse(view.isValid(PASSWORD_8_LONG));\n        assertFalse(view.isValid(PASSWORD_6_LONG));\n        assertFalse(view.isValid(PASSWORD_1_LONG));\n\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n    }\n\n    @Test\n    public void shouldOverrideMinLength() {\n        PasswordComplexity passwordComplexity;\n\n        // NONE is normally >= 1\n        passwordComplexity = new PasswordComplexity(PasswordStrength.NONE, 3);\n        view.setPasswordComplexity(passwordComplexity);\n\n        assertFalse(view.isValid(\"a\"));\n        assertTrue(view.isValid(\"abc\"));\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n\n        // LOW is normally >= 6\n        passwordComplexity = new PasswordComplexity(PasswordStrength.LOW, 8);\n        view.setPasswordComplexity(passwordComplexity);\n\n        assertFalse(view.isValid(\"abcdef\"));\n        assertTrue(view.isValid(\"abcdefgh\"));\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n\n        // FAIR is normally >= 8\n        passwordComplexity = new PasswordComplexity(PasswordStrength.FAIR, 10);\n        view.setPasswordComplexity(passwordComplexity);\n\n        assertFalse(view.isValid(\"ABCdefg9\"));\n        assertTrue(view.isValid(\"ABCdefghi9\"));\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n\n        // GOOD is normally >= 8\n        passwordComplexity = new PasswordComplexity(PasswordStrength.GOOD, 11);\n        view.setPasswordComplexity(passwordComplexity);\n\n        assertFalse(view.isValid(\"ABCdefg9\"));\n        assertTrue(view.isValid(\"ABCdefghij9\"));\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n\n        // EXCELLENT is normally >= 10\n        passwordComplexity = new PasswordComplexity(PasswordStrength.EXCELLENT, 15);\n        view.setPasswordComplexity(passwordComplexity);\n\n        assertFalse(view.isValid(\"ABCdefgh9!\"));\n        assertTrue(view.isValid(\"ABCdefghijklm9!\"));\n        assertFalse(view.isValid(PASSWORD_EMPTY));\n        assertFalse(view.isValid(PASSWORD_TOO_LONG));\n        assertFalse(view.isValid(null));\n    }\n}"
  },
  {
    "path": "lib/src/test/resources/appinfo.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"subscription\": \"dev\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"callback\": \"http://localhost:3000/\",\n  \"hasAllowedOrigins\": true,\n  \"strategies\": [\n    {\n      \"name\": \"auth0\",\n      \"connections\": [\n        {\n          \"name\": \"Username-Password-Authentication\",\n          \"domain\": null,\n          \"forgot_password_url\": \"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:Username-Password-Authentication\",\n          \"signup_url\": \"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:Username-Password-Authentication\",\n          \"showSignup\": true,\n          \"showForgot\": true,\n          \"requires_username\": false\n        },\n        {\n          \"name\": \"CustomDatabase\",\n          \"forgot_password_url\": \"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:CustomDatabase\",\n          \"signup_url\": \"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:CustomDatabase\",\n          \"showSignup\": true,\n          \"showForgot\": true,\n          \"requires_username\": false\n        },\n        {\n          \"name\": \"RestrictiveDatabase\",\n          \"forgot_password_url\": \"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:RestrictiveDatabase\",\n          \"signup_url\": \"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:RestrictiveDatabase\",\n          \"showSignup\": false,\n          \"showForgot\": false,\n          \"requires_username\": false\n        },\n        {\n          \"name\": \"with-strength\",\n          \"forgot_password_url\": \"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:lbalmaceda:with-strength\",\n          \"signup_url\": \"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:lbalmaceda:with-strength\",\n          \"passwordPolicy\": \"excellent\",\n          \"showSignup\": true,\n          \"showForgot\": true\n        }\n      ]\n    },\n    {\n      \"name\": \"ad\",\n      \"connections\": [\n        {\n          \"name\": \"MyAD\",\n          \"domain\": \"pepe.com\",\n          \"domain_aliases\": [\n            \"pepe.com\",\n            \"pep.com\"\n          ]\n        },\n        {\n          \"name\": \"mySecondAD\",\n          \"domain\": \"second.com\",\n          \"domain_aliases\": [\n            \"second.com\"\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"google-apps\",\n      \"connections\": [\n        {\n          \"name\": \"auth0.com\",\n          \"domain\": \"auth0.com\",\n          \"domain_aliases\": [\n            \"auth10.com\"\n          ],\n          \"scope\": [\n            \"email\",\n            \"profile\"\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"facebook\",\n      \"connections\": [\n        {\n          \"name\": \"facebook\",\n          \"scope\": \"public_profile\"\n        }\n      ]\n    },\n    {\n      \"name\": \"google-oauth2\",\n      \"connections\": [\n        {\n          \"name\": \"google-oauth2\",\n          \"scope\": [\n            \"email\",\n            \"profile\"\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"instagram\",\n      \"connections\": [\n        {\n          \"name\": \"instagram\",\n          \"scope\": [\n            \"basic\"\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"sms\",\n      \"connections\": [\n        {\n          \"name\": \"sms\"\n        },\n        {\n          \"name\": \"my-sms-connection\"\n        }\n      ]\n    },\n    {\n      \"name\": \"email\",\n      \"connections\": [\n        {\n          \"name\": \"email\"\n        }\n      ]\n    },\n    {\n      \"name\": \"twitter\",\n      \"connections\": [\n        {\n          \"name\": \"twitter\"\n        },\n        {\n          \"name\": \"twitter-dev\"\n        }\n      ]\n    },\n    {\n      \"name\": \"linkedin\",\n      \"connections\": []\n    }\n  ]\n}"
  },
  {
    "path": "lib/src/test/resources/application.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"subscription\": \"dev\",\n  \"callback\": \"http://localhost:3000/\",\n  \"hasAllowedOrigins\": true,\n  \"strategies\": [{\n      \"name\": \"twitter\",\n      \"connections\": [{\n          \"name\": \"twitter\"\n      }]\n  }]\n}"
  },
  {
    "path": "lib/src/test/resources/db_connection.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"callback\": \"http://localhost:3000/\",\n  \"strategies\": [{\n      \"name\": \"auth0\",\n      \"connections\": [{\n          \"name\": \"Username-Password-Authentication\",\n          \"domain\": null,\n          \"forgot_password_url\": \"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:Username-Password-Authentication\",\n          \"signup_url\": \"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:Username-Password-Authentication\",\n          \"passwordPolicy\": \"good\",\n          \"showSignup\": true,\n          \"showForgot\": true,\n          \"requires_username\": false\n      }]\n  }]\n}"
  },
  {
    "path": "lib/src/test/resources/db_connection_with_complexity.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"callback\": \"http://localhost:3000/\",\n  \"strategies\": [{\n      \"name\": \"auth0\",\n      \"connections\": [{\n          \"name\": \"Username-Password-Authentication\",\n          \"domain\": null,\n          \"forgot_password_url\": \"https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:Username-Password-Authentication\",\n          \"signup_url\": \"https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:Username-Password-Authentication\",\n          \"passwordPolicy\": \"fair\",\n          \"password_complexity_options\": {\n            \"min_length\": 12\n          },\n          \"showSignup\": true,\n          \"showForgot\": true,\n          \"requires_username\": false\n      }]\n  }]\n}"
  },
  {
    "path": "lib/src/test/resources/empty_object.json",
    "content": "{}"
  },
  {
    "path": "lib/src/test/resources/enterprise_connection.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"callback\": \"http://localhost:3000/\",\n  \"strategies\": [{\n      \"name\": \"ad\",\n      \"connections\": [{\n          \"name\": \"ad\",\n          \"domain\": \"auth10.com\",\n          \"domain_aliases\": [\"auth10.com\"]\n      }]\n  }]\n}"
  },
  {
    "path": "lib/src/test/resources/invalid.json",
    "content": "\"AN INVALID JSON\""
  },
  {
    "path": "lib/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker",
    "content": "mock-maker-inline"
  },
  {
    "path": "lib/src/test/resources/social_connection.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"callback\": \"http://localhost:3000/\",\n  \"strategies\": [{\n      \"name\": \"twitter\",\n      \"connections\": [{\n          \"name\": \"twitter\",\n          \"scope\": \"public_profile\"\n      }]\n  }]\n}"
  },
  {
    "path": "lib/src/test/resources/strategy.json",
    "content": "{\n  \"id\": \"CBBlULbbyQHSVWj5EqZSTMhUrJAS3UFA\",\n  \"tenant\": \"samples\",\n  \"authorize\": \"https://samples.auth0.com/authorize\",\n  \"callback\": \"http://localhost:3000/\",\n  \"strategies\": [{\n      \"name\": \"twitter\",\n      \"connections\": [{\n          \"name\": \"twitter\"\n      }]\n  }]\n}"
  },
  {
    "path": "opslevel.yml",
    "content": "---\nversion: 1\nrepository:\n  owner: dx_sdks\n  tier:\n  tags:\n"
  },
  {
    "path": "proguard/proguard-gson.pro",
    "content": "# Gson\n\n-keepattributes Signature\n-keepattributes *Annotation*\n\n-dontwarn com.google.gson.internal.UnsafeAllocator"
  },
  {
    "path": "proguard/proguard-lock-2.pro",
    "content": "# Lock.Android v2\n\n## Parcelables\n-keepnames class * implements android.os.Parcelable {\n    public static final ** CREATOR;\n}\n\n## Descriptor classes\n-keep public class com.auth0.android.lock.events.*\n-keep public class com.auth0.android.lock.adapters.Country\n-keep public interface com.auth0.android.lock.internal.configuration.OAuthConnection\n-keep public interface com.auth0.android.lock.views.interfaces.IdentityListener"
  },
  {
    "path": "proguard/proguard-otto.pro",
    "content": "# Otto\n\n-keepattributes *Annotation*\n-keepclassmembers class ** {\n    @com.squareup.otto.Subscribe public *;\n}"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'Lock.Android'\ninclude ':app'\n\ninclude ':lock'\nproject(':lock').projectDir = new File(rootProject.projectDir, '/lib')"
  }
]