| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef EXTENSIONS_RENDERER_WAKE_EVENT_PAGE_H_ |
| #define EXTENSIONS_RENDERER_WAKE_EVENT_PAGE_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/synchronization/lock.h" |
| #include "content/public/renderer/render_thread_observer.h" |
| #include "ipc/ipc_sync_message_filter.h" |
| #include "v8/include/v8.h" |
| |
| namespace content { |
| class RenderThread; |
| } |
| |
| namespace extensions { |
| class ScriptContext; |
| |
| // This class implements the wake-event-page JavaScript function, which wakes |
| // an event page and runs a callback when done. |
| // |
| // Note, the function will do a round trip to the browser even if event page is |
| // open. Any optimisation to prevent this must be at the JavaScript level. |
| class WakeEventPage : public content::RenderThreadObserver { |
| public: |
| WakeEventPage(); |
| ~WakeEventPage() override; |
| |
| // Returns the single instance of the WakeEventPage object. |
| // |
| // Thread safe. |
| static WakeEventPage* Get(); |
| |
| // Initializes the WakeEventPage. |
| // |
| // This must be called before any bindings are installed, and must be called |
| // on the render thread. |
| void Init(content::RenderThread* render_thread); |
| |
| // Returns the wake-event-page function bound to a given context. The |
| // function will be cached as a hidden value in the context's global object. |
| // |
| // To mix C++ and JavaScript, example usage might be: |
| // |
| // WakeEventPage::Get().GetForContext(context)(function() { |
| // ... |
| // }); |
| // |
| // Thread safe. |
| v8::Local<v8::Function> GetForContext(ScriptContext* context); |
| |
| private: |
| class WakeEventPageNativeHandler; |
| |
| // The response from an ExtensionHostMsg_WakeEvent call, passed true if the |
| // call was successful, false on failure. |
| using OnResponseCallback = base::Callback<void(bool)>; |
| |
| // Makes an ExtensionHostMsg_WakeEvent request for an extension ID. The |
| // second argument is a callback to run when the request has completed. |
| using MakeRequestCallback = |
| base::Callback<void(const std::string&, const OnResponseCallback&)>; |
| |
| // For |requests_|. |
| struct RequestData { |
| RequestData(int thread_id, const OnResponseCallback& on_response); |
| ~RequestData(); |
| |
| // The thread ID the request was made on. |on_response| must be called on |
| // that thread. |
| int thread_id; |
| |
| // Callback to run when the response to the request arrives. |
| OnResponseCallback on_response; |
| }; |
| |
| // Runs |on_response|, passing it |success|. |
| static void RunOnResponseWithResult(const OnResponseCallback& on_response, |
| bool success); |
| |
| // Sends the ExtensionHostMsg_WakeEvent IPC for |extension_id|, and |
| // updates |requests_| bookkeeping. |
| void MakeRequest(const std::string& extension_id, |
| const OnResponseCallback& on_response); |
| |
| // content::RenderThreadObserver: |
| bool OnControlMessageReceived(const IPC::Message& message) override; |
| |
| // OnControlMessageReceived handlers: |
| void OnWakeEventPageResponse(int request_id, bool success); |
| |
| // IPC sender. Belongs to the render thread, but thread safe. |
| scoped_refptr<IPC::SyncMessageFilter> message_filter_; |
| |
| // All in-flight requests, keyed by request ID. Used on multiple threads, so |
| // must be guarded by |requests_lock_|. |
| std::unordered_map<int, std::unique_ptr<RequestData>> requests_; |
| |
| // Lock for |requests_|. |
| base::Lock requests_lock_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WakeEventPage); |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_RENDERER_WAKE_EVENT_PAGE_H_ |