summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd18
-rw-r--r--chrome/browser/chromeos/cros/network_library.cc18
-rw-r--r--chrome/browser/chromeos/cros/network_library.h7
-rw-r--r--chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc336
-rw-r--r--chrome/browser/resources/connection_manager.js21
-rw-r--r--chrome/browser/resources/mobile_setup.html161
-rw-r--r--chrome/browser/resources/mobile_setup.js89
7 files changed, 572 insertions, 78 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 5c031788..3d96e42 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4073,10 +4073,22 @@ Keep your key file in a safe place. You will need it to create new versions of y
<!-- chrome://mobilesetup strings -->
<message name="IDS_MOBILE_SETUP_TITLE" desc="ChromeOS mobile device activation page title">
- Activate your cellular connection
+ Cellular data service management
</message>
- <message name="IDS_MOBILE_SETUP_HEADER" desc="ChromeOS mobile device activation page heade">
- Cellular device activation
+ <message name="IDS_MOBILE_CONNECTING_HEADER" desc="Mobile connection page header while connecting to the provider">
+ Connecting to <ph name="PROVIDER_NAME">$1<ex>Acme Mobile</ex></ph>
+ </message>
+ <message name="IDS_MOBILE_ERROR_HEADER" desc="Mobile connection page header when connection error occur">
+ Connection error:
+ </message>
+ <message name="IDS_MOBILE_ACTIVATING_HEADER" desc="Message header when data service is being activated">
+ Activating your data service
+ </message>
+ <message name="IDS_MOBILE_COMPLETED_HEADER" desc="Message header when data service is completed">
+ Activation complete
+ </message>
+ <message name="IDS_MOBILE_COMPLETED_TEXT" desc="Message when cellular data service activation or payment is completed">
+ Your data service is activated and ready to use
</message>
</if>
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index 1653cd2..b86f62e 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -195,6 +195,24 @@ bool CellularNetwork::StartActivation() const {
void CellularNetwork::Clear() {
WirelessNetwork::Clear();
+ activation_state_ = ACTIVATION_STATE_UNKNOWN;
+ roaming_state_ = ROAMING_STATE_UNKNOWN;
+ network_technology_ = NETWORK_TECHNOLOGY_UNKNOWN;
+ operator_name_.clear();
+ operator_code_.clear();
+ payment_url_.clear();
+ meid_.clear();
+ imei_.clear();
+ imsi_.clear();
+ esn_.clear();
+ mdn_.clear();
+ min_.clear();
+ model_id_.clear();
+ manufacturer_.clear();
+ firmware_revision_.clear();
+ hardware_revision_.clear();
+ last_update_.clear();
+ prl_version_ = 0;
}
void CellularNetwork::ConfigureFromService(const ServiceInfo& service) {
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index b147206..38411d5 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -23,6 +23,7 @@ class Network {
const std::string& device_path() const { return device_path_; }
const std::string& ip_address() const { return ip_address_; }
ConnectionType type() const { return type_; }
+ ConnectionState connection_state() const { return state_; }
bool connecting() const { return state_ == STATE_ASSOCIATION ||
state_ == STATE_CONFIGURATION || state_ == STATE_CARRIER; }
bool connected() const { return state_ == STATE_READY; }
@@ -62,7 +63,7 @@ class Network {
std::string device_path_;
std::string ip_address_;
ConnectionType type_;
- int state_;
+ ConnectionState state_;
ConnectionError error_;
};
@@ -129,8 +130,8 @@ class CellularNetwork : public WirelessNetwork {
const NetworkTechnology network_technology() const {
return network_technology_; }
const NetworkRoamingState roaming_state() const { return roaming_state_; }
- const std::string& operator_name() const { return payment_url_; }
- const std::string& operator_code() const { return payment_url_; }
+ const std::string& operator_name() const { return operator_name_; }
+ const std::string& operator_code() const { return operator_code_; }
const std::string& payment_url() const { return payment_url_; }
const std::string& meid() const { return meid_; }
const std::string& imei() const { return imei_; }
diff --git a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc
index 1c11c09..405ec7e 100644
--- a/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc
+++ b/chrome/browser/chromeos/dom_ui/mobile_setup_ui.cc
@@ -4,18 +4,26 @@
#include "chrome/browser/chromeos/dom_ui/mobile_setup_ui.h"
+#include <map>
#include <string>
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/string_piece.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/weak_ptr.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
+#include "chrome/browser/chromeos/cros/system_library.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/tab_contents/tab_contents.h"
@@ -27,21 +35,65 @@
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/cros/system_library.h"
-
namespace {
// Host page JS API function names.
-const char kJsApiGetDeviceInfo[] = "getDeviceInfo";
+const char kJsApiCloseTab[] = "closeTab";
const char kJsApiSetTransactionStatus[] = "setTransactionStatus";
const wchar_t kJsDeviceStatusChangedHandler[] =
- L"mobile.MobileSetup.onDeviceStatusChanged";
+ L"handler.MobileSetup.deviceStateChanged";
+
+// Collular device states that are reported to DOM UI layer.
+const char kStateUnknown[] = "unknown";
+const char kStateConnecting[] = "connecting";
+const char kStateError[] = "error";
+const char kStateNeedsPayment[] = "payment";
+const char kStateActivating[] = "activating";
+const char kStateDisconnected[] = "disconnected";
+const char kStateConnected[] = "connected";
+const char kFailedPayment[] = "failed_payment";
+
+// Error codes matching codes defined in the cellular config file.
+const char kErrorDefault[] = "default";
+const char kErrorBadConnectionPartial[] = "bad_connection_partial";
+const char kErrorBadConnectionActivated[] = "bad_connection_activated";
+const char kErrorRoamingOnConnection[] = "roaming_connection";
+const char kErrorNoEVDO[] = "no_evdo";
+const char kErrorRoamingActivation[] = "roaming_activation";
+const char kErrorRoamingPartiallyActivated[] = "roaming_partially_activated";
+const char kErrorNoService[] = "no_service";
+const char kFailedPaymentError[] = "failed_payment";
+
+// Cellular configuration file path.
+const char kCellularConfigPath[] =
+ "/usr/share/chromeos-assets/mobile/mobile_config.json";
+
+// Cellular config file field names.
+const char kVersionField[] = "version";
+const char kErrorsField[] = "errors";
} // namespace
+class CellularConfigDocument {
+ public:
+ CellularConfigDocument() {}
+
+ // Return error message for a given code.
+ std::string GetErrorMessage(const std::string& code);
+ const std::string& version() { return version_; }
+
+ bool LoadFromFile(const FilePath& config_path);
+
+ private:
+ std::string version_;
+ std::map<std::string, std::string> error_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(CellularConfigDocument);
+};
+
+static std::map<std::string, std::string> error_messages_;
+
class MobileSetupUIHTMLSource : public ChromeURLDataManager::DataSource {
public:
MobileSetupUIHTMLSource();
@@ -63,32 +115,102 @@ class MobileSetupUIHTMLSource : public ChromeURLDataManager::DataSource {
// The handler for Javascript messages related to the "register" view.
class MobileSetupHandler : public DOMMessageHandler,
+ public chromeos::NetworkLibrary::Observer,
public base::SupportsWeakPtr<MobileSetupHandler> {
public:
MobileSetupHandler();
virtual ~MobileSetupHandler();
// Init work after Attach.
- void Init();
+ void Init(TabContents* contents);
// DOMMessageHandler implementation.
virtual DOMMessageHandler* Attach(DOMUI* dom_ui);
virtual void RegisterMessages();
+ // NetworkLibrary::Observer implementation.
+ virtual void NetworkChanged(chromeos::NetworkLibrary* obj);
+
private:
// Handlers for JS DOMUI messages.
- void HandleGetDeviceInfo(const ListValue* args);
+ void HandleCloseTab(const ListValue* args);
void HandleSetTransactionStatus(const ListValue* args);
// Sends message to host registration page with system/user info data.
void SendDeviceInfo();
- // Converts device the current CelularNetork into JS object.
- bool GetDeviceInfo(DictionaryValue* value);
+ // Converts the currently active CellularNetwork device into a JS object.
+ static bool GetDeviceInfo(DictionaryValue* value);
+ static bool ShouldReportDeviceState(std::string* state, std::string* error);
+
+ // Performs activation state cellular device evaluation.
+ // Returns false if device activation failed. In this case |error|
+ // will contain error message to be reported to DOM UI.
+ static bool CheckForActivationError(chromeos::CellularNetwork network,
+ std::string* error);
+
+ // Return error message for a given code.
+ static std::string GetErrorMessage(const std::string& code);
+ static void LoadCellularConfig();
+ static scoped_ptr<CellularConfigDocument> cellular_config_;
+
+ TabContents* tab_contents_;
DISALLOW_COPY_AND_ASSIGN(MobileSetupHandler);
};
+scoped_ptr<CellularConfigDocument> MobileSetupHandler::cellular_config_;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// CellularConfigDocument
+//
+////////////////////////////////////////////////////////////////////////////////
+
+std::string CellularConfigDocument::GetErrorMessage(const std::string& code) {
+ std::map<std::string, std::string>::iterator iter = error_map_.find(code);
+ if (iter == error_map_.end())
+ return code;
+ return iter->second;
+}
+
+bool CellularConfigDocument::LoadFromFile(const FilePath& config_path) {
+ error_map_.clear();
+
+ std::string config;
+ if (!file_util::ReadFileToString(config_path, &config))
+ return false;
+
+ scoped_ptr<Value> root(base::JSONReader::Read(config, true));
+ DCHECK(root.get() != NULL);
+ if (!root.get() || root->GetType() != Value::TYPE_DICTIONARY) {
+ LOG(INFO) << "Bad cellular config file";
+ return false;
+ }
+
+ DictionaryValue* root_dict = static_cast<DictionaryValue*>(root.get());
+ if (!root_dict->GetString(kVersionField, &version_)) {
+ LOG(INFO) << "Cellular config file missing version";
+ return false;
+ }
+ DictionaryValue* errors = NULL;
+ if (!root_dict->GetDictionary(kErrorsField, &errors))
+ return false;
+ for (DictionaryValue::key_iterator keys = errors->begin_keys();
+ keys != errors->end_keys();
+ ++keys) {
+ std::string value;
+ if (!errors->GetString(*keys, &value)) {
+ LOG(INFO) << "Bad cellular config error value";
+ error_map_.clear();
+ return false;
+ }
+
+ error_map_.insert(std::pair<std::string, std::string>(*keys, value));
+ }
+ return true;
+}
+
////////////////////////////////////////////////////////////////////////////////
//
// MobileSetupUIHTMLSource
@@ -104,8 +226,16 @@ void MobileSetupUIHTMLSource::StartDataRequest(const std::string& path,
int request_id) {
DictionaryValue strings;
strings.SetString("title", l10n_util::GetStringUTF16(IDS_MOBILE_SETUP_TITLE));
- strings.SetString("header",
- l10n_util::GetStringUTF16(IDS_MOBILE_SETUP_HEADER));
+ strings.SetString("connecting_header",
+ l10n_util::GetStringUTF16(IDS_MOBILE_CONNECTING_HEADER));
+ strings.SetString("error_header",
+ l10n_util::GetStringUTF16(IDS_MOBILE_ERROR_HEADER));
+ strings.SetString("activating_header",
+ l10n_util::GetStringUTF16(IDS_MOBILE_ACTIVATING_HEADER));
+ strings.SetString("completed_header",
+ l10n_util::GetStringUTF16(IDS_MOBILE_COMPLETED_HEADER));
+ strings.SetString("completed_text",
+ l10n_util::GetStringUTF16(IDS_MOBILE_COMPLETED_TEXT));
SetFontAndTextDirection(&strings);
static const base::StringPiece html(
@@ -126,42 +256,52 @@ void MobileSetupUIHTMLSource::StartDataRequest(const std::string& path,
// MobileSetupHandler
//
////////////////////////////////////////////////////////////////////////////////
-MobileSetupHandler::MobileSetupHandler() {
+MobileSetupHandler::MobileSetupHandler() : tab_contents_(NULL) {
}
MobileSetupHandler::~MobileSetupHandler() {
+ chromeos::CrosLibrary::Get()->GetNetworkLibrary()->RemoveObserver(this);
}
DOMMessageHandler* MobileSetupHandler::Attach(DOMUI* dom_ui) {
return DOMMessageHandler::Attach(dom_ui);
}
-void MobileSetupHandler::Init() {
- // TODO(zelidag): Register for network change notification to make sure
- // that the status of the cellular network does not flip to something we
- // can't handle (disabled, suddenly activated by divine intervention...).
+void MobileSetupHandler::Init(TabContents* contents) {
+ tab_contents_ = contents;
+ chromeos::CrosLibrary::Get()->GetNetworkLibrary()->AddObserver(this);
+
+ // TODO(zelidrag): We might want to move this to another thread.
+ LoadCellularConfig();
}
void MobileSetupHandler::RegisterMessages() {
- dom_ui_->RegisterMessageCallback(kJsApiGetDeviceInfo,
- NewCallback(this, &MobileSetupHandler::HandleGetDeviceInfo));
+ dom_ui_->RegisterMessageCallback(kJsApiCloseTab,
+ NewCallback(this, &MobileSetupHandler::HandleCloseTab));
dom_ui_->RegisterMessageCallback(kJsApiSetTransactionStatus,
NewCallback(this, &MobileSetupHandler::HandleSetTransactionStatus));
}
-void MobileSetupHandler::HandleGetDeviceInfo(const ListValue* args) {
- const size_t kGetDeviceInfoParamCount = 1;
- if (args->GetSize() != kGetDeviceInfoParamCount)
+void MobileSetupHandler::NetworkChanged(chromeos::NetworkLibrary* cros) {
+ if (!dom_ui_)
return;
-
- // Get change callback function name.
- string16 callback_func_name;
- if (!args->GetString(0, &callback_func_name))
+ DictionaryValue device;
+ GetDeviceInfo(&device);
+ std::string state, error;
+ if (!ShouldReportDeviceState(&state, &error))
return;
- DictionaryValue value;
- if (GetDeviceInfo(&value))
- dom_ui_->CallJavascriptFunction(UTF16ToWide(callback_func_name), value);
+ device.SetString("state", state);
+ if (error.length())
+ device.SetString("error", error);
+ dom_ui_->CallJavascriptFunction(
+ kJsDeviceStatusChangedHandler, device);
+}
+
+void MobileSetupHandler::HandleCloseTab(const ListValue* args) {
+ Browser* browser = BrowserList::GetLastActive();
+ if (browser)
+ browser->CloseTabContents(tab_contents_);
}
void MobileSetupHandler::HandleSetTransactionStatus(const ListValue* args) {
@@ -180,17 +320,110 @@ void MobileSetupHandler::HandleSetTransactionStatus(const ListValue* args) {
network_lib->cellular_networks();
if (!cell_networks.size())
return;
+
+ // We assume only one cellular network will come from flimflam for now.
const chromeos::CellularNetwork& network = *(cell_networks.begin());
- if (LowerCaseEqualsASCII(status, "OK") && network.StartActivation()) {
+ if (LowerCaseEqualsASCII(status, "OK")) {
+ network.StartActivation();
+ } else {
DictionaryValue value;
- if (GetDeviceInfo(&value))
- dom_ui_->CallJavascriptFunction(kJsDeviceStatusChangedHandler, value);
+ value.SetString("state", kFailedPaymentError);
+ dom_ui_->CallJavascriptFunction(kJsDeviceStatusChangedHandler, value);
}
- // TODO(zelidrag): Close the setup tab automatically when payment fails?
- // Pending UX decision on this one.
}
+bool MobileSetupHandler::ShouldReportDeviceState(std::string* state,
+ std::string* error) {
+ DCHECK(state);
+ DCHECK(error);
+ chromeos::NetworkLibrary* network_lib =
+ chromeos::CrosLibrary::Get()->GetNetworkLibrary();
+
+ const chromeos::CellularNetworkVector& cell_networks =
+ network_lib->cellular_networks();
+ // No cellular network present? Treat as network is disconnected.
+ // This could be transient state that is the result of activation process.
+ if (!cell_networks.size()) {
+ *state = kStateDisconnected;
+ return true;
+ }
+ const chromeos::CellularNetwork& network = cell_networks.at(0);
+
+ // First, check if device activation / plan payment failed.
+ // It's slightly more complex than just single state check
+ // that we are doing for other states below.
+ if (!CheckForActivationError(network, error)) {
+ *state = kStateError;
+ return true;
+ }
+
+ switch (network.activation_state()) {
+ case chromeos::ACTIVATION_STATE_UNKNOWN:
+ case chromeos::ACTIVATION_STATE_NOT_ACTIVATED:
+ // If this page is shown, I assume that we have already kicked off the
+ // process of starting the activation even though the device status
+ // reporting might not have caught up with us yet.
+ *state = kStateConnecting;
+ return true;
+ case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED:
+ case chromeos::ACTIVATION_STATE_ACTIVATING:
+ *state = kStateActivating;
+ return true;
+ case chromeos::ACTIVATION_STATE_ACTIVATED:
+ *state = kStateConnected;
+ return true;
+ }
+
+ // We don't report states that we don't understand to DOM UI.
+ *state = kStateUnknown;
+ return false;
+}
+
+
+bool MobileSetupHandler::CheckForActivationError(
+ chromeos::CellularNetwork network, std::string* error) {
+ bool got_error = false;
+ const char* error_code = kErrorDefault;
+
+ // This is the magic of error selecting based
+ if (network.connection_state() == chromeos::STATE_FAILURE &&
+ network.error() == chromeos::ERROR_AAA_FAILED ) {
+ if (network.activation_state() ==
+ chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) {
+ error_code = kErrorBadConnectionPartial;
+ } else if (network.activation_state() ==
+ chromeos::ACTIVATION_STATE_ACTIVATED) {
+ if (network.roaming_state() == chromeos::ROAMING_STATE_HOME) {
+ error_code = kErrorBadConnectionActivated;
+ } else if (network.roaming_state() == chromeos::ROAMING_STATE_ROAMING) {
+ error_code = kErrorRoamingOnConnection;
+ }
+ }
+ got_error = true;
+ } else if (network.connection_state() ==
+ chromeos::STATE_ACTIVATION_FAILURE) {
+ if (network.error() == chromeos::ERROR_NEED_EVDO) {
+ if (network.activation_state() ==
+ chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED)
+ error_code = kErrorNoEVDO;
+ } else if (network.error() == chromeos::ERROR_NEED_HOME_NETWORK) {
+ if (network.activation_state() ==
+ chromeos::ACTIVATION_STATE_NOT_ACTIVATED) {
+ error_code = kErrorRoamingActivation;
+ } else if (network.activation_state() ==
+ chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED) {
+ error_code = kErrorRoamingPartiallyActivated;
+ }
+ }
+ got_error = true;
+ }
+
+ if (got_error)
+ *error = GetErrorMessage(error_code);
+
+ return !got_error;
+}
bool MobileSetupHandler::GetDeviceInfo(DictionaryValue* value) {
DCHECK(value);
@@ -199,14 +432,13 @@ bool MobileSetupHandler::GetDeviceInfo(DictionaryValue* value) {
const chromeos::CellularNetworkVector& cell_networks =
network_lib->cellular_networks();
- if (!cell_networks.size())
+ if (!cell_networks.size()) {
return false;
+ }
const chromeos::CellularNetwork& network = *(cell_networks.begin());
-
value->SetString("carrier", UTF8ToUTF16(network.name()));
value->SetString("payment_url", UTF8ToUTF16(network.payment_url()));
- value->SetInteger("activation_state", network.activation_state());
value->SetString("MEID", UTF8ToUTF16(network.meid()));
value->SetString("IMEI", UTF8ToUTF16(network.imei()));
value->SetString("IMSI", UTF8ToUTF16(network.imsi()));
@@ -215,6 +447,34 @@ bool MobileSetupHandler::GetDeviceInfo(DictionaryValue* value) {
return true;
}
+std::string MobileSetupHandler::GetErrorMessage(const std::string& code) {
+ if (!cellular_config_.get())
+ return "";
+ return cellular_config_->GetErrorMessage(code);
+}
+
+void MobileSetupHandler::LoadCellularConfig() {
+ static bool config_loaded = false;
+ if (config_loaded)
+ return;
+ config_loaded = true;
+ // Load partner customization startup manifest if it is available.
+ FilePath config_path(kCellularConfigPath);
+ if (file_util::PathExists(config_path)) {
+ scoped_ptr<CellularConfigDocument> config(new CellularConfigDocument());
+ bool config_loaded = config->LoadFromFile(config_path);
+ if (config_loaded) {
+ LOG(INFO) << "Cellular config file loaded: " << kCellularConfigPath;
+ // lock
+ cellular_config_.reset(config.release());
+ } else {
+ LOG(ERROR) << "Error loading cellular config file: " <<
+ kCellularConfigPath;
+ }
+ }
+}
+
+
////////////////////////////////////////////////////////////////////////////////
//
// MobileSetupUI
@@ -224,7 +484,7 @@ bool MobileSetupHandler::GetDeviceInfo(DictionaryValue* value) {
MobileSetupUI::MobileSetupUI(TabContents* contents) : DOMUI(contents){
MobileSetupHandler* handler = new MobileSetupHandler();
AddMessageHandler((handler)->Attach(this));
- handler->Init();
+ handler->Init(contents);
MobileSetupUIHTMLSource* html_source = new MobileSetupUIHTMLSource();
// Set up the chrome://mobilesetup/ source.
diff --git a/chrome/browser/resources/connection_manager.js b/chrome/browser/resources/connection_manager.js
index bf443c4..baa3737 100644
--- a/chrome/browser/resources/connection_manager.js
+++ b/chrome/browser/resources/connection_manager.js
@@ -9,15 +9,9 @@ function chromeos() {
chromeos.connectionManager = function() {
};
-chromeos.connectionManager.device_info_callback_ = null;
chromeos.connectionManager.transaction_status_callback_ = null;
chromeos.connectionManager.parent_page_url_ = 'chrome://mobilesetup';
-chromeos.connectionManager.getDeviceInfo = function(callback) {
- chromeos.connectionManager.device_info_callback_ = callback;
- chromeos.connectionManager.requestDeviceInfo_();
-};
-
chromeos.connectionManager.setTransactionStatus = function(status, callback) {
chromeos.connectionManager.transaction_status_callback_ = callback;
chromeos.connectionManager.reportTransactionStatus_(status);
@@ -32,18 +26,3 @@ chromeos.connectionManager.reportTransactionStatus_ = function(status) {
window.parent.postMessage(msg, chromeos.connectionManager.parent_page_url_);
};
-chromeos.connectionManager.requestDeviceInfo_ = function() {
- var msg = {
- 'type': 'requestDeviceInfoMsg',
- 'domain': location.href,
- };
- window.parent.postMessage(msg, chromeos.connectionManager.parent_page_url_);
-}
-
-window.addEventListener('message', function(e) {
- if (e.data.type == 'deviceInfoMsg') {
- if (chromeos.connectionManager.device_info_callback_)
- chromeos.connectionManager.device_info_callback_(e.data.payload);
- }
-});
-
diff --git a/chrome/browser/resources/mobile_setup.html b/chrome/browser/resources/mobile_setup.html
index 1811e7b..5fa2e49 100644
--- a/chrome/browser/resources/mobile_setup.html
+++ b/chrome/browser/resources/mobile_setup.html
@@ -5,18 +5,139 @@
<title i18n-content="title"></title>
<style>
body {
- font-family: sans-serif;
- font-size: 10px;
+ font-size: 100%;
+ -webkit-user-select: none;
+}
+
+iframe {
+ overflow-x: scroll;
+ overflow-y: scroll;
+}
+
+.overlay {
+ position: fixed;
+ left: 0;
+ right: 0;
+ background: rgba(0, 0, 0, .2);
+ top: 0;
+ bottom: 0;
+ z-index: 10;
+ padding: 20px;
+ -webkit-box-align: center;
+ -webkit-box-pack: center;
+}
+
+.overlay > div {
+ background: white;
+ border-radius: 5px;
+ padding: 15px;
+ border: 1px solid #666;
+ -webkit-box-shadow: 3px 3px 3px #666;
+}
+
+.startup {
+ width: 500px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-left:-250px;
+ margin-top:-250px;
+ text-align: center;
}
#payment-form {
- width: 600px;
- height: 300px;
- overflow: hidden;
+ display: -webkit-box;
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.logo {
+ background: url('file:///usr/share/chromeos-assets/mobile/carrier_logo.png') no-repeat;
+ height: 58px;
+}
+
+#error-msg {
+ margin: 20px;
+}
+
+.box {
+ display: -webkit-box;
+}
+
+#final-logo {
+ position: absolute;
+ right: 30px;
+ width: 150px;
+}
+
+#activation-logo {
+ background-position: center;
+ margin-bottom: 20px;
+ margin-top: 20px;
}
-#error-div {
+#splitter {
+ margin-top: 10px;
+ left: 50%;
+ margin-left: 150px;
+ width: 200px;
+ border-bottom: 1px solid #EEE;
+ height: 1px;
}
+
+body[state='connecting'] > #payment-form,
+body[state='connecting'] > #final-message,
+body[state='connecting'] > * > #error-message {
+ display: none
+}
+body[state='connecting'] > #system-status {
+ display: block
+}
+
+body[state='error'] > #payment-form,
+body[state='error'] > #final-message {
+ display: none
+}
+body[state='error'] > * > #error-message,
+body[state='error'] > #system-status {
+ display: block
+}
+
+body[state='payment'] > * > #error-message,
+body[state='payment'] > #final-message,
+body[state='payment'] > #system-status {
+ display: none
+}
+body[state='payment'] > #payment-form {
+ display: block
+}
+
+body[state='activating'] > #payment-form,
+body[state='activating'] > #final-message,
+body[state='activating'] > * > #error-message {
+ display: none
+}
+body[state='activating'] > #system-status {
+ display: block
+}
+
+body[state='connected'] > * > #error-message,
+body[state='connected'] > #system-status {
+ display: none
+}
+body[state='connected'] > #payment-form,
+body[state='connected'] > #final-message {
+ display: block
+}
+
+.testing-only {
+}
+
</style>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/util.js"></script>
@@ -25,8 +146,28 @@ body {
mobile.MobileSetup.getInstance().initialize('payment-form');
</script>
</head>
-<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
-<h1 i18n-content="header"></h1>
-<div id="error-div"></div>
-<iframe id="payment-form" frameborder="0"></iframe></body>
+<body state="connecting" onload="setInterval(mobile.MobileSetup.drawProgress, 100);"
+ i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+ <iframe id="payment-form" frameborder="0"></iframe>
+ <div id="system-status" class="startup">
+ <div class="status-header"><h3 id="header"
+ i18n-content="status_header"></h3></div>
+ <div id="error-message"></div>
+ <canvas id="canvas" width="56" height="56"></canvas>
+ <div id="splitter"></div>
+ <div id="activation-logo" class="logo"></div>
+ </div>
+ <div id="final-message" class="overlay">
+ <div class="box">
+ <div>
+ <div class="header"><h3 i18n-content="completed_header"></h3></div>
+ <div id="action" i18n-content="completed_text"></div>
+ </div>
+ <div id="final-logo" class="logo"></div>
+ </div>
+ </div>
+ <div class="testing-only">
+ <button id="cheat">Fake activation!</button>
+ </div>
+</body>
</html>
diff --git a/chrome/browser/resources/mobile_setup.js b/chrome/browser/resources/mobile_setup.js
index fa1e98e..f6c481d 100644
--- a/chrome/browser/resources/mobile_setup.js
+++ b/chrome/browser/resources/mobile_setup.js
@@ -14,6 +14,15 @@ cr.define('mobile', function() {
// Mobile device information.
deviceInfo_: null,
frame_name_ : '',
+ local_strings_: new LocalStrings();
+ // UI states.
+ state_ : 0,
+ STATE_UNKNOWN_: "unknown",
+ STATE_CONNECTING_: "connecting",
+ STATE_ERROR_: "error",
+ STATE_PAYMENT_: "payment",
+ STATE_ACTIVATING_: "activating",
+ STATE_CONNECTED_: "connected",
initialize: function(frame_name) {
self = this;
@@ -31,9 +40,6 @@ cr.define('mobile', function() {
if (deviceInfo) {
this.deviceInfo_ = deviceInfo;
- // HACK(zelidrag): Remove the next line for real testing.
- this.deviceInfo_.payment_url = 'http://link.to/mobile_activation.html';
-
$(this.frame_name_).contentWindow.location.href =
this.deviceInfo_.payment_url;
}
@@ -51,6 +57,38 @@ cr.define('mobile', function() {
}
},
+ changeState: function(new_state, errorText) {
+ if (state_ == new_state)
+ return;
+ if (new_state == STATE_UNKNOWN_)
+ document.body.setAttribute('state', STATE_CONNECTING_);
+ else
+ document.body.setAttribute('state', new_state);
+ switch(new_state) {
+ case STATE_UNKNOWN_:
+ case STATE_CONNECTING_:
+ $('status-header').textContent =
+ local_strings_.getString('connecting_header');
+ $('error-message').textContent = '';
+ break;
+ case STATE_ERROR_:
+ $('status-header').textContent =
+ local_strings_.getString('error_header');
+ $('error-message').textContent = errorText;
+ break;
+ case STATE_ACTIVATING_:
+ $('status-header').textContent =
+ local_strings_.getString('activating_header');
+ $('error-message').textContent = '';
+ break;
+ }
+ state_ = new_state;
+ },
+
+ updateDeviceStatus_: function(deviceInfo) {
+ this.changeState(deviceInfo.state, deviceInfo.error);
+ },
+
sendDeviceInfo_ : function() {
var msg = {
type: 'deviceInfoMsg',
@@ -67,12 +105,57 @@ cr.define('mobile', function() {
$(this.frame_name_).contentWindow.postMessage(msg,
this.deviceInfo_.payment_url);
}
+
+ };
+
+ MobileSetup.drawProgress = function () {
+ var canvas = $('wheel');
+ var ctx = canvas.getContext('2d');
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ var segmentCount = Math.min(12, canvas.width/1.6) // Number of segments
+ var rotation = 0.75; // Counterclockwise rotation
+
+ // Rotate canvas over time
+ ctx.translate(canvas.width/2, canvas.height/2);
+ ctx.rotate(Math.PI * 2 / (segmentCount + rotation));
+ ctx.translate(-canvas.width/2, -canvas.height/2);
+
+ var gap = canvas.width / 24; // Gap between segments
+ var oRadius = canvas.width/2; // Outer radius
+ var iRadius = oRadius * 0.618; // Inner radius
+ var oCircumference = Math.PI * 2 * oRadius; // Outer circumference
+ var iCircumference = Math.PI * 2 * iRadius; // Inner circumference
+ var oGap = gap / oCircumference; // Gap size as fraction of outer ring
+ var iGap = gap / iCircumference; // Gap size as fraction of inner ring
+ var oArc = Math.PI * 2 * ( 1 / segmentCount - oGap); // Angle of outer arcs
+ var iArc = Math.PI * 2 * ( 1 / segmentCount - iGap); // Angle of inner arcs
+
+ for (i = 0; i < segmentCount; i++){ // Draw each segment
+ var opacity = Math.pow(1.0 - i / segmentCount, 3.0);
+ opacity = (0.15 + opacity * 0.8) // Vary from 0.15 to 0.95
+ var angle = - Math.PI * 2 * i / segmentCount;
+
+ ctx.beginPath();
+ ctx.arc(canvas.width/2, canvas.height/2, oRadius,
+ angle - oArc/2, angle + oArc/2, false);
+ ctx.arc(canvas.width/2, canvas.height/2, iRadius,
+ angle + iArc/2, angle - iArc/2, true);
+ ctx.closePath();
+ ctx.fillStyle = "rgba(240, 30, 29, " + opacity + ")";
+ ctx.fill();
+ }
};
MobileSetup.getDeviceInfoCallback = function(deviceInfo) {
MobileSetup.getInstance().loadPaymentFrame(deviceInfo);
};
+
+ MobileSetup.deviceStateChanged = function(deviceInfo) {
+ MobileSetup.getInstance().updateDeviceStatus_(deviceInfo);
+ };
+
// Export
return {
MobileSetup: MobileSetup