Commit ae170e10 authored by noamsml@chromium.org's avatar noamsml@chromium.org

Modify devices page to match the latest mocks

Incorporate printer list from cloudprint and modify cloud print page to match
mocks, adding necessary functionality along the way.

BUG=286157

Review URL: https://chromiumcodereview.appspot.com/23903011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221887 0039d316-1c4b-4281-b951-d872f2087c98
parent 8438889b
......@@ -15021,7 +15021,7 @@ Do you accept?
Devices
</message>
<message name="IDS_LOCAL_DISCOVERY_REGISTER_CONFIRMATION" desc="Confirmation for registering a printer to Google Cloud Print">
Do you want to add <ph name="PRINTER_NAME">$1</ph> to Google Cloud Print?
The following printers can be added to Google Cloud Print from your local network:
</message>
<message name="IDS_LOCAL_DISCOVERY_REGISTER_USER" desc="Label for user picker in registration dialog">
User:
......@@ -15050,6 +15050,27 @@ Do you accept?
<message name="IDS_LOCAL_DISCOVERY_UNREGISTERED_DEVICES_TITLE" desc="Title for unregistered devices">
Unregistered devices
</message>
<message name="IDS_LOCAL_DISCOVERY_NO_DESCRIPTION" desc="Description for devices with an empty description">
Printer on Google Cloud Print
</message>
<message name="IDS_LOCAL_DISCOVERY_PRINTERS_ON_NETWORK_ZERO" desc="'Zero' case for number indicator for locally discoverable printers">
No other available printers.
</message>
<message name="IDS_LOCAL_DISCOVERY_PRINTERS_ON_NETWORK_ONE" desc="'One' case for number indicator for locally discoverable printers">
One other available printer.
</message>
<message name="IDS_LOCAL_DISCOVERY_PRINTERS_ON_NETWORK_MULTIPLE" desc="General case for number indicator for locally discoverable printers">
<ph name="NUM_PRINTERS">$1</ph> other available printers.
</message>
<message name="IDS_LOCAL_DISCOVERY_LOADING" desc="Loading for local discovery screens">
Loading
</message>
<message name="IDS_LOCAL_DISCOVERY_ADD_PRINTERS" desc="Text on button to add printers to cloud print">
Add Printers
</message>
<message name="IDS_LOCAL_DISCOVERY_NO_PRINTERS_ON_NETWORK_EXPLANATION" desc="Explanatory text in case there are no printers to register on the network">
Looks like there are no printers available to register on the network. If your printer is on and connected to the internet, try registering it using instructions in its instruction manual.
</message>
</messages>
<structures fallback_to_english="true">
......
......@@ -2,26 +2,36 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
.device-info {
-webkit-box-flex: 1;
-webkit-padding-start: 55px;
.device {
margin: 23px 0;
max-width: 695px;
overflow: hidden;
}
.device {
display: -webkit-box;
max-width: 738px;
.device .device-info {
float: left;
}
html[dir='rtl'] .device .device-info {
float: right;
}
.device button {
float: right;
}
html[dir='rtl'] .device button {
float: left;
}
.device .button-container {
-webkit-padding-end: 10px;
display: inline-block;
width: 70px;
.subline,
.device-subline {
color: #999;
margin: 5px 0;
}
.device .button-container button {
margin-top: 0.5em;
padding-bottom: 10px;
padding-top: 10px;
h3.device-name {
margin: 0;
}
.register-page {
......@@ -36,4 +46,18 @@
html[dir='rtl'] .register-page .button-list {
text-align: left;
}
\ No newline at end of file
}
.controls {
border-bottom: 1px solid #eee;
max-width: 711px;
padding: 13px 3px 7px 4px;
}
html[dir='rtl'] .controls {
padding: 13px 4px 7px 3px;
}
.controls .subline {
-webkit-margin-start: 10px;
}
......@@ -6,6 +6,7 @@
<title i18n-content="devicesTitle"></title>
<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
<link rel="stylesheet" href="chrome://resources/css/overlay.css">
<link rel="stylesheet" href="chrome://resources/css/spinner.css">
<link rel="stylesheet" href="local_discovery.css">
<link rel="stylesheet" href="../uber/uber_shared.css">
......@@ -25,17 +26,16 @@
<div id="register-page-choose" class="register-page">
<h1 i18n-content="confirmRegistration"></h1>
<div id="register-message">
<div id="register-message"
i18n-content="noPrintersOnNetworkExplanation">
</div>
<div id="register-picker">
<label i18n-content="registerUser" for="register-user-list"></label>
<select id="register-user-list"></select>
<div id="register-device-picker">
<div class="devices" id="register-device-list">
</div>
</div>
<div class="button-list">
<button class="register-cancel">Cancel</button>
<button class="register-continue"
id="register-confirmation-continue">Continue</button>
<button class="register-cancel" i18n-content="cancel"></button>
</div>
</div>
......@@ -43,15 +43,16 @@
<h1 i18n-content="addingPrinter"></h1>
<div i18n-content="addingMessage1"></div>
<div class="button-list">
<button class="register-cancel">Cancel</button>
<button class="register-cancel" i18n-content="cancel"></button>
</div>
</div>
<div id="register-page-adding2" class="register-page">
<h1 i18n-content="addingPrinter"></h1>
<div i18n-content="addingMessage2"></div>
<div class="inline-spinner"> </div>
<span i18n-content="addingMessage2"></span>
<div class="button-list">
<button class="register-cancel">Cancel</button>
<button class="register-cancel" i18n-content="cancel"></button>
</div>
</div>
......@@ -59,7 +60,7 @@
<h1 i18n-content="addingError"></h1>
<div i18n-content="addingErrorMessage"></div>
<div class="button-list">
<button id="register-error-exit">OK</button>
<button id="register-error-exit" i18n-content="ok"></button>
</div>
</div>
</div>
......@@ -69,13 +70,20 @@
<h1 i18n-content="devicesTitle"></h1>
</header>
<h2 i18n-content="registeredDevicesTitle"></h2>
<div id="registered-devices" class="device-list">
<div class="controls">
<button id="add-printers-button" i18n-content="addPrinters"></button>
<span id="printer-num" class="subline"
i18n-content="printersOnNetworkZero">
</span>
</div>
<h2 i18n-content="unregisteredDevicesTitle"></h2>
<div id="unregistered-devices" class="device-list">
<div id="cloud-devices-loading">
<div class="inline-spinner"> </div> <span i18n-content="loading"></span>
</div>
<div id="cloud-devices">
</div>
</div>
<script src="chrome://resources/js/i18n_template2.js"></script>
......
......@@ -4,10 +4,12 @@
/**
* Javascript for local_discovery.html, served from chrome://devices/
* This is used to show discoverable devices near the user.
* This is used to show discoverable devices near the user as well as
* cloud devices registered to them.
*
* The simple object defined in this javascript file listens for
* callbacks from the C++ code saying that a new device is available.
* The object defined in this javascript file listens for callbacks from the
* C++ code saying that a new device is available as well as manages the UI for
* registering a device on the local network.
*/
......@@ -16,13 +18,18 @@
cr.define('local_discovery', function() {
'use strict';
/**
* Prefix for printer management page URLs, relative to base cloud print URL.
* @type {string}
*/
var PRINTER_MANAGEMENT_PAGE_PREFIX = '#printer/id/';
/**
* Map of service names to corresponding service objects.
* @type {Object.<string,Service>}
*/
var devices = {};
/**
* Object that represents a device in the device list.
* @param {Object} info Information about the device.
......@@ -39,10 +46,6 @@ cr.define('local_discovery', function() {
* @param {Object} info New information about the device.
*/
updateDevice: function(info) {
if (this.domElement && info.is_mine != this.info.is_mine) {
this.deviceContainer(this.info.is_mine).removeChild(this.domElement);
this.deviceContainer(info.is_mine).appendChild(this.domElement);
}
this.info = info;
this.renderDevice();
},
......@@ -51,7 +54,7 @@ cr.define('local_discovery', function() {
* Delete the device.
*/
removeDevice: function() {
this.deviceContainer(this.info.is_mine).removeChild(this.domElement);
this.deviceContainer().removeChild(this.domElement);
},
/**
......@@ -62,42 +65,13 @@ cr.define('local_discovery', function() {
clearElement(this.domElement);
} else {
this.domElement = document.createElement('div');
this.deviceContainer(this.info.is_mine).appendChild(this.domElement);
}
this.domElement.classList.add('device');
this.domElement.classList.add('printer-active');
var deviceInfo = document.createElement('div');
deviceInfo.className = 'device-info';
this.domElement.appendChild(deviceInfo);
var deviceName = document.createElement('h3');
deviceName.className = 'device-name';
deviceName.textContent = this.info.human_readable_name;
deviceInfo.appendChild(deviceName);
var deviceDescription = document.createElement('div');
deviceDescription.className = 'device-description';
deviceDescription.textContent = this.info.description;
deviceInfo.appendChild(deviceDescription);
var buttonContainer = document.createElement('div');
buttonContainer.className = 'button-container';
this.domElement.appendChild(buttonContainer);
var button = document.createElement('button');
button.textContent = loadTimeData.getString('serviceRegister');
if (this.info.registered) {
button.disabled = 'disabled';
} else {
button.addEventListener(
'click',
sendRegisterDevice.bind(null, this.info.service_name));
this.deviceContainer().appendChild(this.domElement);
}
buttonContainer.appendChild(button);
fillDeviceDescription(this.domElement, this.info.human_readable_name,
this.info.description,
loadTimeData.getString('serviceRegister'),
this.register.bind(this));
},
/**
......@@ -105,32 +79,68 @@ cr.define('local_discovery', function() {
* @param {boolean} is_mine Whether or not the device is in the 'Registered'
* section.
*/
deviceContainer: function(is_mine) {
if (is_mine) return $('registered-devices');
return $('unregistered-devices');
deviceContainer: function() {
return $('register-device-list');
},
/**
* Register the device.
*/
register: function() {
chrome.send('registerDevice', [this.info.service_name]);
setRegisterPage('register-page-adding1');
}
};
/**
* Appends a row to the output table listing the new device.
* @param {string} name Name of the device.
* @param {string} info Additional info of the device, if empty device need to
* be deleted.
* Returns a textual representation of the number of printers on the network.
* @return {string} Number of printers on the network as localized string.
*/
function onDeviceUpdate(name, info) {
if (info) {
if (devices.hasOwnProperty(name)) {
devices[name].updateDevice(info);
} else {
devices[name] = new Device(info);
devices[name].renderDevice();
}
function generateNumberPrintersAvailableText(numberPrinters) {
if (numberPrinters == 0) {
return loadTimeData.getString('printersOnNetworkZero');
} else if (numberPrinters == 1) {
return loadTimeData.getString('printersOnNetworkOne');
} else {
devices[name].removeDevice();
delete devices[name];
return loadTimeData.getStringF('printersOnNetworkMultiple',
numberPrinters);
}
}
/**
* Fill device element with the description of a device.
* @param {HTMLElement} device_dom_element Element to be filled.
* @param {string} name Name of device.
* @param {string} description Description of device.
* @param {string} button_text Text to appear on button.
* @param {function()} button_action Action for button.
*/
function fillDeviceDescription(device_dom_element,
name,
description,
button_text,
button_action) {
device_dom_element.classList.add('device');
var deviceInfo = document.createElement('div');
deviceInfo.className = 'device-info';
device_dom_element.appendChild(deviceInfo);
var deviceName = document.createElement('h3');
deviceName.className = 'device-name';
deviceName.textContent = name;
deviceInfo.appendChild(deviceName);
var deviceDescription = document.createElement('div');
deviceDescription.className = 'device-subline';
deviceDescription.textContent = description;
deviceInfo.appendChild(deviceDescription);
var button = document.createElement('button');
button.textContent = button_text;
button.addEventListener('click', button_action);
device_dom_element.appendChild(button);
}
/**
* Hide the register overlay.
*/
......@@ -138,6 +148,7 @@ cr.define('local_discovery', function() {
$('register-overlay').classList.add('showing');
$('overlay').hidden = false;
uber.invokeMethodOnParent('beginInterceptingEvents');
setRegisterPage('register-page-choose');
}
/**
......@@ -160,33 +171,90 @@ cr.define('local_discovery', function() {
}
}
/**
* Register a device.
* @param {string} device The device to register.
*/
function sendRegisterDevice(device) {
chrome.send('registerDevice', [device]);
}
/**
* Announce that a registration failed.
*/
function registrationFailed() {
function onRegistrationFailed() {
setRegisterPage('register-page-error');
}
/**
* Update UI to reflect that registration has been confirmed on the printer.
*/
function registrationConfirmedOnPrinter() {
function onRegistrationConfirmedOnPrinter() {
setRegisterPage('register-page-adding2');
}
/**
* Update device unregistered device list, and update related strings to
* reflect the number of devices available to register.
* @param {string} name Name of the device.
* @param {string} info Additional info of the device or null if the device
* has been removed.
*/
function onUnregisteredDeviceUpdate(name, info) {
if (info) {
if (devices.hasOwnProperty(name)) {
devices[name].updateDevice(info);
} else {
devices[name] = new Device(info);
devices[name].renderDevice();
}
} else {
if (devices.hasOwnProperty(name)) {
devices[name].removeDevice();
delete devices[name];
}
}
var numberPrinters = $('register-device-list').children.length;
$('printer-num').textContent = generateNumberPrintersAvailableText(
numberPrinters);
if (numberPrinters == 0) {
$('register-message').textContent = loadTimeData.getString(
'noPrintersOnNetworkExplanation');
} else {
$('register-message').textContent = loadTimeData.getString(
'registerConfirmMessage');
}
}
/**
* Handle a list of cloud devices available to the user globally.
* @param {Array.<Object>} devices_list List of devices.
*/
function onCloudDeviceListAvailable(devices_list) {
var devicesListLength = devices_list.length;
var devicesContainer = $('cloud-devices');
clearElement(devicesContainer);
$('cloud-devices-loading').hidden = true;
for (var i = 0; i < devicesListLength; i++) {
var devicesDomElement = document.createElement('div');
devicesContainer.appendChild(devicesDomElement);
var description;
if (devices_list[i].description == '') {
description = loadTimeData.getString('noDescription');
} else {
description = devices_list[i].description;
}
fillDeviceDescription(devicesDomElement, devices_list[i].display_name,
description, 'Manage' /*Localize*/,
manageCloudDevice.bind(null, devices_list[i].id));
}
}
/**
* Announce that a registration succeeeded.
*/
function registrationSuccess() {
function onRegistrationSuccess() {
hideRegisterOverlay();
requestPrinterList();
}
/**
......@@ -211,41 +279,24 @@ cr.define('local_discovery', function() {
}
/**
* Request a user account from a list.
* @param {Array} users Array of (index, username) tuples. Username may be
* displayed to the user; index must be passed opaquely to the UI handler.
* Request the printer list.
*/
function requestUser(users, printerName) {
clearElement($('register-user-list'));
var usersLength = users.length;
for (var i = 0; i < usersLength; i++) {
var userIndex = users[i][0];
var userName = users[i][1];
var option = document.createElement('option');
option.textContent = userName;
option.userData = { userIndex: userIndex, userName: userName };
$('register-user-list').appendChild(option);
}
showRegisterOverlay();
setRegisterPage('register-page-choose');
$('register-message').textContent =
loadTimeData.getStringF('registerConfirmMessage', printerName);
function requestPrinterList() {
clearElement($('cloud-devices'));
$('cloud-devices-loading').hidden = false;
chrome.send('requestPrinterList');
}
/**
* Send user selection and begin registration.
* Go to management page for a cloud device.
* @param {string} device_id ID of device.
*/
function beginRegistration() {
var userList = $('register-user-list');
var selectedOption = userList.options[userList.selectedIndex];
var userData = selectedOption.userData;
chrome.send('chooseUser', [userData.userIndex, userData.userName]);
setRegisterPage('register-page-adding1');
function manageCloudDevice(device_id) {
chrome.send('openCloudPrintURL',
[PRINTER_MANAGEMENT_PAGE_PREFIX + device_id]);
}
document.addEventListener('DOMContentLoaded', function() {
uber.onContentFrameLoaded();
......@@ -261,8 +312,8 @@ cr.define('local_discovery', function() {
$('register-error-exit').addEventListener('click', hideRegisterOverlay);
$('register-confirmation-continue').addEventListener(
'click', beginRegistration);
$('add-printers-button').addEventListener('click',
showRegisterOverlay);
updateVisibility();
document.addEventListener('webkitvisibilitychange', updateVisibility,
......@@ -272,13 +323,14 @@ cr.define('local_discovery', function() {
uber.invokeMethodOnParent('setTitle', {title: title});
chrome.send('start');
requestPrinterList();
});
return {
registrationSuccess: registrationSuccess,
registrationFailed: registrationFailed,
onDeviceUpdate: onDeviceUpdate,
requestUser: requestUser,
registrationConfirmedOnPrinter: registrationConfirmedOnPrinter
onRegistrationSuccess: onRegistrationSuccess,
onRegistrationFailed: onRegistrationFailed,
onUnregisteredDeviceUpdate: onUnregisteredDeviceUpdate,
onRegistrationConfirmedOnPrinter: onRegistrationConfirmedOnPrinter,
onCloudDeviceListAvailable: onCloudDeviceListAvailable
};
});
......@@ -48,6 +48,22 @@ content::WebUIDataSource* CreateLocalDiscoveryHTMLSource() {
IDS_LOCAL_DISCOVERY_UNREGISTERED_DEVICES_TITLE);
source->AddLocalizedString("devicesTitle",
IDS_LOCAL_DISCOVERY_DEVICES_PAGE_TITLE);
source->AddLocalizedString("noDescription",
IDS_LOCAL_DISCOVERY_NO_DESCRIPTION);
source->AddLocalizedString("printersOnNetworkZero",
IDS_LOCAL_DISCOVERY_PRINTERS_ON_NETWORK_ZERO);
source->AddLocalizedString("printersOnNetworkOne",
IDS_LOCAL_DISCOVERY_PRINTERS_ON_NETWORK_ONE);
source->AddLocalizedString("printersOnNetworkMultiple",
IDS_LOCAL_DISCOVERY_PRINTERS_ON_NETWORK_MULTIPLE);
source->AddLocalizedString("cancel", IDS_CANCEL);
source->AddLocalizedString("ok", IDS_OK);
source->AddLocalizedString("loading", IDS_LOCAL_DISCOVERY_LOADING);
source->AddLocalizedString("addPrinters", IDS_LOCAL_DISCOVERY_ADD_PRINTERS);
source->AddLocalizedString(
"noPrintersOnNetworkExplanation",
IDS_LOCAL_DISCOVERY_NO_PRINTERS_ON_NETWORK_EXPLANATION);
source->SetJsonPath("strings.js");
......
......@@ -170,7 +170,6 @@ IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, AddRowTest) {
condition_devices_listed().Wait();
DeviceDescription description;
description.id = kSampleDeviceID;
description.name = "Sample device";
description.description = "Sample device description";
......
......@@ -4,18 +4,25 @@
#include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
#include <set>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
#include "chrome/browser/local_discovery/privet_http_impl.h"
#include "chrome/browser/printing/cloud_print/cloud_print_url.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_base.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/page_transition_types.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_util.h"
#include "net/http/http_status_code.h"
......@@ -23,12 +30,12 @@
namespace local_discovery {
namespace {
// TODO(noamsml): This is a temporary shim until automated_url is in the
// response.
const char kPrivetAutomatedClaimURLFormat[] = "%s/confirm?token=%s";
const int kRegistrationAnnouncementTimeoutSeconds = 5;
LocalDiscoveryUIHandler::Factory* g_factory = NULL;
int g_num_visible = 0;
} // namespace
LocalDiscoveryUIHandler::LocalDiscoveryUIHandler() : is_visible_(false) {
......@@ -74,15 +81,20 @@ void LocalDiscoveryUIHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback("registerDevice", base::Bind(
&LocalDiscoveryUIHandler::HandleRegisterDevice,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("chooseUser", base::Bind(
&LocalDiscoveryUIHandler::HandleChooseUser,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("cancelRegistration", base::Bind(
&LocalDiscoveryUIHandler::HandleCancelRegistration,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("requestPrinterList", base::Bind(
&LocalDiscoveryUIHandler::HandleRequestPrinterList,
base::Unretained(this)));
web_ui()->RegisterMessageCallback("openCloudPrintURL", base::Bind(
&LocalDiscoveryUIHandler::HandleOpenCloudPrintURL,
base::Unretained(this)));
}
void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) {
Profile* profile = Profile::FromWebUI(web_ui());
// If privet_lister_ is already set, it is a mock used for tests or the result
// of a reload.
if (!privet_lister_) {
......@@ -91,32 +103,13 @@ void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) {
service_discovery_client_.get(), this));
privet_http_factory_.reset(new PrivetHTTPAsynchronousFactoryImpl(
service_discovery_client_.get(),
Profile::FromWebUI(web_ui())->GetRequestContext()));
profile->GetRequestContext()));
}
privet_lister_->Start();
privet_lister_->DiscoverNewDevices(false);
}
void LocalDiscoveryUIHandler::HandleRegisterDevice(
const base::ListValue* args) {
std::string device_name;
bool rv = args->GetString(0, &device_name);
DCHECK(rv);
current_register_device_ = device_name;
cloud_print_account_manager_.reset(new CloudPrintAccountManager(
Profile::FromWebUI(web_ui())->GetRequestContext(),
GetCloudPrintBaseUrl(device_name),
0 /* Get XSRF token for primary user */,
base::Bind(&LocalDiscoveryUIHandler::OnCloudPrintAccountsResolved,
base::Unretained(this))));
cloud_print_account_manager_->Start();
}
void LocalDiscoveryUIHandler::HandleIsVisible(const base::ListValue* args) {
bool is_visible = false;
bool rv = args->GetBoolean(0, &is_visible);
......@@ -124,19 +117,18 @@ void LocalDiscoveryUIHandler::HandleIsVisible(const base::ListValue* args) {
SetIsVisible(is_visible);
}
void LocalDiscoveryUIHandler::HandleChooseUser(const base::ListValue* args) {
std::string user;
void LocalDiscoveryUIHandler::HandleRegisterDevice(
const base::ListValue* args) {
std::string device;
bool rv = args->GetInteger(0, &current_register_user_index_);
DCHECK(rv);
rv = args->GetString(1, &user);
bool rv = args->GetString(0, &device);
DCHECK(rv);
privet_resolution_ = privet_http_factory_->CreatePrivetHTTP(
current_register_device_,
device_descriptions_[current_register_device_].address,
device,
device_descriptions_[device].address,
base::Bind(&LocalDiscoveryUIHandler::StartRegisterHTTP,
base::Unretained(this), user));
base::Unretained(this)));
privet_resolution_->Start();
}
......@@ -145,11 +137,43 @@ void LocalDiscoveryUIHandler::HandleCancelRegistration(
ResetCurrentRegistration();
}
void LocalDiscoveryUIHandler::HandleRequestPrinterList(
const base::ListValue* args) {
Profile* profile = Profile::FromWebUI(web_ui());
OAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
cloud_print_printer_list_.reset(new CloudPrintPrinterList(
profile->GetRequestContext(),
GetCloudPrintBaseUrl(),
token_service,
this));
cloud_print_printer_list_->Start();
}
void LocalDiscoveryUIHandler::HandleOpenCloudPrintURL(
const base::ListValue* args) {
std::string url;
bool rv = args->GetString(0, &url);
DCHECK(rv);
GURL url_full(GetCloudPrintBaseUrl() + url);
Browser* browser = chrome::FindBrowserWithWebContents(
web_ui()->GetWebContents());
DCHECK(browser);
chrome::AddSelectedTabWithURL(browser,
url_full,
content::PAGE_TRANSITION_FROM_API);
}
void LocalDiscoveryUIHandler::StartRegisterHTTP(
const std::string& user,
scoped_ptr<PrivetHTTPClient> http_client) {
current_http_client_.swap(http_client);
std::string user = GetSyncAccount();
if (!current_http_client_) {
SendRegisterError();
return;
......@@ -165,13 +189,13 @@ void LocalDiscoveryUIHandler::OnPrivetRegisterClaimToken(
const std::string& token,
const GURL& url) {
web_ui()->CallJavascriptFunction(
"local_discovery.registrationConfirmedOnPrinter");
"local_discovery.onRegistrationConfirmedOnPrinter");
if (device_descriptions_.count(current_http_client_->GetName()) == 0) {
SendRegisterError();
return;
}
std::string base_url = GetCloudPrintBaseUrl(current_http_client_->GetName());
std::string base_url = GetCloudPrintBaseUrl();
GURL automated_claim_url(base::StringPrintf(
kPrivetAutomatedClaimURLFormat,
......@@ -180,38 +204,21 @@ void LocalDiscoveryUIHandler::OnPrivetRegisterClaimToken(
Profile* profile = Profile::FromWebUI(web_ui());
if (current_register_user_index_ == kAccountIndexUseOAuth2) {
OAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
OAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
if (!token_service) {
SendRegisterError();
return;
}
confirm_api_call_flow_.reset(new PrivetConfirmApiCallFlow(
profile->GetRequestContext(),
token_service,
automated_claim_url,
base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone,
base::Unretained(this))));
confirm_api_call_flow_->Start();
} else {
if (current_register_user_index_ == 0) {
StartCookieConfirmFlow(current_register_user_index_,
xsrf_token_for_primary_user_,
automated_claim_url);
} else {
cloud_print_account_manager_.reset(new CloudPrintAccountManager(
Profile::FromWebUI(web_ui())->GetRequestContext(),
base_url,
current_register_user_index_,
base::Bind(&LocalDiscoveryUIHandler::OnXSRFTokenForSecondaryAccount,
base::Unretained(this), automated_claim_url)));
cloud_print_account_manager_->Start();
}
if (!token_service) {
SendRegisterError();
return;
}
confirm_api_call_flow_.reset(new PrivetConfirmApiCallFlow(
profile->GetRequestContext(),
token_service,
automated_claim_url,
base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone,
base::Unretained(this))));
confirm_api_call_flow_->Start();
}
void LocalDiscoveryUIHandler::OnPrivetRegisterError(
......@@ -227,10 +234,31 @@ void LocalDiscoveryUIHandler::OnPrivetRegisterError(
void LocalDiscoveryUIHandler::OnPrivetRegisterDone(
PrivetRegisterOperation* operation,
const std::string& device_id) {
std::string name = operation->GetHTTPClient()->GetName();
current_register_operation_.reset();
current_http_client_.reset();
SendRegisterDone();
DeviceDescriptionMap::iterator found = device_descriptions_.find(name);
if (found == device_descriptions_.end() || found->second.id.empty()) {
new_register_device_ = name;
registration_announce_timeout_.Reset(base::Bind(
&LocalDiscoveryUIHandler::OnAnnouncementTimeoutReached,
base::Unretained(this)));
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
registration_announce_timeout_.callback(),
base::TimeDelta::FromSeconds(kRegistrationAnnouncementTimeoutSeconds));
}
}
void LocalDiscoveryUIHandler::OnAnnouncementTimeoutReached() {
new_register_device_.clear();
registration_announce_timeout_.Cancel();
SendRegisterError();
}
void LocalDiscoveryUIHandler::OnConfirmDone(
......@@ -253,15 +281,26 @@ void LocalDiscoveryUIHandler::DeviceChanged(
base::DictionaryValue info;
base::StringValue service_name(name);
scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
info.SetString("service_name", name);
info.SetString("human_readable_name", description.name);
info.SetString("description", description.description);
info.SetBoolean("registered", !description.id.empty());
info.SetBoolean("is_mine", !description.id.empty());
if (description.id.empty()) {
info.SetString("service_name", name);
info.SetString("human_readable_name", description.name);
info.SetString("description", description.description);
web_ui()->CallJavascriptFunction("local_discovery.onDeviceUpdate",
service_name, info);
web_ui()->CallJavascriptFunction(
"local_discovery.onUnregisteredDeviceUpdate",
service_name, info);
} else {
web_ui()->CallJavascriptFunction(
"local_discovery.onUnregisteredDeviceUpdate",
service_name, *null_value);
if (name == new_register_device_) {
new_register_device_.clear();
SendRegisterDone();
}
}
}
void LocalDiscoveryUIHandler::DeviceRemoved(const std::string& name) {
......@@ -269,56 +308,50 @@ void LocalDiscoveryUIHandler::DeviceRemoved(const std::string& name) {
scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
base::StringValue name_value(name);
web_ui()->CallJavascriptFunction("local_discovery.onDeviceUpdate",
web_ui()->CallJavascriptFunction("local_discovery.onUnregisteredDeviceUpdate",
name_value, *null_value);
}
void LocalDiscoveryUIHandler::SendRegisterError() {
web_ui()->CallJavascriptFunction("local_discovery.registrationFailed");
}
void LocalDiscoveryUIHandler::SendRegisterDone() {
web_ui()->CallJavascriptFunction("local_discovery.registrationSuccess");
}
void LocalDiscoveryUIHandler::OnCloudPrintAccountsResolved(
const std::vector<std::string>& accounts,
const std::string& xsrf_token) {
xsrf_token_for_primary_user_ = xsrf_token;
std::string sync_account = GetSyncAccount();
base::ListValue accounts_annotated_list;
void LocalDiscoveryUIHandler::OnCloudPrintPrinterListReady() {
base::ListValue printer_object_list;
std::set<std::string> local_ids;
for (DeviceDescriptionMap::iterator i = device_descriptions_.begin();
i != device_descriptions_.end();
i++) {
std::string device_id = i->second.id;
if (!device_id.empty()) {
const CloudPrintPrinterList::PrinterDetails* details =
cloud_print_printer_list_->GetDetailsFor(device_id);
if (details) {
local_ids.insert(device_id);
printer_object_list.Append(CreatePrinterInfo(*details).release());
}
}
}
if (!sync_account.empty()) {
scoped_ptr<base::ListValue> account_annotated(new base::ListValue);
account_annotated->AppendInteger(kAccountIndexUseOAuth2);
account_annotated->AppendString(sync_account);
accounts_annotated_list.Append(account_annotated.release());
for (CloudPrintPrinterList::iterator i = cloud_print_printer_list_->begin();
i != cloud_print_printer_list_->end(); i++) {
if (local_ids.count(i->id) == 0) {
printer_object_list.Append(CreatePrinterInfo(*i).release());
}
}
int account_index = 0;
for (std::vector<std::string>::const_iterator i = accounts.begin();
i != accounts.end(); i++, account_index++) {
if (*i == sync_account) continue;
web_ui()->CallJavascriptFunction(
"local_discovery.onCloudDeviceListAvailable", printer_object_list);
}
void LocalDiscoveryUIHandler::OnCloudPrintPrinterListUnavailable() {
}
scoped_ptr<base::ListValue> account_annotated(new base::ListValue);
account_annotated->AppendInteger(account_index);
account_annotated->AppendString(*i);
accounts_annotated_list.Append(account_annotated.release());
}
base::StringValue device_name(current_register_device_);
web_ui()->CallJavascriptFunction("local_discovery.requestUser",
accounts_annotated_list, device_name);
void LocalDiscoveryUIHandler::SendRegisterError() {
web_ui()->CallJavascriptFunction("local_discovery.onRegistrationFailed");
}
void LocalDiscoveryUIHandler::OnXSRFTokenForSecondaryAccount(
const GURL& automated_claim_url,
const std::vector<std::string>& accounts,
const std::string& xsrf_token) {
StartCookieConfirmFlow(current_register_user_index_,
xsrf_token,
automated_claim_url);
void LocalDiscoveryUIHandler::SendRegisterDone() {
web_ui()->CallJavascriptFunction("local_discovery.onRegistrationSuccess");
}
void LocalDiscoveryUIHandler::SetIsVisible(bool visible) {
......@@ -340,29 +373,14 @@ std::string LocalDiscoveryUIHandler::GetSyncAccount() {
return signin_manager->GetAuthenticatedUsername();
}
const std::string& LocalDiscoveryUIHandler::GetCloudPrintBaseUrl(
const std::string& device_name) {
return device_descriptions_[device_name].url;
}
std::string LocalDiscoveryUIHandler::GetCloudPrintBaseUrl() {
CloudPrintURL cloud_print_url(Profile::FromWebUI(web_ui()));
void LocalDiscoveryUIHandler::StartCookieConfirmFlow(
int user_index,
const std::string& xsrf_token,
const GURL& automated_claim_url) {
confirm_api_call_flow_.reset(new PrivetConfirmApiCallFlow(
Profile::FromWebUI(web_ui())->GetRequestContext(),
user_index,
xsrf_token,
automated_claim_url,
base::Bind(&LocalDiscoveryUIHandler::OnConfirmDone,
base::Unretained(this))));
confirm_api_call_flow_->Start();
return cloud_print_url.GetCloudPrintServiceURL().spec();
}
// TODO(noamsml): Create master object for registration flow.
void LocalDiscoveryUIHandler::ResetCurrentRegistration() {
current_register_device_.clear();
if (current_register_operation_.get()) {
current_register_operation_->Cancel();
current_register_operation_.reset();
......@@ -370,10 +388,18 @@ void LocalDiscoveryUIHandler::ResetCurrentRegistration() {
confirm_api_call_flow_.reset();
privet_resolution_.reset();
cloud_print_account_manager_.reset();
xsrf_token_for_primary_user_.clear();
current_register_user_index_ = 0;
current_http_client_.reset();
}
scoped_ptr<base::DictionaryValue> LocalDiscoveryUIHandler::CreatePrinterInfo(
const CloudPrintPrinterList::PrinterDetails& description) {
scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
return_value->SetString("id", description.id);
return_value->SetString("display_name", description.display_name);
return_value->SetString("description", description.description);
return return_value.Pass();
}
} // namespace local_discovery
......@@ -9,7 +9,9 @@
#include <string>
#include <vector>
#include "base/cancelable_callback.h"
#include "chrome/browser/local_discovery/cloud_print_account_manager.h"
#include "chrome/browser/local_discovery/cloud_print_printer_list.h"
#include "chrome/browser/local_discovery/privet_confirm_api_flow.h"
#include "chrome/browser/local_discovery/privet_constants.h"
#include "chrome/browser/local_discovery/privet_device_lister.h"
......@@ -28,7 +30,8 @@ namespace local_discovery {
// into the Javascript to update the page.
class LocalDiscoveryUIHandler : public content::WebUIMessageHandler,
public PrivetRegisterOperation::Delegate,
public PrivetDeviceLister::Delegate {
public PrivetDeviceLister::Delegate,
public CloudPrintPrinterList::Delegate {
public:
class Factory {
public:
......@@ -73,11 +76,15 @@ class LocalDiscoveryUIHandler : public content::WebUIMessageHandler,
const DeviceDescription& description) OVERRIDE;
virtual void DeviceRemoved(const std::string& name) OVERRIDE;
// CloudPrintPrinterList::Delegate implementation.
virtual void OnCloudPrintPrinterListReady() OVERRIDE;
virtual void OnCloudPrintPrinterListUnavailable() OVERRIDE;
private:
// Message handlers:
// For registering a device.
void HandleRegisterDevice(const base::ListValue* args);
typedef std::map<std::string, DeviceDescription> DeviceDescriptionMap;
// Message handlers:
// For when the page is ready to recieve device notifications.
void HandleStart(const base::ListValue* args);
......@@ -85,30 +92,26 @@ class LocalDiscoveryUIHandler : public content::WebUIMessageHandler,
void HandleIsVisible(const base::ListValue* args);
// For when a user choice is made.
void HandleChooseUser(const base::ListValue* args);
void HandleRegisterDevice(const base::ListValue* args);
// For when a cancelation is made.
void HandleCancelRegistration(const base::ListValue* args);
// For requesting the printer list.
void HandleRequestPrinterList(const base::ListValue* args);
// For opening URLs (relative to the Google Cloud Print base URL) in a new
// tab.
void HandleOpenCloudPrintURL(const base::ListValue* args);
// For when the IP address of the printer has been resolved for registration.
void StartRegisterHTTP(
const std::string& user,
scoped_ptr<PrivetHTTPClient> http_client);
// For when the confirm operation on the cloudprint server has finished
// executing.
void OnConfirmDone(CloudPrintBaseApiFlow::Status status);
// For when the cloud print account list is resolved.
void OnCloudPrintAccountsResolved(const std::vector<std::string>& accounts,
const std::string& xsrf_token);
// For when XSRF token is received for a secondary account.
void OnXSRFTokenForSecondaryAccount(
const GURL& automated_claim_url,
const std::vector<std::string>& accounts,
const std::string& xsrf_token);
// Signal to the web interface an error has ocurred while registering.
void SendRegisterError();
......@@ -121,24 +124,23 @@ class LocalDiscoveryUIHandler : public content::WebUIMessageHandler,
// Get the sync account email.
std::string GetSyncAccount();
// Get the base cloud print URL for a given device.
const std::string& GetCloudPrintBaseUrl(const std::string& device_name);
// Start the confirm flow for a cookie based authentication.
void StartCookieConfirmFlow(
int user_index,
const std::string& xsrf_token,
const GURL& automatic_claim_url);
// Get the base cloud print URL.
std::string GetCloudPrintBaseUrl();
// Reset and cancel the current registration.
void ResetCurrentRegistration();
scoped_ptr<base::DictionaryValue> CreatePrinterInfo(
const CloudPrintPrinterList::PrinterDetails& description);
// Announcement hasn't been sent for a certain time after registration
// finished. Consider it failed.
// TODO(noamsml): Re-resolve service first.
void OnAnnouncementTimeoutReached();
// The current HTTP client (used for the current operation).
scoped_ptr<PrivetHTTPClient> current_http_client_;
// Device currently registering.
std::string current_register_device_;
// The current register operation. Only one allowed at any time.
scoped_ptr<PrivetRegisterOperation> current_register_operation_;
......@@ -158,20 +160,20 @@ class LocalDiscoveryUIHandler : public content::WebUIMessageHandler,
scoped_ptr<PrivetHTTPAsynchronousFactory::Resolution> privet_resolution_;
// A map of current device descriptions provided by the PrivetDeviceLister.
std::map<std::string, DeviceDescription> device_descriptions_;
DeviceDescriptionMap device_descriptions_;
// Whether or not the page is marked as visible.
bool is_visible_;
// Cloud print account manager to enumerate accounts and get XSRF token.
scoped_ptr<CloudPrintAccountManager> cloud_print_account_manager_;
// Device whose state must be updated to "registered" to complete
// registration.
std::string new_register_device_;
// XSRF token.
std::string xsrf_token_for_primary_user_;
// List of printers from cloud print.
scoped_ptr<CloudPrintPrinterList> cloud_print_printer_list_;
// Current user index (for multi-login), or kAccountIndexUseOAuth2 for sync
// credentials.
int current_register_user_index_;
// Announcement timeout for registration.
base::CancelableCallback<void()> registration_announce_timeout_;
DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUIHandler);
};
......
......@@ -5,7 +5,7 @@
var $ = document.getElementById.bind(document);
function checkOneDevice() {
var devices = $('registered-devices').children;
var devices = $('register-device-list').children;
assertEquals(1, devices.length);
var firstDevice = devices[0];
......@@ -13,14 +13,13 @@ function checkOneDevice() {
assertEquals('Sample device', deviceName);
var deviceDescription =
firstDevice.querySelector('.device-description').textContent;
firstDevice.querySelector('.device-subline').textContent;
assertEquals('Sample device description', deviceDescription);
var button = firstDevice.querySelector('button');
assertEquals(true, button.disabled);
assertEquals(false, button.disabled);
}
function checkNoDevices() {
assertEquals(0, $('unregistered-devices').children.length);
assertEquals(0, $('registered-devices').children.length);
assertEquals(0, $('register-device-list').children.length);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment