Index: chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc |
=================================================================== |
--- chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc (revision 107314) |
+++ chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc (working copy) |
@@ -31,8 +31,10 @@ |
#include "chrome/browser/ui/webui/chrome_url_data_manager.h" |
#include "chrome/common/jstemplate_builder.h" |
#include "chrome/common/pref_names.h" |
+#include "chrome/common/render_messages.h" |
#include "chrome/common/url_constants.h" |
#include "content/browser/browser_thread.h" |
+#include "content/browser/renderer_host/render_view_host_observer.h" |
#include "content/browser/tab_contents/tab_contents.h" |
#include "googleurl/src/gurl.h" |
#include "grit/browser_resources.h" |
@@ -47,9 +49,15 @@ |
// Host page JS API function names. |
const char kJsApiStartActivation[] = "startActivation"; |
const char kJsApiSetTransactionStatus[] = "setTransactionStatus"; |
+const char kJsApiPaymentPortalLoad[] = "paymentPortalLoad"; |
+const char kJsApiResultOK[] = "ok"; |
-const char kJsDeviceStatusChangedHandler[] = |
+const char kJsDeviceStatusChangedCallback[] = |
"mobile.MobileSetup.deviceStateChanged"; |
+const char kJsPortalFrameLoadFailedCallback[] = |
+ "mobile.MobileSetup.portalFrameLoadError"; |
+const char kJsPortalFrameLoadCompletedCallback[] = |
+ "mobile.MobileSetup.portalFrameLoadCompleted"; |
// Error codes matching codes defined in the cellular config file. |
const char kErrorDefault[] = "default"; |
@@ -79,6 +87,8 @@ |
const int kMaxActivationAttempt = 3; |
// Number of times we will retry to reconnect if connection fails. |
const int kMaxConnectionRetry = 10; |
+// Number of times we will retry to reconnect and reload payment portal page. |
+const int kMaxPortalReconnectCount = 5; |
// Number of times we will retry to reconnect if connection fails. |
const int kMaxConnectionRetryOTASP = 30; |
// Number of times we will retry to reconnect after payment is processed. |
@@ -113,6 +123,46 @@ |
} // namespace |
+// Observes IPC messages from the rederer and notifies JS if frame loading error |
+// appears. |
+class PortalFrameLoadObserver : public RenderViewHostObserver { |
+ public: |
+ PortalFrameLoadObserver(RenderViewHost* host, WebUI* webui) |
+ : RenderViewHostObserver(host), webui_(webui) { |
+ DCHECK(webui_); |
+ Send(new ChromeViewMsg_StartFrameSniffer(routing_id(), |
+ UTF8ToUTF16("paymentForm"))); |
+ } |
+ |
+ virtual ~PortalFrameLoadObserver() {} |
+ |
+ // IPC::Channel::Listener implementation. |
+ virtual bool OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(PortalFrameLoadObserver, message) |
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FrameLoadingError, OnFrameLoadError) |
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FrameLoadingCompleted, |
+ OnFrameLoadCompleted) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+ } |
+ |
+ private: |
+ void OnFrameLoadError(int error) { |
+ base::FundamentalValue result_value(error); |
+ webui_->CallJavascriptFunction( |
+ kJsPortalFrameLoadFailedCallback, result_value); |
+ } |
+ |
+ void OnFrameLoadCompleted() { |
+ webui_->CallJavascriptFunction(kJsPortalFrameLoadCompletedCallback); |
+ } |
+ |
+ WebUI* webui_; |
+ DISALLOW_COPY_AND_ASSIGN(PortalFrameLoadObserver); |
+}; |
+ |
class CellularConfigDocument { |
public: |
CellularConfigDocument() {} |
@@ -183,12 +233,14 @@ |
PLAN_ACTIVATION_RECONNECTING_OTASP_TRY = 2, |
PLAN_ACTIVATION_INITIATING_ACTIVATION = 3, |
PLAN_ACTIVATION_RECONNECTING = 4, |
- PLAN_ACTIVATION_SHOWING_PAYMENT = 5, |
- PLAN_ACTIVATION_DELAY_OTASP = 6, |
- PLAN_ACTIVATION_START_OTASP = 7, |
- PLAN_ACTIVATION_OTASP = 8, |
- PLAN_ACTIVATION_RECONNECTING_OTASP = 9, |
- PLAN_ACTIVATION_DONE = 10, |
+ PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING = 5, |
+ PLAN_ACTIVATION_SHOWING_PAYMENT = 6, |
+ PLAN_ACTIVATION_RECONNECTING_PAYMENT = 7, |
+ PLAN_ACTIVATION_DELAY_OTASP = 8, |
+ PLAN_ACTIVATION_START_OTASP = 9, |
+ PLAN_ACTIVATION_OTASP = 10, |
+ PLAN_ACTIVATION_RECONNECTING_OTASP = 11, |
+ PLAN_ACTIVATION_DONE = 12, |
PLAN_ACTIVATION_ERROR = 0xFF, |
} PlanActivationState; |
@@ -227,6 +279,7 @@ |
// Handlers for JS WebUI messages. |
void HandleSetTransactionStatus(const ListValue* args); |
void HandleStartActivation(const ListValue* args); |
+ void HandlePaymentPortalLoad(const ListValue* args); |
void SetTransactionStatus(const std::string& status); |
// Schedules activation process via task proxy. |
void InitiateActivation(); |
@@ -319,6 +372,8 @@ |
int connection_retry_count_; |
// Post payment reconnect wait counters. |
int reconnect_wait_count_; |
+ // Payment portal reload/reconnect attempt count. |
+ int payment_reconnect_count_; |
// Activation retry attempt count; |
int activation_attempt_; |
// Connection start time. |
@@ -460,6 +515,7 @@ |
already_running_(false), |
connection_retry_count_(0), |
reconnect_wait_count_(0), |
+ payment_reconnect_count_(0), |
activation_attempt_(0) { |
} |
@@ -497,6 +553,9 @@ |
web_ui_->RegisterMessageCallback(kJsApiSetTransactionStatus, |
base::Bind(&MobileSetupHandler::HandleSetTransactionStatus, |
base::Unretained(this))); |
+ web_ui_->RegisterMessageCallback(kJsApiPaymentPortalLoad, |
+ base::Bind(&MobileSetupHandler::HandlePaymentPortalLoad, |
+ base::Unretained(this))); |
} |
void MobileSetupHandler::OnNetworkManagerChanged( |
@@ -536,6 +595,42 @@ |
base::Bind(&TaskProxy::HandleSetTransactionStatus, task.get())); |
} |
+void MobileSetupHandler::HandlePaymentPortalLoad(const ListValue* args) { |
+ const size_t kPaymentPortalLoadParamCount = 1; |
+ if (args->GetSize() != kPaymentPortalLoadParamCount) |
+ return; |
+ // Get change callback function name. |
+ std::string result; |
+ if (!args->GetString(0, &result)) |
+ return; |
+ chromeos::CellularNetwork* network = GetCellularNetwork(service_path_); |
+ if (!network) { |
+ ChangeState(NULL, PLAN_ACTIVATION_ERROR, |
+ GetErrorMessage(kErrorNoService)); |
+ return; |
+ } |
+ if (state_ == PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING || |
+ state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) { |
+ if (LowerCaseEqualsASCII(result, kJsApiResultOK)) { |
+ payment_reconnect_count_ = 0; |
+ ChangeState(network, PLAN_ACTIVATION_SHOWING_PAYMENT, std::string()); |
+ } else { |
+ payment_reconnect_count_++; |
+ if (payment_reconnect_count_ > kMaxPortalReconnectCount) { |
+ ChangeState(NULL, PLAN_ACTIVATION_ERROR, |
+ GetErrorMessage(kErrorNoService)); |
+ return; |
+ } |
+ // Disconnect now, this should force reconnection and we will retry to |
+ // load the frame containing payment portal again. |
+ DisconnectFromNetwork(network); |
+ } |
+ } else { |
+ NOTREACHED() << "Called paymentPortalLoad while in unexpected state: " |
+ << GetStateDescription(state_); |
+ } |
+} |
+ |
void MobileSetupHandler::InitiateActivation() { |
scoped_refptr<TaskProxy> task = new TaskProxy(AsWeakPtr(), 0); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
@@ -593,7 +688,7 @@ |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// The payment is received, try to reconnect and check the status all over |
// again. |
- if (LowerCaseEqualsASCII(status, "ok") && |
+ if (LowerCaseEqualsASCII(status, kJsApiResultOK) && |
state_ == PLAN_ACTIVATION_SHOWING_PAYMENT) { |
chromeos::NetworkLibrary* lib = |
chromeos::CrosLibrary::Get()->GetNetworkLibrary(); |
@@ -623,6 +718,7 @@ |
// Permit network connection changes only in reconnecting states. |
if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY && |
state_ != PLAN_ACTIVATION_RECONNECTING && |
+ state_ != PLAN_ACTIVATION_RECONNECTING_PAYMENT && |
state_ != PLAN_ACTIVATION_RECONNECTING_OTASP) |
return; |
chromeos::CellularNetwork* network = GetCellularNetwork(service_path_); |
@@ -676,6 +772,7 @@ |
// Permit network connection changes only in reconnecting states. |
if (state_ != PLAN_ACTIVATION_RECONNECTING_OTASP_TRY && |
state_ != PLAN_ACTIVATION_RECONNECTING && |
+ state_ != PLAN_ACTIVATION_RECONNECTING_PAYMENT && |
state_ != PLAN_ACTIVATION_RECONNECTING_OTASP) |
return false; |
if (network) |
@@ -732,6 +829,7 @@ |
LOG(WARNING) << "Cellular service lost"; |
if (state_ == PLAN_ACTIVATION_RECONNECTING_OTASP_TRY || |
state_ == PLAN_ACTIVATION_RECONNECTING || |
+ state_ == PLAN_ACTIVATION_RECONNECTING_PAYMENT || |
state_ == PLAN_ACTIVATION_RECONNECTING_OTASP) { |
// This might be the legit case when service is lost after activation. |
// We need to make sure we force reconnection as soon as it shows up. |
@@ -761,7 +859,7 @@ |
new_state = PLAN_ACTIVATION_RECONNECTING; |
} else if (network->connected()) { |
if (network->restricted_pool()) { |
- new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
+ new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING; |
} else { |
new_state = PLAN_ACTIVATION_DONE; |
} |
@@ -819,7 +917,7 @@ |
new_state = GetNextReconnectState(state_); |
} else if (network->connected()) { |
if (network->restricted_pool()) { |
- new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
+ new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING; |
} else { |
new_state = PLAN_ACTIVATION_DONE; |
} |
@@ -828,7 +926,7 @@ |
case chromeos::ACTIVATION_STATE_PARTIALLY_ACTIVATED: |
if (network->connected()) { |
if (network->restricted_pool()) |
- new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
+ new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING; |
} else { |
new_state = GetNextReconnectState(state_); |
} |
@@ -843,6 +941,7 @@ |
break; |
} |
case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
+ case PLAN_ACTIVATION_RECONNECTING_PAYMENT: |
case PLAN_ACTIVATION_RECONNECTING: { |
if (network->connected()) { |
// Make sure other networks are not interfering with our detection of |
@@ -874,7 +973,7 @@ |
// If we have already received payment, don't show the payment |
// page again. We should try to reconnect after some |
// time instead. |
- new_state = PLAN_ACTIVATION_SHOWING_PAYMENT; |
+ new_state = PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING; |
} |
} else if (network->activation_state() == |
chromeos::ACTIVATION_STATE_ACTIVATED) { |
@@ -932,7 +1031,12 @@ |
case PLAN_ACTIVATION_PAGE_LOADING: |
break; |
// Just ignore all signals until the site confirms payment. |
- case PLAN_ACTIVATION_SHOWING_PAYMENT: |
+ case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING: |
+ case PLAN_ACTIVATION_SHOWING_PAYMENT: { |
+ if (network->disconnected()) |
+ new_state = PLAN_ACTIVATION_RECONNECTING_PAYMENT; |
+ break; |
+ } |
// Activation completed/failed, ignore network changes. |
case PLAN_ACTIVATION_DONE: |
case PLAN_ACTIVATION_ERROR: |
@@ -1022,8 +1126,12 @@ |
return "INITIATING_ACTIVATION"; |
case PLAN_ACTIVATION_RECONNECTING: |
return "RECONNECTING"; |
+ case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING: |
+ return "PAYMENT_PORTAL_LOADING"; |
case PLAN_ACTIVATION_SHOWING_PAYMENT: |
return "SHOWING_PAYMENT"; |
+ case PLAN_ACTIVATION_RECONNECTING_PAYMENT: |
+ return "RECONNECTING_PAYMENT"; |
case PLAN_ACTIVATION_START_OTASP: |
return "START_OTASP"; |
case PLAN_ACTIVATION_DELAY_OTASP: |
@@ -1068,7 +1176,7 @@ |
if (error_description.length()) |
device_dict.SetString("error", error_description); |
web_ui_->CallJavascriptFunction( |
- kJsDeviceStatusChangedHandler, device_dict); |
+ kJsDeviceStatusChangedCallback, device_dict); |
} |
@@ -1129,6 +1237,7 @@ |
break; |
case PLAN_ACTIVATION_RECONNECTING_OTASP_TRY: |
case PLAN_ACTIVATION_RECONNECTING: |
+ case PLAN_ACTIVATION_RECONNECTING_PAYMENT: |
case PLAN_ACTIVATION_RECONNECTING_OTASP: { |
// Start reconnect timer. This will ensure that we are not left in |
// limbo by the network library. |
@@ -1147,6 +1256,7 @@ |
} |
case PLAN_ACTIVATION_PAGE_LOADING: |
return; |
+ case PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING: |
case PLAN_ACTIVATION_SHOWING_PAYMENT: |
// Fix for fix SSL for the walled gardens where cert chain verification |
// might not work. |
@@ -1343,3 +1453,9 @@ |
Profile* profile = Profile::FromBrowserContext(contents->browser_context()); |
profile->GetChromeURLDataManager()->AddDataSource(html_source); |
} |
+ |
+void MobileSetupUI::RenderViewCreated(RenderViewHost* host) { |
+ ChromeWebUI::RenderViewCreated(host); |
+ // Destroyed by the corresponding RenderViewHost. |
+ new PortalFrameLoadObserver(host, tab_contents()->web_ui()); |
+} |