Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / client_cert_resolver.cc
index a416061..ed1de01 100644 (file)
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/task_runner.h"
 #include "base/threading/worker_pool.h"
-#include "base/time/time.h"
 #include "chromeos/cert_loader.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill_service_client.h"
@@ -138,7 +138,8 @@ std::vector<CertAndIssuer> CreateSortedCertAndIssuerList(
        it != certs.end(); ++it) {
     const net::X509Certificate& cert = **it;
     if (cert.valid_expiry().is_null() || cert.HasExpired() ||
-        !HasPrivateKey(cert)) {
+        !HasPrivateKey(cert) ||
+        !CertLoader::IsCertificateHardwareBacked(&cert)) {
       continue;
     }
     net::ScopedCERTCertificate issuer_handle(
@@ -221,17 +222,15 @@ bool ClientCertificatesLoaded() {
     VLOG(1) << "Certificates not loaded yet.";
     return false;
   }
-  if (!CertLoader::Get()->IsHardwareBacked()) {
-    VLOG(1) << "TPM is not available.";
-    return false;
-  }
   return true;
 }
 
 }  // namespace
 
 ClientCertResolver::ClientCertResolver()
-    : network_state_handler_(NULL),
+    : resolve_task_running_(false),
+      network_properties_changed_(false),
+      network_state_handler_(NULL),
       managed_network_config_handler_(NULL),
       weak_ptr_factory_(this) {
 }
@@ -264,6 +263,18 @@ void ClientCertResolver::SetSlowTaskRunnerForTest(
   slow_task_runner_for_test_ = task_runner;
 }
 
+void ClientCertResolver::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void ClientCertResolver::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+bool ClientCertResolver::IsAnyResolveTaskRunning() const {
+  return resolve_task_running_;
+}
+
 // static
 bool ClientCertResolver::ResolveCertificatePatternSync(
     const client_cert::ConfigType client_cert_type,
@@ -346,8 +357,9 @@ void ClientCertResolver::OnCertificatesLoaded(
   ResolveNetworks(networks);
 }
 
-void ClientCertResolver::PolicyApplied(const std::string& service_path) {
-  VLOG(2) << "PolicyApplied " << service_path;
+void ClientCertResolver::PolicyAppliedToNetwork(
+    const std::string& service_path) {
+  VLOG(2) << "PolicyAppliedToNetwork " << service_path;
   if (!ClientCertificatesLoaded())
     return;
   // Compare this network with all certificates.
@@ -365,7 +377,7 @@ void ClientCertResolver::PolicyApplied(const std::string& service_path) {
 
 void ClientCertResolver::ResolveNetworks(
     const NetworkStateHandler::NetworkStateList& networks) {
-  scoped_ptr<std::vector<NetworkAndCertPattern> > networks_with_pattern(
+  scoped_ptr<std::vector<NetworkAndCertPattern>> networks_to_resolve(
       new std::vector<NetworkAndCertPattern>);
 
   // Filter networks with ClientCertPattern. As ClientCertPatterns can only be
@@ -401,11 +413,24 @@ void ClientCertResolver::ResolveNetworks(
     if (cert_config.client_cert_type != ::onc::client_cert::kPattern)
       continue;
 
-    networks_with_pattern->push_back(
+    networks_to_resolve->push_back(
         NetworkAndCertPattern(network->path(), cert_config));
   }
-  if (networks_with_pattern->empty())
+
+  if (networks_to_resolve->empty()) {
+    VLOG(1) << "No networks to resolve.";
+    NotifyResolveRequestCompleted();
+    return;
+  }
+
+  if (resolve_task_running_) {
+    VLOG(1) << "A resolve task is already running. Queue this request.";
+    for (const NetworkAndCertPattern& network_and_pattern :
+         *networks_to_resolve) {
+      queued_networks_to_resolve_.insert(network_and_pattern.service_path);
+    }
     return;
+  }
 
   VLOG(2) << "Start task for resolving client cert patterns.";
   base::TaskRunner* task_runner = slow_task_runner_for_test_.get();
@@ -413,18 +438,37 @@ void ClientCertResolver::ResolveNetworks(
     task_runner =
         base::WorkerPool::GetTaskRunner(true /* task is slow */).get();
 
+  resolve_task_running_ = true;
   NetworkCertMatches* matches = new NetworkCertMatches;
   task_runner->PostTaskAndReply(
       FROM_HERE,
       base::Bind(&FindCertificateMatches,
                  CertLoader::Get()->cert_list(),
-                 base::Owned(networks_with_pattern.release()),
+                 base::Owned(networks_to_resolve.release()),
                  matches),
       base::Bind(&ClientCertResolver::ConfigureCertificates,
                  weak_ptr_factory_.GetWeakPtr(),
                  base::Owned(matches)));
 }
 
+void ClientCertResolver::ResolvePendingNetworks() {
+  NetworkStateHandler::NetworkStateList networks;
+  network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
+                                               true /* configured_only */,
+                                               false /* visible_only */,
+                                               0 /* no limit */,
+                                               &networks);
+
+  NetworkStateHandler::NetworkStateList networks_to_resolve;
+  for (const NetworkState* network : networks) {
+    if (queued_networks_to_resolve_.count(network->path()) > 0)
+      networks_to_resolve.push_back(network);
+  }
+  VLOG(1) << "Resolve pending " << networks_to_resolve.size() << " networks.";
+  queued_networks_to_resolve_.clear();
+  ResolveNetworks(networks_to_resolve);
+}
+
 void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) {
   for (NetworkCertMatches::const_iterator it = matches->begin();
        it != matches->end(); ++it) {
@@ -439,6 +483,7 @@ void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) {
                                       it->pkcs11_id,
                                       &shill_properties);
     }
+    network_properties_changed_ = true;
     DBusThreadManager::Get()->GetShillServiceClient()->
         SetProperties(dbus::ObjectPath(it->service_path),
                         shill_properties,
@@ -446,6 +491,19 @@ void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) {
                         base::Bind(&LogError, it->service_path));
     network_state_handler_->RequestUpdateForNetwork(it->service_path);
   }
+  if (queued_networks_to_resolve_.empty())
+    NotifyResolveRequestCompleted();
+  else
+    ResolvePendingNetworks();
+}
+
+void ClientCertResolver::NotifyResolveRequestCompleted() {
+  VLOG(2) << "Notify observers: " << (network_properties_changed_ ? "" : "no ")
+          << "networks changed.";
+  resolve_task_running_ = false;
+  const bool changed = network_properties_changed_;
+  network_properties_changed_ = false;
+  FOR_EACH_OBSERVER(Observer, observers_, ResolveRequestCompleted(changed));
 }
 
 }  // namespace chromeos