15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#ifndef COMPONENTS_CAPTIVE_PORTAL_CAPTIVE_PORTAL_DETECTOR_H_
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#define COMPONENTS_CAPTIVE_PORTAL_CAPTIVE_PORTAL_DETECTOR_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/captive_portal/captive_portal_export.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/captive_portal/captive_portal_types.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GURL;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace captive_portal {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass CAPTIVE_PORTAL_EXPORT CaptivePortalDetector
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : public net::URLFetcherDelegate,
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      public base::NonThreadSafe {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Results {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Results()
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        : result(captive_portal::RESULT_NO_RESPONSE),
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          response_code(net::URLFetcher::RESPONSE_CODE_INVALID) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    captive_portal::CaptivePortalResult result;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int response_code;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta retry_after_delta;
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    GURL landing_url;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::Callback<void(const Results& results)> DetectionCallback;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The test URL.  When connected to the Internet, it should return a
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // blank page with a 204 status code.  When behind a captive portal,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requests for this URL should get an HTTP redirect or a login
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // page.  When neither is true, no server should respond to requests
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for this URL.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kDefaultURL[];
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit CaptivePortalDetector(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<net::URLRequestContextGetter>& request_context);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CaptivePortalDetector();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Triggers a check for a captive portal. After completion, runs the
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |callback|.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DetectCaptivePortal(const GURL& url, const DetectionCallback& callback);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels captive portal check.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class CaptivePortalDetectorTestBase;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // net::URLFetcherDelegate:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes a net::URLFetcher that has finished trying to retrieve the
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test URL, and fills a Results struct based on its result.  If the
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response is a 503 with a Retry-After header, |retry_after| field
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of |results| is populated accordingly.  Otherwise, it's set to
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base::TimeDelta().
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetCaptivePortalResultFromResponse(const net::URLFetcher* url_fetcher,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Results* results) const;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current time. Used only when determining time until a
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retry-After date.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time GetCurrentTime() const;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if a captive portal check is currently running.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool FetchingURL() const;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets current test time. Used by unit tests.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_time_for_testing(const base::Time& time) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    time_for_testing_ = time;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advances current test time. Used by unit tests.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void advance_time_for_testing(const base::TimeDelta& delta) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    time_for_testing_ += delta;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URL request context.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> request_context_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DetectionCallback detection_callback_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::URLFetcher> url_fetcher_;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test time used by unit tests.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time time_for_testing_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CaptivePortalDetector);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace captive_portal
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif  // COMPONENTS_CAPTIVE_PORTAL_CAPTIVE_PORTAL_DETECTOR_H_
108