1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef COMPONENTS_RAPPOR_LOG_UPLOADER_H_
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define COMPONENTS_RAPPOR_LOG_UPLOADER_H_
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <queue>
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <string>
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/compiler_specific.h"
12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/macros.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/time/time.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/timer/timer.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/gurl.h"
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace net {
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class URLFetcher;
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace rappor {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Uploads logs from RapporService.  Logs are passed in via QueueLog(), stored
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// internally, and uploaded one at a time.  A queued log will be uploaded at a
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// fixed interval after the successful upload of the previous logs.  If an
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// upload fails, the uploader will keep retrying the upload with an exponential
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// backoff interval.
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class LogUploader : public net::URLFetcherDelegate {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Constructor takes the |server_url| that logs should be uploaded to, the
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // |mime_type| of the uploaded data, and |request_context| to create uploads
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // with.
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  LogUploader(const GURL& server_url,
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              const std::string& mime_type,
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              net::URLRequestContextGetter* request_context);
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // If the object is destroyed (or the program terminates) while logs are
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // queued, the logs are lost.
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~LogUploader();
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Adds an entry to the queue of logs to be uploaded to the server.  The
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // uploader makes no assumptions about the format of |log| and simply sends
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // it verbatim to the server.
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void QueueLog(const std::string& log);
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected:
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Checks if an upload has been scheduled.
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool IsUploadScheduled() const;
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Schedules a future call to StartScheduledUpload if one isn't already
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // pending.  Can be overridden for testing.
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void ScheduleNextUpload(base::TimeDelta interval);
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Starts transmission of the next log. Exposed for tests.
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void StartScheduledUpload();
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Increases the upload interval each time it's called, to handle the case
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // where the server is having issues. Exposed for tests.
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static base::TimeDelta BackOffUploadInterval(base::TimeDelta);
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Implements net::URLFetcherDelegate. Called after transmission completes
66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // (whether successful or not).
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Called when the upload is completed.
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnUploadFinished(bool server_is_healthy, bool more_logs_remaining);
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The server URL to upload logs to.
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const GURL server_url_;
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The mime type to specify on uploaded logs.
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const std::string mime_type_;
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The request context used to send uploads.
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> request_context_;
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The outstanding transmission that appears as a URL Fetch operation.
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<net::URLFetcher> current_fetch_;
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The logs that still need to be uploaded.
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::queue<std::string> queued_logs_;
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // A timer used to delay before attempting another upload.
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::OneShotTimer<LogUploader> upload_timer_;
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Indicates that the last triggered upload hasn't resolved yet.
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool has_callback_pending_;
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The interval to wait after an upload's URLFetcher completion before
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // starting the next upload attempt.
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::TimeDelta upload_interval_;
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LogUploader);
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace rappor
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // COMPONENTS_RAPPOR_LOG_UPLOADER_H_
103