1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_INSTALL_SIGNER_H_
6#define CHROME_BROWSER_EXTENSIONS_INSTALL_SIGNER_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/callback.h"
14#include "base/memory/scoped_ptr.h"
15#include "extensions/common/extension.h"
16
17namespace base {
18class DictionaryValue;
19}
20
21namespace net {
22class URLFetcher;
23class URLRequestContextGetter;
24}
25
26namespace extensions {
27
28// This represents a list of ids signed with a private key using an algorithm
29// that includes some salt bytes.
30struct InstallSignature {
31  // The set of ids that have been signed.
32  ExtensionIdSet ids;
33
34  // Both of these are just arrays of bytes, NOT base64-encoded.
35  std::string salt;
36  std::string signature;
37
38  // The date that the signature should expire, in YYYY-MM-DD format.
39  std::string expire_date;
40
41  // The time this signature was obtained from the server. Note that this
42  // is computed locally and *not* signed by the server key.
43  base::Time timestamp;
44
45  // The set of ids that the server indicated were invalid (ie not signed).
46  // Note that this is computed locally and *not* signed by the signature.
47  ExtensionIdSet invalid_ids;
48
49  InstallSignature();
50  ~InstallSignature();
51
52  // Helper methods for serialization to/from a base::DictionaryValue.
53  void ToValue(base::DictionaryValue* value) const;
54
55  static scoped_ptr<InstallSignature> FromValue(
56      const base::DictionaryValue& value);
57};
58
59// Objects of this class encapsulate an operation to get a signature proving
60// that a set of ids are hosted in the webstore.
61class InstallSigner {
62 public:
63  typedef base::Callback<void(scoped_ptr<InstallSignature>)> SignatureCallback;
64
65  // IMPORTANT NOTE: It is possible that only some, but not all, of the entries
66  // in |ids| will be successfully signed by the backend. Callers should always
67  // check the set of ids in the InstallSignature passed to their callback, as
68  // it may contain only a subset of the ids they passed in.
69  InstallSigner(net::URLRequestContextGetter* context_getter,
70                const ExtensionIdSet& ids);
71  ~InstallSigner();
72
73  // Returns a set of ids that are forced to be considered not from webstore,
74  // e.g. by a command line flag used for testing.
75  static ExtensionIdSet GetForcedNotFromWebstore();
76
77  // Begins the process of fetching a signature from the backend. This should
78  // only be called once! If you want to get another signature, make another
79  // instance of this class.
80  void GetSignature(const SignatureCallback& callback);
81
82  // Returns whether the signature in InstallSignature is properly signed with a
83  // known public key.
84  static bool VerifySignature(const InstallSignature& signature);
85
86 private:
87  // A very simple delegate just used to call ourself back when a url fetch is
88  // complete.
89  class FetcherDelegate;
90
91  // A helper function that calls |callback_| with an indication that an error
92  // happened (currently done by passing an empty pointer).
93  void ReportErrorViaCallback();
94
95  // Called when |url_fetcher_| has returned a result to parse the response,
96  // and then call HandleSignatureResult with structured data.
97  void ParseFetchResponse();
98
99  // Handles the result from a backend fetch.
100  void HandleSignatureResult(const std::string& signature,
101                             const std::string& expire_date,
102                             const ExtensionIdSet& invalid_ids);
103
104  // The final callback for when we're done.
105  SignatureCallback callback_;
106
107  // The current set of ids we're trying to verify. This may contain fewer ids
108  // than we started with.
109  ExtensionIdSet ids_;
110
111  // An array of random bytes used as an input to hash with the machine id,
112  // which will need to be persisted in the eventual InstallSignature we get.
113  std::string salt_;
114
115  // These are used to make the call to a backend server for a signature.
116  net::URLRequestContextGetter* context_getter_;
117  scoped_ptr<net::URLFetcher> url_fetcher_;
118  scoped_ptr<FetcherDelegate> delegate_;
119
120  // The time the request to the server was started.
121  base::Time request_start_time_;
122
123  DISALLOW_COPY_AND_ASSIGN(InstallSigner);
124};
125
126}  // namespace extensions
127
128#endif  // CHROME_BROWSER_EXTENSIONS_INSTALL_SIGNER_H_
129