Googlebook OS is an operating system for Googlebook devices, built on the Android technology stack and paired with desktop foundations from ChromeOS. Googlebooks support the same WebExtensions platform that exists on Windows, macOS, and ChromeOS, but there are some differences with how they run there.
- Platform detection is rarely needed, but existing checks can
misfire because extension APIs report
androidwhile the user agent reports ChromeOS. - Native messaging isn't available yet, but it is being worked on. Expect it to route messages to an installed Android app rather than a desktop executable.
- Keyboard shortcuts use Linux keybindings rather than
chromeosentries. SharedArrayBufferrequires opting into cross-origin isolation, and must run in an extension page or offscreen document rather than a service worker.- ChromeOS-only APIs aren't supported on Googlebook OS,
even though the user agent reports
Chrome OS. Extensions that declare these permissions still install, but the API namespaces areundefinedat runtime. browser.system.storageisn't supported on Googlebook OS, so the API namespace isundefinedat runtime.
Platform detection
Most extensions don't need to detect Googlebook OS. Follow standard web development best practices, such as feature detection and responsive design, rather than checking which operating system the browser runs on.
If your extension already checks the operating system, extension APIs and the user agent return different platforms on Googlebook OS.
chrome.runtime.getPlatformInfo().osreturns'android'. If your extension shares code with mobile browsers and assumes'android'means a phone, Googlebook users will get your mobile UI on a laptop.navigator.userAgentcontainsCrOS. For general page layout, matching a Chromebook works well. However,navigator.userAgentData.platformreturns'Android', and if your extension checks the user agent to show ChromeOS keyboard shortcut hints (such as theSearchkey) or to call ChromeOS-only APIs, those checks will misfire on a Googlebook.
The following table compares these signals across platforms.
| Signal | Googlebook OS | Android phone | Chromebook | Windows, macOS, Linux |
|---|---|---|---|---|
runtime.getPlatformInfo().os |
android |
android |
cros |
mac, win, linux |
navigator.userAgentData.platform |
Android |
Android |
Chrome OS |
Windows, macOS, Linux |
navigator.userAgentData.mobile |
false |
true |
false |
false |
In contrast, navigator.userAgent returns an identical reduced user-agent
string on both Googlebook OS
and ChromeOS, because both platforms report the frozen X11; CrOS x86_64
14541.0.0 platform token.
// Googlebook OS
Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/157.0.0.0 Safari/537.36
// ChromeOS
Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/157.0.0.0 Safari/537.36
As with all web development, platform detection can be unreliable, so only use
it when you can't use feature detection to test directly for what you need. If
you do need to distinguish Googlebook OS from both an Android phone and a
Chromebook, it is possible by combining
runtime.getPlatformInfo()
with the mobile hint from User-Agent Client
Hints.
async function getPlatform() {
const { os, arch } = await chrome.runtime.getPlatformInfo();
// userAgentData is undefined in browsers that don't implement User-Agent
// Client Hints, so read mobile defensively.
const mobile = navigator.userAgentData?.mobile;
return {
os,
arch,
isGooglebook: os === 'android' && mobile === false,
isPhone: os === 'android' && mobile !== false
};
}
While this particular combination of string comparisons does uniquely point to Googlebook OS devices at the time of product launch, that may not always be the case. As more devices start to ship out over time, in a multitude of form factors there may come a time where some Googlebook OS devices don't match that detection.
To detect Googlebooks from web pages or on the server using client hints, see Identify Googlebooks.
Native messaging
Native messaging isn't
available yet on Googlebook OS, but it is being worked on. Expect it to have
extensions communicating with installed Android apps rather than local desktop
executables. For now, extensions that declare the nativeMessaging permission
still install and run on Googlebook OS, but connection attempts fail. Make sure
your extension handles connection failures gracefully and falls back to a
web-based workflow when the native host is unavailable. Follow issue
555299632 for updates.
Keyboard shortcuts
commands shortcuts follow the same
rules as Chrome on Linux. Chrome reads the linux entry of suggested_key on
Googlebook OS, so shortcuts defined under chromeos don't apply. Search key
combinations don't work either, as there is no "Search" key on Googlebook OS
devices.
SharedArrayBuffer
On Windows, macOS, Linux, and ChromeOS, extensions can use SharedArrayBuffer
automatically in any context. On Googlebook OS, extensions must explicitly opt
into cross-origin
isolation in
manifest.json to use SharedArrayBuffer.
Opting into cross-origin isolation enables SharedArrayBuffer in extension
documents such as popups, options pages, and offscreen
documents. However, it doesn't enable
SharedArrayBuffer in extension service workers, because Chrome doesn't yet
support cross-origin isolation for service workers (issue
40150182). If your background logic relies on
SharedArrayBuffer (for example, to run threaded WebAssembly), run that code in
an offscreen document instead of your service worker.
ChromeOS-only APIs
APIs marked ChromeOS only in the Chrome
Extensions API reference (such as documentScan, fileSystemProvider,
vpnProvider, and printing) aren't supported on Googlebook OS, even though
navigator.userAgent includes CrOS. Extensions that declare these permissions
still install and run, but the API namespaces are undefined at runtime. Check
that an API namespace exists before calling it rather than relying on user-agent
detection.
browser.system.storage
The browser.system.storage
API isn't supported on Googlebook OS. Extensions that declare the
system.storage permission in manifest.json still install and run, but the
namespace is undefined at runtime. Check whether the API is defined before
calling getInfo(), ejectDevice(), or registering storage listeners.