Repository: GoogleChrome/chrome-extensions-samples
Branch: main
Commit: c4393862e164
Files: 2371
Total size: 10.6 MB
Directory structure:
gitextract_wq83segv/
├── .allstar/
│ └── binary_artifacts.yaml
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── bug_report.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── lint.yml
│ └── sample-list-generator.yml
├── .gitignore
├── .husky/
│ └── pre-commit
├── .prettierignore
├── .prettierrc.json
├── .repo/
│ ├── migrate-samples.js
│ └── sample-list-generator/
│ ├── .gitignore
│ ├── README.md
│ ├── extension-apis.json
│ ├── package.json
│ ├── src/
│ │ ├── constants.ts
│ │ ├── index.ts
│ │ ├── libs/
│ │ │ ├── api-detector.ts
│ │ │ ├── api-loader.ts
│ │ │ └── sample-collector.ts
│ │ ├── prepare-chrome-types.ts
│ │ ├── types.ts
│ │ └── utils/
│ │ ├── filesystem.ts
│ │ └── manifest.ts
│ └── test/
│ └── api-detector/
│ └── api-detector.test.ts
├── CONTRIBUTING.md
├── LICENSE
├── README-template.md
├── README.md
├── _archive/
│ ├── apps/
│ │ ├── README.md
│ │ ├── libraries/
│ │ │ └── gapi-chrome-apps-lib/
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ └── gapi-chrome-apps.js
│ │ └── samples/
│ │ ├── analytics/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── google-analytics-bundle.js
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── sample_support_metadata.json
│ │ ├── appengine-channelapi/
│ │ │ ├── README.md
│ │ │ ├── app/
│ │ │ │ ├── README.md
│ │ │ │ ├── channel_in_a_webview.js
│ │ │ │ ├── game.js
│ │ │ │ ├── index.css
│ │ │ │ ├── index.html
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ └── appengine/
│ │ │ ├── app.yaml
│ │ │ ├── chatactoe.py
│ │ │ └── static/
│ │ │ └── channel_in_a_webview.html
│ │ ├── appsquare/
│ │ │ ├── README.md
│ │ │ ├── assets/
│ │ │ │ └── icon.psd
│ │ │ ├── background.js
│ │ │ ├── foursquare.js
│ │ │ ├── loader.js
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── appview/
│ │ │ ├── README.md
│ │ │ ├── embedded-app/
│ │ │ │ ├── README.md
│ │ │ │ ├── camera.html
│ │ │ │ ├── camera.js
│ │ │ │ ├── default.html
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ └── host-app/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── blink1/
│ │ │ ├── README.md
│ │ │ ├── blink1.js
│ │ │ ├── color-picker.html
│ │ │ ├── color-picker.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── style.css
│ │ │ └── udev/
│ │ │ └── 61-blink1.rules
│ │ ├── bluetooth-samples/
│ │ │ ├── battery-service-demo/
│ │ │ │ ├── README.md
│ │ │ │ ├── background.js
│ │ │ │ ├── main.html
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── style.css
│ │ │ │ └── ui.js
│ │ │ ├── device-info-demo/
│ │ │ │ ├── README.md
│ │ │ │ ├── background.js
│ │ │ │ ├── main.html
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── style.css
│ │ │ │ └── ui.js
│ │ │ └── heart-rate-sensor/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── style.css
│ │ │ └── ui.js
│ │ ├── calculator/
│ │ │ ├── README.md
│ │ │ ├── calculator.html
│ │ │ ├── controller.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── model.js
│ │ │ ├── sample_support_metadata.json
│ │ │ ├── style.css
│ │ │ ├── tests/
│ │ │ │ ├── calculator_test.html
│ │ │ │ └── calculator_test.js
│ │ │ └── view.js
│ │ ├── camera-capture/
│ │ │ ├── README.md
│ │ │ ├── app.js
│ │ │ ├── background.js
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── clock/
│ │ │ ├── README.md
│ │ │ ├── alarm.js
│ │ │ ├── clock.js
│ │ │ ├── index.html
│ │ │ ├── lib/
│ │ │ │ └── tipTipv13/
│ │ │ │ ├── jquery.tipTip.js
│ │ │ │ ├── jquery.tipTip.minified.js
│ │ │ │ └── tipTip.css
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── script.js
│ │ │ ├── stopwatch.js
│ │ │ ├── style.css
│ │ │ ├── tests/
│ │ │ │ ├── clock_test.html
│ │ │ │ ├── clock_test.js
│ │ │ │ └── lib/
│ │ │ │ ├── prototype.js
│ │ │ │ └── right.js
│ │ │ └── timer.js
│ │ ├── context-menu/
│ │ │ ├── README.md
│ │ │ ├── a.html
│ │ │ ├── a.js
│ │ │ ├── b.html
│ │ │ ├── b.js
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── dart/
│ │ │ ├── README.md
│ │ │ ├── clock.html
│ │ │ ├── compile.sh
│ │ │ ├── css/
│ │ │ │ └── clock.css
│ │ │ ├── dart/
│ │ │ │ ├── balls.dart
│ │ │ │ ├── clock.dart
│ │ │ │ ├── clock.dart.precompiled.js
│ │ │ │ └── numbers.dart
│ │ │ ├── js/
│ │ │ │ ├── browser_dart_csp_safe.js
│ │ │ │ └── main.js
│ │ │ ├── manifest.json
│ │ │ ├── pubspec.yaml
│ │ │ └── sample_support_metadata.json
│ │ ├── desktop-capture/
│ │ │ ├── README.md
│ │ │ ├── app.js
│ │ │ ├── background.js
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── dialog-element/
│ │ │ ├── README.md
│ │ │ ├── dialog.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── styles.css
│ │ ├── diff/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ ├── editor.css
│ │ │ │ └── style.css
│ │ │ ├── js/
│ │ │ │ ├── background.js
│ │ │ │ ├── diff.js
│ │ │ │ └── filesystem.js
│ │ │ ├── lib/
│ │ │ │ ├── diff_match_patch.js
│ │ │ │ ├── diff_match_patch_test.html
│ │ │ │ ├── diff_match_patch_test.js
│ │ │ │ ├── diff_match_patch_uncompressed.js
│ │ │ │ └── jquery.activity-indicator.js
│ │ │ ├── main.html
│ │ │ └── manifest.json
│ │ ├── dojo/
│ │ │ ├── .gitignore
│ │ │ ├── Markdown_1.0.1/
│ │ │ │ ├── License.text
│ │ │ │ ├── Markdown Readme.text
│ │ │ │ └── Markdown.pl
│ │ │ ├── README.md
│ │ │ ├── build.sh
│ │ │ ├── crxmake.sh
│ │ │ ├── executable_list
│ │ │ └── include/
│ │ │ └── main.css
│ │ ├── filesystem-access/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── index.html
│ │ │ ├── js/
│ │ │ │ ├── app.js
│ │ │ │ └── dnd.js
│ │ │ └── manifest.json
│ │ ├── frameless-window/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── frameless_window.html
│ │ │ ├── frameless_window.js
│ │ │ ├── manifest.json
│ │ │ ├── style.css
│ │ │ └── titlebar.js
│ │ ├── gcm-notifications/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── register.html
│ │ │ └── register.js
│ │ ├── gdrive/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ ├── bootstrap.css
│ │ │ │ └── main.css
│ │ │ ├── js/
│ │ │ │ ├── app.js
│ │ │ │ ├── background.js
│ │ │ │ ├── dnd.js
│ │ │ │ ├── gdocs.js
│ │ │ │ ├── upload.js
│ │ │ │ └── util.js
│ │ │ ├── main.html
│ │ │ └── manifest.json
│ │ ├── github-auth/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── hello-world/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ └── styles/
│ │ │ └── main.css
│ │ ├── hello-world-sync/
│ │ │ ├── README.md
│ │ │ ├── app.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ └── style.css
│ │ ├── hid/
│ │ │ ├── README.md
│ │ │ ├── control-panel.html
│ │ │ ├── control-panel.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── style.css
│ │ ├── identity/
│ │ │ ├── README.md
│ │ │ ├── identity.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support/
│ │ │ │ ├── README.md
│ │ │ │ ├── google-code-prettify/
│ │ │ │ │ ├── lang-css.js
│ │ │ │ │ └── run_prettify.js
│ │ │ │ ├── prettify.css
│ │ │ │ ├── prettify.js
│ │ │ │ ├── prettify_theme.css
│ │ │ │ ├── sample_support.js
│ │ │ │ ├── show_snippets.html
│ │ │ │ ├── show_snippets.js
│ │ │ │ ├── snippets.css
│ │ │ │ └── standard.css
│ │ │ └── sample_support_metadata.json
│ │ ├── image-edit/
│ │ │ ├── README.md
│ │ │ ├── app.js
│ │ │ ├── background.js
│ │ │ ├── dnd.js
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── instagram-auth/
│ │ │ ├── README.md
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── styles/
│ │ │ └── main.css
│ │ ├── io2012-presentation/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ ├── presentation.css
│ │ │ │ └── theme.css
│ │ │ ├── diff-sample-files/
│ │ │ │ ├── new-manifest.json
│ │ │ │ └── old-manifest.json
│ │ │ ├── helloworld/
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── snippets
│ │ │ │ ├── window.html
│ │ │ │ └── window.js
│ │ │ ├── js/
│ │ │ │ ├── main.js
│ │ │ │ ├── servo.js
│ │ │ │ ├── slide-config.js
│ │ │ │ ├── slide-controller.js
│ │ │ │ ├── slide-deck.js
│ │ │ │ └── slides.js
│ │ │ ├── manifest.json
│ │ │ ├── presentation.html
│ │ │ ├── servo/
│ │ │ │ ├── background.js
│ │ │ │ ├── main.html
│ │ │ │ ├── manifest.json
│ │ │ │ ├── servo.js
│ │ │ │ └── styles.css
│ │ │ └── windowing_api/
│ │ │ ├── copycat.html
│ │ │ ├── original.html
│ │ │ ├── window.css
│ │ │ └── window.js
│ │ ├── ioio/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── keyboard-handler/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── window.html
│ │ │ └── window.js
│ │ ├── managed-in-app-payments/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ └── app.css
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── scripts/
│ │ │ ├── app.js
│ │ │ └── buy.js
│ │ ├── manga-cam/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── css/
│ │ │ │ └── index.css
│ │ │ ├── index.html
│ │ │ ├── js/
│ │ │ │ ├── index.js
│ │ │ │ ├── loader.js
│ │ │ │ ├── postproc.js
│ │ │ │ └── shaders/
│ │ │ │ ├── blur.x.glsl
│ │ │ │ ├── blur.y.glsl
│ │ │ │ ├── copy.fs.glsl
│ │ │ │ ├── flake.fs.glsl
│ │ │ │ ├── index.include.glsl
│ │ │ │ ├── merge.fs.glsl
│ │ │ │ ├── packing.include.glsl
│ │ │ │ ├── sobel.fs.glsl
│ │ │ │ └── toonize.fs.glsl
│ │ │ └── manifest.json
│ │ ├── mdns-browser/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── dns.js
│ │ │ ├── header.css
│ │ │ ├── main.css
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── service-types.js
│ │ ├── media-gallery/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ ├── media-gallery.js
│ │ │ ├── page.html
│ │ │ ├── runtime.js
│ │ │ └── styles.css
│ │ ├── messaging/
│ │ │ ├── README.md
│ │ │ ├── app1/
│ │ │ │ ├── README.md
│ │ │ │ ├── index.html
│ │ │ │ ├── index.js
│ │ │ │ ├── main.css
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ ├── app2/
│ │ │ │ ├── README.md
│ │ │ │ ├── index.html
│ │ │ │ ├── index.js
│ │ │ │ ├── main.css
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ └── extension/
│ │ │ ├── README.md
│ │ │ ├── eventPage.js
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.css
│ │ │ └── manifest.json
│ │ ├── mini-code-edit/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── cm/
│ │ │ │ ├── LICENSE
│ │ │ │ ├── README.md
│ │ │ │ ├── demo/
│ │ │ │ │ ├── activeline.html
│ │ │ │ │ ├── changemode.html
│ │ │ │ │ ├── closetag.html
│ │ │ │ │ ├── complete.html
│ │ │ │ │ ├── emacs.html
│ │ │ │ │ ├── folding.html
│ │ │ │ │ ├── formatting.html
│ │ │ │ │ ├── fullscreen.html
│ │ │ │ │ ├── loadmode.html
│ │ │ │ │ ├── marker.html
│ │ │ │ │ ├── matchhighlighter.html
│ │ │ │ │ ├── mustache.html
│ │ │ │ │ ├── preview.html
│ │ │ │ │ ├── resize.html
│ │ │ │ │ ├── runmode.html
│ │ │ │ │ ├── search.html
│ │ │ │ │ ├── theme.html
│ │ │ │ │ ├── vim.html
│ │ │ │ │ └── visibletabs.html
│ │ │ │ ├── doc/
│ │ │ │ │ ├── compress.html
│ │ │ │ │ ├── docs.css
│ │ │ │ │ ├── internals.html
│ │ │ │ │ ├── manual.html
│ │ │ │ │ ├── oldrelease.html
│ │ │ │ │ ├── reporting.html
│ │ │ │ │ └── upgrade_v2.2.html
│ │ │ │ ├── index.html
│ │ │ │ ├── keymap/
│ │ │ │ │ ├── emacs.js
│ │ │ │ │ └── vim.js
│ │ │ │ ├── lib/
│ │ │ │ │ ├── codemirror.css
│ │ │ │ │ ├── codemirror.js
│ │ │ │ │ └── util/
│ │ │ │ │ ├── closetag.js
│ │ │ │ │ ├── dialog.css
│ │ │ │ │ ├── dialog.js
│ │ │ │ │ ├── foldcode.js
│ │ │ │ │ ├── formatting.js
│ │ │ │ │ ├── javascript-hint.js
│ │ │ │ │ ├── loadmode.js
│ │ │ │ │ ├── match-highlighter.js
│ │ │ │ │ ├── overlay.js
│ │ │ │ │ ├── runmode.js
│ │ │ │ │ ├── search.js
│ │ │ │ │ ├── searchcursor.js
│ │ │ │ │ ├── simple-hint.css
│ │ │ │ │ └── simple-hint.js
│ │ │ │ ├── mode/
│ │ │ │ │ ├── clike/
│ │ │ │ │ │ ├── clike.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── clojure/
│ │ │ │ │ │ ├── clojure.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── coffeescript/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── coffeescript.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── css/
│ │ │ │ │ │ ├── css.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── diff/
│ │ │ │ │ │ ├── diff.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── ecl/
│ │ │ │ │ │ ├── ecl.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── erlang/
│ │ │ │ │ │ ├── erlang.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── gfm/
│ │ │ │ │ │ ├── gfm.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── go/
│ │ │ │ │ │ ├── go.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── groovy/
│ │ │ │ │ │ ├── groovy.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── haskell/
│ │ │ │ │ │ ├── haskell.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── htmlembedded/
│ │ │ │ │ │ ├── htmlembedded.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── htmlmixed/
│ │ │ │ │ │ ├── htmlmixed.js
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── javascript/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── javascript.js
│ │ │ │ │ ├── jinja2/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── jinja2.js
│ │ │ │ │ ├── less/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── less.js
│ │ │ │ │ ├── lua/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── lua.js
│ │ │ │ │ ├── markdown/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── markdown.js
│ │ │ │ │ ├── mysql/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── mysql.js
│ │ │ │ │ ├── ntriples/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── ntriples.js
│ │ │ │ │ ├── pascal/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── pascal.js
│ │ │ │ │ ├── perl/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── perl.js
│ │ │ │ │ ├── php/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── php.js
│ │ │ │ │ ├── pig/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── pig.js
│ │ │ │ │ ├── plsql/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── plsql.js
│ │ │ │ │ ├── properties/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── properties.js
│ │ │ │ │ ├── python/
│ │ │ │ │ │ ├── LICENSE.txt
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── python.js
│ │ │ │ │ ├── r/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── r.js
│ │ │ │ │ ├── rpm/
│ │ │ │ │ │ ├── changes/
│ │ │ │ │ │ │ ├── changes.js
│ │ │ │ │ │ │ └── index.html
│ │ │ │ │ │ └── spec/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── spec.css
│ │ │ │ │ │ └── spec.js
│ │ │ │ │ ├── rst/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── rst.js
│ │ │ │ │ ├── ruby/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── ruby.js
│ │ │ │ │ ├── rust/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── rust.js
│ │ │ │ │ ├── scheme/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── scheme.js
│ │ │ │ │ ├── shell/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── shell.js
│ │ │ │ │ ├── smalltalk/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── smalltalk.js
│ │ │ │ │ ├── smarty/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── smarty.js
│ │ │ │ │ ├── sparql/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── sparql.js
│ │ │ │ │ ├── stex/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── stex.js
│ │ │ │ │ │ └── test.html
│ │ │ │ │ ├── tiddlywiki/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── tiddlywiki.css
│ │ │ │ │ │ └── tiddlywiki.js
│ │ │ │ │ ├── tiki/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── tiki.css
│ │ │ │ │ │ └── tiki.js
│ │ │ │ │ ├── vbscript/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── vbscript.js
│ │ │ │ │ ├── velocity/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── velocity.js
│ │ │ │ │ ├── verilog/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── verilog.js
│ │ │ │ │ ├── xml/
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ └── xml.js
│ │ │ │ │ ├── xquery/
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ ├── test/
│ │ │ │ │ │ │ ├── index.html
│ │ │ │ │ │ │ ├── testBase.js
│ │ │ │ │ │ │ ├── testEmptySequenceKeyword.js
│ │ │ │ │ │ │ ├── testMultiAttr.js
│ │ │ │ │ │ │ ├── testNamespaces.js
│ │ │ │ │ │ │ ├── testProcessingInstructions.js
│ │ │ │ │ │ │ └── testQuotes.js
│ │ │ │ │ │ └── xquery.js
│ │ │ │ │ └── yaml/
│ │ │ │ │ ├── index.html
│ │ │ │ │ └── yaml.js
│ │ │ │ ├── test/
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── mode_test.css
│ │ │ │ │ ├── mode_test.js
│ │ │ │ │ └── test.js
│ │ │ │ └── theme/
│ │ │ │ ├── ambiance.css
│ │ │ │ ├── blackboard.css
│ │ │ │ ├── cobalt.css
│ │ │ │ ├── eclipse.css
│ │ │ │ ├── elegant.css
│ │ │ │ ├── erlang-dark.css
│ │ │ │ ├── lesser-dark.css
│ │ │ │ ├── monokai.css
│ │ │ │ ├── neat.css
│ │ │ │ ├── night.css
│ │ │ │ ├── rubyblue.css
│ │ │ │ └── xq-dark.css
│ │ │ ├── editor.js
│ │ │ ├── img/
│ │ │ │ └── README.txt
│ │ │ ├── main.html
│ │ │ ├── manifest.json
│ │ │ ├── snippets.js
│ │ │ └── style.css
│ │ ├── multicast/
│ │ │ ├── ChatClient.js
│ │ │ ├── Collection.js
│ │ │ ├── MulticastSocket.js
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── index.css
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── manifest.json
│ │ ├── one-time-payment/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ ├── app.css
│ │ │ │ └── bootstrap.css
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── scripts/
│ │ │ └── app.js
│ │ ├── optional-permissions/
│ │ │ ├── README.md
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── permissions.html
│ │ │ └── permissions.js
│ │ ├── parrot-ar-drone/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── lib/
│ │ │ │ ├── API.js
│ │ │ │ ├── Command.js
│ │ │ │ ├── Gamepad.js
│ │ │ │ ├── NavData.js
│ │ │ │ ├── Sequence.js
│ │ │ │ └── Util.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ ├── scripts/
│ │ │ │ └── app.js
│ │ │ ├── styles/
│ │ │ │ └── drone.css
│ │ │ └── third-party/
│ │ │ └── gamepad.js
│ │ ├── platform-title/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── main.css
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── platform-mac.css
│ │ ├── printing/
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── a.js
│ │ │ ├── application.js
│ │ │ ├── controls.html
│ │ │ ├── controls.js
│ │ │ ├── document.html
│ │ │ ├── document.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── printout.html
│ │ │ ├── printout.js
│ │ │ └── style.css
│ │ ├── restarted-demo/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── main.html
│ │ │ ├── manifest.json
│ │ │ └── sample_support_metadata.json
│ │ ├── rich-notifications/
│ │ │ ├── README.md
│ │ │ ├── app.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ ├── styles.css
│ │ │ └── window.html
│ │ ├── sandbox/
│ │ │ ├── LICENSE.handlebars
│ │ │ ├── README.md
│ │ │ ├── handlebars-1.0.0.beta.6.js
│ │ │ ├── main.js
│ │ │ ├── mainpage.html
│ │ │ ├── mainpage.js
│ │ │ ├── manifest.json
│ │ │ ├── sandbox.html
│ │ │ └── styles/
│ │ │ └── main.css
│ │ ├── sandboxed-content/
│ │ │ ├── README.md
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sandboxed.html
│ │ │ └── styles/
│ │ │ └── main.css
│ │ ├── serial/
│ │ │ ├── adkjs/
│ │ │ │ ├── README.md
│ │ │ │ ├── app/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── comm.html
│ │ │ │ │ ├── css/
│ │ │ │ │ │ └── main.css
│ │ │ │ │ ├── img/
│ │ │ │ │ │ └── icon.xcf
│ │ │ │ │ ├── js/
│ │ │ │ │ │ ├── adk.js
│ │ │ │ │ │ ├── background.js
│ │ │ │ │ │ └── serial.js
│ │ │ │ │ └── manifest.json
│ │ │ │ └── firmware/
│ │ │ │ ├── arduino_libs/
│ │ │ │ │ ├── AndroidAccessory/
│ │ │ │ │ │ ├── AndroidAccessory.cpp
│ │ │ │ │ │ └── AndroidAccessory.h
│ │ │ │ │ ├── CapSense/
│ │ │ │ │ │ ├── CapSense.cpp
│ │ │ │ │ │ └── CapSense.h
│ │ │ │ │ ├── TimedAction/
│ │ │ │ │ │ ├── TimedAction.cpp
│ │ │ │ │ │ └── TimedAction.h
│ │ │ │ │ └── USB_Host_Shield/
│ │ │ │ │ ├── Max3421e.cpp
│ │ │ │ │ ├── Max3421e.h
│ │ │ │ │ ├── Max3421e_constants.h
│ │ │ │ │ ├── Max_LCD.cpp
│ │ │ │ │ ├── Max_LCD.h
│ │ │ │ │ ├── README
│ │ │ │ │ ├── Usb.cpp
│ │ │ │ │ ├── Usb.h
│ │ │ │ │ └── ch9.h
│ │ │ │ └── demokitclient/
│ │ │ │ └── demokitclient.ino
│ │ │ ├── espruino/
│ │ │ │ ├── README.md
│ │ │ │ ├── index.html
│ │ │ │ ├── launch.js
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ └── ledtoggle/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── launch.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── sketches/
│ │ │ └── serial_light/
│ │ │ └── serial_light.ino
│ │ ├── serial-control-signals/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── logic.js
│ │ │ ├── main.html
│ │ │ ├── manifest.json
│ │ │ └── styles.css
│ │ ├── servo/
│ │ │ ├── README.md
│ │ │ ├── Servo/
│ │ │ │ └── Servo.ino
│ │ │ ├── background.js
│ │ │ ├── main.html
│ │ │ ├── manifest.json
│ │ │ ├── servo.js
│ │ │ └── styles.css
│ │ ├── storage/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── syncfs-editor/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ └── editor.css
│ │ │ ├── js/
│ │ │ │ ├── background.js
│ │ │ │ ├── editor.js
│ │ │ │ ├── filer.js
│ │ │ │ ├── main.js
│ │ │ │ └── utils.js
│ │ │ ├── main.html
│ │ │ └── manifest.json
│ │ ├── systemInfo/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── systemInfo.js
│ │ ├── tasks/
│ │ │ ├── README.md
│ │ │ ├── gapi-chrome-apps.js
│ │ │ ├── gapiCallback.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── sample_support_metadata.json
│ │ ├── tcpserver/
│ │ │ ├── README.md
│ │ │ ├── commands/
│ │ │ │ ├── BrowserCommands.js
│ │ │ │ └── webview.html
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ ├── server.js
│ │ │ ├── styles/
│ │ │ │ ├── main.css
│ │ │ │ └── webview.css
│ │ │ └── tcp-server.js
│ │ ├── telnet/
│ │ │ ├── README.md
│ │ │ ├── ansi-converter.js
│ │ │ ├── launch.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ ├── tcp-client.js
│ │ │ ├── terminal.css
│ │ │ ├── terminal.html
│ │ │ └── terminal.js
│ │ ├── text-editor/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── editor.html
│ │ │ ├── editor.js
│ │ │ ├── icons/
│ │ │ │ └── Readme.txt
│ │ │ ├── lib/
│ │ │ │ ├── ace/
│ │ │ │ │ ├── ace.js
│ │ │ │ │ ├── anchor.js
│ │ │ │ │ ├── anchor_test.js
│ │ │ │ │ ├── background_tokenizer.js
│ │ │ │ │ ├── commands/
│ │ │ │ │ │ ├── command_manager.js
│ │ │ │ │ │ ├── command_manager_test.js
│ │ │ │ │ │ ├── default_commands.js
│ │ │ │ │ │ └── multi_select_commands.js
│ │ │ │ │ ├── config.js
│ │ │ │ │ ├── css/
│ │ │ │ │ │ └── editor.css
│ │ │ │ │ ├── document.js
│ │ │ │ │ ├── document_test.js
│ │ │ │ │ ├── edit_session/
│ │ │ │ │ │ ├── bracket_match.js
│ │ │ │ │ │ ├── fold.js
│ │ │ │ │ │ ├── fold_line.js
│ │ │ │ │ │ └── folding.js
│ │ │ │ │ ├── edit_session.js
│ │ │ │ │ ├── edit_session_test.js
│ │ │ │ │ ├── editor.js
│ │ │ │ │ ├── editor_change_document_test.js
│ │ │ │ │ ├── editor_highlight_selected_word_test.js
│ │ │ │ │ ├── editor_navigation_test.js
│ │ │ │ │ ├── editor_text_edit_test.js
│ │ │ │ │ ├── ext/
│ │ │ │ │ │ ├── static.css
│ │ │ │ │ │ ├── static_highlight.js
│ │ │ │ │ │ ├── static_highlight_test.js
│ │ │ │ │ │ └── textarea.js
│ │ │ │ │ ├── keyboard/
│ │ │ │ │ │ ├── hash_handler.js
│ │ │ │ │ │ ├── keybinding/
│ │ │ │ │ │ │ ├── emacs.js
│ │ │ │ │ │ │ └── vim.js
│ │ │ │ │ │ ├── keybinding.js
│ │ │ │ │ │ ├── state_handler.js
│ │ │ │ │ │ └── textinput.js
│ │ │ │ │ ├── layer/
│ │ │ │ │ │ ├── cursor.js
│ │ │ │ │ │ ├── gutter.js
│ │ │ │ │ │ ├── marker.js
│ │ │ │ │ │ ├── text.js
│ │ │ │ │ │ └── text_test.js
│ │ │ │ │ ├── lib/
│ │ │ │ │ │ ├── browser_focus.js
│ │ │ │ │ │ ├── dom.js
│ │ │ │ │ │ ├── es5-shim.js
│ │ │ │ │ │ ├── event.js
│ │ │ │ │ │ ├── event_emitter.js
│ │ │ │ │ │ ├── event_emitter_test.js
│ │ │ │ │ │ ├── fixoldbrowsers.js
│ │ │ │ │ │ ├── keys.js
│ │ │ │ │ │ ├── lang.js
│ │ │ │ │ │ ├── net.js
│ │ │ │ │ │ ├── oop.js
│ │ │ │ │ │ ├── regexp.js
│ │ │ │ │ │ └── useragent.js
│ │ │ │ │ ├── mode/
│ │ │ │ │ │ ├── behaviour/
│ │ │ │ │ │ │ ├── cstyle.js
│ │ │ │ │ │ │ ├── xml.js
│ │ │ │ │ │ │ └── xquery.js
│ │ │ │ │ │ ├── behaviour.js
│ │ │ │ │ │ ├── c_cpp.js
│ │ │ │ │ │ ├── c_cpp_highlight_rules.js
│ │ │ │ │ │ ├── clojure.js
│ │ │ │ │ │ ├── clojure_highlight_rules.js
│ │ │ │ │ │ ├── coffee/
│ │ │ │ │ │ │ ├── coffee-script.js
│ │ │ │ │ │ │ ├── helpers.js
│ │ │ │ │ │ │ ├── lexer.js
│ │ │ │ │ │ │ ├── nodes.js
│ │ │ │ │ │ │ ├── parser.js
│ │ │ │ │ │ │ ├── parser_test.js
│ │ │ │ │ │ │ ├── rewriter.js
│ │ │ │ │ │ │ └── scope.js
│ │ │ │ │ │ ├── coffee.js
│ │ │ │ │ │ ├── coffee_highlight_rules.js
│ │ │ │ │ │ ├── coffee_highlight_rules_test.js
│ │ │ │ │ │ ├── coffee_worker.js
│ │ │ │ │ │ ├── coldfusion.js
│ │ │ │ │ │ ├── coldfusion_highlight_rules.js
│ │ │ │ │ │ ├── coldfusion_test.js
│ │ │ │ │ │ ├── csharp.js
│ │ │ │ │ │ ├── csharp_highlight_rules.js
│ │ │ │ │ │ ├── css/
│ │ │ │ │ │ │ └── csslint.js
│ │ │ │ │ │ ├── css.js
│ │ │ │ │ │ ├── css_highlight_rules.js
│ │ │ │ │ │ ├── css_highlight_rules_test.js
│ │ │ │ │ │ ├── css_test.js
│ │ │ │ │ │ ├── css_worker.js
│ │ │ │ │ │ ├── css_worker_test.js
│ │ │ │ │ │ ├── doc_comment_highlight_rules.js
│ │ │ │ │ │ ├── folding/
│ │ │ │ │ │ │ ├── cstyle.js
│ │ │ │ │ │ │ ├── cstyle_test.js
│ │ │ │ │ │ │ ├── fold_mode.js
│ │ │ │ │ │ │ ├── html.js
│ │ │ │ │ │ │ ├── html_test.js
│ │ │ │ │ │ │ ├── mixed.js
│ │ │ │ │ │ │ ├── pythonic.js
│ │ │ │ │ │ │ ├── pythonic_test.js
│ │ │ │ │ │ │ ├── xml.js
│ │ │ │ │ │ │ └── xml_test.js
│ │ │ │ │ │ ├── golang.js
│ │ │ │ │ │ ├── golang_highlight_rules.js
│ │ │ │ │ │ ├── groovy.js
│ │ │ │ │ │ ├── groovy_highlight_rules.js
│ │ │ │ │ │ ├── haxe.js
│ │ │ │ │ │ ├── haxe_highlight_rules.js
│ │ │ │ │ │ ├── html.js
│ │ │ │ │ │ ├── html_highlight_rules.js
│ │ │ │ │ │ ├── html_highlight_rules_test.js
│ │ │ │ │ │ ├── html_test.js
│ │ │ │ │ │ ├── java.js
│ │ │ │ │ │ ├── java_highlight_rules.js
│ │ │ │ │ │ ├── javascript.js
│ │ │ │ │ │ ├── javascript_highlight_rules.js
│ │ │ │ │ │ ├── javascript_highlight_rules_test.js
│ │ │ │ │ │ ├── javascript_test.js
│ │ │ │ │ │ ├── javascript_worker.js
│ │ │ │ │ │ ├── javascript_worker_test.js
│ │ │ │ │ │ ├── json/
│ │ │ │ │ │ │ └── json_parse.js
│ │ │ │ │ │ ├── json.js
│ │ │ │ │ │ ├── json_highlight_rules.js
│ │ │ │ │ │ ├── json_worker.js
│ │ │ │ │ │ ├── json_worker_test.js
│ │ │ │ │ │ ├── latex.js
│ │ │ │ │ │ ├── latex_highlight_rules.js
│ │ │ │ │ │ ├── less.js
│ │ │ │ │ │ ├── less_highlight_rules.js
│ │ │ │ │ │ ├── liquid.js
│ │ │ │ │ │ ├── liquid_highlight_rules.js
│ │ │ │ │ │ ├── liquid_highlight_rules_test.js
│ │ │ │ │ │ ├── lua.js
│ │ │ │ │ │ ├── lua_highlight_rules.js
│ │ │ │ │ │ ├── markdown.js
│ │ │ │ │ │ ├── markdown_highlight_rules.js
│ │ │ │ │ │ ├── matching_brace_outdent.js
│ │ │ │ │ │ ├── matching_parens_outdent.js
│ │ │ │ │ │ ├── ocaml.js
│ │ │ │ │ │ ├── ocaml_highlight_rules.js
│ │ │ │ │ │ ├── perl.js
│ │ │ │ │ │ ├── perl_highlight_rules.js
│ │ │ │ │ │ ├── pgsql.js
│ │ │ │ │ │ ├── pgsql_highlight_rules.js
│ │ │ │ │ │ ├── php.js
│ │ │ │ │ │ ├── php_highlight_rules.js
│ │ │ │ │ │ ├── powershell.js
│ │ │ │ │ │ ├── powershell_highlight_rules.js
│ │ │ │ │ │ ├── python.js
│ │ │ │ │ │ ├── python_highlight_rules.js
│ │ │ │ │ │ ├── python_test.js
│ │ │ │ │ │ ├── ruby.js
│ │ │ │ │ │ ├── ruby_highlight_rules.js
│ │ │ │ │ │ ├── ruby_highlight_rules_test.js
│ │ │ │ │ │ ├── scad.js
│ │ │ │ │ │ ├── scad_highlight_rules.js
│ │ │ │ │ │ ├── scala.js
│ │ │ │ │ │ ├── scala_highlight_rules.js
│ │ │ │ │ │ ├── scss.js
│ │ │ │ │ │ ├── scss_highlight_rules.js
│ │ │ │ │ │ ├── sh.js
│ │ │ │ │ │ ├── sh_highlight_rules.js
│ │ │ │ │ │ ├── sql.js
│ │ │ │ │ │ ├── sql_highlight_rules.js
│ │ │ │ │ │ ├── svg.js
│ │ │ │ │ │ ├── svg_highlight_rules.js
│ │ │ │ │ │ ├── text.js
│ │ │ │ │ │ ├── text_highlight_rules.js
│ │ │ │ │ │ ├── text_test.js
│ │ │ │ │ │ ├── textile.js
│ │ │ │ │ │ ├── textile_highlight_rules.js
│ │ │ │ │ │ ├── xml.js
│ │ │ │ │ │ ├── xml_highlight_rules.js
│ │ │ │ │ │ ├── xml_highlight_rules_test.js
│ │ │ │ │ │ ├── xml_test.js
│ │ │ │ │ │ ├── xml_util.js
│ │ │ │ │ │ ├── xquery.js
│ │ │ │ │ │ └── xquery_highlight_rules.js
│ │ │ │ │ ├── model/
│ │ │ │ │ │ └── editor.js
│ │ │ │ │ ├── mouse/
│ │ │ │ │ │ ├── default_gutter_handler.js
│ │ │ │ │ │ ├── default_handlers.js
│ │ │ │ │ │ ├── dragdrop.js
│ │ │ │ │ │ ├── fold_handler.js
│ │ │ │ │ │ ├── mouse_event.js
│ │ │ │ │ │ ├── mouse_handler.js
│ │ │ │ │ │ └── multi_select_handler.js
│ │ │ │ │ ├── multi_select.js
│ │ │ │ │ ├── multi_select_test.js
│ │ │ │ │ ├── narcissus/
│ │ │ │ │ │ ├── definitions.js
│ │ │ │ │ │ ├── lexer.js
│ │ │ │ │ │ ├── options.js
│ │ │ │ │ │ └── parser.js
│ │ │ │ │ ├── placeholder.js
│ │ │ │ │ ├── placeholder_test.js
│ │ │ │ │ ├── range.js
│ │ │ │ │ ├── range_list.js
│ │ │ │ │ ├── range_list_test.js
│ │ │ │ │ ├── range_test.js
│ │ │ │ │ ├── renderloop.js
│ │ │ │ │ ├── requirejs/
│ │ │ │ │ │ └── text.js
│ │ │ │ │ ├── scrollbar.js
│ │ │ │ │ ├── search.js
│ │ │ │ │ ├── search_test.js
│ │ │ │ │ ├── selection.js
│ │ │ │ │ ├── selection_test.js
│ │ │ │ │ ├── split.js
│ │ │ │ │ ├── test/
│ │ │ │ │ │ ├── all.js
│ │ │ │ │ │ ├── all_browser.js
│ │ │ │ │ │ ├── assertions.js
│ │ │ │ │ │ ├── asyncjs/
│ │ │ │ │ │ │ ├── assert.js
│ │ │ │ │ │ │ ├── async.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── test.js
│ │ │ │ │ │ │ └── utils.js
│ │ │ │ │ │ ├── benchmark.js
│ │ │ │ │ │ ├── mockdom.js
│ │ │ │ │ │ ├── mockrenderer.js
│ │ │ │ │ │ └── tests.html
│ │ │ │ │ ├── theme/
│ │ │ │ │ │ ├── chrome.js
│ │ │ │ │ │ ├── clouds.js
│ │ │ │ │ │ ├── clouds_midnight.js
│ │ │ │ │ │ ├── cobalt.js
│ │ │ │ │ │ ├── crimson_editor.js
│ │ │ │ │ │ ├── dawn.js
│ │ │ │ │ │ ├── dreamweaver.js
│ │ │ │ │ │ ├── eclipse.js
│ │ │ │ │ │ ├── idle_fingers.js
│ │ │ │ │ │ ├── kr_theme.js
│ │ │ │ │ │ ├── merbivore.js
│ │ │ │ │ │ ├── merbivore_soft.js
│ │ │ │ │ │ ├── mono_industrial.js
│ │ │ │ │ │ ├── monokai.js
│ │ │ │ │ │ ├── pastel_on_dark.js
│ │ │ │ │ │ ├── solarized_dark.js
│ │ │ │ │ │ ├── solarized_light.js
│ │ │ │ │ │ ├── textmate.js
│ │ │ │ │ │ ├── tomorrow.js
│ │ │ │ │ │ ├── tomorrow_night.js
│ │ │ │ │ │ ├── tomorrow_night_blue.js
│ │ │ │ │ │ ├── tomorrow_night_bright.js
│ │ │ │ │ │ ├── tomorrow_night_eighties.js
│ │ │ │ │ │ ├── twilight.js
│ │ │ │ │ │ └── vibrant_ink.js
│ │ │ │ │ ├── token_iterator.js
│ │ │ │ │ ├── token_iterator_test.js
│ │ │ │ │ ├── tokenizer.js
│ │ │ │ │ ├── undomanager.js
│ │ │ │ │ ├── unicode.js
│ │ │ │ │ ├── virtual_renderer.js
│ │ │ │ │ ├── virtual_renderer_test.js
│ │ │ │ │ └── worker/
│ │ │ │ │ ├── jshint.js
│ │ │ │ │ ├── jslint.js
│ │ │ │ │ ├── mirror.js
│ │ │ │ │ ├── worker.js
│ │ │ │ │ └── worker_client.js
│ │ │ │ └── pilot/
│ │ │ │ ├── browser_focus.js
│ │ │ │ ├── canon.js
│ │ │ │ ├── dom.js
│ │ │ │ ├── event.js
│ │ │ │ ├── event_emitter.js
│ │ │ │ ├── fixoldbrowsers.js
│ │ │ │ ├── index.js
│ │ │ │ ├── keys.js
│ │ │ │ ├── lang.js
│ │ │ │ ├── oop.js
│ │ │ │ └── useragent.js
│ │ │ ├── manifest.json
│ │ │ ├── modes.js
│ │ │ ├── require.js
│ │ │ ├── require_config.js
│ │ │ └── styles.css
│ │ ├── todomvc/
│ │ │ ├── background.js
│ │ │ ├── bower.json
│ │ │ ├── bower_components/
│ │ │ │ ├── director/
│ │ │ │ │ └── build/
│ │ │ │ │ └── director.js
│ │ │ │ └── todomvc-common/
│ │ │ │ └── base.css
│ │ │ ├── index.html
│ │ │ ├── js/
│ │ │ │ ├── alarms.js
│ │ │ │ ├── app.js
│ │ │ │ ├── bootstrap.js
│ │ │ │ ├── controller.js
│ │ │ │ ├── export.js
│ │ │ │ ├── helpers.js
│ │ │ │ ├── model.js
│ │ │ │ ├── store.js
│ │ │ │ └── view.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ └── styles.css
│ │ ├── tts/
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── ttsdemo.css
│ │ │ ├── ttsdemo.html
│ │ │ └── ttsdemo.js
│ │ ├── udp/
│ │ │ ├── README.md
│ │ │ ├── demo.js
│ │ │ ├── echo_mco.html
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── mco.js
│ │ │ ├── networking.js
│ │ │ ├── raf.js
│ │ │ ├── sample_support_metadata.json
│ │ │ └── server/
│ │ │ └── dropping-server.js
│ │ ├── url-handler/
│ │ │ ├── README.md
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── usb/
│ │ │ ├── device-info/
│ │ │ │ ├── README.md
│ │ │ │ ├── background.js
│ │ │ │ ├── index.html
│ │ │ │ ├── manifest.json
│ │ │ │ ├── script.js
│ │ │ │ └── style.css
│ │ │ └── knob/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── knob.html
│ │ │ ├── knob.js
│ │ │ └── manifest.json
│ │ ├── usb-label-printer/
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── dettach_kernel_driver.py
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── styles/
│ │ │ └── main.css
│ │ ├── weather/
│ │ │ ├── README.md
│ │ │ ├── lib/
│ │ │ │ └── iscroll.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ ├── style.css
│ │ │ ├── weather.html
│ │ │ └── weather.js
│ │ ├── web-store/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── css/
│ │ │ │ └── index.css
│ │ │ ├── index.html
│ │ │ ├── js/
│ │ │ │ ├── index.js
│ │ │ │ ├── webstore.js
│ │ │ │ └── zip/
│ │ │ │ ├── deflate.js
│ │ │ │ ├── inflate.js
│ │ │ │ └── zip.js
│ │ │ └── manifest.json
│ │ ├── webgl-pointer-lock/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── js/
│ │ │ │ ├── Detector.js
│ │ │ │ └── showlogo3d.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── obj/
│ │ │ │ └── html5rocks.js
│ │ │ └── styles/
│ │ │ └── main.css
│ │ ├── webserver/
│ │ │ ├── README.md
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ └── styles/
│ │ │ ├── bootstrap.css
│ │ │ └── main.css
│ │ ├── websocket-server/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── http.js
│ │ │ ├── index.css
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── manifest.json
│ │ │ ├── sample_support_metadata.json
│ │ │ └── sha1.js
│ │ ├── webview-samples/
│ │ │ ├── browser/
│ │ │ │ ├── README.md
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── browser.js
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ ├── declarative-web-request/
│ │ │ │ ├── README.md
│ │ │ │ ├── blocked.css
│ │ │ │ ├── blocked.html
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── config.js
│ │ │ │ ├── content_blocker.js
│ │ │ │ ├── content_blocker_main.js
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ ├── insert-css/
│ │ │ │ ├── README.md
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── config.js
│ │ │ │ ├── css.js
│ │ │ │ ├── css_main.js
│ │ │ │ ├── inject.css
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ ├── local-resources/
│ │ │ │ ├── README.md
│ │ │ │ ├── app.css
│ │ │ │ ├── bad_app.html
│ │ │ │ ├── crash.js
│ │ │ │ ├── good_app.html
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ └── trusted.html
│ │ │ ├── multi-tab-browser/
│ │ │ │ ├── README.md
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── browser.js
│ │ │ │ ├── browser_main.js
│ │ │ │ ├── config.js
│ │ │ │ ├── context_menu.js
│ │ │ │ ├── exit_box_controller.js
│ │ │ │ ├── find_box_controller.js
│ │ │ │ ├── guest_messaging.js
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── permission_box_controller.js
│ │ │ │ ├── popup.js
│ │ │ │ ├── tabs.js
│ │ │ │ └── zoom_box_controller.js
│ │ │ ├── new-window/
│ │ │ │ ├── README.md
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── browser.js
│ │ │ │ ├── browser_main.js
│ │ │ │ ├── config.js
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.js
│ │ │ │ ├── tabs.js
│ │ │ │ └── title.js
│ │ │ ├── new-window-user-agent/
│ │ │ │ ├── README.md
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── browser.js
│ │ │ │ ├── browser_main.js
│ │ │ │ ├── config.js
│ │ │ │ ├── context_menu.js
│ │ │ │ ├── guest_messaging.js
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.js
│ │ │ │ └── tabs.js
│ │ │ ├── shared-script/
│ │ │ │ ├── README.md
│ │ │ │ ├── app.css
│ │ │ │ ├── correct_injection.html
│ │ │ │ ├── correct_injection.js
│ │ │ │ ├── incorrect_injection.html
│ │ │ │ ├── incorrect_injection.js
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ └── more_dragons.js
│ │ │ ├── user-agent/
│ │ │ │ ├── README.md
│ │ │ │ ├── browser.css
│ │ │ │ ├── browser.html
│ │ │ │ ├── browser.js
│ │ │ │ ├── browser_bindings.js
│ │ │ │ ├── config.js
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ └── webview/
│ │ │ ├── README.md
│ │ │ ├── index.css
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── main.js
│ │ │ ├── manifest.json
│ │ │ └── page_hosted_in_external_server.html
│ │ ├── window-options/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── css/
│ │ │ │ └── window.css
│ │ │ ├── icon_128.xcf
│ │ │ ├── manifest.json
│ │ │ ├── window.html
│ │ │ └── window.js
│ │ ├── window-state/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── icon_128.xcf
│ │ │ ├── manifest.json
│ │ │ ├── window.css
│ │ │ ├── window.html
│ │ │ └── window.js
│ │ └── windows/
│ │ ├── README.md
│ │ ├── copycat.html
│ │ ├── main.js
│ │ ├── manifest.json
│ │ ├── original.html
│ │ ├── scripts/
│ │ │ └── window.js
│ │ └── styles/
│ │ └── window.css
│ └── mv2/
│ ├── api/
│ │ ├── bookmarks/
│ │ │ └── basic/
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── browserAction/
│ │ │ ├── make_page_red/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ ├── print/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ ├── set_icon_path/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ └── set_page_color/
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── browsingData/
│ │ │ └── basic/
│ │ │ ├── manifest.json
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── commands/
│ │ │ ├── background.js
│ │ │ ├── browser_action.html
│ │ │ └── manifest.json
│ │ ├── contentSettings/
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── contextMenus/
│ │ │ ├── basic/
│ │ │ │ ├── manifest.json
│ │ │ │ └── sample.js
│ │ │ ├── event_page/
│ │ │ │ ├── manifest.json
│ │ │ │ └── sample.js
│ │ │ └── global_context_search/
│ │ │ ├── background.js
│ │ │ ├── locales.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ └── options.js
│ │ ├── cookies/
│ │ │ ├── background.js
│ │ │ ├── manager.html
│ │ │ ├── manager.js
│ │ │ └── manifest.json
│ │ ├── debugger/
│ │ │ ├── live-headers/
│ │ │ │ ├── background.js
│ │ │ │ ├── headers.html
│ │ │ │ ├── headers.js
│ │ │ │ └── manifest.json
│ │ │ └── pause-resume/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── default_command_override/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── desktopCapture/
│ │ │ ├── app.js
│ │ │ ├── background.js
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ ├── deviceInfo/
│ │ │ └── basic/
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── devtools/
│ │ │ ├── network/
│ │ │ │ └── chrome-firephp/
│ │ │ │ ├── background.js
│ │ │ │ ├── devtools.html
│ │ │ │ ├── devtools.js
│ │ │ │ └── manifest.json
│ │ │ └── panels/
│ │ │ └── chrome-query/
│ │ │ ├── devtools.html
│ │ │ ├── devtools.js
│ │ │ └── manifest.json
│ │ ├── displaySource/
│ │ │ └── tabCast/
│ │ │ ├── README
│ │ │ ├── background.js
│ │ │ ├── main.css
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── document_scan/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── scan.css
│ │ │ ├── scan.html
│ │ │ └── scan.js
│ │ ├── downloads/
│ │ │ ├── download_filename_controller/
│ │ │ │ ├── bg.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── options.html
│ │ │ │ └── options.js
│ │ │ ├── download_links/
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.html
│ │ │ │ ├── popup.js
│ │ │ │ └── send_links.js
│ │ │ ├── download_manager/
│ │ │ │ ├── _locales/
│ │ │ │ │ └── en/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── background.js
│ │ │ │ ├── icons.html
│ │ │ │ ├── icons.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.css
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ ├── download_open/
│ │ │ │ ├── _locales/
│ │ │ │ │ └── en/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ └── downloads_overwrite/
│ │ │ ├── bg.js
│ │ │ └── manifest.json
│ │ ├── eventPage/
│ │ │ └── basic/
│ │ │ ├── background.js
│ │ │ ├── content.js
│ │ │ └── manifest.json
│ │ ├── extension/
│ │ │ └── isAllowedAccess/
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ ├── popup.js
│ │ │ └── sample.css
│ │ ├── fileSystemProvider/
│ │ │ ├── archive/
│ │ │ │ ├── background.js
│ │ │ │ ├── example1.fake
│ │ │ │ ├── example2.fake
│ │ │ │ └── manifest.json
│ │ │ └── basic/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── fontSettings/
│ │ │ ├── css/
│ │ │ │ ├── chrome_shared.css
│ │ │ │ ├── overlay.css
│ │ │ │ ├── uber_shared.css
│ │ │ │ └── widgets.css
│ │ │ ├── js/
│ │ │ │ ├── cr/
│ │ │ │ │ ├── ui/
│ │ │ │ │ │ └── overlay.js
│ │ │ │ │ └── ui.js
│ │ │ │ └── cr.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── pending_changes.js
│ │ │ ├── slider.css
│ │ │ └── slider.js
│ │ ├── history/
│ │ │ ├── historyOverride/
│ │ │ │ ├── history.html
│ │ │ │ ├── logic.js
│ │ │ │ ├── manifest.json
│ │ │ │ └── style.css
│ │ │ └── showHistory/
│ │ │ ├── manifest.json
│ │ │ ├── typedUrls.html
│ │ │ └── typedUrls.js
│ │ ├── i18n/
│ │ │ ├── cld/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ ├── detectLanguage/
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ ├── getMessage/
│ │ │ │ ├── _locales/
│ │ │ │ │ ├── en_US/
│ │ │ │ │ │ └── messages.json
│ │ │ │ │ ├── es/
│ │ │ │ │ │ └── messages.json
│ │ │ │ │ └── sr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ └── localizedHostedApp/
│ │ │ ├── _locales/
│ │ │ │ ├── de/
│ │ │ │ │ └── messages.json
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ └── manifest.json
│ │ ├── idle/
│ │ │ └── idle_simple/
│ │ │ ├── background.js
│ │ │ ├── history.html
│ │ │ ├── history.js
│ │ │ └── manifest.json
│ │ ├── input.ime/
│ │ │ └── basic/
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ ├── messaging/
│ │ │ └── timer/
│ │ │ ├── manifest.json
│ │ │ ├── page.js
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── nativeMessaging/
│ │ │ ├── README.md
│ │ │ ├── app/
│ │ │ │ ├── main.html
│ │ │ │ ├── main.js
│ │ │ │ └── manifest.json
│ │ │ └── host/
│ │ │ ├── com.google.chrome.example.echo-win.json
│ │ │ ├── com.google.chrome.example.echo.json
│ │ │ ├── install_host.bat
│ │ │ ├── install_host.sh
│ │ │ ├── native-messaging-example-host
│ │ │ ├── native-messaging-example-host.bat
│ │ │ ├── uninstall_host.bat
│ │ │ └── uninstall_host.sh
│ │ ├── notifications/
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ └── style.css
│ │ ├── omnibox/
│ │ │ ├── newtab_search/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ └── simple-example/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── override/
│ │ │ ├── blank_ntp/
│ │ │ │ ├── blank.html
│ │ │ │ └── manifest.json
│ │ │ └── override_igoogle/
│ │ │ ├── manifest.json
│ │ │ └── redirect.html
│ │ ├── pageAction/
│ │ │ ├── pageaction_by_content/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ ├── pageaction_by_url/
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ └── set_icon/
│ │ │ ├── background.html
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── permissions/
│ │ │ ├── extension-questions/
│ │ │ │ ├── manifest.json
│ │ │ │ ├── options.html
│ │ │ │ ├── options.js
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ └── extension-questions.crx
│ │ ├── power/
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── preferences/
│ │ │ ├── allowThirdPartyCookies/
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.css
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ └── enableReferrer/
│ │ │ ├── manifest.json
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── printing/
│ │ │ ├── manifest.json
│ │ │ ├── printers.css
│ │ │ ├── printers.html
│ │ │ └── printers.js
│ │ ├── printingMetrics/
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── print_jobs.css
│ │ │ ├── print_jobs.html
│ │ │ └── print_jobs.js
│ │ ├── processes/
│ │ │ ├── process_monitor/
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ └── show_tabs/
│ │ │ ├── manifest.json
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── storage/
│ │ │ └── stylizr/
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── tabCapture/
│ │ │ ├── eventPage.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── receiver.html
│ │ │ └── receiver.js
│ │ ├── tabs/
│ │ │ ├── inspector/
│ │ │ │ ├── background.js
│ │ │ │ ├── jstemplate_compiled.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── tabs_api.html
│ │ │ │ └── tabs_api.js
│ │ │ ├── pin/
│ │ │ │ ├── README
│ │ │ │ ├── background.js
│ │ │ │ └── manifest.json
│ │ │ ├── screenshot/
│ │ │ │ ├── background.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── screenshot.html
│ │ │ │ └── screenshot.js
│ │ │ └── zoom/
│ │ │ ├── README
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── topsites/
│ │ │ ├── basic/
│ │ │ │ ├── manifest.json
│ │ │ │ ├── popup.html
│ │ │ │ └── popup.js
│ │ │ └── magic8ball/
│ │ │ ├── manifest.json
│ │ │ ├── newTab.css
│ │ │ ├── newTab.html
│ │ │ └── newTab.js
│ │ ├── ttsEngine/
│ │ │ └── console_tts_engine/
│ │ │ ├── console_tts_engine.html
│ │ │ ├── console_tts_engine.js
│ │ │ └── manifest.json
│ │ ├── water_alarm_notification/
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── webNavigation/
│ │ │ └── basic/
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── navigation_collector.js
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── webview/
│ │ │ ├── capturevisibleregion/
│ │ │ │ ├── display.html
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ ├── test.html
│ │ │ │ ├── test.js
│ │ │ │ └── test2.html
│ │ │ ├── comm_demo_app/
│ │ │ │ ├── app.js
│ │ │ │ ├── main.js
│ │ │ │ ├── manifest.json
│ │ │ │ └── test.html
│ │ │ └── comm_demo_ext/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ └── windows/
│ │ └── merge_windows/
│ │ ├── NOTICE
│ │ ├── background.js
│ │ └── manifest.json
│ ├── extensions/
│ │ ├── app_launcher/
│ │ │ ├── manifest.json
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── buildbot/
│ │ │ ├── active_issues.js
│ │ │ ├── bg.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ ├── popup.js
│ │ │ ├── prefs.js
│ │ │ ├── try_status.js
│ │ │ └── utils.js
│ │ ├── calendar/
│ │ │ ├── _locales/
│ │ │ │ ├── ar/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── bg/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ca/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── cs/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── da/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── de/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── el/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── en/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── en_GB/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── es/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── es_419/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── et/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── fi/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── fil/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── fr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── he/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── hi/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── hr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── hu/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── id/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── it/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ja/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ko/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── lt/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── lv/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── nb/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── nl/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── pl/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── pt_BR/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── pt_PT/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ro/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ru/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sk/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sl/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sv/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── th/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── tr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── uk/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── vi/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── zh_CN/
│ │ │ │ │ └── messages.json
│ │ │ │ └── zh_TW/
│ │ │ │ └── messages.json
│ │ │ ├── javascript/
│ │ │ │ ├── background.js
│ │ │ │ └── options.js
│ │ │ ├── manifest.json
│ │ │ └── views/
│ │ │ └── options.html
│ │ ├── catblock/
│ │ │ ├── background.js
│ │ │ ├── loldogs.js
│ │ │ └── manifest.json
│ │ ├── catifier/
│ │ │ ├── event_page.js
│ │ │ └── manifest.json
│ │ ├── chrome_search/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── constant_context/
│ │ │ ├── background.js
│ │ │ ├── content_script.js
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── download_images/
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── email_this_page/
│ │ │ ├── background.js
│ │ │ ├── content_script.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ └── options.js
│ │ ├── fx/
│ │ │ ├── bg.js
│ │ │ ├── content.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ └── options.js
│ │ ├── gdocs/
│ │ │ ├── README
│ │ │ ├── background.html
│ │ │ ├── chrome_ex_oauth.html
│ │ │ ├── chrome_ex_oauth.js
│ │ │ ├── chrome_ex_oauthsimple.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ └── popup.html
│ │ ├── gmail/
│ │ │ ├── _locales/
│ │ │ │ ├── ar/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── bg/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ca/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── cs/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── da/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── de/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── el/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── en/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── en_GB/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── es/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── es_419/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── et/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── fi/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── fil/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── fr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── he/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── hi/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── hr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── hu/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── id/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── it/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ja/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ko/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── lt/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── lv/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── nb/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── nl/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── pl/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── pt_BR/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── pt_PT/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ro/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── ru/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sk/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sl/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── sv/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── th/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── tr/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── uk/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── vi/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── zh_CN/
│ │ │ │ │ └── messages.json
│ │ │ │ └── zh_TW/
│ │ │ │ └── messages.json
│ │ │ ├── background.html
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── imageinfo/
│ │ │ ├── NOTICE
│ │ │ ├── background.js
│ │ │ ├── imageinfo/
│ │ │ │ ├── binaryajax.js
│ │ │ │ ├── exif.js
│ │ │ │ ├── imageinfo.js
│ │ │ │ └── readme.txt
│ │ │ ├── info.css
│ │ │ ├── info.html
│ │ │ ├── info.js
│ │ │ └── manifest.json
│ │ ├── irc/
│ │ │ ├── README.txt
│ │ │ ├── app/
│ │ │ │ └── manifest.json
│ │ │ ├── conf/
│ │ │ │ ├── irc.xml
│ │ │ │ ├── jetty.xml
│ │ │ │ └── webdefault.xml
│ │ │ └── servlet/
│ │ │ ├── WEB-INF/
│ │ │ │ └── web.xml
│ │ │ ├── addChannel.html
│ │ │ ├── addServer.html
│ │ │ ├── index.html
│ │ │ ├── irc.js
│ │ │ ├── jstemplate/
│ │ │ │ ├── jsevalcontext.js
│ │ │ │ ├── jstemplate.js
│ │ │ │ └── util.js
│ │ │ ├── notification.html
│ │ │ ├── src/
│ │ │ │ └── org/
│ │ │ │ └── chromium/
│ │ │ │ └── IRCProxyWebSocket.java
│ │ │ ├── styles.css
│ │ │ └── util.js
│ │ ├── managed_bookmarks/
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ └── schema.json
│ │ ├── mappy/
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── mappy_content_script.js
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── maps_app/
│ │ │ └── manifest.json
│ │ ├── news/
│ │ │ ├── README
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── css/
│ │ │ │ ├── feed.css
│ │ │ │ └── options.css
│ │ │ ├── javascript/
│ │ │ │ ├── feed.js
│ │ │ │ ├── options.js
│ │ │ │ └── util.js
│ │ │ ├── manifest.json
│ │ │ └── views/
│ │ │ ├── background.html
│ │ │ ├── feed.html
│ │ │ └── options.html
│ │ ├── news_a11y/
│ │ │ ├── README
│ │ │ ├── feed.css
│ │ │ ├── feed.html
│ │ │ ├── feed.js
│ │ │ ├── feed_iframe.css
│ │ │ ├── feed_iframe.js
│ │ │ └── manifest.json
│ │ ├── news_i18n/
│ │ │ ├── README
│ │ │ ├── _locales/
│ │ │ │ ├── en/
│ │ │ │ │ └── messages.json
│ │ │ │ ├── es/
│ │ │ │ │ └── messages.json
│ │ │ │ └── sr/
│ │ │ │ └── messages.json
│ │ │ ├── feed.css
│ │ │ ├── feed.html
│ │ │ ├── feed.js
│ │ │ └── manifest.json
│ │ ├── no_cookies/
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ ├── oauth_contacts/
│ │ │ ├── NOTICE
│ │ │ ├── README
│ │ │ ├── background.js
│ │ │ ├── chrome_ex_oauth.html
│ │ │ ├── chrome_ex_oauth.js
│ │ │ ├── chrome_ex_oauthsimple.js
│ │ │ ├── contacts.html
│ │ │ ├── contacts.js
│ │ │ ├── manifest.json
│ │ │ └── onload.js
│ │ ├── optional_permissions/
│ │ │ ├── logic.js
│ │ │ ├── manifest.json
│ │ │ ├── newtab.html
│ │ │ └── style.css
│ │ ├── plugin_settings/
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── css/
│ │ │ │ ├── plugin_list.css
│ │ │ │ └── rule_list.css
│ │ │ ├── domui/
│ │ │ │ ├── css/
│ │ │ │ │ ├── button.css
│ │ │ │ │ ├── chrome_shared.css
│ │ │ │ │ ├── list.css
│ │ │ │ │ └── select.css
│ │ │ │ └── js/
│ │ │ │ ├── cr/
│ │ │ │ │ ├── event_target.js
│ │ │ │ │ ├── ui/
│ │ │ │ │ │ ├── array_data_model.js
│ │ │ │ │ │ ├── list.js
│ │ │ │ │ │ ├── list_item.js
│ │ │ │ │ │ ├── list_selection_controller.js
│ │ │ │ │ │ ├── list_selection_model.js
│ │ │ │ │ │ └── list_single_selection_model.js
│ │ │ │ │ └── ui.js
│ │ │ │ ├── cr.js
│ │ │ │ └── util.js
│ │ │ ├── js/
│ │ │ │ ├── chrome_stubs.js
│ │ │ │ ├── main.js
│ │ │ │ ├── plugin_list.js
│ │ │ │ ├── plugin_list_test.html
│ │ │ │ ├── plugin_settings.js
│ │ │ │ ├── plugin_settings_test.html
│ │ │ │ ├── rule_list.js
│ │ │ │ └── rule_list_test.html
│ │ │ ├── manifest.json
│ │ │ ├── options/
│ │ │ │ ├── css/
│ │ │ │ │ └── list.css
│ │ │ │ └── js/
│ │ │ │ ├── deletable_item_list.js
│ │ │ │ └── inline_editable_list.js
│ │ │ └── options.html
│ │ ├── proxy_configuration/
│ │ │ ├── _locales/
│ │ │ │ └── en/
│ │ │ │ └── messages.json
│ │ │ ├── background.js
│ │ │ ├── manifest.json
│ │ │ ├── popup.css
│ │ │ ├── popup.html
│ │ │ ├── popup.js
│ │ │ ├── proxy_error_handler.js
│ │ │ ├── proxy_form_controller.js
│ │ │ └── test/
│ │ │ ├── jsunittest.js
│ │ │ ├── proxy_form_controller_test.html
│ │ │ ├── proxy_form_controller_test.js
│ │ │ └── unittest.css
│ │ ├── speak_selection/
│ │ │ ├── background.js
│ │ │ ├── content_script.js
│ │ │ ├── keycodes.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ └── tabs.js
│ │ ├── talking_alarm_clock/
│ │ │ ├── audio/
│ │ │ │ ├── cuckoo.ogg
│ │ │ │ ├── digital.ogg
│ │ │ │ ├── metal.ogg
│ │ │ │ ├── ringing.ogg
│ │ │ │ └── rooster.ogg
│ │ │ ├── background.js
│ │ │ ├── common.js
│ │ │ ├── credits.html
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── ttsdebug/
│ │ │ ├── manifest.json
│ │ │ ├── ttsdebug.css
│ │ │ ├── ttsdebug.html
│ │ │ └── ttsdebug.js
│ │ └── ttsdemo/
│ │ ├── manifest.json
│ │ ├── ttsdemo.html
│ │ └── ttsdemo.js
│ ├── howto/
│ │ ├── sandbox/
│ │ │ ├── LICENSE.handlebars
│ │ │ ├── eventpage.html
│ │ │ ├── eventpage.js
│ │ │ ├── handlebars-1.0.0.beta.6.js
│ │ │ ├── manifest.json
│ │ │ └── sandbox.html
│ │ └── tab_shortcuts/
│ │ ├── manifest.json
│ │ └── tab_shortcuts.js
│ ├── readme.md
│ └── tutorials/
│ ├── analytics/
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── broken_background_color/
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── popup.html
│ │ └── popup.js
│ ├── get_started/
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── popup.html
│ │ └── popup.js
│ ├── get_started_complete/
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── popup.html
│ │ └── popup.js
│ ├── getstarted/
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── hello_extensions/
│ │ ├── hello.html
│ │ └── manifest.json
│ ├── oauth_starter/
│ │ ├── background.js
│ │ ├── index.html
│ │ ├── manifest.json
│ │ └── oauth.js
│ └── oauth_tutorial_complete/
│ ├── background.js
│ ├── index.html
│ ├── manifest.json
│ └── oauth.js
├── api-samples/
│ ├── action/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── demo/
│ │ │ ├── index.css
│ │ │ ├── index.html
│ │ │ └── index.js
│ │ ├── manifest.json
│ │ ├── popups/
│ │ │ ├── a.html
│ │ │ ├── b.html
│ │ │ └── popup.html
│ │ └── third-party/
│ │ └── awsm/
│ │ └── awsm.css
│ ├── alarms/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── bg-wrapper.js
│ │ ├── index.css
│ │ ├── index.html
│ │ ├── index.js
│ │ └── manifest.json
│ ├── bookmarks/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── browsingData/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.css
│ │ ├── popup.html
│ │ └── popup.js
│ ├── commands/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── popup.css
│ │ ├── popup.html
│ │ └── popup.js
│ ├── contentSettings/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── contextMenus/
│ │ ├── basic/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ └── sample.js
│ │ └── global_context_search/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── locales.js
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── cookies/
│ │ └── cookie-clearer/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── debugger/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── declarativeNetRequest/
│ │ ├── no-cookies/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ ├── rules_1.json
│ │ │ └── service-worker.js
│ │ ├── url-blocker/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ ├── rules_1.json
│ │ │ └── service_worker.js
│ │ └── url-redirect/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── rules_1.json
│ │ └── service_worker.js
│ ├── default_command_override/
│ │ ├── README.md
│ │ ├── background.js
│ │ └── manifest.json
│ ├── devtools/
│ │ ├── inspectedWindow/
│ │ │ ├── README.md
│ │ │ ├── devtools.html
│ │ │ ├── devtools.js
│ │ │ ├── manifest.json
│ │ │ ├── panel.html
│ │ │ └── panel.js
│ │ └── panels/
│ │ ├── devtools.html
│ │ ├── devtools.js
│ │ ├── manifest.json
│ │ └── readme.md
│ ├── favicon/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── fontSettings/
│ │ ├── fontSettings Advanced/
│ │ │ ├── README.md
│ │ │ ├── css/
│ │ │ │ ├── chrome_shared.css
│ │ │ │ ├── overlay.css
│ │ │ │ ├── uber_shared.css
│ │ │ │ └── widgets.css
│ │ │ ├── js/
│ │ │ │ ├── cr/
│ │ │ │ │ ├── ui/
│ │ │ │ │ │ └── overlay.js
│ │ │ │ │ └── ui.js
│ │ │ │ └── cr.js
│ │ │ ├── manifest.json
│ │ │ ├── options.html
│ │ │ ├── options.js
│ │ │ ├── pending_changes.js
│ │ │ ├── slider.css
│ │ │ └── slider.js
│ │ └── fontSettings Basic/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── history/
│ │ ├── historyOverride/
│ │ │ ├── README.md
│ │ │ ├── history.html
│ │ │ ├── logic.js
│ │ │ ├── manifest.json
│ │ │ └── style.css
│ │ └── showHistory/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ ├── popup.js
│ │ └── service-worker.js
│ ├── identity/
│ │ ├── README.md
│ │ ├── identity.js
│ │ ├── index.html
│ │ ├── main.js
│ │ ├── manifest.json
│ │ └── style.css
│ ├── idle/
│ │ ├── README.md
│ │ ├── history.html
│ │ ├── history.js
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── il8n/
│ │ ├── README.md
│ │ ├── _locales/
│ │ │ ├── en/
│ │ │ │ └── messages.json
│ │ │ └── fr/
│ │ │ └── messages.json
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── nativeMessaging/
│ │ ├── README.md
│ │ ├── extension/
│ │ │ ├── main.html
│ │ │ ├── main.js
│ │ │ └── manifest.json
│ │ └── host/
│ │ ├── com.google.chrome.example.echo-win.json
│ │ ├── com.google.chrome.example.echo.json
│ │ ├── install_host.bat
│ │ ├── install_host.sh
│ │ ├── native-messaging-example-host
│ │ ├── native-messaging-example-host.bat
│ │ ├── uninstall_host.bat
│ │ └── uninstall_host.sh
│ ├── omnibox/
│ │ ├── new-tab-search/
│ │ │ ├── README.md
│ │ │ ├── background.js
│ │ │ └── manifest.json
│ │ └── simple-example/
│ │ ├── README.md
│ │ ├── logs.css
│ │ ├── logs.html
│ │ ├── logs.js
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── override/
│ │ └── blank_ntp/
│ │ ├── README.md
│ │ ├── blank.html
│ │ └── manifest.json
│ ├── power/
│ │ ├── README.md
│ │ ├── _locales/
│ │ │ └── en/
│ │ │ └── messages.json
│ │ ├── background.js
│ │ └── manifest.json
│ ├── printing/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── printers.css
│ │ ├── printers.html
│ │ └── printers.js
│ ├── privacy/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── readingList/
│ │ ├── README.md
│ │ ├── index.css
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── manifest.json
│ │ └── sw.js
│ ├── richNotification/
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ ├── popup.js
│ │ └── readme.md
│ ├── sandbox/
│ │ ├── sandbox/
│ │ │ ├── LICENSE.handlebars
│ │ │ ├── handlebars-1.0.0.beta.6.js
│ │ │ ├── mainpage.html
│ │ │ ├── mainpage.js
│ │ │ ├── manifest.json
│ │ │ ├── sandbox.html
│ │ │ ├── sandbox.md
│ │ │ ├── service-worker.js
│ │ │ └── styles/
│ │ │ └── main.css
│ │ └── sandboxed-content/
│ │ ├── README.md
│ │ ├── main.html
│ │ ├── manifest.json
│ │ ├── sandboxed.html
│ │ ├── service-worker.js
│ │ └── styles/
│ │ └── main.css
│ ├── scripting/
│ │ ├── README.md
│ │ ├── content-script.js
│ │ ├── index.css
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── manifest.json
│ │ └── sw.js
│ ├── storage/
│ │ └── stylizr/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── popup.html
│ │ └── popup.js
│ ├── tabCapture/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── receiver.html
│ │ ├── receiver.js
│ │ └── service-worker.js
│ ├── tabs/
│ │ ├── inspector/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ ├── service-worker.js
│ │ │ ├── window_and_tabs_manager.css
│ │ │ ├── window_and_tabs_manager.html
│ │ │ └── window_and_tabs_manager.js
│ │ ├── pin/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ └── service-worker.js
│ │ ├── screenshot/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ ├── screenshot.html
│ │ │ ├── screenshot.js
│ │ │ └── service-worker.js
│ │ └── zoom/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ ├── popup.js
│ │ └── service-worker.js
│ ├── topSites/
│ │ ├── basic/
│ │ │ ├── README.md
│ │ │ ├── manifest.json
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ └── magic8ball/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── newTab.css
│ │ ├── newTab.html
│ │ └── newTab.js
│ ├── userScripts/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── options.css
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── sw.js
│ │ └── user-script.js
│ ├── web-accessible-resources/
│ │ ├── README.md
│ │ ├── content-script.js
│ │ ├── index.html
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── webNavigation/
│ │ └── basic/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── webRequest/
│ │ └── http-auth/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── service-worker.js
│ └── windows/
│ ├── README.md
│ ├── background.js
│ └── manifest.json
├── eslint.config.js
├── functional-samples/
│ ├── ai.gemini-in-the-cloud/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── package.json
│ │ └── sidepanel/
│ │ ├── index.css
│ │ ├── index.html
│ │ └── index.js
│ ├── ai.gemini-on-device/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── package.json
│ │ ├── privacy.txt
│ │ ├── rollup.config.mjs
│ │ └── sidepanel/
│ │ ├── index.css
│ │ ├── index.html
│ │ └── index.js
│ ├── ai.gemini-on-device-alt-texter/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── ai.gemini-on-device-audio-scribe/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── bridge.js
│ │ ├── demo-chat-app/
│ │ │ ├── index.html
│ │ │ ├── script.js
│ │ │ └── style.css
│ │ ├── manifest.json
│ │ ├── override-createobject-url.js
│ │ ├── sidepanel.html
│ │ └── sidepanel.js
│ ├── ai.gemini-on-device-calendar-mate/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── package.json
│ │ └── rollup.config.mjs
│ ├── ai.gemini-on-device-summarization/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── package.json
│ │ ├── rollup.config.mjs
│ │ ├── scripts/
│ │ │ └── extract-content.js
│ │ └── sidepanel/
│ │ ├── index.css
│ │ ├── index.html
│ │ └── index.js
│ ├── cookbook.file_handlers/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── view-file.html
│ │ └── view-file.js
│ ├── cookbook.geolocation-contentscript/
│ │ ├── README.md
│ │ ├── content-script.js
│ │ └── manifest.json
│ ├── cookbook.geolocation-offscreen/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── offscreen.html
│ │ ├── offscreen.js
│ │ └── service_worker.js
│ ├── cookbook.geolocation-popup/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── cookbook.offscreen-clipboard-write/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── offscreen.html
│ │ └── offscreen.js
│ ├── cookbook.offscreen-dom/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── offscreen.html
│ │ └── offscreen.js
│ ├── cookbook.permissions-addhostaccessrequest/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── banner.js
│ │ └── manifest.json
│ ├── cookbook.push/
│ │ ├── README.md
│ │ ├── background.js
│ │ └── manifest.json
│ ├── cookbook.sidepanel-global/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ ├── sidepanel.html
│ │ └── sidepanel.js
│ ├── cookbook.sidepanel-multiple/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ └── sidepanels/
│ │ ├── main-sp.html
│ │ └── welcome-sp.html
│ ├── cookbook.sidepanel-open/
│ │ ├── README.md
│ │ ├── content-script.js
│ │ ├── manifest.json
│ │ ├── page.html
│ │ ├── script.js
│ │ ├── service-worker.js
│ │ ├── sidepanel-global.html
│ │ └── sidepanel-tab.html
│ ├── cookbook.sidepanel-site-specific/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ └── sidepanel.html
│ ├── cookbook.wasm-helloworld-print/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ └── wasm/
│ │ ├── .gitignore
│ │ ├── Cargo.toml
│ │ ├── pkg/
│ │ │ ├── helloworld_demo.d.ts
│ │ │ ├── helloworld_demo.js
│ │ │ ├── helloworld_demo_bg.wasm
│ │ │ └── helloworld_demo_bg.wasm.d.ts
│ │ └── src/
│ │ └── lib.rs
│ ├── cookbook.wasm-helloworld-print-nomodule/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ └── wasm/
│ │ ├── .gitignore
│ │ ├── Cargo.toml
│ │ ├── pkg/
│ │ │ ├── helloworld_demo.d.ts
│ │ │ ├── helloworld_demo.js
│ │ │ ├── helloworld_demo_bg.wasm
│ │ │ └── helloworld_demo_bg.wasm.d.ts
│ │ └── src/
│ │ └── lib.rs
│ ├── libraries-xhr-in-sw/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── package.json
│ │ ├── rollup.config.mjs
│ │ ├── sidepanel/
│ │ │ ├── index.html
│ │ │ └── script.js
│ │ └── third_party/
│ │ ├── fetchTitle.js
│ │ └── xhr-shim/
│ │ ├── LICENSE
│ │ └── xhr-shim.js
│ ├── reference.mv3-content-scripts/
│ │ ├── README.md
│ │ ├── content-script.js
│ │ ├── manifest.json
│ │ ├── popup.css
│ │ ├── popup.html
│ │ └── popup.js
│ ├── sample.bookmarks/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.css
│ │ ├── popup.html
│ │ ├── popup.js
│ │ └── third-party/
│ │ ├── jquery-1.12.4.js
│ │ ├── jquery-ui-1.12.1.js
│ │ ├── jquery-ui.css
│ │ ├── jquery-ui.structure.css
│ │ └── jquery-ui.theme.css
│ ├── sample.catifier/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── rules.json
│ ├── sample.co2meter/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── co2-state-iframe.html
│ │ ├── co2-state-iframe.js
│ │ ├── images/
│ │ │ └── icon32.psd
│ │ ├── main-page.html
│ │ ├── main-page.js
│ │ ├── manifest.json
│ │ ├── modules/
│ │ │ ├── co2_meter.js
│ │ │ ├── constant.js
│ │ │ └── icon.js
│ │ ├── popup.html
│ │ └── popup.js
│ ├── sample.dnr-rule-manager/
│ │ ├── README.md
│ │ ├── manager.css
│ │ ├── manager.html
│ │ ├── manager.js
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ ├── popup.js
│ │ └── service_worker.js
│ ├── sample.favicon-cs/
│ │ ├── README.md
│ │ ├── content.js
│ │ ├── manifest.json
│ │ └── style.css
│ ├── sample.milestones/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── sample.optional_permissions/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── newtab.html
│ │ ├── newtab.js
│ │ └── style.css
│ ├── sample.page-redder/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── sample.sidepanel-dictionary/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ ├── sidepanel.html
│ │ └── sidepanel.js
│ ├── sample.tabcapture-recorder/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── offscreen.html
│ │ ├── offscreen.js
│ │ └── service-worker.js
│ ├── sample.theme/
│ │ ├── Cached Theme.pak
│ │ ├── README.md
│ │ └── manifest.json
│ ├── sample.water_alarm_notification/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── manifest.json
│ │ ├── popup.html
│ │ └── popup.js
│ ├── sample.webgpu/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── tutorial.broken-color/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── popup.html
│ │ ├── popup.js
│ │ └── service-worker.js
│ ├── tutorial.custom-cursor/
│ │ ├── README.md
│ │ ├── counter.js
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ └── style.css
│ ├── tutorial.focus-mode/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── focus-mode.css
│ │ └── manifest.json
│ ├── tutorial.focus-mode-debugging/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── fixed/
│ │ │ ├── background.js
│ │ │ └── focus-mode.js
│ │ ├── focus-mode.css
│ │ ├── focus-mode.js
│ │ └── manifest.json
│ ├── tutorial.getting-started/
│ │ ├── README.md
│ │ ├── background.js
│ │ ├── button.css
│ │ ├── manifest.json
│ │ ├── options.html
│ │ ├── options.js
│ │ ├── popup.html
│ │ └── popup.js
│ ├── tutorial.google-analytics/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup/
│ │ │ ├── popup.html
│ │ │ └── popup.js
│ │ ├── scripts/
│ │ │ └── google-analytics.js
│ │ └── service-worker.js
│ ├── tutorial.hello-world/
│ │ ├── README.md
│ │ ├── hello.html
│ │ ├── manifest.json
│ │ └── popup.js
│ ├── tutorial.mole-game/
│ │ ├── README.md
│ │ ├── controller/
│ │ │ ├── manifest.json
│ │ │ └── service-worker.js
│ │ └── mole/
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── tutorial.open-api-reference/
│ │ ├── README.md
│ │ ├── api-list.js
│ │ ├── content.js
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ ├── sw-omnibox.js
│ │ ├── sw-suggestions.js
│ │ └── sw-tips.js
│ ├── tutorial.puppeteer/
│ │ ├── README.md
│ │ ├── index.test.js
│ │ └── package.json
│ ├── tutorial.quick-api-reference/
│ │ ├── README.md
│ │ ├── content.js
│ │ ├── manifest.json
│ │ ├── service-worker.js
│ │ ├── sw-omnibox.js
│ │ └── sw-tips.js
│ ├── tutorial.reading-time/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ └── scripts/
│ │ └── content.js
│ ├── tutorial.tabs-manager/
│ │ ├── README.md
│ │ ├── manifest.json
│ │ ├── popup.css
│ │ ├── popup.html
│ │ └── popup.js
│ ├── tutorial.terminate-sw/
│ │ ├── README.md
│ │ ├── puppeteer/
│ │ │ ├── .eslintrc
│ │ │ ├── index.test.js
│ │ │ └── package.json
│ │ ├── selenium/
│ │ │ ├── .eslintrc
│ │ │ ├── index.test.js
│ │ │ └── package.json
│ │ └── test-extension/
│ │ ├── manifest.json
│ │ ├── page.html
│ │ ├── page.js
│ │ ├── service-worker-broken.js
│ │ └── service-worker-fixed.js
│ └── tutorial.websockets/
│ ├── README.md
│ ├── manifest.json
│ └── service-worker.js
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .allstar/binary_artifacts.yaml
================================================
# Ignore reason: Packed extension for demo purposes.
ignorePaths:
- _archive/mv2/api/permissions/extension-questions.crx
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
⚠️ If you have general Chrome Extensions questions, consider posting to the [Chromium Extensions Group](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-extensions) or [Stack Overflow](https://stackoverflow.com/questions/tagged/google-chrome-extension).
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior, or file the issue is found in:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Notes**
Anything additional here. 🌈
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
================================================
FILE: .github/workflows/lint.yml
================================================
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install modules
run: npm ci
- name: Run ESLint
run: npm run lint
================================================
FILE: .github/workflows/sample-list-generator.yml
================================================
name: Sample List Generator
on:
push:
branches:
- main
defaults:
run:
working-directory: ./.repo/sample-list-generator
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm install
- name: Generate sample list
run: npm run start
- name: Upload to artifacts
uses: actions/upload-artifact@v4
with:
name: extension-samples.json
path: ./.repo/sample-list-generator/extension-samples.json
if-no-files-found: error
================================================
FILE: .gitignore
================================================
*~
*.DS_store
node_modules
# Temporary directory for debugging extension samples
_debug
_metadata
dist
**/*.swp
================================================
FILE: .husky/pre-commit
================================================
npx lint-staged
================================================
FILE: .prettierignore
================================================
_archive
third-party
node_modules
dist
================================================
FILE: .prettierrc.json
================================================
{
"printWidth": 80,
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "always"
}
================================================
FILE: .repo/migrate-samples.js
================================================
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Intended to be run as a script on the old samples page, to
* extract a list of samples and render as a Markdown table.
*/
var sampleHeadings = Array.from(document.querySelectorAll('main h2'));
var samples = sampleHeadings2.map((heading) => {
const title = heading.textContent;
const link = heading.querySelector('a');
const href = link.href;
const expectedHrefPrefix = 'https://developer.chrome.com/extensions/examples/'
let id = '';
if (href.startsWith(expectedHrefPrefix)) {
id = href.substr(expectedHrefPrefix.length).replace(/\.zip$/, '');
} else {
console.warn('bad href', href);
}
let notes = '';
// probably a TEXT node
let curr = heading;
for (;;) {
curr = curr.nextSibling;
if (!(curr instanceof Text)) {
break;
}
notes += curr.textContent;
}
notes = notes.trim();
notes = notes.replace(/\s+/g, ' ');
// curr probably points to Calls: now
const callNodes = Array.from(curr.querySelectorAll('ul li code'));
const calls = callNodes.map((node) => node.textContent);
return {title, id, notes, calls};
});
var formatCallsList = (calls) => {
const parts = calls.map((call) => `
${call} `);
return ``;
};
var formatRow = (sample) => {
return `[${sample.title}](${sample.id}) ${sample.notes} | ${formatCallsList(sample.calls)}`;
};
var formatTable = (all) => {
return `Sample | Calls\n--- | ---\n${all.map(formatRow).join('\n')}`;
};
================================================
FILE: .repo/sample-list-generator/.gitignore
================================================
extension-samples.json
================================================
FILE: .repo/sample-list-generator/README.md
================================================
# Sample List Generator
## Overview
It's a script that generates `./extension-samples.json` with the list of all the samples available. Currently, this JSON will be provided to [developer.chrome.com](https://developer.chrome.com) for generating a list page containing all the samples. This allows developers to quickly find the sample they want to reference.
## How to use
### Install dependencies
```bash
npm install
```
### Run prefetch script (optional)
The prefetch script will generate a list of all the available extension apis on [developer.chrome.com](https://developer.chrome.com/docs/extensions/reference) and save it to `./extension-apis.json`.
The file `./extension-apis.json` will be committed so you don't need to run this script unless you want to update the list.
```bash
npm run prepare-chrome-types
```
### Run the generator
```bash
npm start
```
### Run the tests
```bash
npm test
```
## Types
```ts
type ApiTypeResult = 'event' | 'method' | 'property' | 'type' | 'unknown';
interface ApiItem {
type: ApiTypeResult;
namespace: string;
propertyName: string;
}
interface SampleItem {
type: 'API_SAMPLE' | 'FUNCTIONAL_SAMPLE';
name: string;
title: string;
description: string;
repo_link: string;
apis: ApiItem[];
permissions: string[];
}
// the type of extension-samples.json file is SampleItem[]
```
## Example
Here is an example of the generated `extension-samples.json` file:
```json
[
{
"type": "API_SAMPLE",
"name": "alarms",
"title": "Alarms API Demo",
"description": "",
"repo_link": "https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/alarms",
"permissions": ["alarms"],
"apis": [
{
"type": "event",
"namespace": "runtime",
"propertyName": "onInstalled"
},
{
"type": "event",
"namespace": "action",
"propertyName": "onClicked"
},
{
"type": "event",
"namespace": "alarms",
"propertyName": "onAlarm"
},
{
"type": "type",
"namespace": "runtime",
"propertyName": "OnInstalledReason"
},
{
"type": "method",
"namespace": "alarms",
"propertyName": "create"
},
{
"type": "method",
"namespace": "tabs",
"propertyName": "create"
},
{
"type": "method",
"namespace": "alarms",
"propertyName": "clear"
},
{
"type": "method",
"namespace": "alarms",
"propertyName": "clearAll"
},
{
"type": "method",
"namespace": "alarms",
"propertyName": "getAll"
}
]
},
{
"type": "FUNCTIONAL_SAMPLE",
"name": "tutorial.getting-started",
"title": "Getting Started Example",
"description": "Build an Extension!",
"repo_link": "https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/tutorial.getting-started",
"permissions": ["storage", "activeTab", "scripting"],
"apis": [
{
"type": "event",
"namespace": "runtime",
"propertyName": "onInstalled"
},
{
"type": "property",
"namespace": "storage",
"propertyName": "sync"
},
{
"type": "method",
"namespace": "tabs",
"propertyName": "query"
},
{
"type": "method",
"namespace": "scripting",
"propertyName": "executeScript"
}
]
}
]
```
================================================
FILE: .repo/sample-list-generator/extension-apis.json
================================================
{
"_comment": "This file is autogenerated by running `npm run prepare-chrome-types`, do not edit.",
"accessibilityFeatures": {
"properties": [
"animationPolicy",
"autoclick",
"caretHighlight",
"cursorColor",
"cursorHighlight",
"dictation",
"dockedMagnifier",
"focusHighlight",
"highContrast",
"largeCursor",
"screenMagnifier",
"selectToSpeak",
"spokenFeedback",
"stickyKeys",
"switchAccess",
"virtualKeyboard"
],
"methods": [],
"types": [],
"events": []
},
"action": {
"properties": [],
"methods": [
"disable",
"enable",
"getBadgeBackgroundColor",
"getBadgeText",
"getBadgeTextColor",
"getPopup",
"getTitle",
"getUserSettings",
"isEnabled",
"openPopup",
"setBadgeBackgroundColor",
"setBadgeText",
"setBadgeTextColor",
"setIcon",
"setPopup",
"setTitle"
],
"types": [
"OpenPopupOptions",
"TabDetails",
"UserSettings",
"UserSettingsChange"
],
"events": ["onClicked", "onUserSettingsChanged"]
},
"alarms": {
"properties": [],
"methods": ["clear", "clearAll", "create", "get", "getAll"],
"types": ["Alarm", "AlarmCreateInfo"],
"events": ["onAlarm"]
},
"app.runtime": {
"properties": [],
"methods": [],
"types": ["EmbedRequest", "LaunchData", "LaunchItem", "LaunchSource"],
"events": ["onEmbedRequested", "onLaunched", "onRestarted"]
},
"app.window": {
"properties": [],
"methods": [
"canSetVisibleOnAllWorkspaces",
"create",
"current",
"get",
"getAll"
],
"types": [
"AppWindow",
"Bounds",
"BoundsSpecification",
"ContentBounds",
"CreateWindowOptions",
"FrameOptions",
"State",
"WindowType"
],
"events": [
"onBoundsChanged",
"onClosed",
"onFullscreened",
"onMaximized",
"onMinimized",
"onRestored"
]
},
"app": {
"properties": [],
"methods": ["getDetails", "getIsInstalled", "installState", "runningState"],
"types": ["DOMWindow", "Details", "InstallState", "RunningState"],
"events": []
},
"appviewTag": {
"properties": [],
"methods": ["connect"],
"types": ["EmbedRequest"],
"events": []
},
"audio": {
"properties": [],
"methods": [
"getDevices",
"getMute",
"setActiveDevices",
"setMute",
"setProperties"
],
"types": [
"AudioDeviceInfo",
"DeviceFilter",
"DeviceIdLists",
"DeviceProperties",
"LevelChangedEvent",
"MuteChangedEvent",
"DeviceType",
"StreamType"
],
"events": ["onDeviceListChanged", "onLevelChanged", "onMuteChanged"]
},
"bluetooth": {
"properties": [],
"methods": [
"getAdapterState",
"getDevice",
"getDevices",
"startDiscovery",
"stopDiscovery"
],
"types": [
"AdapterState",
"BluetoothFilter",
"Device",
"DeviceType",
"FilterType",
"Transport",
"VendorIdSource"
],
"events": [
"onAdapterStateChanged",
"onDeviceAdded",
"onDeviceChanged",
"onDeviceRemoved"
]
},
"bluetoothLowEnergy": {
"properties": [],
"methods": [
"connect",
"createCharacteristic",
"createDescriptor",
"createService",
"disconnect",
"getCharacteristic",
"getCharacteristics",
"getDescriptor",
"getDescriptors",
"getIncludedServices",
"getService",
"getServices",
"notifyCharacteristicValueChanged",
"readCharacteristicValue",
"readDescriptorValue",
"registerAdvertisement",
"registerService",
"removeService",
"resetAdvertising",
"sendRequestResponse",
"setAdvertisingInterval",
"startCharacteristicNotifications",
"stopCharacteristicNotifications",
"unregisterAdvertisement",
"unregisterService",
"writeCharacteristicValue",
"writeDescriptorValue"
],
"types": [
"Advertisement",
"Characteristic",
"ConnectProperties",
"Descriptor",
"Device",
"ManufacturerData",
"Notification",
"NotificationProperties",
"Request",
"Response",
"Service",
"ServiceData",
"AdvertisementType",
"CharacteristicProperty",
"DescriptorPermission"
],
"events": [
"onCharacteristicReadRequest",
"onCharacteristicValueChanged",
"onCharacteristicWriteRequest",
"onDescriptorReadRequest",
"onDescriptorValueChanged",
"onDescriptorWriteRequest",
"onServiceAdded",
"onServiceChanged",
"onServiceRemoved"
]
},
"bluetoothSocket": {
"properties": [],
"methods": [
"close",
"connect",
"create",
"disconnect",
"getInfo",
"getSockets",
"listenUsingL2cap",
"listenUsingRfcomm",
"send",
"setPaused",
"update"
],
"types": [
"AcceptErrorInfo",
"AcceptInfo",
"CreateInfo",
"ListenOptions",
"ReceiveErrorInfo",
"ReceiveInfo",
"SocketInfo",
"SocketProperties",
"AcceptError",
"ReceiveError"
],
"events": ["onAccept", "onAcceptError", "onReceive", "onReceiveError"]
},
"bookmarks": {
"properties": [
"MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE",
"MAX_WRITE_OPERATIONS_PER_HOUR"
],
"methods": [
"create",
"get",
"getChildren",
"getRecent",
"getSubTree",
"getTree",
"move",
"remove",
"removeTree",
"search",
"update"
],
"types": [
"BookmarkTreeNode",
"CreateDetails",
"BookmarkTreeNodeUnmodifiable",
"FolderType"
],
"events": [
"onChanged",
"onChildrenReordered",
"onCreated",
"onImportBegan",
"onImportEnded",
"onMoved",
"onRemoved"
]
},
"browser": {
"properties": [],
"methods": ["openTab"],
"types": ["OpenTabOptions"],
"events": []
},
"browserAction": {
"properties": [],
"methods": [
"disable",
"enable",
"getBadgeBackgroundColor",
"getBadgeText",
"getPopup",
"getTitle",
"setBadgeBackgroundColor",
"setBadgeText",
"setIcon",
"setPopup",
"setTitle"
],
"types": ["TabDetails", "ColorArray", "ImageDataType"],
"events": ["onClicked"]
},
"browsingData": {
"properties": [],
"methods": [
"remove",
"removeAppcache",
"removeCache",
"removeCacheStorage",
"removeCookies",
"removeDownloads",
"removeFileSystems",
"removeFormData",
"removeHistory",
"removeIndexedDB",
"removeLocalStorage",
"removePasswords",
"removePluginData",
"removeServiceWorkers",
"removeWebSQL",
"settings"
],
"types": ["DataTypeSet", "RemovalOptions"],
"events": []
},
"certificateProvider": {
"properties": [],
"methods": [
"reportSignature",
"requestPin",
"setCertificates",
"stopPinRequest"
],
"types": [
"CertificateInfo",
"CertificatesUpdateRequest",
"ClientCertificateInfo",
"PinResponseDetails",
"ReportSignatureDetails",
"RequestPinDetails",
"SetCertificatesDetails",
"SignRequest",
"SignatureRequest",
"StopPinRequestDetails",
"Algorithm",
"Error",
"Hash",
"PinRequestErrorType",
"PinRequestType"
],
"events": [
"onCertificatesRequested",
"onCertificatesUpdateRequested",
"onSignDigestRequested",
"onSignatureRequested"
]
},
"chrome_url_overrides": {
"properties": [],
"methods": [],
"types": ["UrlOverrideInfo"],
"events": []
},
"clipboard": {
"properties": [],
"methods": ["setImageData"],
"types": ["AdditionalDataItem", "DataItemType", "ImageType"],
"events": ["onClipboardDataChanged"]
},
"commands": {
"properties": [],
"methods": ["getAll"],
"types": ["Command"],
"events": ["onCommand"]
},
"contentScripts": {
"properties": [],
"methods": [],
"types": ["ContentScript"],
"events": []
},
"contentSettings": {
"properties": [
"autoVerify",
"automaticDownloads",
"camera",
"clipboard",
"cookies",
"fullscreen",
"images",
"javascript",
"location",
"microphone",
"mouselock",
"notifications",
"plugins",
"popups",
"unsandboxedPlugins"
],
"methods": [],
"types": [
"ContentSetting",
"ResourceIdentifier",
"AutoVerifyContentSetting",
"CameraContentSetting",
"ClipboardContentSetting",
"CookiesContentSetting",
"FullscreenContentSetting",
"ImagesContentSetting",
"JavascriptContentSetting",
"LocationContentSetting",
"MicrophoneContentSetting",
"MouselockContentSetting",
"MultipleAutomaticDownloadsContentSetting",
"NotificationsContentSetting",
"PluginsContentSetting",
"PopupsContentSetting",
"PpapiBrokerContentSetting",
"Scope"
],
"events": []
},
"contextMenus": {
"properties": ["ACTION_MENU_TOP_LEVEL_LIMIT"],
"methods": ["create", "remove", "removeAll", "update"],
"types": ["CreateProperties", "OnClickData", "ContextType", "ItemType"],
"events": ["onClicked"]
},
"cookies": {
"properties": [],
"methods": [
"get",
"getAll",
"getAllCookieStores",
"getPartitionKey",
"remove",
"set"
],
"types": [
"Cookie",
"CookieDetails",
"CookiePartitionKey",
"CookieStore",
"FrameDetails",
"OnChangedCause",
"SameSiteStatus"
],
"events": ["onChanged"]
},
"crossOriginIsolation": {
"properties": [],
"methods": [],
"types": ["ResponseHeader"],
"events": []
},
"debugger": {
"properties": [],
"methods": ["attach", "detach", "getTargets", "sendCommand"],
"types": [
"Debuggee",
"DebuggerSession",
"TargetInfo",
"DetachReason",
"TargetInfoType"
],
"events": ["onDetach", "onEvent"]
},
"declarativeContent": {
"properties": [],
"methods": [],
"types": [
"PageStateMatcher",
"RequestContentScript",
"SetIcon",
"ShowAction",
"ShowPageAction",
"ImageDataType"
],
"events": ["onPageChanged"]
},
"declarativeNetRequest": {
"properties": [
"DYNAMIC_RULESET_ID",
"GETMATCHEDRULES_QUOTA_INTERVAL",
"GUARANTEED_MINIMUM_STATIC_RULES",
"MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL",
"MAX_NUMBER_OF_DYNAMIC_RULES",
"MAX_NUMBER_OF_ENABLED_STATIC_RULESETS",
"MAX_NUMBER_OF_REGEX_RULES",
"MAX_NUMBER_OF_SESSION_RULES",
"MAX_NUMBER_OF_STATIC_RULESETS",
"MAX_NUMBER_OF_UNSAFE_DYNAMIC_RULES",
"MAX_NUMBER_OF_UNSAFE_SESSION_RULES",
"SESSION_RULESET_ID"
],
"methods": [
"getAvailableStaticRuleCount",
"getDisabledRuleIds",
"getDynamicRules",
"getEnabledRulesets",
"getMatchedRules",
"getSessionRules",
"isRegexSupported",
"setExtensionActionOptions",
"testMatchOutcome",
"updateDynamicRules",
"updateEnabledRulesets",
"updateSessionRules",
"updateStaticRules"
],
"types": [
"ExtensionActionOptions",
"GetDisabledRuleIdsOptions",
"GetRulesFilter",
"HeaderInfo",
"IsRegexSupportedResult",
"MatchedRule",
"MatchedRuleInfo",
"MatchedRuleInfoDebug",
"MatchedRulesFilter",
"ModifyHeaderInfo",
"QueryKeyValue",
"QueryTransform",
"Redirect",
"RegexOptions",
"RequestDetails",
"Rule",
"RuleAction",
"RuleCondition",
"RulesMatchedDetails",
"Ruleset",
"TabActionCountUpdate",
"TestMatchOutcomeResult",
"TestMatchRequestDetails",
"URLTransform",
"UpdateRuleOptions",
"UpdateRulesetOptions",
"UpdateStaticRulesOptions",
"DomainType",
"HeaderOperation",
"RequestMethod",
"ResourceType",
"RuleActionType",
"UnsupportedRegexReason"
],
"events": ["onRuleMatchedDebug"]
},
"declarativeWebRequest": {
"properties": [],
"methods": [],
"types": [
"AddRequestCookie",
"AddResponseCookie",
"AddResponseHeader",
"CancelRequest",
"EditRequestCookie",
"EditResponseCookie",
"IgnoreRules",
"RedirectByRegEx",
"RedirectRequest",
"RedirectToEmptyDocument",
"RedirectToTransparentImage",
"RemoveRequestCookie",
"RemoveRequestHeader",
"RemoveResponseCookie",
"RemoveResponseHeader",
"RequestMatcher",
"SendMessageToExtension",
"SetRequestHeader",
"FilterResponseCookie",
"HeaderFilter",
"RequestCookie",
"ResponseCookie",
"Stage"
],
"events": ["onMessage", "onRequest"]
},
"desktopCapture": {
"properties": [],
"methods": ["cancelChooseDesktopMedia", "chooseDesktopMedia"],
"types": [
"DesktopCaptureSourceType",
"SelfCapturePreferenceEnum",
"SystemAudioPreferenceEnum"
],
"events": []
},
"devtools.inspectedWindow": {
"properties": ["tabId"],
"methods": ["eval", "getResources", "reload"],
"types": ["Resource"],
"events": ["onResourceAdded", "onResourceContentCommitted"]
},
"devtools.network": {
"properties": [],
"methods": ["getHAR"],
"types": ["Request"],
"events": ["onNavigated", "onRequestFinished"]
},
"devtools.panels": {
"properties": ["elements", "sources", "themeName"],
"methods": ["create", "openResource", "setOpenResourceHandler"],
"types": [
"Button",
"ElementsPanel",
"ExtensionPanel",
"ExtensionSidebarPane",
"SourcesPanel"
],
"events": []
},
"devtools.performance": {
"properties": [],
"methods": [],
"types": [],
"events": ["onProfilingStarted", "onProfilingStopped"]
},
"devtools.recorder": {
"properties": [],
"methods": ["createView", "registerRecorderExtensionPlugin"],
"types": ["RecorderExtensionPlugin", "RecorderView"],
"events": []
},
"diagnostics": {
"properties": [],
"methods": ["sendPacket"],
"types": ["SendPacketOptions", "SendPacketResult"],
"events": []
},
"dns": {
"properties": [],
"methods": ["resolve"],
"types": ["ResolveCallbackResolveInfo"],
"events": []
},
"documentScan": {
"properties": [],
"methods": [
"cancelScan",
"closeScanner",
"getOptionGroups",
"getScannerList",
"openScanner",
"readScanData",
"scan",
"setOptions",
"startScan"
],
"types": [
"CancelScanResponse",
"CloseScannerResponse",
"DeviceFilter",
"GetOptionGroupsResponse",
"GetScannerListResponse",
"OpenScannerResponse",
"OptionConstraint",
"OptionGroup",
"OptionSetting",
"ReadScanDataResponse",
"ScanOptions",
"ScanResults",
"ScannerInfo",
"ScannerOption",
"SetOptionResult",
"SetOptionsResponse",
"StartScanOptions",
"StartScanResponse",
"Configurability",
"ConnectionType",
"ConstraintType",
"OperationResult",
"OptionType",
"OptionUnit"
],
"events": []
},
"dom": {
"properties": [],
"methods": ["openOrClosedShadowRoot"],
"types": [],
"events": []
},
"downloads": {
"properties": [],
"methods": [
"acceptDanger",
"cancel",
"download",
"erase",
"getFileIcon",
"open",
"pause",
"removeFile",
"resume",
"search",
"setShelfEnabled",
"setUiOptions",
"show",
"showDefaultFolder"
],
"types": [
"BooleanDelta",
"DoubleDelta",
"DownloadDelta",
"DownloadItem",
"DownloadOptions",
"DownloadQuery",
"FilenameSuggestion",
"GetFileIconOptions",
"HeaderNameValuePair",
"StringDelta",
"UiOptions",
"DangerType",
"FilenameConflictAction",
"HttpMethod",
"InterruptReason",
"State"
],
"events": ["onChanged", "onCreated", "onDeterminingFilename", "onErased"]
},
"enterprise.deviceAttributes": {
"properties": [],
"methods": [
"getDeviceAnnotatedLocation",
"getDeviceAssetId",
"getDeviceHostname",
"getDeviceSerialNumber",
"getDirectoryDeviceId"
],
"types": [],
"events": []
},
"enterprise.hardwarePlatform": {
"properties": [],
"methods": ["getHardwarePlatformInfo"],
"types": ["HardwarePlatformInfo"],
"events": []
},
"enterprise.kioskInput": {
"properties": [],
"methods": ["setCurrentInputMethod"],
"types": ["SetCurrentInputMethodOptions"],
"events": []
},
"enterprise.networkingAttributes": {
"properties": [],
"methods": ["getNetworkDetails"],
"types": ["NetworkDetails"],
"events": []
},
"enterprise.platformKeys": {
"properties": [],
"methods": [
"challengeKey",
"challengeMachineKey",
"challengeUserKey",
"getCertificates",
"getTokens",
"importCertificate",
"removeCertificate"
],
"types": [
"ChallengeKeyOptions",
"RegisterKeyOptions",
"Token",
"Algorithm",
"Scope"
],
"events": []
},
"events": {
"properties": [],
"methods": [],
"types": ["Event", "Rule", "UrlFilter"],
"events": []
},
"extension": {
"properties": ["inIncognitoContext", "lastError"],
"methods": [
"getBackgroundPage",
"getExtensionTabs",
"getURL",
"getViews",
"isAllowedFileSchemeAccess",
"isAllowedIncognitoAccess",
"sendRequest",
"setUpdateUrlData"
],
"types": ["ViewType"],
"events": ["onRequest", "onRequestExternal"]
},
"extensionTypes": {
"properties": [],
"methods": [],
"types": [
"DeleteInjectionDetails",
"ImageDetails",
"InjectDetails",
"CSSOrigin",
"DocumentLifecycle",
"ExecutionWorld",
"FrameType",
"ImageFormat",
"RunAt"
],
"events": []
},
"extensionsManifestTypes": {
"properties": [],
"methods": [],
"types": [
"ContentCapabilities",
"ExternallyConnectable",
"OptionsUI",
"UsbPrinters",
"bluetooth",
"sockets",
"KioskSecondaryApps",
"SocketHostPatterns",
"automation"
],
"events": []
},
"fileBrowserHandler": {
"properties": [],
"methods": [],
"types": ["FileHandlerExecuteEventDetails"],
"events": ["onExecute"]
},
"fileHandlers": {
"properties": [],
"methods": [],
"types": ["FileHandler", "Icon"],
"events": []
},
"fileSystem": {
"properties": [],
"methods": [
"chooseEntry",
"getDisplayPath",
"getVolumeList",
"getWritableEntry",
"isRestorable",
"isWritableEntry",
"requestFileSystem",
"restoreEntry",
"retainEntry"
],
"types": [
"AcceptOption",
"ChooseEntryOptions",
"RequestFileSystemOptions",
"Volume",
"VolumeListChangedEvent",
"ChooseEntryType"
],
"events": ["onVolumeListChanged"]
},
"fileSystemProvider": {
"properties": [],
"methods": ["get", "getAll", "mount", "notify", "unmount"],
"types": [
"AbortRequestedOptions",
"Action",
"AddWatcherRequestedOptions",
"Change",
"CloseFileRequestedOptions",
"CloudFileInfo",
"CloudIdentifier",
"ConfigureRequestedOptions",
"CopyEntryRequestedOptions",
"CreateDirectoryRequestedOptions",
"CreateFileRequestedOptions",
"DeleteEntryRequestedOptions",
"EntryMetadata",
"ExecuteActionRequestedOptions",
"FileSystemInfo",
"GetActionsRequestedOptions",
"GetMetadataRequestedOptions",
"MountOptions",
"MoveEntryRequestedOptions",
"NotifyOptions",
"OpenFileRequestedOptions",
"OpenedFile",
"ReadDirectoryRequestedOptions",
"ReadFileRequestedOptions",
"RemoveWatcherRequestedOptions",
"TruncateRequestedOptions",
"UnmountOptions",
"UnmountRequestedOptions",
"Watcher",
"WriteFileRequestedOptions",
"ChangeType",
"CommonActionId",
"OpenFileMode",
"ProviderError"
],
"events": [
"onAbortRequested",
"onAddWatcherRequested",
"onCloseFileRequested",
"onConfigureRequested",
"onCopyEntryRequested",
"onCreateDirectoryRequested",
"onCreateFileRequested",
"onDeleteEntryRequested",
"onExecuteActionRequested",
"onGetActionsRequested",
"onGetMetadataRequested",
"onMountRequested",
"onMoveEntryRequested",
"onOpenFileRequested",
"onReadDirectoryRequested",
"onReadFileRequested",
"onRemoveWatcherRequested",
"onTruncateRequested",
"onUnmountRequested",
"onWriteFileRequested"
]
},
"fontSettings": {
"properties": [],
"methods": [
"clearDefaultFixedFontSize",
"clearDefaultFontSize",
"clearFont",
"clearMinimumFontSize",
"getDefaultFixedFontSize",
"getDefaultFontSize",
"getFont",
"getFontList",
"getMinimumFontSize",
"setDefaultFixedFontSize",
"setDefaultFontSize",
"setFont",
"setMinimumFontSize"
],
"types": ["FontName", "GenericFamily", "LevelOfControl", "ScriptCode"],
"events": [
"onDefaultFixedFontSizeChanged",
"onDefaultFontSizeChanged",
"onFontChanged",
"onMinimumFontSizeChanged"
]
},
"gcm": {
"properties": ["MAX_MESSAGE_SIZE"],
"methods": ["register", "send", "unregister"],
"types": [],
"events": ["onMessage", "onMessagesDeleted", "onSendError"]
},
"hid": {
"properties": [],
"methods": [
"connect",
"disconnect",
"getDevices",
"receive",
"receiveFeatureReport",
"send",
"sendFeatureReport"
],
"types": [
"DeviceFilter",
"GetDevicesOptions",
"HidCollectionInfo",
"HidConnectInfo",
"HidDeviceInfo"
],
"events": ["onDeviceAdded", "onDeviceRemoved"]
},
"history": {
"properties": [],
"methods": [
"addUrl",
"deleteAll",
"deleteRange",
"deleteUrl",
"getVisits",
"search"
],
"types": ["HistoryItem", "UrlDetails", "VisitItem", "TransitionType"],
"events": ["onVisitRemoved", "onVisited"]
},
"i18n": {
"properties": [],
"methods": [
"detectLanguage",
"getAcceptLanguages",
"getMessage",
"getUILanguage"
],
"types": ["LanguageCode"],
"events": []
},
"identity": {
"properties": [],
"methods": [
"clearAllCachedAuthTokens",
"getAccounts",
"getAuthToken",
"getProfileUserInfo",
"getRedirectURL",
"launchWebAuthFlow",
"removeCachedAuthToken"
],
"types": [
"AccountInfo",
"GetAuthTokenResult",
"InvalidTokenDetails",
"ProfileDetails",
"ProfileUserInfo",
"TokenDetails",
"WebAuthFlowDetails",
"AccountStatus"
],
"events": ["onSignInChanged"]
},
"idle": {
"properties": [],
"methods": ["getAutoLockDelay", "queryState", "setDetectionInterval"],
"types": ["IdleState"],
"events": ["onStateChanged"]
},
"incognito": {
"properties": [],
"methods": [],
"types": ["IncognitoMode"],
"events": []
},
"input.ime": {
"properties": [],
"methods": [
"clearComposition",
"commitText",
"deleteSurroundingText",
"hideInputView",
"keyEventHandled",
"sendKeyEvents",
"setAssistiveWindowButtonHighlighted",
"setAssistiveWindowProperties",
"setCandidateWindowProperties",
"setCandidates",
"setComposition",
"setCursorPosition",
"setMenuItems",
"updateMenuItems"
],
"types": [
"AssistiveWindowProperties",
"InputContext",
"KeyboardEvent",
"MenuItem",
"MenuParameters",
"AssistiveWindowButton",
"AssistiveWindowType",
"AutoCapitalizeType",
"InputContextType",
"KeyboardEventType",
"MenuItemStyle",
"MouseButton",
"ScreenType",
"UnderlineStyle",
"WindowPosition"
],
"events": [
"onActivate",
"onAssistiveWindowButtonClicked",
"onBlur",
"onCandidateClicked",
"onDeactivated",
"onFocus",
"onInputContextUpdate",
"onKeyEvent",
"onMenuItemActivated",
"onReset",
"onSurroundingTextChanged"
]
},
"instanceID": {
"properties": [],
"methods": [
"deleteID",
"deleteToken",
"getCreationTime",
"getID",
"getToken"
],
"types": [],
"events": ["onTokenRefresh"]
},
"loginState": {
"properties": [],
"methods": ["getProfileType", "getSessionState"],
"types": ["ProfileType", "SessionState"],
"events": ["onSessionStateChanged"]
},
"management": {
"properties": [],
"methods": [
"createAppShortcut",
"generateAppForLink",
"get",
"getAll",
"getPermissionWarningsById",
"getPermissionWarningsByManifest",
"getSelf",
"installReplacementWebApp",
"launchApp",
"setEnabled",
"setLaunchType",
"uninstall",
"uninstallSelf"
],
"types": [
"ExtensionInfo",
"IconInfo",
"UninstallOptions",
"ExtensionDisabledReason",
"ExtensionInstallType",
"ExtensionType",
"LaunchType"
],
"events": ["onDisabled", "onEnabled", "onInstalled", "onUninstalled"]
},
"manifestTypes": {
"properties": [],
"methods": [],
"types": [
"ChromeSettingsOverrides",
"FileSystemProviderCapabilities",
"FileSystemProviderSource"
],
"events": []
},
"mdns": {
"properties": ["MAX_SERVICE_INSTANCES_PER_EVENT"],
"methods": ["forceDiscovery"],
"types": ["MDnsService"],
"events": ["onServiceList"]
},
"mediaGalleries": {
"properties": [],
"methods": [
"addGalleryWatch",
"addUserSelectedFolder",
"getMediaFileSystemMetadata",
"getMediaFileSystems",
"getMetadata",
"removeGalleryWatch"
],
"types": [
"AddGalleryWatchResult",
"GalleryChangeDetails",
"MediaFileSystemMetadata",
"MediaFileSystemsDetails",
"MediaMetadata",
"MediaMetadataOptions",
"StreamInfo",
"GalleryChangeType",
"GetMediaFileSystemsInteractivity",
"GetMetadataType"
],
"events": ["onGalleryChanged"]
},
"networking.onc": {
"properties": [],
"methods": [
"createNetwork",
"disableNetworkType",
"enableNetworkType",
"forgetNetwork",
"getCaptivePortalStatus",
"getDeviceStates",
"getGlobalPolicy",
"getManagedProperties",
"getNetworks",
"getProperties",
"getState",
"requestNetworkScan",
"setProperties",
"startConnect",
"startDisconnect"
],
"types": [
"CellularProperties",
"CellularProviderProperties",
"CellularStateProperties",
"CertificatePattern",
"DeviceStateProperties",
"EAPProperties",
"EthernetProperties",
"EthernetStateProperties",
"FoundNetworkProperties",
"GlobalPolicy",
"IPConfigProperties",
"IssuerSubjectPattern",
"ManagedBoolean",
"ManagedCellularProperties",
"ManagedDOMString",
"ManagedDOMStringList",
"ManagedEthernetProperties",
"ManagedIPConfigProperties",
"ManagedIPConfigType",
"ManagedLong",
"ManagedManualProxySettings",
"ManagedProperties",
"ManagedProxyLocation",
"ManagedProxySettings",
"ManagedProxySettingsType",
"ManagedThirdPartyVPNProperties",
"ManagedVPNProperties",
"ManagedWiFiProperties",
"ManualProxySettings",
"NetworkConfigProperties",
"NetworkFilter",
"NetworkProperties",
"NetworkStateProperties",
"PaymentPortal",
"ProxyLocation",
"ProxySettings",
"SIMLockStatus",
"ThirdPartyVPNProperties",
"VPNProperties",
"VPNStateProperties",
"WiFiProperties",
"WiFiStateProperties",
"WiMAXProperties",
"ActivationStateType",
"CaptivePortalStatus",
"ClientCertificateType",
"ConnectionStateType",
"DeviceStateType",
"IPConfigType",
"NetworkType",
"ProxySettingsType"
],
"events": [
"onDeviceStateListChanged",
"onNetworkListChanged",
"onNetworksChanged",
"onPortalDetectionCompleted"
]
},
"notifications": {
"properties": [],
"methods": ["clear", "create", "getAll", "getPermissionLevel", "update"],
"types": [
"NotificationBitmap",
"NotificationButton",
"NotificationItem",
"NotificationOptions",
"PermissionLevel",
"TemplateType"
],
"events": [
"onButtonClicked",
"onClicked",
"onClosed",
"onPermissionLevelChanged",
"onShowSettings"
]
},
"oauth2": {
"properties": [],
"methods": [],
"types": ["OAuth2Info"],
"events": []
},
"offscreen": {
"properties": [],
"methods": ["closeDocument", "createDocument"],
"types": ["CreateParameters", "Reason"],
"events": []
},
"omnibox": {
"properties": [],
"methods": ["setDefaultSuggestion"],
"types": [
"DefaultSuggestResult",
"SuggestResult",
"DescriptionStyleType",
"OnInputEnteredDisposition"
],
"events": [
"onDeleteSuggestion",
"onInputCancelled",
"onInputChanged",
"onInputEntered",
"onInputStarted"
]
},
"pageAction": {
"properties": [],
"methods": [
"getPopup",
"getTitle",
"hide",
"setIcon",
"setPopup",
"setTitle",
"show"
],
"types": ["TabDetails", "ImageDataType"],
"events": ["onClicked"]
},
"pageCapture": {
"properties": [],
"methods": ["saveAsMHTML"],
"types": [],
"events": []
},
"permissions": {
"properties": [],
"methods": [
"addHostAccessRequest",
"contains",
"getAll",
"remove",
"removeHostAccessRequest",
"request"
],
"types": ["Permissions"],
"events": ["onAdded", "onRemoved"]
},
"platformKeys": {
"properties": [],
"methods": [
"getKeyPair",
"getKeyPairBySpki",
"selectClientCertificates",
"subtleCrypto",
"verifyTLSServerCertificate"
],
"types": [
"ClientCertificateRequest",
"Match",
"SelectDetails",
"VerificationDetails",
"VerificationResult",
"ClientCertificateType"
],
"events": []
},
"power": {
"properties": [],
"methods": ["releaseKeepAwake", "reportActivity", "requestKeepAwake"],
"types": ["Level"],
"events": []
},
"printerProvider": {
"properties": [],
"methods": [],
"types": ["PrintJob", "PrinterInfo", "PrintError"],
"events": [
"onGetCapabilityRequested",
"onGetPrintersRequested",
"onGetUsbPrinterInfoRequested",
"onPrintRequested"
]
},
"printing": {
"properties": [
"MAX_GET_PRINTER_INFO_CALLS_PER_MINUTE",
"MAX_SUBMIT_JOB_CALLS_PER_MINUTE"
],
"methods": [
"cancelJob",
"getJobStatus",
"getPrinterInfo",
"getPrinters",
"submitJob"
],
"types": [
"GetPrinterInfoResponse",
"Printer",
"SubmitJobRequest",
"SubmitJobResponse",
"JobStatus",
"PrinterSource",
"PrinterStatus",
"SubmitJobStatus"
],
"events": ["onJobStatusChanged"]
},
"printingMetrics": {
"properties": [],
"methods": ["getPrintJobs"],
"types": [
"MediaSize",
"PrintJobInfo",
"PrintSettings",
"Printer",
"ColorMode",
"DuplexMode",
"PrintJobSource",
"PrintJobStatus",
"PrinterSource"
],
"events": ["onPrintJobFinished"]
},
"privacy": {
"properties": ["network", "services", "websites"],
"methods": [],
"types": ["IPHandlingPolicy"],
"events": []
},
"processes": {
"properties": [],
"methods": ["getProcessIdForTab", "getProcessInfo", "terminate"],
"types": ["Cache", "Process", "TaskInfo", "ProcessType"],
"events": [
"onCreated",
"onExited",
"onUnresponsive",
"onUpdated",
"onUpdatedWithMemory"
]
},
"proxy": {
"properties": ["settings"],
"methods": [],
"types": [
"PacScript",
"ProxyConfig",
"ProxyRules",
"ProxyServer",
"Mode",
"Scheme"
],
"events": ["onProxyError"]
},
"readingList": {
"properties": [],
"methods": ["addEntry", "query", "removeEntry", "updateEntry"],
"types": [
"AddEntryOptions",
"QueryInfo",
"ReadingListEntry",
"RemoveOptions",
"UpdateEntryOptions"
],
"events": ["onEntryAdded", "onEntryRemoved", "onEntryUpdated"]
},
"runtime": {
"properties": ["id", "lastError"],
"methods": [
"connect",
"connectNative",
"getBackgroundPage",
"getContexts",
"getManifest",
"getPackageDirectoryEntry",
"getPlatformInfo",
"getURL",
"openOptionsPage",
"reload",
"requestUpdateCheck",
"restart",
"restartAfterDelay",
"sendMessage",
"sendNativeMessage",
"setUninstallURL"
],
"types": [
"ContextFilter",
"ExtensionContext",
"MessageSender",
"PlatformInfo",
"Port",
"ContextType",
"OnInstalledReason",
"OnRestartRequiredReason",
"PlatformArch",
"PlatformNaclArch",
"PlatformOs",
"RequestUpdateCheckStatus"
],
"events": [
"onBrowserUpdateAvailable",
"onConnect",
"onConnectExternal",
"onConnectNative",
"onInstalled",
"onMessage",
"onMessageExternal",
"onRestartRequired",
"onStartup",
"onSuspend",
"onSuspendCanceled",
"onUpdateAvailable",
"onUserScriptConnect",
"onUserScriptMessage"
]
},
"scripting": {
"properties": [],
"methods": [
"executeScript",
"getRegisteredContentScripts",
"insertCSS",
"registerContentScripts",
"removeCSS",
"unregisterContentScripts",
"updateContentScripts"
],
"types": [
"CSSInjection",
"ContentScriptFilter",
"InjectionResult",
"InjectionTarget",
"RegisteredContentScript",
"ScriptInjection",
"ExecutionWorld",
"StyleOrigin"
],
"events": []
},
"search": {
"properties": [],
"methods": ["query"],
"types": ["QueryInfo", "Disposition"],
"events": []
},
"serial": {
"properties": [],
"methods": [
"clearBreak",
"connect",
"disconnect",
"flush",
"getConnections",
"getControlSignals",
"getDevices",
"getInfo",
"send",
"setBreak",
"setControlSignals",
"setPaused",
"update"
],
"types": [
"ConnectionInfo",
"ConnectionOptions",
"DeviceControlSignals",
"DeviceInfo",
"HostControlSignals",
"ReceiveErrorInfo",
"ReceiveInfo",
"SendInfo",
"DataBits",
"ParityBit",
"ReceiveError",
"SendError",
"StopBits"
],
"events": ["onReceive", "onReceiveError"]
},
"sessions": {
"properties": ["MAX_SESSION_RESULTS"],
"methods": ["getDevices", "getRecentlyClosed", "restore"],
"types": ["Device", "Filter", "Session"],
"events": ["onChanged"]
},
"sharedModule": {
"properties": [],
"methods": [],
"types": ["Export", "Import"],
"events": []
},
"sidePanel": {
"properties": [],
"methods": [
"getOptions",
"getPanelBehavior",
"open",
"setOptions",
"setPanelBehavior"
],
"types": [
"GetPanelOptions",
"OpenOptions",
"PanelBehavior",
"PanelOptions",
"SidePanel"
],
"events": []
},
"socket": {
"properties": [],
"methods": [
"accept",
"bind",
"connect",
"create",
"destroy",
"disconnect",
"getInfo",
"getJoinedGroups",
"getNetworkList",
"joinGroup",
"leaveGroup",
"listen",
"read",
"recvFrom",
"secure",
"sendTo",
"setKeepAlive",
"setMulticastLoopbackMode",
"setMulticastTimeToLive",
"setNoDelay",
"write"
],
"types": [
"AcceptInfo",
"CreateInfo",
"CreateOptions",
"NetworkInterface",
"ReadInfo",
"RecvFromInfo",
"SecureOptions",
"SocketInfo",
"TLSVersionConstraints",
"WriteInfo",
"SocketType"
],
"events": []
},
"sockets.tcp": {
"properties": [],
"methods": [
"close",
"connect",
"create",
"disconnect",
"getInfo",
"getSockets",
"secure",
"send",
"setKeepAlive",
"setNoDelay",
"setPaused",
"update"
],
"types": [
"CreateInfo",
"ReceiveErrorInfo",
"ReceiveInfo",
"SecureOptions",
"SendInfo",
"SocketInfo",
"SocketProperties",
"TLSVersionConstraints",
"DnsQueryType"
],
"events": ["onReceive", "onReceiveError"]
},
"sockets.tcpServer": {
"properties": [],
"methods": [
"close",
"create",
"disconnect",
"getInfo",
"getSockets",
"listen",
"setPaused",
"update"
],
"types": [
"AcceptErrorInfo",
"AcceptInfo",
"CreateInfo",
"SocketInfo",
"SocketProperties"
],
"events": ["onAccept", "onAcceptError"]
},
"sockets.udp": {
"properties": [],
"methods": [
"bind",
"close",
"create",
"getInfo",
"getJoinedGroups",
"getSockets",
"joinGroup",
"leaveGroup",
"send",
"setBroadcast",
"setMulticastLoopbackMode",
"setMulticastTimeToLive",
"setPaused",
"update"
],
"types": [
"CreateInfo",
"ReceiveErrorInfo",
"ReceiveInfo",
"SendInfo",
"SocketInfo",
"SocketProperties",
"DnsQueryType"
],
"events": ["onReceive", "onReceiveError"]
},
"storage": {
"properties": ["local", "managed", "session", "sync"],
"methods": [],
"types": ["StorageArea", "StorageChange", "AccessLevel"],
"events": ["onChanged"]
},
"syncFileSystem": {
"properties": [],
"methods": [
"getConflictResolutionPolicy",
"getFileStatus",
"getFileStatuses",
"getServiceStatus",
"getUsageAndQuota",
"requestFileSystem",
"setConflictResolutionPolicy"
],
"types": [
"FileInfo",
"FileStatusInfo",
"ServiceInfo",
"StorageInfo",
"ConflictResolutionPolicy",
"FileStatus",
"ServiceStatus",
"SyncAction",
"SyncDirection"
],
"events": ["onFileStatusChanged", "onServiceStatusChanged"]
},
"system.cpu": {
"properties": [],
"methods": ["getInfo"],
"types": ["CpuInfo", "CpuTime", "ProcessorInfo"],
"events": []
},
"system.display": {
"properties": [],
"methods": [
"clearTouchCalibration",
"completeCustomTouchCalibration",
"enableUnifiedDesktop",
"getDisplayLayout",
"getInfo",
"overscanCalibrationAdjust",
"overscanCalibrationComplete",
"overscanCalibrationReset",
"overscanCalibrationStart",
"setDisplayLayout",
"setDisplayProperties",
"setMirrorMode",
"showNativeTouchCalibration",
"startCustomTouchCalibration"
],
"types": [
"Bounds",
"DisplayLayout",
"DisplayMode",
"DisplayProperties",
"DisplayUnitInfo",
"Edid",
"GetInfoFlags",
"Insets",
"MirrorModeInfo",
"Point",
"TouchCalibrationPair",
"TouchCalibrationPairQuad",
"ActiveState",
"LayoutPosition",
"MirrorMode"
],
"events": ["onDisplayChanged"]
},
"system.memory": {
"properties": [],
"methods": ["getInfo"],
"types": ["MemoryInfo"],
"events": []
},
"system.network": {
"properties": [],
"methods": ["getNetworkInterfaces"],
"types": ["NetworkInterface"],
"events": []
},
"system.storage": {
"properties": [],
"methods": ["ejectDevice", "getAvailableCapacity", "getInfo"],
"types": [
"StorageAvailableCapacityInfo",
"StorageUnitInfo",
"EjectDeviceResultCode",
"StorageUnitType"
],
"events": ["onAttached", "onDetached"]
},
"systemLog": {
"properties": [],
"methods": ["add"],
"types": ["MessageOptions"],
"events": []
},
"tabCapture": {
"properties": [],
"methods": ["capture", "getCapturedTabs", "getMediaStreamId"],
"types": [
"CaptureInfo",
"CaptureOptions",
"GetMediaStreamOptions",
"MediaStreamConstraint",
"TabCaptureState"
],
"events": ["onStatusChanged"]
},
"tabGroups": {
"properties": ["TAB_GROUP_ID_NONE"],
"methods": ["get", "move", "query", "update"],
"types": ["TabGroup", "Color"],
"events": ["onCreated", "onMoved", "onRemoved", "onUpdated"]
},
"tabs": {
"properties": [
"MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND",
"TAB_ID_NONE",
"TAB_INDEX_NONE"
],
"methods": [
"captureVisibleTab",
"connect",
"create",
"detectLanguage",
"discard",
"duplicate",
"executeScript",
"get",
"getAllInWindow",
"getCurrent",
"getSelected",
"getZoom",
"getZoomSettings",
"goBack",
"goForward",
"group",
"highlight",
"insertCSS",
"move",
"query",
"reload",
"remove",
"removeCSS",
"sendMessage",
"sendRequest",
"setZoom",
"setZoomSettings",
"ungroup",
"update"
],
"types": [
"MutedInfo",
"Tab",
"ZoomSettings",
"MutedInfoReason",
"TabStatus",
"WindowType",
"ZoomSettingsMode",
"ZoomSettingsScope"
],
"events": [
"onActivated",
"onActiveChanged",
"onAttached",
"onCreated",
"onDetached",
"onHighlightChanged",
"onHighlighted",
"onMoved",
"onRemoved",
"onReplaced",
"onSelectionChanged",
"onUpdated",
"onZoomChange"
]
},
"topSites": {
"properties": [],
"methods": ["get"],
"types": ["MostVisitedURL"],
"events": []
},
"tts": {
"properties": [],
"methods": ["getVoices", "isSpeaking", "pause", "resume", "speak", "stop"],
"types": ["TtsEvent", "TtsOptions", "TtsVoice", "EventType", "VoiceGender"],
"events": ["onVoicesChanged"]
},
"ttsEngine": {
"properties": [],
"methods": ["updateLanguage", "updateVoices"],
"types": [
"AudioBuffer",
"AudioStreamOptions",
"LanguageStatus",
"LanguageUninstallOptions",
"SpeakOptions",
"TtsClient",
"LanguageInstallStatus",
"TtsClientSource",
"VoiceGender"
],
"events": [
"onInstallLanguageRequest",
"onLanguageStatusRequest",
"onPause",
"onResume",
"onSpeak",
"onSpeakWithAudioStream",
"onStop",
"onUninstallLanguageRequest"
]
},
"types": {
"properties": [],
"methods": [],
"types": ["ChromeSetting", "ChromeSettingScope", "LevelOfControl"],
"events": []
},
"usb": {
"properties": [],
"methods": [
"bulkTransfer",
"claimInterface",
"closeDevice",
"controlTransfer",
"findDevices",
"getConfiguration",
"getConfigurations",
"getDevices",
"getUserSelectedDevices",
"interruptTransfer",
"isochronousTransfer",
"listInterfaces",
"openDevice",
"releaseInterface",
"requestAccess",
"resetDevice",
"setConfiguration",
"setInterfaceAlternateSetting"
],
"types": [
"ConfigDescriptor",
"ConnectionHandle",
"ControlTransferInfo",
"Device",
"DeviceFilter",
"DevicePromptOptions",
"EndpointDescriptor",
"EnumerateDevicesAndRequestAccessOptions",
"EnumerateDevicesOptions",
"GenericTransferInfo",
"InterfaceDescriptor",
"IsochronousTransferInfo",
"TransferResultInfo",
"Direction",
"Recipient",
"RequestType",
"SynchronizationType",
"TransferType",
"UsageType"
],
"events": ["onDeviceAdded", "onDeviceRemoved"]
},
"userScripts": {
"properties": [],
"methods": [
"configureWorld",
"execute",
"getScripts",
"getWorldConfigurations",
"register",
"resetWorldConfiguration",
"unregister",
"update"
],
"types": [
"InjectionResult",
"InjectionTarget",
"RegisteredUserScript",
"ScriptSource",
"UserScriptFilter",
"UserScriptInjection",
"WorldProperties",
"ExecutionWorld"
],
"events": []
},
"virtualKeyboard": {
"properties": [],
"methods": ["restrictFeatures"],
"types": ["FeatureRestrictions"],
"events": []
},
"vpnProvider": {
"properties": [],
"methods": [
"createConfig",
"destroyConfig",
"notifyConnectionStateChanged",
"sendPacket",
"setParameters"
],
"types": ["Parameters", "PlatformMessage", "UIEvent", "VpnConnectionState"],
"events": [
"onConfigCreated",
"onConfigRemoved",
"onPacketReceived",
"onPlatformMessage",
"onUIEvent"
]
},
"wallpaper": {
"properties": [],
"methods": ["setWallpaper"],
"types": ["WallpaperLayout"],
"events": []
},
"webAccessibleResources": {
"properties": [],
"methods": [],
"types": ["WebAccessibleResource"],
"events": []
},
"webAuthenticationProxy": {
"properties": [],
"methods": [
"attach",
"completeCreateRequest",
"completeGetRequest",
"completeIsUvpaaRequest",
"detach"
],
"types": [
"CreateRequest",
"CreateResponseDetails",
"DOMExceptionDetails",
"GetRequest",
"GetResponseDetails",
"IsUvpaaRequest",
"IsUvpaaResponseDetails"
],
"events": [
"onCreateRequest",
"onGetRequest",
"onIsUvpaaRequest",
"onRemoteSessionStateChange",
"onRequestCanceled"
]
},
"webNavigation": {
"properties": [],
"methods": ["getAllFrames", "getFrame"],
"types": ["TransitionQualifier", "TransitionType"],
"events": [
"onBeforeNavigate",
"onCommitted",
"onCompleted",
"onCreatedNavigationTarget",
"onDOMContentLoaded",
"onErrorOccurred",
"onHistoryStateUpdated",
"onReferenceFragmentUpdated",
"onTabReplaced"
]
},
"webRequest": {
"properties": ["MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES"],
"methods": ["handlerBehaviorChanged"],
"types": [
"BlockingResponse",
"RequestFilter",
"UploadData",
"FormDataItem",
"HttpHeaders",
"IgnoredActionType",
"OnAuthRequiredOptions",
"OnBeforeRedirectOptions",
"OnBeforeRequestOptions",
"OnBeforeSendHeadersOptions",
"OnCompletedOptions",
"OnErrorOccurredOptions",
"OnHeadersReceivedOptions",
"OnResponseStartedOptions",
"OnSendHeadersOptions",
"ResourceType"
],
"events": [
"onActionIgnored",
"onAuthRequired",
"onBeforeRedirect",
"onBeforeRequest",
"onBeforeSendHeaders",
"onCompleted",
"onErrorOccurred",
"onHeadersReceived",
"onResponseStarted",
"onSendHeaders"
]
},
"webviewTag": {
"properties": ["contentWindow", "contextMenus", "request"],
"methods": [
"addContentScripts",
"back",
"canGoBack",
"canGoForward",
"captureVisibleRegion",
"clearData",
"executeScript",
"find",
"forward",
"getAudioState",
"getProcessId",
"getUserAgent",
"getZoom",
"getZoomMode",
"go",
"insertCSS",
"isAudioMuted",
"isSpatialNavigationEnabled",
"isUserAgentOverridden",
"loadDataWithBaseUrl",
"print",
"reload",
"removeContentScripts",
"setAudioMuted",
"setSpatialNavigationEnabled",
"setUserAgentOverride",
"setZoom",
"setZoomMode",
"stop",
"stopFinding",
"terminate"
],
"types": [
"ClearDataOptions",
"ClearDataTypeSet",
"ContentScriptDetails",
"ContentWindow",
"ContextMenuCreateProperties",
"ContextMenuUpdateProperties",
"ContextMenus",
"DialogController",
"DownloadPermissionRequest",
"FileSystemPermissionRequest",
"FindCallbackResults",
"FindOptions",
"FullscreenPermissionRequest",
"GeolocationPermissionRequest",
"HidPermissionRequest",
"InjectDetails",
"InjectionItems",
"LoadPluginPermissionRequest",
"MediaPermissionRequest",
"NewWindow",
"PointerLockPermissionRequest",
"SelectionRect",
"WebRequestEventInterface",
"ContextType",
"ZoomMode"
],
"events": [
"close",
"consolemessage",
"contentload",
"dialog",
"exit",
"findupdate",
"loadabort",
"loadcommit",
"loadredirect",
"loadstart",
"loadstop",
"newwindow",
"permissionrequest",
"responsive",
"sizechanged",
"unresponsive",
"zoomchange"
]
},
"windows": {
"properties": ["WINDOW_ID_CURRENT", "WINDOW_ID_NONE"],
"methods": [
"create",
"get",
"getAll",
"getCurrent",
"getLastFocused",
"remove",
"update"
],
"types": [
"QueryOptions",
"Window",
"CreateType",
"WindowState",
"WindowType"
],
"events": ["onBoundsChanged", "onCreated", "onFocusChanged", "onRemoved"]
}
}
================================================
FILE: .repo/sample-list-generator/package.json
================================================
{
"name": "sample-list-generator",
"version": "1.0.0",
"scripts": {
"start": "ts-node src/index.ts",
"prepare-chrome-types": "ts-node src/prepare-chrome-types.ts",
"test": "mocha --require ts-node/register test/**/*.test.ts"
},
"devDependencies": {
"@types/babel__core": "7.20.1",
"@types/mocha": "10.0.1",
"@types/node-fetch": "2.6.4",
"@types/sinon": "10.0.15",
"mocha": "10.2.0",
"sinon": "15.2.0",
"ts-node": "10.9.1",
"typescript": "5.1.3"
},
"dependencies": {
"@babel/core": "7.22.5",
"node-fetch": "2.6.11",
"typedoc": "0.24.8"
}
}
================================================
FILE: .repo/sample-list-generator/src/constants.ts
================================================
export type FolderTypes = "API_SAMPLE" | "FUNCTIONAL_SAMPLE";
// Define all available folders for samples
export const AVAILABLE_FOLDERS: { path: string, type: FolderTypes }[] = [
{
path: 'api-samples',
type: 'API_SAMPLE'
},
{
path: 'functional-samples',
type: 'FUNCTIONAL_SAMPLE'
}
];
export const REPO_BASE_URL =
'https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/';
================================================
FILE: .repo/sample-list-generator/src/index.ts
================================================
import path from 'path';
import fs from 'fs/promises';
import { getAllSamples } from './libs/sample-collector';
const start = async () => {
const samples = await getAllSamples();
// write to extension-samples.json
await fs.writeFile(
path.join(__dirname, '../extension-samples.json'),
JSON.stringify(samples, null, 2)
);
};
start();
================================================
FILE: .repo/sample-list-generator/src/libs/api-detector.ts
================================================
import {
ApiItem,
ApiItemWithType,
ApiTypeResult,
ExtensionApiMap
} from '../types';
import * as babel from '@babel/core';
import { isIdentifier } from '@babel/types';
import fs from 'fs/promises';
import { getAllJsFiles } from '../utils/filesystem';
import { loadExtensionApis } from './api-loader';
let EXTENSION_API_MAP: ExtensionApiMap = loadExtensionApis();
/**
* Gets the type of an api call.
* @param namespace - The namespace of the api call.
* @param propertyName - The property name of the api call.
* @returns The type of the api call.
* @example
* getApiType('tabs', 'query')
* // returns 'method'
*/
export const getApiType = (
namespace: string,
propertyName: string
): ApiTypeResult => {
namespace = namespace.replace(/_/g, '.');
const apiTypes = EXTENSION_API_MAP[namespace];
if (apiTypes) {
if (apiTypes.methods.includes(propertyName)) {
return 'method';
}
if (apiTypes.events.includes(propertyName)) {
return 'event';
}
if (apiTypes.properties.includes(propertyName)) {
return 'property';
}
if (apiTypes.types.includes(propertyName)) {
return 'type';
}
}
return 'unknown';
};
/**
* Gets all the api calls in a sample.
* @param sampleFolderPath - The path to the sample folder.
* @returns A promise that resolves to an array of apis the sample uses.
*/
export const getApiListForSample = async (
sampleFolderPath: string
): Promise => {
// get all js files in the folder
const jsFiles = await getAllJsFiles(sampleFolderPath);
const calls: ApiItemWithType[] = [];
await Promise.all(
jsFiles.map(async (file) => {
const callsFromFile = await extractApiCalls((await fs.readFile(file)).toString('utf-8'));
calls.push(...callsFromFile);
})
);
return uniqueItems(calls);
};
/**
* Gets the complete API call for the member expression.
* @param path - The path to the MemberExpression node.
* @returns The full member expression.
* @example
* getFullMemberExpression(path.node)
* // returns ['chrome', 'tabs', 'query']
*/
export function getFullMemberExpression(
path: babel.NodePath
): string[] {
const result: string[] = [];
// Include the chrome. or browser. identifier
if (isIdentifier(path.node.object)) {
result.push(path.node.object.name);
} else {
// We don't support expressions
return result;
}
while (path) {
if (isIdentifier(path.node.property)) {
result.push(path.node.property.name);
} else {
// We don't support expressions
break;
}
const parentPath = path.parentPath;
if (!parentPath || !parentPath.isMemberExpression()) {
break;
} else {
path = parentPath;
}
}
return result;
}
/**
* Gets the namespace and property name of an api call.
* @param parts - The parts of the api call.
* @returns The namespace and property name of the api call.
* @example
* getApiItem(['chrome', 'tabs', 'query'])
* // returns { namespace: 'tabs', propertyName: 'query' }
* getApiItem(['chrome', 'devtools', 'inspectedWindow', 'eval'])
* // returns { namespace: 'devtools.inspectedWindow', propertyName: 'eval' }
*/
export function getApiItem(parts: string[]): ApiItem {
let namespace = '';
let propertyName = '';
// For some apis like `chrome.devtools.inspectedWindow.eval`,
// the namespace is actually `devtools.inspectedWindow`.
// So we need to check if the first two parts combined is a valid namespace.
if (EXTENSION_API_MAP[`${parts[0]}.${parts[1]}`]) {
namespace = `${parts[0]}.${parts[1]}`;
propertyName = parts[2];
} else {
namespace = parts[0];
propertyName = parts[1];
}
return { namespace, propertyName };
}
/**
* Filters an array of ApiItemWithType to remove duplicates.
* @param array - The array of ApiItemWithType to filter.
*/
function uniqueItems(array: ApiItemWithType[]) {
const tmp = new Set();
return array.filter((item) => {
const fullApiString = `${item.namespace}.${item.propertyName}`;
return !tmp.has(fullApiString) && tmp.add(fullApiString);
});
}
/**
* Extracts all chrome and browser api calls from a file.
* @param script - The script string to extract api calls from.
* @returns A promise that resolves to an array of ApiItemWithType.
* @example
* extractApiCalls('chrome.tabs.query({})')
* // returns [{ type: 'method', namespace: 'tabs', propertyName: 'query' }]
*/
export const extractApiCalls = (script: string): Promise => {
return new Promise((resolve, reject) => {
const calls: ApiItemWithType[] = [];
babel.parse(
script,
{ ast: true, compact: false },
(err, result) => {
if (err || !result) {
reject(err);
return;
}
babel.traverse(result, {
MemberExpression(path) {
const parts = getFullMemberExpression(path);
// not a chrome or browser api
if (!['chrome', 'browser'].includes(parts.shift() || '')) {
return;
}
const { namespace, propertyName } = getApiItem(parts);
let type = getApiType(namespace, propertyName);
// api not found
if (type === 'unknown') {
console.warn('api not found', namespace, propertyName);
return;
}
calls.push({ type, namespace, propertyName });
}
});
resolve(calls);
}
);
});
};
================================================
FILE: .repo/sample-list-generator/src/libs/api-loader.ts
================================================
import path from 'path';
import fs from 'fs';
import type { ExtensionApiMap } from '../types';
import { isFileExistsSync } from '../utils/filesystem';
export const loadExtensionApis = (): ExtensionApiMap => {
const filePath = path.join(__dirname, '../../extension-apis.json');
// check if extension-apis.json exists
if (!isFileExistsSync(filePath)) {
console.error(
'extension-apis.json does not exist. Please run "npm run prepare-chrome-types" first.'
);
process.exit(1);
}
let data = fs.readFileSync(filePath, 'utf8');
const apiMap = JSON.parse(data);
// Due to the specific implementation of this API, we need to manually add it
// to the list of APIs recognised by the sample list generator.
apiMap['aiOriginTrial.languageModel'] = {
properties: [],
methods: ['create', 'capabilities', 'params', 'availability'],
types: [],
events: []
};
return apiMap;
};
================================================
FILE: .repo/sample-list-generator/src/libs/sample-collector.ts
================================================
import path from 'path';
import fs from 'fs/promises';
import { AVAILABLE_FOLDERS, REPO_BASE_URL } from '../constants';
import { getApiListForSample } from './api-detector';
import type { AvailableFolderItem, SampleItem } from '../types';
import { getBasePath, isDirectory, isFileExists } from '../utils/filesystem';
import { getManifest } from '../utils/manifest';
export const getAllSamples = async () => {
let samples: SampleItem[] = [];
// loop through all available folders
// e.g. api-samples, functional-samples
for (let samplesFolder of AVAILABLE_FOLDERS) {
const currentSamples = await getSamples(
samplesFolder.path,
samplesFolder.type
);
samples.push(...currentSamples);
}
return samples;
};
const getSamples = async (
currentRootFolderPath: string,
sampleType: AvailableFolderItem['type']
): Promise => {
const samples: SampleItem[] = [];
const basePath = getBasePath();
// get all contents in the folder
const contents = await fs.readdir(path.join(basePath, currentRootFolderPath));
for (let content of contents) {
const currentPath = path.join(basePath, currentRootFolderPath, content);
// if content is not a folder, skip
if (!(await isDirectory(currentPath))) {
continue;
}
const manifestPath = path.join(currentPath, 'manifest.json');
// check if manifest.json exists
const manifestExists = await isFileExists(manifestPath);
if (manifestExists) {
// get manifest metadata
const manifestData = await getManifest(manifestPath);
// add to samples
samples.push({
type: sampleType,
name: content,
repo_link: new URL(
`${REPO_BASE_URL}${currentPath.replace(basePath, '')}`
).toString(),
apis: await getApiListForSample(currentPath),
title: manifestData.name || content,
description: manifestData.description || '',
permissions: manifestData.permissions || []
});
} else {
// if manifest.json does not exist, loop through all folders in current folder
const currentSamples = await getSamples(
path.join(currentRootFolderPath, content),
sampleType
);
samples.push(...currentSamples);
}
}
return samples;
};
================================================
FILE: .repo/sample-list-generator/src/prepare-chrome-types.ts
================================================
import fetch from 'node-fetch';
import path from 'path';
import fs from 'fs/promises';
import { ExtensionApiMap } from './types';
import { ReflectionKind } from 'typedoc';
// Bucket used to store processed types data
const STORAGE_BUCKET = process.env.STORAGE_BUCKET;
// Fetch the latest version of the chrome types from storage
const fetchChromeTypes = async (): Promise> => {
if (!STORAGE_BUCKET) {
throw new Error('The STORAGE_BUCKET environment variable must be set.');
}
console.log('Fetching chrome types...');
const response = await fetch(
`https://storage.googleapis.com/download/storage/v1/b/${STORAGE_BUCKET}/o/chrome-types.json?alt=media`
);
const chromeTypes = await response.json();
return chromeTypes;
};
const run = async () => {
const result: ExtensionApiMap = {};
const chromeTypes = await fetchChromeTypes();
for (const [chromeApiKey, chromeApiDetails] of Object.entries(chromeTypes)) {
const apiDetails: ExtensionApiMap[string] = {
properties: [],
methods: [],
types: [],
events: []
};
for (let property of chromeApiDetails._type.properties) {
const name = property.name as string;
// check property type
let propertyType = 'types';
if (property.kind & ReflectionKind.VariableOrProperty) {
propertyType = 'properties';
}
if (
property.type?.type === 'reference' &&
['CustomChromeEvent', 'events.Event', 'Event'].includes(
property.type.name
)
) {
propertyType = 'events';
}
if (property.signatures) {
propertyType = 'methods';
}
apiDetails[propertyType].push(name);
}
result[chromeApiKey] = apiDetails;
}
console.log('Writing to file...');
await fs.writeFile(
path.join(__dirname, '../extension-apis.json'),
JSON.stringify(
{
_comment:
'This file is autogenerated by running `npm run prepare-chrome-types`, do not edit.',
...result
},
null,
2
)
);
console.log('Done!');
};
run();
================================================
FILE: .repo/sample-list-generator/src/types.ts
================================================
import type { FolderTypes } from './constants';
export interface ApiItem {
namespace: string;
propertyName: string;
}
export interface ApiItemWithType extends ApiItem {
type: ApiTypeResult;
}
export interface ManifestData {
[key: string]: string;
name: string;
description: string;
permissions: string[];
}
export interface LocaleData {
[key: string]: {
message: string;
description: string;
};
}
export type SampleItem = {
type: FolderTypes;
name: string;
repo_link: string;
apis: ApiItem[];
title: string;
description: string;
permissions: string[];
};
export interface AvailableFolderItem {
path: string;
type: FolderTypes;
}
export type ApiTypeResult =
| 'event'
| 'method'
| 'property'
| 'type'
| 'unknown';
export type ExtensionApiMap = Record>
================================================
FILE: .repo/sample-list-generator/src/utils/filesystem.ts
================================================
import fs from 'fs/promises';
import { accessSync } from 'fs';
import path from 'path';
export const getAllFiles = async (dir: string): Promise => {
const result: string[] = [];
for (const file of await fs.readdir(dir)) {
const filePath = path.join(dir, file);
const stats = await fs.stat(filePath);
if (stats.isFile()) {
result.push(filePath);
} else if (stats.isDirectory()) {
if (file === "node_modules") continue;
result.push(...(await getAllFiles(filePath)));
}
}
return result;
};
export const getAllJsFiles = async (dir: string): Promise => {
const allFiles = await getAllFiles(dir);
return allFiles.filter((file) =>
file.endsWith('.js')
);
}
export const isDirectory = async (path: string): Promise => {
return (await fs.stat(path)).isDirectory()
}
export const isFileExists = async (filePath: string): Promise => {
try {
await fs.access(filePath);
return true;
} catch {
return false;
}
};
export const isFileExistsSync = (filePath: string): boolean => {
try {
accessSync(filePath);
return true;
} catch {
return false;
}
};
export const getBasePath = (): string => {
return path.join(__dirname, '../../../../');
};
================================================
FILE: .repo/sample-list-generator/src/utils/manifest.ts
================================================
import fs from 'fs/promises';
import { dirname } from 'path';
import { ManifestData, LocaleData } from '../types';
const localeRegex = /__MSG_([^_]*)__/
function usesLocaleFiles(obj: object): boolean {
// recursively check if any value in a supplied object
// is a string that starts with __MSG_. If found, it
// means that the extension uses locale files.
return Object.values(obj).some((value) => {
if (Object.prototype.toString.call(value) === '[object Object]') {
return usesLocaleFiles(value);
}
return typeof value === 'string' && value.startsWith('__MSG_')
});
}
export const getManifest = async (
manifestPath: string
): Promise => {
const manifest = await fs.readFile(manifestPath, 'utf8');
const parsedManifest = JSON.parse(manifest);
if (usesLocaleFiles(parsedManifest)) {
const directory = dirname(manifestPath);
const localeFile: string = await fs.readFile(`${directory}/_locales/en/messages.json`, 'utf8')
const localeData: LocaleData = JSON.parse(localeFile);
for (const [key, value] of Object.entries(parsedManifest)) {
if (typeof value === 'string' && value.startsWith('__MSG_')) {
const localeKey: string | undefined = value.match(localeRegex)?.[1];
if (localeKey) {
const localeKeyData = localeData[localeKey]
const localeMessage: string = localeKeyData?.message;
parsedManifest[key] = localeMessage;
}
}
}
}
return parsedManifest;
};
================================================
FILE: .repo/sample-list-generator/test/api-detector/api-detector.test.ts
================================================
import { describe, it, beforeEach } from 'mocha';
import assert from 'assert';
import sinon from 'sinon';
import {
getApiType,
extractApiCalls,
getApiItem
} from '../../src/libs/api-detector';
describe('API Detector', function () {
beforeEach(function () {
sinon.reset();
});
describe('extractApiCalls()', function () {
it('should return correct api list for sample file (normal)', async function () {
const file = `
let a = 1;
let b = chrome.action.getBadgeText();
let c = chrome.action.setBadgeText(a);
chrome.action.onClicked.addListener(function (tab) {
console.log('clicked');
});
alert(chrome.contextMenus.ACTION_MENU_TOP_LEVEL_LIMIT)
`;
const result = await extractApiCalls(file);
assert.deepEqual(result, [
{
namespace: 'action',
propertyName: 'getBadgeText',
type: 'method'
},
{
namespace: 'action',
propertyName: 'setBadgeText',
type: 'method'
},
{
namespace: 'action',
propertyName: 'onClicked',
type: 'event'
},
{
namespace: 'contextMenus',
propertyName: 'ACTION_MENU_TOP_LEVEL_LIMIT',
type: 'property'
}
]);
});
it('should return correct api list for sample file (storage)', async function () {
const file = `
let b = await chrome.storage.local.get();
let c = await chrome.storage.sync.get();
let d = await chrome.storage.managed.get();
let e = await chrome.storage.session.get();
let f = await chrome.storage.onChanged.addListener();
`;
const result = await extractApiCalls(file);
assert.deepEqual(result, [
{
namespace: 'storage',
propertyName: 'local',
type: 'property'
},
{
namespace: 'storage',
propertyName: 'sync',
type: 'property'
},
{
namespace: 'storage',
propertyName: 'managed',
type: 'property'
},
{
namespace: 'storage',
propertyName: 'session',
type: 'property'
},
{
namespace: 'storage',
propertyName: 'onChanged',
type: 'event'
}
]);
});
it('should return correct api list for sample file (async)', async function () {
const file = `
let a = 1;
let b = await chrome.action.getBadgeText();
await chrome.action.setBadgeText(a);
`;
const result = await extractApiCalls(file);
assert.deepEqual(result, [
{
namespace: 'action',
propertyName: 'getBadgeText',
type: 'method'
},
{
namespace: 'action',
propertyName: 'setBadgeText',
type: 'method'
}
]);
});
it('should return correct api list for sample file (special case)', async function () {
const file = `
let a = 1;
let b = await chrome.system.cpu.getInfo();
chrome.devtools.network.onRequestFinished.addListener(
function(request) {
if (request.response.bodySize > 40*1024) {
chrome.devtools.inspectedWindow.eval(
'console.log("Large image: " + unescape("' +
escape(request.request.url) + '"))');
}
}
);
`;
const result = await extractApiCalls(file);
assert.deepEqual(result, [
{
namespace: 'system.cpu',
propertyName: 'getInfo',
type: 'method'
},
{
namespace: 'devtools.network',
propertyName: 'onRequestFinished',
type: 'event'
},
{
namespace: 'devtools.inspectedWindow',
propertyName: 'eval',
type: 'method'
}
]);
});
});
describe('getApiType()', function () {
it('should return correct type of api in normal case', function () {
let apiType = getApiType('action', 'getBadgeText');
assert.equal(apiType, 'method');
});
it('should return correct type of api in special case', function () {
let apiType = getApiType('devtools.network', 'onNavigated');
assert.equal(apiType, 'event');
});
it('should return unknown when api not found', function () {
let apiType = getApiType('action', '123');
assert.equal(apiType, 'unknown');
});
});
describe('getApiItem()', function () {
it('should return correct api item', function () {
let apiItem = getApiItem(['action', 'getBadgeText']);
assert.deepEqual(apiItem, {
namespace: 'action',
propertyName: 'getBadgeText'
});
});
it('should return correct api item (storage)', function () {
let apiItem = getApiItem(['storage', 'sync', 'get']);
assert.deepEqual(apiItem, {
namespace: 'storage',
propertyName: 'sync'
});
apiItem = getApiItem(['storage', 'sync', 'onChanged']);
assert.deepEqual(apiItem, {
namespace: 'storage',
propertyName: 'sync'
});
apiItem = getApiItem(['storage', 'onChanged']);
assert.deepEqual(apiItem, {
namespace: 'storage',
propertyName: 'onChanged'
});
});
it('should return correct api item (special case)', function () {
let apiItem = getApiItem([
'devtools',
'network',
'onRequestFinished',
'addListener'
]);
assert.deepEqual(apiItem, {
namespace: 'devtools.network',
propertyName: 'onRequestFinished'
});
});
});
});
================================================
FILE: CONTRIBUTING.md
================================================
# How to Contribute
We'd love to accept your patches and contributions to this project.
## Before you begin
### Sign our Contributor License Agreement
Contributions to this project must be accompanied by a
[Contributor License Agreement](https://cla.developers.google.com/about) (CLA).
You (or your employer) retain the copyright to your contribution; this simply
gives us permission to use and redistribute your contributions as part of the
project.
If you or your current employer have already signed the Google CLA (even if it
was for a different project), you probably don't need to do it again.
Visit to see your current agreements or to
sign a new one.
### Review our Community Guidelines
This project follows [Google's Open Source Community
Guidelines](https://opensource.google/conduct/).
## Contribution process
### Create an issue first
Before adding a new sample, [create an issue first](https://github.com/GoogleChrome/chrome-extensions-samples/issues/new).
Describe why this sample is needed and how you plan to implement it. Only once
you've got the approval from one of the maintainers start working on a PR. Non
trivial PRs without an approved issue will be rejected.
### Code Reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
### Setting up your Environment
If you want to contribute to this repository, you need to first [create your own fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
After forking chrome-extensions-samples to your own Github account, run the
following steps to get started:
```sh
# clone your fork to your local machine
git clone https://github.com/your-fork/chrome-extensions-samples.git
cd chrome-extensions-samples
# install dependencies
npm install
```
### Writing a README
All new code samples or samples updated from Manifest V2 should include a
README file. Please copy the [provided template](./README-template.md) into
your sample's folder and follow the instructions therein.
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README-template.md
================================================
_To create a README for your sample_
1. _Copy this file to your sample folder._
1. _Enter the requested information below._
1. _Delete these instructions._
_For API samples use the name of the API. For example, a sample about the `chrome.declarativeNetRequest` would simply be called "chrome.declarativeNetRequest". (Do not use special formatting in headings.) For functional samples, the title should be what the sample demonstrates_
# Title
_Describe what the sample demonstrates. If this is an API sample, link to the API._
This sample demonstrates ...
## Overview
_Describe how the sample demonstrates the API or use case and briefly describe how to use it._
## Implementation Notes
_Add any information that doesn't fit elsewhere in the README._
## Running this extension
1. Clone this repository.
2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).
3. _Add the rest of the instructions here_
================================================
FILE: README.md
================================================
# Chrome Extensions samples
Official samples for Chrome Extensions and the Chrome Apps platform. (Chrome Apps are deprecated. Learn more [on the Chromium blog](https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html)).
For more information on extensions, see [Chrome Developers](https://developer.chrome.com).
## Explore samples
The directory structure is as follows:
- [api-samples/](api-samples/) - extensions focused on a single API package
- [functional-samples/](functional-samples/) - full featured extensions spanning multiple API packages
- [\_archive/apps/](_archive/apps/) - deprecated Chrome Apps platform (not listed below)
- [\_archive/mv2/](_archive/mv2/) - resources for manifest version 2
You can also use the [Samples](https://developer.chrome.com/docs/extensions/samples/) page to discover extensions by type, permissions, and extension API.
## Installation
To experiment with these samples, please clone this repo and use 'Load Unpacked Extension'.
Read more on [Development Basics](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).
## Contributing
Please see [the CONTRIBUTING file](/CONTRIBUTING.md) for information on contributing to the `chrome-extensions-samples` project.
## License
`chrome-extensions-samples` are authored by Google and are licensed under the [Apache License, Version 2.0](/LICENSE).
================================================
FILE: _archive/apps/README.md
================================================
# Chrome Apps samples
Official samples for deprecated Chrome Apps platform. If you want to learn about the platform, you can:
1. look at the source code of the samples below. Most samples have a "Try it now" button that allows you to install and play with it.
2. read the [official docs](http://developer.chrome.com/apps)
If you have questions, [search](http://stackoverflow.com/questions/tagged/google-chrome-app) or [ask at StackOverflow](http://stackoverflow.com/questions/ask?tags=google-chrome-app) (observe the google-chrome-app tag) or join the [Chromium Apps](https://groups.google.com/a/chromium.org/forum/?fromgroups#!forum/chromium-apps) Google group.
# Samples
Sample | API or feature | Link
--- | --- |:---:
analytics | storage ios android |
appengine-channelapi/app | webview |
appsquare | geolocation identity storage |
appview/embedded-app | getUserMedia |
appview/host-app | appview |
blink1 | hid usb |
bluetooth-samples/battery-service-demo | bluetooth |
bluetooth-samples/device-info-demo | bluetooth |
bluetooth-samples/heart-rate-sensor | bluetooth |
calculator | clipboard ios android |
camera-capture | getUserMedia |
clock | framelessWindows geolocation richNotifications storage |
context-menu | contextMenu |
dart | dart ios |
desktop-capture | desktopCapture |
dialog-element | |
diff | clipboard fileSystem storage |
filesystem-access | fileSystem storage |
frameless-window | framelessWindows |
gcm-notifications | gcm richNotifications storage |
gdrive | framelessWindows identity |
github-auth | identity |
hello-world | ios android |
hello-world-sync | storage ios android |
hid | hid |
identity | identity android |
image-edit | fileSystem storage |
instagram-auth | identity |
io2012-presentation | framelessWindows getUserMedia serial storage webview | -
io2012-presentation/helloworld | | -
io2012-presentation/servo | getUserMedia serial | -
ioio | bluetooth |
keyboard-handler | |
managed-in-app-payments | in-app-payments | -
manga-cam | framelessWindows getUserMedia syncFileSystem |
mdns-browser | framelessWindows sockets systemInfo |
media-gallery | mediaGallery |
messaging/app1 | messaging |
messaging/app2 | messaging |
messaging/extension | messaging richNotifications |
mini-code-edit | commands contextMenu fileSystem |
multicast | framelessWindows messaging sockets storage |
one-time-payment | identity storage |
optional-permissions | optionalPermissions |
parrot-ar-drone | old_sockets sockets android |
platform-title | framelessWindows |
printing | print storage systemInfo |
restarted-demo | storage ios |
rich-notifications | richNotifications android |
sandbox | sandbox |
sandboxed-content | sandbox |
serial-control-signals | serial |
serial/adkjs/app | serial |
serial/espruino | serial |
serial/ledtoggle | serial |
servo | getUserMedia serial |
storage | |
syncfs-editor | syncFileSystem |
systemInfo | systemInfo |
tasks | identity android |
tcpserver | sockets systemInfo webview |
telnet | sockets |
text-editor | clipboard fileSystem |
todomvc | alarms fileSystem richNotifications storage syncFileSystem android | -
tts | tts | -
udp | sockets ios |
url-handler | storage webview | -
usb-label-printer | fileSystem getUserMedia optionalPermissions usb |
usb/device-info | usb |
usb/knob | optionalPermissions usb |
weather | geolocation storage ios |
web-store | fileSystem identity storage webstore |
webgl-pointer-lock | framelessWindows pointerLock |
webserver | sockets systemInfo android |
websocket-server | sockets ios |
webview-samples/browser | webview |
webview-samples/declarative-web-request | storage webview |
webview-samples/insert-css | storage webview |
webview-samples/local-resources | webview |
webview-samples/multi-tab-browser | contextMenu webview | -
webview-samples/new-window | webview |
webview-samples/new-window-user-agent | contextMenu webview | -
webview-samples/shared-script | webview |
webview-samples/user-agent | webview |
webview-samples/webview | geolocation getUserMedia pointerLock webview |
window-options | fullscreen |
window-state | fullscreen |
windows | framelessWindows |
# Samples by features
API or feature | Samples
--- | ---
alarms | todomvc
appview | appview_host-app
bluetooth | bluetooth-samples_battery-service-demo bluetooth-samples_device-info-demo bluetooth-samples_heart-rate-sensor ioio
clipboard | calculator diff text-editor
commands | mini-code-edit
contextMenu | context-menu mini-code-edit webview-samples_multi-tab-browser webview-samples_new-window-user-agent
dart | dart
desktopCapture | desktop-capture
fileSystem | diff filesystem-access image-edit mini-code-edit text-editor todomvc usb-label-printer web-store
framelessWindows | clock frameless-window gdrive io2012-presentation manga-cam mdns-browser multicast platform-title webgl-pointer-lock windows
fullscreen | window-options window-state
gcm | gcm-notifications
geolocation | appsquare clock weather webview-samples_webview
getUserMedia | appview_embedded-app camera-capture io2012-presentation io2012-presentation_servo manga-cam servo usb-label-printer webview-samples_webview
hid | blink1 hid
identity | appsquare gdrive github-auth identity instagram-auth one-time-payment tasks web-store
in-app-payments | managed-in-app-payments
mediaGallery | media-gallery
messaging | messaging_app1 messaging_app2 messaging_extension multicast
old_sockets | parrot-ar-drone
optionalPermissions | optional-permissions usb-label-printer usb_knob
pointerLock | webgl-pointer-lock webview-samples_webview
print | printing
richNotifications | clock gcm-notifications messaging_extension rich-notifications todomvc
sandbox | sandbox sandboxed-content
serial | io2012-presentation io2012-presentation_servo serial-control-signals serial_adkjs_app serial_espruino serial_ledtoggle servo
sockets | mdns-browser multicast parrot-ar-drone tcpserver telnet udp webserver websocket-server
storage | analytics appsquare clock diff filesystem-access gcm-notifications hello-world-sync image-edit io2012-presentation multicast one-time-payment printing restarted-demo todomvc url-handler weather web-store webview-samples_declarative-web-request webview-samples_insert-css
syncFileSystem | manga-cam syncfs-editor todomvc
systemInfo | mdns-browser printing systemInfo tcpserver webserver
tts | tts
usb | blink1 usb-label-printer usb_device-info usb_knob
webstore | web-store
webview | appengine-channelapi_app io2012-presentation tcpserver url-handler webview-samples_browser webview-samples_declarative-web-request webview-samples_insert-css webview-samples_local-resources webview-samples_multi-tab-browser webview-samples_new-window webview-samples_new-window-user-agent webview-samples_shared-script webview-samples_user-agent webview-samples_webview
# Mobile support
You can generate native mobile versions of the samples below using the procedure
described here .
Sample Android support iOS support
analytics Supported. Supported.
calculator Supported. Visual issues caused by fixed-size layout Supported. Visual issues caused by fixed-size layout
dart Supported. Visual issues caused by fixed-size layout
hello-world Supported. Supported.
hello-world-sync Supported. sync storage doesn't actually sync - works local Supported. sync storage doesn't actually sync - works local
identity Supported. You need to add an Android OAuth app in the Cloud API console of the OAuth project. The app's SHA1 can be the debug one (see more here ), and the package name is org.chromium.identity.MyApp. If you don't add the Android OAuth app and tries to use the OAuth client-id from the Chrome app, you will get a generic message GoogleAuthException
parrot-ar-drone Supported. Communication to the Drone works, but the UI requires a connected gamepad.
restarted-demo Supported. Restart must be done via Safari remote debugging.
rich-notifications Supported.
tasks Supported.
todomvc Supported.
udp Supported.
weather Supported.
webserver Supported. Directory picking doesn't work on some versions of Android
websocket-server Supported.
# Libraries and tools
* [Google APIs client library for Chrome Apps](https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/_archive/apps/libraries/gapi-chrome-apps-lib)
* [Google Analytics for Chrome Apps and Extensions](https://github.com/GoogleChrome/chrome-platform-analytics)
================================================
FILE: _archive/apps/libraries/gapi-chrome-apps-lib/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: _archive/apps/libraries/gapi-chrome-apps-lib/README.md
================================================
# Google API javascript client library loader for Chrome Packaged Apps
Provides the Google API javascript client 'gapi' as
appropriate for hosted websites, or if in a Chrome packaged
app implement a minimal set of functionality that is Content
Security Policy compliant and uses the chrome identity api.
## Status
This library is likely not suitable for use without additional modifications.
## Usage
To be expanded upon, but essentially:
- Add 'identity' permission to manifest.
- Reference this script instead of the apis.google.com online version.
- Call gapi methods as usual.
## Examples:
* [Tasks app using GAPI](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/tasks)
## Resources
* [JavaScript Client Library Reference](https://developers.google.com/api-client-library/javascript/reference/referencedocs)
================================================
FILE: _archive/apps/libraries/gapi-chrome-apps-lib/gapi-chrome-apps.js
================================================
/**
* Copyright 2013 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* gapi-chrome-apps version 0.001
*
* Provides the Google API javascript client 'gapi' as
* appropriate for hosted websites, or if in a Chrome packaged
* app implement a minimal set of functionality that is Content
* Security Policy compliant and uses the chrome identity api.
*
* https://github.com/GoogleChrome/chrome-app-samples/tree/master/gapi-chrome-apps-lib
*
*/
"use strict";
(function () {
if (typeof gapi !== 'undefined')
throw new Error('gapi already defined.');
if (typeof gapiIsLoaded !== 'function')
throw new Error('gapiIsLoaded callback function must be defined prior to ' +
'loading gapi-chrome-apps.js');
// If not running in a chrome packaged app, load web gapi:
if (!(chrome && chrome.app && chrome.app.runtime)) {
// Load web gapi.
var script = document.createElement('script');
script.src = 'https://apis.google.com/js/client.js?onload=gapiIsLoaded';
document.documentElement.appendChild(script);
return;
}
window.gapi = {};
window.gapi.auth = {};
window.gapi.client = {};
var access_token = undefined;
gapi.auth.authorize = function (params, callback) {
if (typeof callback !== 'function')
throw new Error('callback required');
var details = {};
details.interactive = params.immediate === false || false;
if (params.accountHint) {
// Specifying this prevents the account chooser from appearing on Android.
details.accountHint = params.accountHint;
}
console.assert(!params.response_type || params.response_type == 'token');
var callbackWrapper = function (getAuthTokenCallbackParam) {
access_token = getAuthTokenCallbackParam;
// TODO: error conditions?
if (typeof access_token !== 'undefined')
callback({ access_token: access_token});
else
callback();
}
chrome.identity.getAuthToken(details, callbackWrapper);
};
gapi.client.request = function (args) {
if (typeof args !== 'object')
throw new Error('args required');
if (typeof args.callback !== 'function')
throw new Error('callback required');
if (typeof args.path !== 'string')
throw new Error('path required');
if (args.root && args.root === 'string') {
var path = args.root + args.path;
} else {
var path = 'https://www.googleapis.com' + args.path;
}
if (typeof args.params === 'object') {
var deliminator = '?';
for (var i in args.params) {
path += deliminator + encodeURIComponent(i) + "="
+ encodeURIComponent(args.params[i]);
deliminator = '&';
}
}
var xhr = new XMLHttpRequest();
xhr.open(args.method || 'GET', path);
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
if (typeof args.body !== 'undefined') {
xhr.setRequestHeader('content-type', 'application/json');
xhr.send(JSON.stringify(args.body));
} else {
xhr.send();
}
xhr.onerror = function () {
// TODO, error handling.
debugger;
};
xhr.onload = function() {
var rawResponseObject = {
// TODO: body, headers.
gapiRequest: {
data: {
status: this.status,
statusText: this.statusText
}
}
};
var rawResp = JSON.stringify(rawResponseObject);
if (this.response) {
var jsonResp = JSON.parse(this.response);
args.callback(jsonResp, rawResp);
} else {
args.callback(null, rawResp);
}
};
};
// Call client handler when gapi is ready.
setTimeout(function () { gapiIsLoaded(); }, 0);
})();
================================================
FILE: _archive/apps/samples/analytics/README.md
================================================

# Analytics
This example demonstrates how to include support for Google Analytics in your
packaged application. It uses the
[chrome-platform-analytics](https://github.com/GoogleChrome/chrome-platform-analytics) library,
which allows tracking app views or any arbitrary event to Google Analytics.
See more at the [project wiki](https://github.com/GoogleChrome/chrome-platform-analytics/wiki)
*Please note: You will need to modify main.js to include real Google Analytics credentials.*
## Resources
* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)
* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)
* [chrome-platform-analytics](https://github.com/GoogleChrome/chrome-platform-analytics/wiki)
## Screenshot

================================================
FILE: _archive/apps/samples/analytics/background.js
================================================
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('main.html', {"id": "analyticsWinID"}, function() {});
});
================================================
FILE: _archive/apps/samples/analytics/google-analytics-bundle.js
================================================
(function() { var g,aa=aa||{},h=this,ba=function(){},ca=function(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&
!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==b&&"undefined"==typeof a.call)return"object";return b},m=function(a){return"array"==ca(a)},da=function(a){var b=ca(a);return"array"==b||"object"==b&&"number"==typeof a.length},n=function(a){return"string"==typeof a},ea=function(a){return"number"==typeof a},p=function(a){return"function"==ca(a)},q=function(a){var b=typeof a;return"object"==b&&null!=a||"function"==b},fa=function(a,b,c){return a.call.apply(a.bind,
arguments)},ga=function(a,b,c){if(!a)throw Error();if(2b?1:0};var w=Array.prototype,ja=w.indexOf?function(a,b,c){return w.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(n(a))return n(b)&&1==b.length?a.indexOf(b,c):-1;for(;cb?null:n(a)?a.charAt(b):a[b]},pa=function(a,b){var c=ja(a,b),d;(d=0<=c)&&w.splice.call(a,c,1);return d},qa=function(a){return w.concat.apply(w,
arguments)},ra=function(a,b,c){return 2>=arguments.length?w.slice.call(a,b):w.slice.call(a,b,c)};var sa="StopIteration"in h?h.StopIteration:Error("StopIteration"),ta=function(){};ta.prototype.next=function(){throw sa;};ta.prototype.vc=function(){return this};var ua=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)},va=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},wa=function(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b},xa=function(a,b){var c;t:{for(c in a)if(b.call(void 0,a[c],c,a))break t;c=void 0}return c&&a[c]},ya="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),za=function(a,b){for(var c,d,e=1;e2*this.h&&Aa(this),!0):!1};var Aa=function(a){if(a.h!=a.b.length){for(var b=0,c=0;b=c.length)throw sa;var k=c[b++];return a?k:d[k]}};return k};var y=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};var Ba,Ca,Da={id:"hitType",name:"t",valueType:"text",maxLength:void 0,defaultValue:void 0},Ea={id:"sessionControl",name:"sc",valueType:"text",maxLength:void 0,defaultValue:void 0},Fa={id:"description",name:"cd",valueType:"text",maxLength:2048,defaultValue:void 0},Ga={id:"eventCategory",name:"ec",valueType:"text",maxLength:150,defaultValue:void 0},Ha={id:"eventAction",name:"ea",valueType:"text",maxLength:500,defaultValue:void 0},Ia={id:"eventLabel",name:"el",valueType:"text",maxLength:500,defaultValue:void 0},
Ja={id:"eventValue",name:"ev",valueType:"integer",maxLength:void 0,defaultValue:void 0},Ka={pd:Da,Qc:{id:"anonymizeIp",name:"aip",valueType:"boolean",maxLength:void 0,defaultValue:void 0},Ad:{id:"queueTime",name:"qt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Wc:{id:"cacheBuster",name:"z",valueType:"text",maxLength:void 0,defaultValue:void 0},Gd:Ea,Wd:{id:"userId",name:"uid",valueType:"text",maxLength:void 0,defaultValue:void 0},xd:{id:"nonInteraction",name:"ni",valueType:"boolean",
maxLength:void 0,defaultValue:void 0},fd:Fa,Pd:{id:"title",name:"dt",valueType:"text",maxLength:1500,defaultValue:void 0},Sc:{id:"appId",name:"aid",valueType:"text",maxLength:150,defaultValue:void 0},Tc:{id:"appInstallerId",name:"aiid",valueType:"text",maxLength:150,defaultValue:void 0},jd:Ga,hd:Ha,kd:Ia,ld:Ja,Id:{id:"socialNetwork",name:"sn",valueType:"text",maxLength:50,defaultValue:void 0},Hd:{id:"socialAction",name:"sa",valueType:"text",maxLength:50,defaultValue:void 0},Jd:{id:"socialTarget",
name:"st",valueType:"text",maxLength:2048,defaultValue:void 0},Sd:{id:"transactionId",name:"ti",valueType:"text",maxLength:500,defaultValue:void 0},Rd:{id:"transactionAffiliation",name:"ta",valueType:"text",maxLength:500,defaultValue:void 0},Td:{id:"transactionRevenue",name:"tr",valueType:"currency",maxLength:void 0,defaultValue:void 0},Ud:{id:"transactionShipping",name:"ts",valueType:"currency",maxLength:void 0,defaultValue:void 0},Vd:{id:"transactionTax",name:"tt",valueType:"currency",maxLength:void 0,
defaultValue:void 0},dd:{id:"currencyCode",name:"cu",valueType:"text",maxLength:10,defaultValue:void 0},td:{id:"itemPrice",name:"ip",valueType:"currency",maxLength:void 0,defaultValue:void 0},ud:{id:"itemQuantity",name:"iq",valueType:"integer",maxLength:void 0,defaultValue:void 0},rd:{id:"itemCode",name:"ic",valueType:"text",maxLength:500,defaultValue:void 0},sd:{id:"itemName",name:"in",valueType:"text",maxLength:500,defaultValue:void 0},qd:{id:"itemCategory",name:"iv",valueType:"text",maxLength:500,
defaultValue:void 0},bd:{id:"campaignSource",name:"cs",valueType:"text",maxLength:100,defaultValue:void 0},$c:{id:"campaignMedium",name:"cm",valueType:"text",maxLength:50,defaultValue:void 0},ad:{id:"campaignName",name:"cn",valueType:"text",maxLength:100,defaultValue:void 0},Zc:{id:"campaignKeyword",name:"ck",valueType:"text",maxLength:500,defaultValue:void 0},Xc:{id:"campaignContent",name:"cc",valueType:"text",maxLength:500,defaultValue:void 0},Yc:{id:"campaignId",name:"ci",valueType:"text",maxLength:100,
defaultValue:void 0},od:{id:"gclid",name:"gclid",valueType:"text",maxLength:void 0,defaultValue:void 0},ed:{id:"dclid",name:"dclid",valueType:"text",maxLength:void 0,defaultValue:void 0},zd:{id:"pageLoadTime",name:"plt",valueType:"integer",maxLength:void 0,defaultValue:void 0},gd:{id:"dnsTime",name:"dns",valueType:"integer",maxLength:void 0,defaultValue:void 0},Kd:{id:"tcpConnectTime",name:"tcp",valueType:"integer",maxLength:void 0,defaultValue:void 0},Fd:{id:"serverResponseTime",name:"srt",valueType:"integer",
maxLength:void 0,defaultValue:void 0},yd:{id:"pageDownloadTime",name:"pdt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Bd:{id:"redirectResponseTime",name:"rrt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Ld:{id:"timingCategory",name:"utc",valueType:"text",maxLength:150,defaultValue:void 0},Od:{id:"timingVar",name:"utv",valueType:"text",maxLength:500,defaultValue:void 0},Nd:{id:"timingValue",name:"utt",valueType:"integer",maxLength:void 0,defaultValue:void 0},Md:{id:"timingLabel",
name:"utl",valueType:"text",maxLength:500,defaultValue:void 0},md:{id:"exDescription",name:"exd",valueType:"text",maxLength:150,defaultValue:void 0},nd:{id:"exFatal",name:"exf",valueType:"boolean",maxLength:void 0,defaultValue:"1"}},La=function(a){if(1>a||200a||200 a)return"0";if(3>a)return"1-2";a=Math.floor(Math.log(a-1)/Math.log(2));return Math.pow(2,a)+1+"-"+Math.pow(2,a+1)},Oa=function(a,b){for(var c=0,d=a.length-1,e=0;c<=d;){var f=Math.floor((c+d)/2),e=a[f];if(b<=e){d=0==f?0:a[f-1];if(b>d)return(d+1).toString()+"-"+e.toString();d=f-1}else if(b>e){if(f>=a.length-1)return(a[a.length-1]+1).toString()+"+";c=f+1}}return"<= 0"};var z=function(){this.ab=[]},Pa=function(){return new z};g=z.prototype;g.when=function(a){this.ab.push(a);return this};g.zb=function(a){var b=arguments;this.when(function(a){return 0<=ja(b,a.Gb())});return this};g.Oc=function(a,b){var c=ra(arguments,1);this.when(function(b){b=b.T().get(a);return 0<=ja(c,b)});return this};g.xb=function(a,b){if(q(this.e))throw Error("Filter has already been set.");this.e=q(b)?r(a,b):a;return this};
g.Ca=function(){if(0==this.ab.length)throw Error("Must specify at least one predicate using #when or a helper method.");if(!q(this.e))throw Error("Must specify a delegate filter using #applyFilter.");return r(function(a){ma(this.ab,function(b){return b(a)})&&this.e(a)},this)};var A=function(){this.Ab=!1;this.Bb="";this.qb=!1;this.za=null};A.prototype.wc=function(a){this.Ab=!0;this.Bb=a||" - ";return this};A.prototype.Nc=function(){this.qb=!0;return this};A.prototype.Ec=function(){return Qa(this,Na)};A.prototype.Fc=function(a){return Qa(this,ha(Oa,a))};
var Qa=function(a,b){if(null!=a.za)throw Error("LabelerBuilder: Only one labeling strategy may be used.");a.za=r(function(a){var d=a.T().get(Ja),e=a.T().get(Ia);ea(d)&&(d=b(d),null!=e&&this.Ab&&(d=e+this.Bb+d),a.T().set(Ia,d))},a);return a};A.prototype.Ca=function(){if(null==this.za)throw Error("LabelerBuilder: a labeling strategy must be specified prior to calling build().");return Pa().zb("event").xb(r(function(a){this.za(a);this.qb&&a.T().remove(Ja)},this)).Ca()};var Ra=function(a,b){var c=Array.prototype.slice.call(arguments),d=c.shift();if("undefined"==typeof d)throw Error("[goog.string.format] Template required");return d.replace(/%([0\-\ \+]*)(\d+)?(\.(\d+))?([%sfdiu])/g,function(a,b,d,l,N,J,U,V){if("%"==J)return"%";var Db=c.shift();if("undefined"==typeof Db)throw Error("[goog.string.format] Not enough arguments");arguments[0]=Db;return B[J].apply(null,arguments)})},B={s:function(a,b,c){return isNaN(c)||""==c||a.length>=c?a:a=-1a?"-":0<=b.indexOf("+")?"+":0<=b.indexOf(" ")?" ":"";0<=a&&(d=f+d);if(isNaN(c)||d.length>=c)return d;d=isNaN(e)?Math.abs(a).toString():Math.abs(a).toFixed(e);a=c-d.length-f.length;return d=0<=b.indexOf("-",0)?f+d+Array(a+1).join(" "):f+Array(a+1).join(0<=b.indexOf("0",0)?"0":" ")+d},d:function(a,b,c,d,e,f,k,l){return B.f(parseInt(a,10),b,c,d,0,f,k,l)}};B.i=B.d;
B.u=B.d;var Sa=function(a){if("function"==typeof a.t)return a.t();if(n(a))return a.split("");if(da(a)){for(var b=[],c=a.length,d=0;dparseFloat(a))?String(b):a}(),bb={},M=function(a){var b;
if(!(b=bb[a])){b=0;for(var c=String(ab).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),f=0;0==b&&f=a.keyCode)a.keyCode=-1}catch(b){}};O.prototype.l=function(){};var jb="closure_listenable_"+(1E6*Math.random()|0),kb=function(a){return!(!a||!a[jb])},lb=0;var mb=function(a,b,c,d,e){this.O=a;this.proxy=null;this.src=b;this.type=c;this.pa=!!d;this.sa=e;this.key=++lb;this.removed=this.qa=!1},nb=function(a){a.removed=!0;a.O=null;a.proxy=null;a.src=null;a.sa=null};var P=function(a){this.src=a;this.j={};this.Z=0};P.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.j[f];a||(a=this.j[f]=[],this.Z++);var k=ob(a,b,d,e);-1e.keyCode||void 0!=e.returnValue)){t:{var f=!1;if(0==e.keyCode)try{e.keyCode=-1;break t}catch(k){f=!0}if(f||void 0==e.returnValue)e.returnValue=!0}e=[];for(f=c.currentTarget;f;f=f.parentNode)e.push(f);for(var f=a.type,l=e.length-1;!c.U&&0<=l;l--)c.currentTarget=e[l],d&=Fb(e[l],f,!0,c);for(l=0;!c.U&&l>>0),ub=function(a){if(p(a))return a;a[Gb]||(a[Gb]=function(b){return a.handleEvent(b)});return a[Gb]};var Q=function(){E.call(this);this.A=new P(this);this.kc=this;this.Qa=null};u(Q,E);Q.prototype[jb]=!0;g=Q.prototype;g.addEventListener=function(a,b,c,d){tb(this,a,b,c,d)};g.removeEventListener=function(a,b,c,d){Bb(this,a,b,c,d)};
g.dispatchEvent=function(a){var b,c=this.Qa;if(c){b=[];for(var d=1;c;c=c.Qa)b.push(c),++d}c=this.kc;d=a.type||a;if(n(a))a=new F(a,c);else if(a instanceof F)a.target=a.target||c;else{var e=a;a=new F(d,c);za(a,e)}var e=!0,f;if(b)for(var k=b.length-1;!a.U&&0<=k;k--)f=a.currentTarget=b[k],e=Hb(f,d,!0,a)&&e;a.U||(f=a.currentTarget=c,e=Hb(f,d,!0,a)&&e,a.U||(e=Hb(f,d,!1,a)&&e));if(b)for(k=0;!a.U&&k=b.Ia&&b.cancel())}this.hb?this.hb.call(this.gb,this):this.Ka=!0;this.C||this.w(new dc)}};S.prototype.ib=function(a,b){this.Ja=!1;ec(this,a,b)};
var ec=function(a,b,c){a.C=!0;a.v=c;a.W=!b;fc(a)},hc=function(a){if(a.C){if(!a.Ka)throw new gc;a.Ka=!1}};S.prototype.G=function(a){hc(this);ec(this,!0,a)};S.prototype.w=function(a){hc(this);ec(this,!1,a)};S.prototype.J=function(a,b){return ic(this,a,null,b)};var ic=function(a,b,c,d){a.ja.push([b,c,d]);a.C&&fc(a);return a};S.prototype.then=function(a,b,c){var d,e,f=new R(function(a,b){d=a;e=b});ic(this,d,function(a){a instanceof dc?f.cancel():e(a)});return f.then(a,b,c)};Sb(S);
var jc=function(a){var b=new S;ic(a,b.G,b.w,b);return b},kc=function(a){return la(a.ja,function(a){return p(a[1])})},fc=function(a){if(a.ka&&a.C&&kc(a)){var b=a.ka,c=lc[b];c&&(h.clearTimeout(c.ma),delete lc[b]);a.ka=0}a.o&&(a.o.Ia--,delete a.o);for(var b=a.v,d=c=!1;a.ja.length&&!a.Ja;){var e=a.ja.shift(),f=e[0],k=e[1],e=e[2];if(f=a.W?k:f)try{var l=f.call(e||a.gb,b);void 0!==l&&(a.W=a.W&&(l==b||l instanceof Error),a.v=b=l);Tb(b)&&(d=!0,a.Ja=!0)}catch(N){b=N,a.W=!0,kc(a)||(c=!0)}}a.v=b;d&&(l=r(a.ib,
a,!0),d=r(a.ib,a,!1),b instanceof S?(ic(b,l,d),b.Lb=!0):b.then(l,d));c&&(b=new mc(b),lc[b.ma]=b,a.ka=b.ma)},nc=function(a){var b=new S;b.G(a);return b},pc=function(){var a=oc,b=new S;b.w(a);return b},gc=function(){v.call(this)};u(gc,v);gc.prototype.message="Deferred has already fired";gc.prototype.name="AlreadyCalledError";var dc=function(){v.call(this)};u(dc,v);dc.prototype.message="Deferred was canceled";dc.prototype.name="CanceledError";
var mc=function(a){this.ma=h.setTimeout(r(this.pc,this),0);this.ga=a};mc.prototype.pc=function(){delete lc[this.ma];throw this.ga;};var lc={};var qc=function(a){this.$a=[];this.e=a};qc.prototype.S=function(a){if(!p(a))throw Error("Invalid filter. Must be a function.");this.$a.push(a)};qc.prototype.send=function(a,b){for(var c=new T(a,b),d=0;db.maxLength&&a.set(b,c.substring(0,b.maxLength))})},ed=function(a){Ua(a,function(b,c){void 0!==b.defaultValue&&c==b.defaultValue&&a.remove(b)})};var oc={status:"device-offline",Ba:void 0},fd={status:"rate-limited",Ba:void 0},gd={status:"sampled-out",Ba:void 0},hd={status:"sent",Ba:void 0};var id=function(a,b){this.Wb=a;this.e=b};id.prototype.send=function(a,b){var c;c=this.Wb;var d=c.pb(),e=Math.floor((d-c.ob)*c.Sb);0c.$?c=!1:(c.$-=1,c=!0);return c||"item"==a||"transaction"==a?this.e.send(a,b):nc(fd)};var jd=function(){this.$=60;this.Tb=500;this.Sb=5E-4;this.pb=function(){return(new Date).getTime()};this.ob=this.pb()};var kd=function(a,b){this.k=a;this.e=b};kd.prototype.send=function(a,b){var c=b.get(vc),c=parseInt(c.split("-")[1],16),d;"timing"!=a?d=this.k.V:((d=b.get(yc))&&b.remove(yc),d||(d=this.k.V));return c<655.36*d?this.e.send(a,b):nc(gd)};var ld=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#(.*))?$/,md=L,nd=function(a,b){if(md){md=!1;var c=h.location;if(c){var d=c.href;if(d&&(d=(d=nd(3,d))?decodeURI(d):d)&&d!=c.hostname)throw md=!0,Error();}}return b.match(ld)[a]||null};var od=function(){};od.prototype.Eb=null;var qd=function(a){var b;(b=a.Eb)||(b={},pd(a)&&(b[0]=!0,b[1]=!0),b=a.Eb=b);return b};var rd,sd=function(){};u(sd,od);var td=function(a){return(a=pd(a))?new ActiveXObject(a):new XMLHttpRequest},pd=function(a){if(!a.Hb&&"undefined"==typeof XMLHttpRequest&&"undefined"!=typeof ActiveXObject){for(var b=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],c=0;cthis.na?c.w({status:"payload-too-big",Ba:Ra("Encoded hit length == %s, but should be <= %s.",d.length,this.na)}):xd(this.$b,function(){c.G(hd)},d);return c};var Jd=function(a,b){var c=new Fd;c.add(Da.name,a);Ua(b,function(a,b){c.add(a.name,b.toString())});return c.toString()};var Kd=function(a,b,c){this.k=a;this.Qb=b;this.na=c};Kd.prototype.Sa=function(){if(!this.q){var a=this.k;if(!jc(a.ha).C)throw Error("Cannot construct shared channel prior to settings being ready.");new ad;var b=new cd(new Id(this.Qb,this.na)),c=new jd;this.q=new bd(a,new kd(a,new id(c,b)))}return this.q};var Ld=new x,Md=function(){if(!Ba){var a=new Tc("google-analytics");Ba=new X(a)}return Ba};t("goog.async.Deferred",S);t("goog.async.Deferred.prototype.addCallback",S.prototype.J);t("goog.events.EventTarget",Q);t("goog.events.EventTarget.prototype.listen",Q.prototype.listen);t("analytics.getService",function(a){var b=Ld.get(a,null);if(null===b){var b=chrome.runtime.getManifest().version,c=Md();if(!Ca){var d=Md();Ca=new Wc(d,new Kd(d,"https://www.google-analytics.com/collect",8192))}b=new Hc("ca1.5.2",a,b,c,Ca);Ld.set(a,b)}return b});t("analytics.internal.GoogleAnalyticsService",Hc);
t("analytics.internal.GoogleAnalyticsService.prototype.getTracker",Hc.prototype.Cc);t("analytics.internal.GoogleAnalyticsService.prototype.getConfig",Hc.prototype.Bc);t("analytics.internal.ServiceSettings",X);t("analytics.internal.ServiceSettings.prototype.setTrackingPermitted",X.prototype.Lc);t("analytics.internal.ServiceSettings.prototype.isTrackingPermitted",X.prototype.va);t("analytics.internal.ServiceSettings.prototype.setSampleRate",X.prototype.Kc);t("analytics.internal.ServiceTracker",W);
t("analytics.internal.ServiceTracker.prototype.send",W.prototype.send);t("analytics.internal.ServiceTracker.prototype.sendAppView",W.prototype.Gc);t("analytics.internal.ServiceTracker.prototype.sendEvent",W.prototype.Hc);t("analytics.internal.ServiceTracker.prototype.sendSocial",W.prototype.Jc);t("analytics.internal.ServiceTracker.prototype.sendException",W.prototype.Ic);t("analytics.internal.ServiceTracker.prototype.sendTiming",W.prototype.Cb);
t("analytics.internal.ServiceTracker.prototype.startTiming",W.prototype.Mc);t("analytics.internal.ServiceTracker.Timing",Gc);t("analytics.internal.ServiceTracker.Timing.prototype.send",Gc.prototype.send);t("analytics.internal.ServiceTracker.prototype.forceSessionStart",W.prototype.Ac);t("analytics.internal.ServiceTracker.prototype.addFilter",W.prototype.S);t("analytics.internal.FilterChannel.Hit",T);t("analytics.internal.FilterChannel.Hit.prototype.getHitType",T.prototype.Gb);
t("analytics.internal.FilterChannel.Hit.prototype.getParameters",T.prototype.T);t("analytics.internal.FilterChannel.Hit.prototype.cancel",T.prototype.cancel);t("analytics.ParameterMap",C);t("analytics.ParameterMap.Entry",C.Entry);t("analytics.ParameterMap.prototype.set",C.prototype.set);t("analytics.ParameterMap.prototype.get",C.prototype.get);t("analytics.ParameterMap.prototype.remove",C.prototype.remove);t("analytics.ParameterMap.prototype.toObject",C.prototype.Jb);
t("analytics.HitTypes.APPVIEW","appview");t("analytics.HitTypes.EVENT","event");t("analytics.HitTypes.SOCIAL","social");t("analytics.HitTypes.TRANSACTION","transaction");t("analytics.HitTypes.ITEM","item");t("analytics.HitTypes.TIMING","timing");t("analytics.HitTypes.EXCEPTION","exception");ua(Ka,function(a){var b=a.id.replace(/[A-Z]/,"_$&").toUpperCase();t("analytics.Parameters."+b,a)});t("analytics.filters.EventLabelerBuilder",A);
t("analytics.filters.EventLabelerBuilder.prototype.appendToExistingLabel",A.prototype.wc);t("analytics.filters.EventLabelerBuilder.prototype.stripValue",A.prototype.Nc);t("analytics.filters.EventLabelerBuilder.prototype.powersOfTwo",A.prototype.Ec);t("analytics.filters.EventLabelerBuilder.prototype.rangeBounds",A.prototype.Fc);t("analytics.filters.EventLabelerBuilder.prototype.build",A.prototype.Ca);t("analytics.filters.FilterBuilder",z);t("analytics.filters.FilterBuilder.builder",Pa);
t("analytics.filters.FilterBuilder.prototype.when",z.prototype.when);t("analytics.filters.FilterBuilder.prototype.whenHitType",z.prototype.zb);t("analytics.filters.FilterBuilder.prototype.whenValue",z.prototype.Oc);t("analytics.filters.FilterBuilder.prototype.applyFilter",z.prototype.xb);t("analytics.filters.FilterBuilder.prototype.build",z.prototype.Ca);t("analytics.EventBuilder",D);t("analytics.EventBuilder.builder",function(){return Va});t("analytics.EventBuilder.prototype.category",D.prototype.xc);
t("analytics.EventBuilder.prototype.action",D.prototype.action);t("analytics.EventBuilder.prototype.label",D.prototype.label);t("analytics.EventBuilder.prototype.value",D.prototype.value);t("analytics.EventBuilder.prototype.dimension",D.prototype.yc);t("analytics.EventBuilder.prototype.metric",D.prototype.Dc);t("analytics.EventBuilder.prototype.send",D.prototype.send); })()
================================================
FILE: _archive/apps/samples/analytics/main.html
================================================
Analytics sample app
================================================
FILE: _archive/apps/samples/analytics/main.js
================================================
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var service, tracker, out;
function initAnalyticsConfig(config) {
document.getElementById('settings-loading').hidden = true;
document.getElementById('settings-loaded').hidden = false;
var checkbox = document.getElementById('analytics');
checkbox.checked = config.isTrackingPermitted();
checkbox.onchange = function() {
config.setTrackingPermitted(checkbox.checked);
};
}
function startApp() {
// Initialize the Analytics service object with the name of your app.
service = analytics.getService('ice_cream_app');
service.getConfig().addCallback(initAnalyticsConfig);
// Get a Tracker using your Google Analytics app Tracking ID.
tracker = service.getTracker('UA-XXXXX-X');
// Record an "appView" each time the user launches your app or goes to a new
// screen within the app.
tracker.sendAppView('MainView');
var button1 = document.getElementById('chocolate');
var button2 = document.getElementById('vanilla');
out = document.getElementById('out');
[button1, button2].forEach(addButtonListener);
}
function addButtonListener(button) {
button.addEventListener('click', function() {
tracker.sendEvent('Flavor', 'Choose', button.id);
out.textContent = 'You chose: ' + button.textContent;
});
}
window.onload = startApp;
================================================
FILE: _archive/apps/samples/analytics/manifest.json
================================================
{
"name": "Analytics Sample App",
"description": "An example app using Google Analytics without the Closure library",
"version": "1.2.5",
"manifest_version": 2,
"icons": {"128": "icon_128.png"},
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": [
"https://www.google-analytics.com/*",
"storage"
]
}
================================================
FILE: _archive/apps/samples/analytics/sample_support_metadata.json
================================================
{
"sample": "analytics",
"files_with_snippets": [ ],
"android": {"works": true},
"ios": {"works": true}
}
================================================
FILE: _archive/apps/samples/appengine-channelapi/README.md
================================================

# AppEngine Channel API example
This is an example of how to use the AppEngine's Channel API in a Chrome Packaged App. Since the Channel API is not directly compatible with the CSP restrictions in a packaged app, this sample uses a WebView and a "proxy" object that communicates with the Webview using async postMessage.
This code is an adaptation of the [Tic Tac Toe game](https://code.google.com/p/channel-tac-toe/) used by the AppEngine team to demonstrate the Channel API. The main modifications from the original game are:
- index.html is not rendered as a template in the server, it is embedded in the app. All responses from the server are JSON messages;
- the server doesn't use the appengine's user library, since that would require another authentication step. Instead, the server attributes a random UUID to the first user and another to the second. This user ID is returned to the client that uses it in the following calls. It is not secure, but simple enough for this sample. In a real application, this method would allow an eaversdropper to capture the GET request and replay with different commands;
- all the interations with the channel API are abstracted in the ChannelAPI object defined by channel_in_a_webview.js. This object communicates with the webview page (channel_in_a_webview.html), served to the webview from the appengine server.
To run:
- go to the `appengine` folder and type `dev_appserver.py .`
- install the Chrome Packaged App in the `app` folder
- run the Chrome packaged app twice and copy the game ID from one screen to the other
- play
* [Appengine Channel API](https://developers.google.com/appengine/docs/python/channel)
* [Webview](https://developer.chrome.com/apps/tags/webview)
## Screenshot

================================================
FILE: _archive/apps/samples/appengine-channelapi/app/README.md
================================================

================================================
FILE: _archive/apps/samples/appengine-channelapi/app/channel_in_a_webview.js
================================================
(function (exports) {
function ChannelInAWebview(rootUrl) {
this.webview = document.createElement('webview');
this.webview.src = rootUrl+'/static/channel_in_a_webview.html';
this.webview.style.width='0px';
this.webview.style.height='0px';
this.webview.style.display='none';
this.webview.style.width='10px';
this.webview.style.height='10px';
this.webview.style.display='block';
this.webview.style.border='1px solid red';
document.body.appendChild(this.webview);
this.onOpened = this.onMessage = null;
window.addEventListener('message', function(e) {
// sanity check for origin
if ( this.webview.src.indexOf(e.origin)!=0 ) {
console.error("Invalid origin of message, ignoring");
return;
}
// onOpened event
if ( this.onOpened && e.data && 'onOpened' in e.data ) {
this.onOpened();
}
// onMessage event
if ( this.onMessage && e.data && 'onMessage' in e.data ) {
this.onMessage.call(this, e.data['onMessage']);
}
}.bind(this));
}
ChannelInAWebview.prototype._sendMessageToWebview = function(data) {
this.webview.contentWindow.postMessage(data, this.webview.src);
}
ChannelInAWebview.prototype.openChannel = function(token) {
this._sendMessageToWebview({'openChannel': token});
}
exports.ChannelInAWebview = ChannelInAWebview;
})(window);
================================================
FILE: _archive/apps/samples/appengine-channelapi/app/game.js
================================================
ROOT = 'http:/localhost:8080';
window.addEventListener('DOMContentLoaded', init);
function init() {
var xhr = new XMLHttpRequest();
xhr.open('GET', ROOT);
xhr.onload = function(e) {
game(JSON.parse(e.target.responseText));
};
xhr.send();
}
function game(data) {
// event listeners:
document.querySelector('#go').addEventListener('click', function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', ROOT+'/?g='+document.querySelector('#another_game_key').value);
xhr.onload = function(e) {
initialize(JSON.parse(e.target.responseText));
};
xhr.send();
});
var handleMouseOver = function(e) { highlightSquare(parseInt(e.target.id)) };
var handleOnClick = function(e) { moveInSquare(parseInt(e.target.id)) };
var i;
for (i = 0; i < 9; i++) {
var square = document.getElementById(i);
square.onmouseover = handleMouseOver;
square.onclick = handleOnClick;
}
var state = {
};
updateGame = function() {
for (i = 0; i < 9; i++) {
var square = document.getElementById(i);
square.innerHTML = state.board[i];
if (state.winner != '' && state.winningBoard != '') {
if (state.winningBoard[i] == state.board[i]) {
if (state.winner == state.me) {
square.style.background = "green";
} else {
square.style.background = "red";
}
} else {
square.style.background = "white";
}
}
}
var display = {
'other-player': 'none',
'your-move': 'none',
'their-move': 'none',
'you-won': 'none',
'you-lost': 'none',
'board': 'block'
};
if (!state.userO || state.userO == '') {
display['other-player'] = 'block';
display['board'] = 'none';
} else if (state.winner == state.me) {
display['you-won'] = 'block';
} else if (state.winner != '') {
display['you-lost'] = 'block';
} else if (isMyMove()) {
display['your-move'] = 'block';
} else {
display['their-move'] = 'block';
}
for (var label in display) {
document.getElementById(label).style.display = display[label];
}
};
isMyMove = function() {
return (state.winner == "") &&
(state.moveX == (state.userX == state.me));
}
myPiece = function() {
return state.userX == state.me ? 'X' : 'O';
}
sendMessage = function(path, opt_param) {
path = ROOT + path + '?g=' + state.game_key;
if (state.me) {
path += '&u=' + state.me;
}
if (opt_param) {
path += '&' + opt_param;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send();
};
moveInSquare = function(id) {
if (isMyMove() && state.board[id] == ' ') {
sendMessage('/move', 'i=' + id);
}
}
highlightSquare = function(id) {
if (state.winner != "") {
return;
}
for (i = 0; i < 9; i++) {
if (i == id && isMyMove()) {
if (state.board[i] = ' ') {
color = 'lightBlue';
} else {
color = 'lightGrey';
}
} else {
color = 'white';
}
document.getElementById(i).style['background'] = color;
}
}
onOpened = function() {
sendMessage('/opened');
};
onMessage = function(m) {
var newState = JSON.parse(m.data);
state.board = newState.board || state.board;
state.userX = newState.userX || state.userX;
state.userO = newState.userO || state.userO;
state.moveX = newState.moveX;
state.winner = newState.winner || "";
state.winningBoard = newState.winningBoard || "";
updateGame();
}
initialize = function(data) {
state = {
game_key: data.game_key,
me: data.me
}
var gamelinks = document.querySelectorAll('.gamelink');
for (var i=0; i
Channel-based Tic Tac Toe
Waiting for another player to join.
Send them this game ID to play:
or enter a game ID another player sent you:
go
Your move! Click a square to place your piece.
Waiting for other player to move...
You won this game!
You lost this game.