ScalaJS bindings for Chrome Extention/App and ChromeOS APIs
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bindings/src/main/scala/chrome
examples
interop
project
sbt-plugin/src/main/scala/net/lullabyte
shared/src/main/scala/chrome
.gitignore
.travis.yml
LICENSE add license file Jun 14, 2015
README.md
build.sbt
scalastyle-config.xml fix stylecheck and execute it as part of travis Jun 14, 2015

README.md

Chrome for Scala.js Build Status Gitter Latest version Javadocs

The goal of this project is to provide an easy and typesafe way to create Chrome apps and extensions in Scala using the Scala.js project.

Chrome API bindings

The bindings provide access to the Chrome app and extension APIs. There are two levels for each API. One that provides the raw JavaScript bindings and a second one which wraps the raw API in a more Scala idiomatic way.

The package structure is similar to the original JavaScript API.

// original JavaScript
chrome.system.cpu.getInfo(function(info){
  if (chrome.runtime.lastError === undefined) {
    console.log(info);
  } else {
    console.log("ohoh something went wrong!");
  }
});
// raw bindings
chrome.system.cpu.bindings.CPU.getInfo((info: CPUInfo) => {
    if (chrome.runtime.bindings.Runtime.lastError.isEmpty) {
        println(info)
    } else {
        println("ohoh something went wrong!")
    }
})

// Scala idiomatic way using Future
chrome.system.cpu.CPU.getInfo.onComplete {
  case Success(info) => println(info)
  case Failure(error) => println("ohoh something went wrong!")
}

The Scala idiomatic binding provides the following general changes:

  • Futures instead of callbacks
  • Error handling using types like Future / Try instead of global error variable.
  • Using Option for things that may or may not be defined.

SBT Plugin

The job of the SBT plugin is to help with common tasks for developing Chrome apps/extensions. It also provides a way to configure your app/extension in your SBT file and automatically generate the manifest file.

  • chromePackage will create a ZIP file you can upload to the Chrome Web Store.
  • chromeUnpackedOpt (or chromeUnpackedFast) will build your projects with (or without) optimizations enabled. The output will be in target/chrome/unpacked-opt (or target/chrome/unpacked-fast) and can be loaded by Chrome as an unpacked extension/app.

Getting Started

Add this to your project/plugins.sbt:

addSbtPlugin("net.lullabyte" % "sbt-chrome-plugin" % "0.5.0")

Add this to your project dependencies:

"net.lullabyte" %%% "scala-js-chrome" % "0.5.0"

with scalajs-bundler

to use the <project-name>-f{ast,ull}opt-bundle.js generated by scalajs-bundler add the following to your build.sbt:

fastOptJsLib := Attributed.blank((webpack in (Compile, fastOptJS)).value.head)
fullOptJsLib := Attributed.blank((webpack in (Compile, fullOptJS)).value.head)

NOTE: if code seems to be executing duplicate times unintentionally, try removing these lines from the project's build.sbt

scalaJSUseMainModuleInitializer := true
scalaJSUseMainModuleInitializer in Test := false

Creating a basic Window

import chrome.app.runtime.bindings.LaunchData
import chrome.app.window.Window
import utils.ChromeApp

import scalajs.concurrent.JSExecutionContext.Implicits.queue

object ChromeAppExample extends ChromeApp {

  override def onLaunched(launchData: LaunchData): Unit = {
    println("hello world from scala!")
    Window.create("assets/html/App.html").foreach { window =>
      /**
         Access to the document of the newly created window.
         From here you can change the HTML of the window with whatever
         library you want to use.
      */
      window.contentWindow.document
    }
  }

}

For a more complete example see chrome-system-monitor and scala-js-chrome examples.

UI Libraries

There are already multiple libraries to manipulate HTML and build your UI available for Scala.js:

Known Issues

In Chrome apps and extensions there are multiple places where you can run JavaScript. Normally you split your logic into different files and load them into whatever context they need to run. Since Scala.js compiles your whole project into one big file all contexts need to load this big file with all the logic even if they only need a small subset. This can cause your app you use more memory then it need to. In some cases this can be worked around for example the a background page can manipulate the DOM of an App window so you don't need any JavaScript at all in the window itself.