Watch the Internet Explorer registry keys so we can detect proxy settings changes faster.

Previously we would poll on a background thread every 5 seconds (triggered by network activity) to check for changes. This meant there was a 5 second window during which new requests might still be using the old settings.

With this CL, the settings are noticed almost immediately and the continuous polling is de-emphasized.

(We still poll, but less often. This is a precaution since we are relying on implementation details of a winhttp function, and can't be sure it won't change in the future, or is even completely accurate right now).

BUG=52120
TEST=Open chrome://net-internals/#requests. Request some webpage. Now make changes to the Internet explorer proxy settinsg. You should see a PROXY_CONFIG_CHANGED event emitted immediately after saving each change in the dialog box.

Review URL: http://codereview.chromium.org/3161016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56305 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/proxy/polling_proxy_config_service.cc b/net/proxy/polling_proxy_config_service.cc
index ac42d9c0..2db97929 100644
--- a/net/proxy/polling_proxy_config_service.cc
+++ b/net/proxy/polling_proxy_config_service.cc
@@ -22,10 +22,11 @@
   Core(base::TimeDelta poll_interval,
        GetConfigFunction get_config_func)
       : get_config_func_(get_config_func),
+        poll_interval_(poll_interval),
+        have_initialized_origin_loop_(false),
         has_config_(false),
         poll_task_outstanding_(false),
-        poll_interval_(poll_interval),
-        have_initialized_origin_loop_(false) {
+        poll_task_queued_(false) {
   }
 
   // Called when the parent PollingProxyConfigService is destroyed
@@ -66,22 +67,33 @@
     LazyInitializeOriginLoop();
     DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
 
-    if (poll_task_outstanding_)
-      return;  // Still waiting for earlier test to finish.
-
-    base::TimeTicks now = base::TimeTicks::Now();
-
     if (last_poll_time_.is_null() ||
-        (now - last_poll_time_) > poll_interval_) {
-      last_poll_time_ = now;
-      poll_task_outstanding_ = true;
-      WorkerPool::PostTask(
-          FROM_HERE,
-          NewRunnableMethod(
-              this, &Core::PollOnWorkerThread, get_config_func_), true);
+        (base::TimeTicks::Now() - last_poll_time_) > poll_interval_) {
+      CheckForChangesNow();
     }
   }
 
+  void CheckForChangesNow() {
+    LazyInitializeOriginLoop();
+    DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
+
+    if (poll_task_outstanding_) {
+      // Only allow one task to be outstanding at a time. If we get a poll
+      // request while we are busy, we will defer it until the current poll
+      // completes.
+      poll_task_queued_ = true;
+      return;
+    }
+
+    last_poll_time_ = base::TimeTicks::Now();
+    poll_task_outstanding_ = true;
+    poll_task_queued_ = false;
+    WorkerPool::PostTask(
+        FROM_HERE,
+        NewRunnableMethod(
+            this, &Core::PollOnWorkerThread, get_config_func_), true);
+  }
+
  private:
   void PollOnWorkerThread(GetConfigFunction func) {
     ProxyConfig config;
@@ -111,6 +123,9 @@
       last_config_ = config;
       FOR_EACH_OBSERVER(Observer, observers_, OnProxyConfigChanged(config));
     }
+
+    if (poll_task_queued_)
+      CheckForChangesNow();
   }
 
   void LazyInitializeOriginLoop() {
@@ -126,15 +141,17 @@
 
   GetConfigFunction get_config_func_;
   ObserverList<Observer> observers_;
-  bool has_config_;
-  bool poll_task_outstanding_;
   ProxyConfig last_config_;
   base::TimeTicks last_poll_time_;
   base::TimeDelta poll_interval_;
-  bool have_initialized_origin_loop_;
 
   Lock lock_;
   scoped_refptr<base::MessageLoopProxy> origin_loop_proxy_;
+
+  bool have_initialized_origin_loop_;
+  bool has_config_;
+  bool poll_task_outstanding_;
+  bool poll_task_queued_;
 };
 
 PollingProxyConfigService::PollingProxyConfigService(
@@ -163,4 +180,8 @@
   core_->OnLazyPoll();
 }
 
+void PollingProxyConfigService::CheckForChangesNow() {
+  core_->CheckForChangesNow();
+}
+
 }  // namespace net