OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 CONTENT_BROWSER_BROWSER_ASSOCIATED_INTERFACE_H_ |
| 6 #define CONTENT_BROWSER_BROWSER_ASSOCIATED_INTERFACE_H_ |
| 7 |
| 8 #include <memory> |
| 9 #include <string> |
| 10 |
| 11 #include "base/macros.h" |
| 12 #include "base/memory/ref_counted.h" |
| 13 #include "content/common/content_export.h" |
| 14 #include "content/public/browser/browser_message_filter.h" |
| 15 #include "content/public/browser/browser_thread.h" |
| 16 #include "ipc/ipc_channel_proxy.h" |
| 17 #include "mojo/public/cpp/bindings/associated_binding.h" |
| 18 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" |
| 19 |
| 20 namespace content { |
| 21 |
| 22 // A helper interface which owns an associated interface binding on the IO |
| 23 // thread. Subclassess of BrowserMessageFilter may use this to simplify |
| 24 // the transition to Mojo interfaces. |
| 25 // |
| 26 // In general the correct pattern for using this is as follows: |
| 27 // |
| 28 // class FooMessageFilter : public BrowserMessageFilter, |
| 29 // public BrowserAssociatedInterface<mojom::Foo>, |
| 30 // public mojom::Foo { |
| 31 // public: |
| 32 // FooMessageFilter() |
| 33 // : BrowserMessageFilter(FooMsgStart), |
| 34 // BrowserAssociatedInterface<mojom::Foo>(this, this) {} |
| 35 // |
| 36 // // BrowserMessageFilter implementation: |
| 37 // bool OnMessageReceived(const IPC::Message& message) override { |
| 38 // // ... |
| 39 // return true; |
| 40 // } |
| 41 // |
| 42 // // mojom::Foo implementation: |
| 43 // void DoStuff() override { /* ... */ } |
| 44 // }; |
| 45 // |
| 46 // The remote side of an IPC channel can request the |mojom::Foo| associated |
| 47 // interface and use it would use any other associated interface proxy. Messages |
| 48 // received for |mojom::Foo| on the local side of the channel will retain FIFO |
| 49 // with respect to classical IPC messages received via OnMessageReceived(). |
| 50 // |
| 51 // See BrowserAssociatedInterfaceTest.Basic for a simple working example usage. |
| 52 template <typename Interface> |
| 53 class BrowserAssociatedInterface { |
| 54 public: |
| 55 // |filter| and |impl| must live at least as long as this object. |
| 56 BrowserAssociatedInterface(BrowserMessageFilter* filter, Interface* impl) |
| 57 : internal_state_(new InternalState(impl)) { |
| 58 internal_state_->Initialize(); |
| 59 filter->AddAssociatedInterface( |
| 60 Interface::Name_, |
| 61 base::Bind(&InternalState::BindRequest, internal_state_)); |
| 62 } |
| 63 |
| 64 ~BrowserAssociatedInterface() { |
| 65 internal_state_->ShutDown(); |
| 66 } |
| 67 |
| 68 private: |
| 69 class InternalState : public base::RefCountedThreadSafe<InternalState> { |
| 70 public: |
| 71 explicit InternalState(Interface* impl) : impl_(impl) {} |
| 72 |
| 73 void Initialize() { |
| 74 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 75 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 76 base::Bind(&InternalState::Initialize, this)); |
| 77 return; |
| 78 } |
| 79 binding_.reset(new mojo::AssociatedBinding<Interface>(impl_)); |
| 80 } |
| 81 |
| 82 void ShutDown() { |
| 83 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 84 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 85 base::Bind(&InternalState::ShutDown, this)); |
| 86 return; |
| 87 } |
| 88 binding_.reset(); |
| 89 } |
| 90 |
| 91 void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) { |
| 92 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 93 // If this interface has already been shut down or is already bound, we |
| 94 // drop the request. |
| 95 if (!binding_ || binding_->is_bound()) |
| 96 return; |
| 97 |
| 98 binding_->Bind(mojo::MakeAssociatedRequest<Interface>(std::move(handle))); |
| 99 binding_->set_connection_error_handler( |
| 100 base::Bind(&InternalState::ShutDown, base::Unretained(this))); |
| 101 } |
| 102 |
| 103 private: |
| 104 friend class base::RefCountedThreadSafe<InternalState>; |
| 105 |
| 106 ~InternalState() {} |
| 107 |
| 108 Interface* impl_; |
| 109 std::unique_ptr<mojo::AssociatedBinding<Interface>> binding_; |
| 110 |
| 111 DISALLOW_COPY_AND_ASSIGN(InternalState); |
| 112 }; |
| 113 |
| 114 scoped_refptr<InternalState> internal_state_; |
| 115 |
| 116 DISALLOW_COPY_AND_ASSIGN(BrowserAssociatedInterface); |
| 117 }; |
| 118 |
| 119 }; |
| 120 |
| 121 #endif // CONTENT_BROWSER_BROWSER_ASSOCIATED_INTERFACE_H_ |
OLD | NEW |