diff --git a/build/common.gypi b/build/common.gypi
index 8789ef12a55533..0879daca73c9af 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -1395,6 +1395,10 @@
'ozone_platform_ozonex%': 0,
'ozone_platform_test%': 0,
+ # Chrome OS: whether to also build the upcoming version of
+ # ChromeVox, which can then be enabled via a command-line switch.
+ 'use_chromevox_next%': 0,
+
'conditions': [
# Enable the Syzygy optimization step for the official builds.
['OS=="win" and buildtype=="Official" and syzyasan!=1', {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 346964c4ae167f..21f77c3ffe5718 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -297,6 +297,7 @@
+
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index facaf8eb7b9bba..99129d8cb5d646 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -330,6 +330,11 @@ std::string ComponentLoader::AddChromeVoxExtension() {
const CommandLine* command_line = CommandLine::ForCurrentProcess();
int idr = command_line->HasSwitch(chromeos::switches::kGuestSession) ?
IDR_CHROMEVOX_GUEST_MANIFEST : IDR_CHROMEVOX_MANIFEST;
+
+ // TODO(dtseng): Guest mode manifest for ChromeVox Next pending work to
+ // generate manifests.
+ if (command_line->HasSwitch(chromeos::switches::kEnableChromeVoxNext))
+ idr = IDR_CHROMEVOX2_MANIFEST;
return Add(idr, base::FilePath(extension_misc::kChromeVoxExtensionPath));
}
diff --git a/chrome/browser/resources/chromeos/chromevox2/OWNERS b/chrome/browser/resources/chromeos/chromevox2/OWNERS
new file mode 100644
index 00000000000000..dfab84a016434b
--- /dev/null
+++ b/chrome/browser/resources/chromeos/chromevox2/OWNERS
@@ -0,0 +1,4 @@
+aboxhall@chromium.org
+dmazzoni@chromium.org
+dtseng@chromium.org
+plundblad@chromium.org
diff --git a/chrome/browser/resources/chromeos/chromevox2/chromevox.gyp b/chrome/browser/resources/chromeos/chromevox2/chromevox.gyp
new file mode 100644
index 00000000000000..5772ca077a0821
--- /dev/null
+++ b/chrome/browser/resources/chromeos/chromevox2/chromevox.gyp
@@ -0,0 +1,31 @@
+# Copyright 2014 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.
+
+{
+ 'conditions': [
+ ['chromeos==1 and disable_nacl==0 and disable_nacl_untrusted==0', {
+ 'targets': [
+ {
+ 'target_name': 'chromevox2_resources',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/resources/chromeos/chromevox/cvox2/background',
+ 'files': [
+ 'cvox2/background/background.html',
+ 'cvox2/background/background.js',
+ ],
+ },
+ {
+ 'destination': '<(PRODUCT_DIR)/resources/chromeos/chromevox/cvox2/injected',
+ 'files': [
+ 'cvox2/injected/injected.js',
+ ],
+ },
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.html b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.html
new file mode 100644
index 00000000000000..429931d816d733
--- /dev/null
+++ b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.html
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js
new file mode 100644
index 00000000000000..dcd93fbbd7323d
--- /dev/null
+++ b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js
@@ -0,0 +1,93 @@
+// Copyright 2014 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 The entry point for all ChromeVox2 related code for the
+ * background page.
+ */
+
+/** ChromeVox2 namespace */
+var cvox2 = function() {};
+
+/** Namespace for global objects in the background page. */
+cvox2.global = function() {};
+
+/** Classic Chrome accessibility API. */
+cvox2.global.accessibility =
+ chrome.accessibilityPrivate || chrome.experimental.accessibility;
+
+/**
+ * ChromeVox2 background page.
+ */
+cvox2.Background = function() {
+ // Only needed with unmerged ChromeVox classic loaded before.
+ cvox2.global.accessibility.setAccessibilityEnabled(false);
+ chrome.automation.getDesktop(this.onGotDesktop.bind(this));
+};
+
+cvox2.Background.prototype = {
+ /**
+ * ID of the port used to communicate between content script and background
+ * page.
+ * @const {string}
+ */
+ PORT_ID: 'chromevox2',
+
+ /**
+ * Waits until a desktop automation tree becomes available.
+ * Thereafter, registers a simple exploration mode for the desktop tree.
+ * @param {AutomationTree} tree The desktop automation tree.
+ */
+ onGotDesktop: function(tree) {
+ if (!tree.root) {
+ window.setTimeout(this.onGotDesktop, 500);
+ return;
+ }
+ chrome.extension.onConnect.addListener(function(port) {
+ if (port.name != this.PORT_ID)
+ return;
+ var cur = tree.root;
+ port.onMessage.addListener(function(message) {
+ switch (message.keydown) {
+ case 37:
+ cur = cur.previousSibling() || cur;
+ break;
+ case 38:
+ cur = cur.parent() || cur;
+ break;
+ case 39:
+ cur = cur.nextSibling() || cur;
+ break;
+ case 40:
+ cur = cur.firstChild() || cur;
+ break;
+ }
+ var index = 1;
+ if (cur.parent())
+ index = cur.parent().children().indexOf(cur) + 1;
+ var name = '';
+ if (cur.attributes && cur.attributes['ax_attr_name'])
+ name = cur.attributes['ax_attr_name'];
+ var utterance = index + ' ' + name + cur.role;
+ chrome.tts.speak(String(utterance), {lang: 'en-US'});
+ });
+ }.bind(this));
+
+ // Register all automation event listeners.
+ tree.root.addEventListener('focus', this.onDesktopEvent.bind(this), true);
+ },
+
+ /**
+ * A generic handler for all desktop automation events.
+ * @param {AutomationEvent} evt The event.
+ */
+ onDesktopEvent: function(evt) {
+ var output = evt.target.attributes.name + ' ' + evt.target.role;
+ cvox.ChromeVox.tts.speak(output);
+ cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output));
+ }
+};
+
+/** @type {cvox2.Background} */
+cvox2.global.backgroundObj = new cvox2.Background();
diff --git a/chrome/browser/resources/chromeos/chromevox2/cvox2/injected/injected.js b/chrome/browser/resources/chromeos/chromevox2/cvox2/injected/injected.js
new file mode 100644
index 00000000000000..2174053ec910c1
--- /dev/null
+++ b/chrome/browser/resources/chromeos/chromevox2/cvox2/injected/injected.js
@@ -0,0 +1,19 @@
+// Copyright 2014 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 The entry point for all ChromeVox2 related code for the
+ * injected content script.
+ * This script will temporarily forward any events we need during the
+ * ChromeVox/ChromeVox2 timeframe where extension APIs do not exist (e.g.
+ * keyboard events).
+ */
+
+/** namespace */
+var cvox2 = function() {};
+
+var port = chrome.extension.connect({name: 'chromevox2'});
+document.body.addEventListener('keydown', function(evt) {
+ port.postMessage({keydown: evt.keyCode});
+}, true);
diff --git a/chrome/browser/resources/chromeos/chromevox2/manifest.json b/chrome/browser/resources/chromeos/chromevox2/manifest.json
new file mode 100644
index 00000000000000..259514eb386b7c
--- /dev/null
+++ b/chrome/browser/resources/chromeos/chromevox2/manifest.json
@@ -0,0 +1,38 @@
+{
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDltVl1k15pjRzuZfMc3B69inxwm2bZeZ2O8/zFO+NluHnBm3GJ3fzdOoFGJd+M16I8p7zxxQyHeDMfWYASyCeB8XnUEDKjqNLQfCnncsANzHsYoEbYj2nEUML2P13b9q+AAvpCBpAJ4cZp81e9n1y/vbSXHE4385cgkKueItzikQIDAQAB",
+ "manifest_version": 2,
+ "name": "ChromeVox",
+ "version": "1.0",
+ "description": "ChromeVox - Giving Voice to Chrome.",
+ "background": {
+ "page": "cvox2/background/background.html"
+ },
+ "content_scripts": [
+ {
+ "matches": [ "" ],
+ "exclude_globs": [ "chrome-extension://mndnfokpggljbaajbnioimlmbfngpief/chromevox/background/background.html" ],
+ "all_frames": true,
+ "js": [
+ "cvox2/injected/injected.js"
+ ]
+ }
+ ],
+ "permissions": [
+ "accessibilityPrivate",
+ "automation",
+ "bookmarks",
+ "tabs",
+ "experimental",
+ "history",
+ "tts",
+ "systemPrivate",
+ "brailleDisplayPrivate",
+ "commandLinePrivate",
+ ""
+ ],
+ "automation": {
+ "desktop": true,
+ "interact": true
+ },
+ "default_locale": "en"
+}
diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp
index b6e48ac7588dfa..630d9434862a43 100644
--- a/chrome/chrome_resources.gyp
+++ b/chrome/chrome_resources.gyp
@@ -114,6 +114,14 @@
],
}],
['chromeos==1 and disable_nacl==0 and disable_nacl_untrusted==0', {
+ 'conditions': [
+ # TODO(dtseng): Remove use_chromevox_next once ChromeVox Next is ready for testing.
+ ['use_chromevox_next==1', {
+ 'dependencies': [
+ 'browser/resources/chromeos/chromevox2/chromevox.gyp:chromevox2_resources',
+ ],
+ }],
+ ],
'copies' : [
{
'destination': '<(PRODUCT_DIR)/resources/chromeos/braille_ime',
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 91c825f4d5c9ad..7b83453a39ab07 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -68,6 +68,10 @@ const char kEchoExtensionPath[] = "echo-ext-path";
// Enables switching between different cellular carriers from the UI.
const char kEnableCarrierSwitching[] = "enable-carrier-switching";
+// Enables the next generation version of ChromeVox. Only valid with
+// use_chromevox_next=1 within your GYP_DEFINES.
+const char kEnableChromeVoxNext[] = "enable-chromevox-next";
+
// Enables consumer management, which allows user to enroll, remotely lock and
// locate the device.
const char kEnableConsumerManagement[] = "enable-consumer-management";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index a2a12680236152..5db10832e5f4a7 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -38,6 +38,7 @@ CHROMEOS_EXPORT extern const char kDisableQuickofficeComponentApp[];
CHROMEOS_EXPORT extern const char kDisableVolumeAdjustSound[];
CHROMEOS_EXPORT extern const char kEchoExtensionPath[];
CHROMEOS_EXPORT extern const char kEnableCarrierSwitching[];
+CHROMEOS_EXPORT extern const char kEnableChromeVoxNext[];
CHROMEOS_EXPORT extern const char kEnableConsumerManagement[];
CHROMEOS_EXPORT extern const char kEnableFileManagerMTP[];
CHROMEOS_EXPORT extern const char kEnableRollbackOption[];