diff options
author | stanleyw@chromium.org <stanleyw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-12 03:05:08 +0000 |
---|---|---|
committer | stanleyw@chromium.org <stanleyw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-12 03:05:08 +0000 |
commit | 52a90fd0b17a770e05112ca5c64051e1121065fd (patch) | |
tree | f3fe599a31717ff2c6b10cfefc059d924a5b3e5c /chrome | |
parent | 56dbfb73e1bab8bef7f7d51bd06ab1e3207a1c60 (diff) | |
download | chromium_src-52a90fd0b17a770e05112ca5c64051e1121065fd.zip chromium_src-52a90fd0b17a770e05112ca5c64051e1121065fd.tar.gz chromium_src-52a90fd0b17a770e05112ca5c64051e1121065fd.tar.bz2 |
Adding cellular connect/disconnect support
Change-Id: I40bbe3a4bdc94831c1fdf51eedddbeeca1c232e8
Including Cellular Connect/Disconnect support into the library.
Also adding the first test cases of text message receiving and verifying
that a notification window appears with the correct text.
Moved chromeos_wifi_sanity to chromeos_network_sanity so it makes sense
to add cellular test cases into the suite.
BUG=None
TEST=chromeos_txt_msg_functional.py
Review URL: http://codereview.chromium.org/8072020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104986 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
9 files changed, 402 insertions, 60 deletions
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index ffffeaf..f610bca 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -848,29 +848,57 @@ class ToggleNetworkDeviceObserver DISALLOW_COPY_AND_ASSIGN(ToggleNetworkDeviceObserver); }; -// Waits for a connection success or failure for the specified -// network and returns the status to the automation provider. -class NetworkConnectObserver +class NetworkStatusObserver : public chromeos::NetworkLibrary::NetworkManagerObserver { public: - NetworkConnectObserver(AutomationProvider* automation, - IPC::Message* reply_message); + NetworkStatusObserver(AutomationProvider* automation, + IPC::Message* reply_message); + virtual ~NetworkStatusObserver(); - virtual ~NetworkConnectObserver(); - - virtual const chromeos::WifiNetwork* GetWifiNetwork( + virtual const chromeos::Network* GetNetwork( chromeos::NetworkLibrary* network_library) = 0; - // NetworkLibrary::NetworkManagerObserver implementation. virtual void OnNetworkManagerChanged(chromeos::NetworkLibrary* obj); + virtual void NetworkStatusCheck(const chromeos::Network* network) = 0; - private: + protected: base::WeakPtr<AutomationProvider> automation_; scoped_ptr<IPC::Message> reply_message_; + private: + DISALLOW_COPY_AND_ASSIGN(NetworkStatusObserver); +}; + +// Waits for a connection success or failure for the specified +// network and returns the status to the automation provider. +class NetworkConnectObserver : public NetworkStatusObserver { + public: + NetworkConnectObserver(AutomationProvider* automation, + IPC::Message* reply_message); + + virtual void NetworkStatusCheck(const chromeos::Network* network); + + private: DISALLOW_COPY_AND_ASSIGN(NetworkConnectObserver); }; +// Waits until a network has disconnected. Then returns success +// or failure. +class NetworkDisconnectObserver : public NetworkStatusObserver { + public: + NetworkDisconnectObserver(AutomationProvider* automation, + IPC::Message* reply_message, + const std::string& service_path); + + virtual void NetworkStatusCheck(const chromeos::Network* network); + const chromeos::Network* GetNetwork( + chromeos::NetworkLibrary* network_library); + + private: + std::string service_path_; + DISALLOW_COPY_AND_ASSIGN(NetworkDisconnectObserver); +}; + // Waits for a connection success or failure for the specified // network and returns the status to the automation provider. class ServicePathConnectObserver : public NetworkConnectObserver { @@ -879,16 +907,31 @@ class ServicePathConnectObserver : public NetworkConnectObserver { IPC::Message* reply_message, const std::string& service_path); - virtual const chromeos::WifiNetwork* GetWifiNetwork( + const chromeos::Network* GetNetwork( chromeos::NetworkLibrary* network_library); private: std::string service_path_; - DISALLOW_COPY_AND_ASSIGN(ServicePathConnectObserver); }; // Waits for a connection success or failure for the specified +// network and returns the status to the automation provider. +class SSIDConnectObserver : public NetworkConnectObserver { + public: + SSIDConnectObserver(AutomationProvider* automation, + IPC::Message* reply_message, + const std::string& ssid); + + const chromeos::Network* GetNetwork( + chromeos::NetworkLibrary* network_library); + + private: + std::string ssid_; + DISALLOW_COPY_AND_ASSIGN(SSIDConnectObserver); +}; + +// Waits for a connection success or failure for the specified // virtual network and returns the status to the automation provider. class VirtualConnectObserver : public chromeos::NetworkLibrary::NetworkManagerObserver { @@ -962,23 +1005,6 @@ class EnrollmentObserver DISALLOW_COPY_AND_ASSIGN(EnrollmentObserver); }; -// Waits for a connection success or failure for the specified -// network and returns the status to the automation provider. -class SSIDConnectObserver : public NetworkConnectObserver { - public: - SSIDConnectObserver(AutomationProvider* automation, - IPC::Message* reply_message, - const std::string& ssid); - - virtual const chromeos::WifiNetwork* GetWifiNetwork( - chromeos::NetworkLibrary* network_library); - - private: - std::string ssid_; - - DISALLOW_COPY_AND_ASSIGN(SSIDConnectObserver); -}; - // Waits for profile photo to be captured by the camera, // saved to file, and the path set in local state preferences class PhotoCaptureObserver : public chromeos::TakePhotoDialog::Observer, diff --git a/chrome/browser/automation/automation_provider_observers_chromeos.cc b/chrome/browser/automation/automation_provider_observers_chromeos.cc index 43f6b10..7c7549b7 100644 --- a/chrome/browser/automation/automation_provider_observers_chromeos.cc +++ b/chrome/browser/automation/automation_provider_observers_chromeos.cc @@ -195,23 +195,23 @@ void ToggleNetworkDeviceObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { } } -NetworkConnectObserver::NetworkConnectObserver(AutomationProvider* automation, +NetworkStatusObserver::NetworkStatusObserver(AutomationProvider* automation, IPC::Message* reply_message) : automation_(automation->AsWeakPtr()), reply_message_(reply_message) { NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary(); network_library->AddNetworkManagerObserver(this); } -NetworkConnectObserver::~NetworkConnectObserver() { +NetworkStatusObserver::~NetworkStatusObserver() { NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary(); network_library->RemoveNetworkManagerObserver(this); } -void NetworkConnectObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { - const chromeos::WifiNetwork* wifi = GetWifiNetwork(obj); - if (!wifi) { +void NetworkStatusObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { + const chromeos::Network* network = GetNetwork(obj); + if (!network) { // The network was not found, and we assume it no longer exists. - // This could be because the SSID is invalid, or the network went away. + // This could be because the ssid is invalid, or the network went away. if (automation_) { scoped_ptr<DictionaryValue> return_value(new DictionaryValue); return_value->SetString("error_string", "Network not found."); @@ -222,15 +222,24 @@ void NetworkConnectObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { return; } - if (wifi->failed()) { + NetworkStatusCheck(network); +} + +NetworkConnectObserver::NetworkConnectObserver( + AutomationProvider* automation, IPC::Message* reply_message) + : NetworkStatusObserver(automation, reply_message) {} + +void NetworkConnectObserver::NetworkStatusCheck(const chromeos::Network* + network) { + if (network->failed()) { if (automation_) { scoped_ptr<DictionaryValue> return_value(new DictionaryValue); - return_value->SetString("error_string", wifi->GetErrorString()); + return_value->SetString("error_string", network->GetErrorString()); AutomationJSONReply(automation_, reply_message_.release()) .SendSuccess(return_value.get()); } delete this; - } else if (wifi->connected()) { + } else if (network->connected()) { if (automation_) AutomationJSONReply(automation_, reply_message_.release()).SendSuccess(NULL); @@ -241,15 +250,53 @@ void NetworkConnectObserver::OnNetworkManagerChanged(NetworkLibrary* obj) { // success condition, so just continue waiting for more network events. } +NetworkDisconnectObserver::NetworkDisconnectObserver( + AutomationProvider* automation, IPC::Message* reply_message, + const std::string& service_path) + : NetworkStatusObserver(automation, reply_message), + service_path_(service_path) {} + +void NetworkDisconnectObserver::NetworkStatusCheck(const chromeos::Network* + network) { + if (!network->connected()) { + AutomationJSONReply(automation_, reply_message_.release()).SendSuccess( + NULL); + delete this; + } +} + +const chromeos::Network* NetworkDisconnectObserver::GetNetwork( + NetworkLibrary* network_library) { + return network_library->FindNetworkByPath(service_path_); +} + ServicePathConnectObserver::ServicePathConnectObserver( AutomationProvider* automation, IPC::Message* reply_message, const std::string& service_path) : NetworkConnectObserver(automation, reply_message), - service_path_(service_path) {} + service_path_(service_path) {} -const chromeos::WifiNetwork* ServicePathConnectObserver::GetWifiNetwork( +const chromeos::Network* ServicePathConnectObserver::GetNetwork( NetworkLibrary* network_library) { - return network_library->FindWifiNetworkByPath(service_path_); + return network_library->FindNetworkByPath(service_path_); +} + +SSIDConnectObserver::SSIDConnectObserver( + AutomationProvider* automation, IPC::Message* reply_message, + const std::string& ssid) + : NetworkConnectObserver(automation, reply_message), ssid_(ssid) {} + +const chromeos::Network* SSIDConnectObserver::GetNetwork( + NetworkLibrary* network_library) { + const chromeos::WifiNetworkVector& wifi_networks = + network_library->wifi_networks(); + for (chromeos::WifiNetworkVector::const_iterator iter = wifi_networks.begin(); + iter != wifi_networks.end(); ++iter) { + const chromeos::WifiNetwork* wifi = *iter; + if (wifi->name() == ssid_) + return wifi; + } + return NULL; } VirtualConnectObserver::VirtualConnectObserver(AutomationProvider* automation, @@ -374,24 +421,6 @@ void EnrollmentObserver::OnEnrollmentComplete( delete this; } -SSIDConnectObserver::SSIDConnectObserver( - AutomationProvider* automation, IPC::Message* reply_message, - const std::string& ssid) - : NetworkConnectObserver(automation, reply_message), ssid_(ssid) {} - -const chromeos::WifiNetwork* SSIDConnectObserver::GetWifiNetwork( - NetworkLibrary* network_library) { - const chromeos::WifiNetworkVector& wifi_networks = - network_library->wifi_networks(); - for (chromeos::WifiNetworkVector::const_iterator iter = wifi_networks.begin(); - iter != wifi_networks.end(); ++iter) { - const chromeos::WifiNetwork* wifi = *iter; - if (wifi->name() == ssid_) - return wifi; - } - return NULL; -} - PhotoCaptureObserver::PhotoCaptureObserver( AutomationProvider* automation, IPC::Message* reply_message) diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index 4c0a523..288275f 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -2340,6 +2340,10 @@ void TestingAutomationProvider::SendJSONRequest(int handle, &TestingAutomationProvider::GetProxySettings; handler_map["SetProxySettings"] = &TestingAutomationProvider::SetProxySettings; + handler_map["ConnectToCellularNetwork"] = + &TestingAutomationProvider::ConnectToCellularNetwork; + handler_map["DisconnectFromCellularNetwork"] = + &TestingAutomationProvider::DisconnectFromCellularNetwork; handler_map["ConnectToWifiNetwork"] = &TestingAutomationProvider::ConnectToWifiNetwork; handler_map["ConnectToHiddenWifiNetwork"] = diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h index 834ec90..d836e13 100644 --- a/chrome/browser/automation/testing_automation_provider.h +++ b/chrome/browser/automation/testing_automation_provider.h @@ -1275,6 +1275,12 @@ class TestingAutomationProvider : public AutomationProvider, void SetProxySettings(base::DictionaryValue* args, IPC::Message* reply_message); + void ConnectToCellularNetwork(base::DictionaryValue* args, + IPC::Message* reply_message); + + void DisconnectFromCellularNetwork(base::DictionaryValue* args, + IPC::Message* reply_message); + void ConnectToWifiNetwork(base::DictionaryValue* args, IPC::Message* reply_message); diff --git a/chrome/browser/automation/testing_automation_provider_chromeos.cc b/chrome/browser/automation/testing_automation_provider_chromeos.cc index 25d0171..38ccb97 100644 --- a/chrome/browser/automation/testing_automation_provider_chromeos.cc +++ b/chrome/browser/automation/testing_automation_provider_chromeos.cc @@ -553,6 +553,54 @@ void TestingAutomationProvider::SetProxySettings(DictionaryValue* args, reply.SendSuccess(NULL); } +void TestingAutomationProvider::ConnectToCellularNetwork( + DictionaryValue* args, IPC::Message* reply_message) { + if (!EnsureCrosLibraryLoaded(this, reply_message)) + return; + + std::string service_path; + if (!args->GetString("service_path", &service_path)) { + AutomationJSONReply(this, reply_message).SendError( + "Invalid or missing args."); + return; + } + + NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary(); + chromeos::CellularNetwork* cellular = + network_library->FindCellularNetworkByPath(service_path); + if (!cellular) { + AutomationJSONReply(this, reply_message).SendError( + "No network found with specified service path."); + return; + } + + // Set up an observer (it will delete itself). + new ServicePathConnectObserver(this, reply_message, service_path); + + network_library->ConnectToCellularNetwork(cellular); + network_library->RequestNetworkScan(); +} + +void TestingAutomationProvider::DisconnectFromCellularNetwork( + DictionaryValue* args, IPC::Message* reply_message) { + if (!EnsureCrosLibraryLoaded(this, reply_message)) + return; + + NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary(); + const chromeos::CellularNetwork* cellular = + network_library->cellular_network(); + if (!cellular) { + AutomationJSONReply(this, reply_message).SendError( + "Not connected to any cellular network."); + return; + } + + // Set up an observer (it will delete itself). + new NetworkDisconnectObserver(this, reply_message, cellular->service_path()); + + network_library->DisconnectFromNetwork(cellular); +} + void TestingAutomationProvider::ConnectToWifiNetwork( DictionaryValue* args, IPC::Message* reply_message) { if (!EnsureCrosLibraryLoaded(this, reply_message)) diff --git a/chrome/test/functional/chromeos_cellular_sanity.py b/chrome/test/functional/chromeos_cellular_sanity.py new file mode 100644 index 0000000..28e9b65 --- /dev/null +++ b/chrome/test/functional/chromeos_cellular_sanity.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# Copyright (c) 2011 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. + +import logging +import os +import sys +import time + +import pyauto_functional +import pyauto # pyauto_functional must come before pyauto + +class ChromeosCellularSanity(pyauto.PyUITest): + """Tests for ChromeOS network related functions.""" + + assert os.popen('modem status').read(), 'Device needs modem to run test.' + + def testConnectCellularNetwork(self): + """Connect to the cellular network if present.""" + + self.ConnectToCellularNetwork() + self.assertTrue(self.NetworkScan().get('connected_cellular'), + 'Failed to connect to cellular network.') + self.DisconnectFromCellularNetwork() + self.assertFalse(self.NetworkScan().get('connected_cellular'), + 'Failed to disconnect from cellular network.') + + +if __name__ == '__main__': + pyauto_functional.Main() diff --git a/chrome/test/functional/chromeos_txt_msg_functional.py b/chrome/test/functional/chromeos_txt_msg_functional.py new file mode 100644 index 0000000..e5baef7 --- /dev/null +++ b/chrome/test/functional/chromeos_txt_msg_functional.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +# Copyright (c) 2011 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. + +from email.MIMEText import MIMEText +import logging +import os +import re +import smtplib +import sys +import urllib + +import pyauto_functional +import pyauto + +sys.path.append(os.path.join(pyauto.PyUITest.DataDir(), 'pyauto_private', + 'chromeos', 'network')) +from gsm_sim_info import SIM, PROVIDER_TXT_SERVER + + +class ChromeosTxtMsgSanity(pyauto.PyUITest): + """Tests for ChromeOS text message handling""" + + def _SendText(self, mail_server, sender, phone_number, + mobile_provider, msg): + """Sends a text message to a specific phone + + Args: + mail_server: An SMTP instance. + sender: Sender's email address. + phone_number: The phone number the txt message is directed to. + mobile_provider: A cellular provider defined in + gsm_sim_info.PROVIDER_TXT_SERVER + msg: The message to be sent. + + """ + recipient = ('%s@%s' % (phone_number, + PROVIDER_TXT_SERVER[mobile_provider])) + self._SendMail(mail_server, sender, recipient, None, msg) + + def _SendMail(self, mail_server, sender, recipients, + msg_subject, msg_body): + """Sends an email using the provided smtp connection + + Args: + mail_server: An SMTP instace. + sender: Senders email address. + recipients: Recipients email address. + msg_subject: The subject line of the email. + msg_body: The body of the email. + """ + msg = MIMEText(msg_body) + msg['To'] = recipients + msg['From'] = sender + if msg_subject: + msg['Subject'] = msg_subject + mail_server.sendmail(sender, recipients, msg.as_string()) + + def _GetGmailServerInstance(self, email, password): + """Creates an SMTP connection with the gmail mail server + + Args: + email: A gmail address. + password: The password for the gmail address. + + Returns: + An SMTP connection instance. + """ + mail_server = smtplib.SMTP('smtp.gmail.com', 587) + mail_server.starttls() + mail_server.ehlo() + mail_server.login(email, password) + return mail_server + + def _GetIMSI(self): + """Obtains the IMSI by running modem status + + Returns: + IMSI of device + """ + modem_status = os.popen('modem status').read() + imsi = re.search('IMSI:\s(\d+)', modem_status) + if not imsi: + raise Exception('GSM Modem not detected in device') + return imsi.groups()[0] + + def _GetSIMInfo(self): + """Returns information necessary to send messages + + Returns: + A dictionary with the following format + { + 'mdn' : <phone number>, + 'carrier': <carrier name> + } + """ + imsi = self._GetIMSI() + sim_info = SIM.get(imsi, {}) + if not sim_info: + raise Exception('Phone number for sim with IMSI=%s is not ' + 'recognized within config file' % imsi) + return sim_info + + def setUp(self): + # Connect to cellular service if not already connected. + pyauto.PyUITest.setUp(self) + connected_cellular = self.NetworkScan().get('connected_cellular') + if not connected_cellular: + self.ConnectToCellularNetwork() + if not self.NetworkScan().get('connected_cellular'): + raise Exception('Could not connect to cellular service.') + else: + logging.debug('Already connected to cellular service %s' % + connected_cellular) + + # Obtain sender, recipient, and SMTP instance. + self.credentials = self.GetPrivateInfo()['test_account_with_smtp'] + self.sim = self._GetSIMInfo() + self.mail_server = self._GetGmailServerInstance( + self.credentials['username'], + self.credentials['password']) + + def tearDown(self): + self.DisconnectFromCellularNetwork() + self.mail_server.close() + for window in range(len(self.GetActiveNotifications())): + self.CloseNotification(window) + pyauto.PyUITest.tearDown(self) + + def testTxtMsgNotification(self): + """Notifications are displayed for text messages""" + msg = 'This is the text message' + self._SendText(self.mail_server, self.credentials['username'], + self.sim['mdn'], self.sim['carrier'], msg) + self.WaitForNotificationCount(1) + notification_result = self.GetActiveNotifications()[0]['content_url'] + self.assertTrue(re.search(urllib.pathname2url(msg), + notification_result), 'Invalid message was displayed. ' + 'Expected "%s" but did not find it"' % msg) + + def testLongTxtMsgNotification(self): + """Notifications are displayed for long (>160 char) text messages.""" + long_msg = 'This is a really long message with spaces. Testing to '\ + 'make sure that chromeos is able to catch it and '\ + 'create a notifications for this message.' + self._SendText(self.mail_server, self.credentials['username'], + self.sim['mdn'], self.sim['carrier'], long_msg) + self.WaitForNotificationCount(1) + + # GetActiveNotifications throws an exception if the text message never + # arrives. + txt_msg = self.GetActiveNotifications()[0] + txt_msg = txt_windows[0]['content_url'] + self.assertTrue(re.search(urllib.pathname2url(long_msg), + txt_msg), 'Invalid message was displayed. ' + 'Expected "%s" but did not find it"' % long_msg) + + +if __name__ == '__main__': + pyauto_functional.Main() diff --git a/chrome/test/functional/chromeos_wifi_sanity.py b/chrome/test/functional/chromeos_wifi_sanity.py index d708369..e90ebf4 100644 --- a/chrome/test/functional/chromeos_wifi_sanity.py +++ b/chrome/test/functional/chromeos_wifi_sanity.py @@ -10,7 +10,7 @@ import chromeos_network # pyauto_functional must come before chromeos_network class ChromeosWifiSanity(chromeos_network.PyNetworkUITest): - """Tests for ChromeOS wifi.""" + """Tests for ChromeOS network related functions.""" def testNetworkInfoAndScan(self): """Get basic info on networks.""" diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py index eb4bcca..0a7c9e3 100644 --- a/chrome/test/pyautolib/pyauto.py +++ b/chrome/test/pyautolib/pyauto.py @@ -3719,6 +3719,43 @@ class PyUITest(pyautolib.PyUITestBase, unittest.TestCase): } self._GetResultFromJSONRequest(cmd_dict, windex=-1, timeout=50000) + def ConnectToCellularNetwork(self): + """Connects to the available cellular network. + + Blocks until connection succeeds or fails. + + Returns: + An error string if an error occured. + None otherwise. + + Raises: + pyauto_errors.JSONInterfaceError if the automation call returns an error. + """ + # Every device should only have one cellular network present, so we can + # scan for it. + cellular_networks = self.NetworkScan().get('cellular_networks', {}).keys() + self.assertTrue(cellular_networks, 'Could not find cellular service.') + service_path = cellular_networks[0] + + cmd_dict = { + 'command': 'ConnectToCellularNetwork', + 'service_path': service_path, + } + result = self._GetResultFromJSONRequest(cmd_dict, windex=-1, timeout=50000) + return result.get('error_string') + + def DisconnectFromCellularNetwork(self): + """Disconnect from the connected cellular network. + + Blocks until disconnect is complete. + + Raises: + pyauto_errors.JSONInterfaceError if the automation call returns an error. + """ + cmd_dict = { + 'command': 'DisconnectFromCellularNetwork', + } + self._GetResultFromJSONRequest(cmd_dict, windex=-1) def ConnectToWifiNetwork(self, service_path, password=''): """Connect to a wifi network by its service path. |