1// Copyright 2014 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 EXTENSIONS_RENDERER_REQUEST_SENDER_H_
6#define EXTENSIONS_RENDERER_REQUEST_SENDER_H_
7
8#include <map>
9#include <string>
10
11#include "base/memory/linked_ptr.h"
12#include "v8/include/v8.h"
13
14namespace base {
15class ListValue;
16}
17
18namespace extensions {
19class Dispatcher;
20class ScriptContext;
21
22struct PendingRequest;
23
24// Responsible for sending requests for named extension API functions to the
25// extension host and routing the responses back to the caller.
26class RequestSender {
27 public:
28  // Source represents a user of RequestSender. Every request is associated with
29  // a Source object, which will be notified when the corresponding response
30  // arrives. When a Source object is going away and there are pending requests,
31  // it should call InvalidateSource() to make sure no notifications are sent to
32  // it later.
33  class Source {
34   public:
35    virtual ~Source() {}
36
37    virtual ScriptContext* GetContext() = 0;
38    virtual void OnResponseReceived(const std::string& name,
39                                    int request_id,
40                                    bool success,
41                                    const base::ListValue& response,
42                                    const std::string& error) = 0;
43  };
44
45  // Helper class to (re)set the |source_tab_id_| below.
46  class ScopedTabID {
47   public:
48    ScopedTabID(RequestSender* request_sender, int tab_id);
49    ~ScopedTabID();
50
51   private:
52    RequestSender* const request_sender_;
53    const int tab_id_;
54    const int previous_tab_id_;
55
56    DISALLOW_COPY_AND_ASSIGN(ScopedTabID);
57  };
58
59  explicit RequestSender(Dispatcher* dispatcher);
60  ~RequestSender();
61
62  // In order to avoid collision, all |request_id|s passed into StartRequest()
63  // should be generated by this method.
64  int GetNextRequestId() const;
65
66  // Makes a call to the API function |name| that is to be handled by the
67  // extension host. The response to this request will be received in
68  // HandleResponse().
69  // TODO(koz): Remove |request_id| and generate that internally.
70  //            There are multiple of these per render view though, so we'll
71  //            need to vend the IDs centrally.
72  void StartRequest(Source* source,
73                    const std::string& name,
74                    int request_id,
75                    bool has_callback,
76                    bool for_io_thread,
77                    base::ListValue* value_args);
78
79  // Handles responses from the extension host to calls made by StartRequest().
80  void HandleResponse(int request_id,
81                      bool success,
82                      const base::ListValue& response,
83                      const std::string& error);
84
85  // Notifies this that a request source is no longer valid.
86  // TODO(kalman): Do this in a generic/safe way.
87  void InvalidateSource(Source* source);
88
89 private:
90  friend class ScopedTabID;
91  typedef std::map<int, linked_ptr<PendingRequest> > PendingRequestMap;
92
93  void InsertRequest(int request_id, PendingRequest* pending_request);
94  linked_ptr<PendingRequest> RemoveRequest(int request_id);
95
96  Dispatcher* dispatcher_;
97  PendingRequestMap pending_requests_;
98
99  int source_tab_id_;  // Id of the tab sending the request, or -1 if no tab.
100
101  DISALLOW_COPY_AND_ASSIGN(RequestSender);
102};
103
104}  // namespace extensions
105
106#endif  // EXTENSIONS_RENDERER_REQUEST_SENDER_H_
107