1// Copyright (c) 2012 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_CHROMEOS_DBUS_PROXY_RESOLUTION_SERVICE_PROVIDER_H_
6#define CHROME_BROWSER_CHROMEOS_DBUS_PROXY_RESOLUTION_SERVICE_PROVIDER_H_
7
8#include <string>
9
10#include "base/compiler_specific.h"
11#include "base/memory/ref_counted.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/memory/weak_ptr.h"
14#include "base/synchronization/lock.h"
15#include "base/threading/platform_thread.h"
16#include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
17#include "dbus/exported_object.h"
18
19namespace dbus {
20class MethodCall;
21class Response;
22}
23
24namespace chromeos {
25
26class ProxyResolverInterface;
27
28// This class provides proxy resolution service for CrosDBusService.
29// It processes proxy resolution requests for ChromeOS clients.
30//
31// The following methods are exported.
32//
33// Interface: org.chromium.LibCrosServiceInterface (kLibCrosServiceInterface)
34// Method: ResolveNetworkProxy (kResolveNetworkProxy)
35// Parameters: string:source_url
36//             string:signal_interface
37//             string:signal_name
38//
39//   Resolves the proxy for |source_url|. Returns the result
40//   as a D-Bus signal sent to |signal_interface| and |signal_name|.
41//
42//   The returned signal will contain the three values:
43//   - string:source_url - requested source URL.
44//   - string:proxy_info - proxy info for the source URL in PAC format
45//                         like "PROXY cache.example.com:12345"
46//   - string:error_message - error message. Empty if successful.
47//
48// This service can be manually tested using dbus-monitor and
49// dbus-send. For instance, you can resolve proxy configuration for
50// http://www.gmail.com/ as follows:
51//
52// 1. Open a terminal and run the following:
53//
54//   % dbus-monitor --system interface=org.chromium.TestInterface
55//
56// 2. Open another terminal and run the following:
57//
58//   % dbus-send --system --type=method_call
59//       --dest=org.chromium.LibCrosService
60//       /org/chromium/LibCrosService
61//       org.chromium.LibCrosServiceInterface.ResolveNetworkProxy
62//       string:http://www.gmail.com/
63//       string:org.chromium.TestInterface
64//       string:TestSignal
65//
66// 3. Go back to the original terminal and check the output which should
67// look like:
68//
69// signal sender=:1.23 -> dest=(null destination) serial=12345
70// path=/org/chromium/LibCrosService; interface=org.chromium.TestInterface;
71// member=TestSignal
72//   string "http://www.gmail.com/"
73//   string "PROXY proxy.example.com:8080"
74//   string ""
75//
76
77class ProxyResolutionServiceProvider
78    : public CrosDBusService::ServiceProviderInterface {
79 public:
80  virtual ~ProxyResolutionServiceProvider();
81
82  // CrosDBusService::ServiceProviderInterface override.
83  virtual void Start(
84      scoped_refptr<dbus::ExportedObject> exported_object) OVERRIDE;
85
86  // Creates the instance.
87  static ProxyResolutionServiceProvider* Create();
88
89 private:
90  explicit ProxyResolutionServiceProvider(ProxyResolverInterface *resovler);
91
92  // Creates the instance for testing. Takes the ownership of |resovler|
93  friend class ProxyResolutionServiceProviderTest;
94  static ProxyResolutionServiceProvider* CreateForTesting(
95      ProxyResolverInterface* resolver);
96
97  // Called from ExportedObject, when ResolveProxyHandler() is exported as
98  // a D-Bus method, or failed to be exported.
99  void OnExported(const std::string& interface_name,
100                  const std::string& method_name,
101                  bool success);
102
103  // Callback to be invoked when ChromeOS clients send network proxy
104  // resolution requests to the service running in chrome executable.
105  // Called on UI thread from dbus request.
106  void ResolveProxyHandler(dbus::MethodCall* method_call,
107      dbus::ExportedObject::ResponseSender response_sender);
108
109  // Calls ResolveProxyHandler() if weak_ptr is not NULL. Used to ensure a
110  // safe shutdown.
111  static void CallResolveProxyHandler(
112      base::WeakPtr<ProxyResolutionServiceProvider> weak_ptr,
113      dbus::MethodCall* method_call,
114      dbus::ExportedObject::ResponseSender response_sender);
115
116  // Returns true if the current thread is on the origin thread.
117  bool OnOriginThread();
118
119  scoped_refptr<dbus::ExportedObject> exported_object_;
120  scoped_ptr<ProxyResolverInterface> resolver_;
121  base::PlatformThreadId origin_thread_id_;
122  base::WeakPtrFactory<ProxyResolutionServiceProvider> weak_ptr_factory_;
123
124  DISALLOW_COPY_AND_ASSIGN(ProxyResolutionServiceProvider);
125};
126
127// The interface is defined so we can mock out the proxy resolver
128// implementation.
129class ProxyResolverInterface {
130 public:
131  // Resolves the proxy for the given URL. Returns the result as a
132  // signal sent to |signal_interface| and
133  // |signal_name|. |exported_object| will be used to send the
134  // signal. The signal contains the three string members:
135  //
136  // - source url: the requested source URL.
137  // - proxy info: proxy info for the source URL in PAC format.
138  // - error message: empty if the proxy resolution was successful.
139  virtual void ResolveProxy(
140      const std::string& source_url,
141      const std::string& signal_interface,
142      const std::string& signal_name,
143      scoped_refptr<dbus::ExportedObject> exported_object) = 0;
144
145  virtual ~ProxyResolverInterface();
146};
147
148}  // namespace chromeos
149
150#endif  // CHROME_BROWSER_CHROMEOS_DBUS_PROXY_RESOLUTION_SERVICE_PROVIDER_H_
151