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_RENDERER_EXTENSIONS_OBJECT_BACKED_NATIVE_HANDLER_H_ 6 #define CHROME_RENDERER_EXTENSIONS_OBJECT_BACKED_NATIVE_HANDLER_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/bind.h" 12 #include "base/memory/linked_ptr.h" 13 #include "chrome/renderer/extensions/native_handler.h" 14 #include "chrome/renderer/extensions/scoped_persistent.h" 15 #include "chrome/renderer/extensions/unsafe_persistent.h" 16 #include "v8/include/v8.h" 17 18 namespace extensions { 19 class ChromeV8Context; 20 21 // An ObjectBackedNativeHandler is a factory for JS objects with functions on 22 // them that map to native C++ functions. Subclasses should call RouteFunction() 23 // in their constructor to define functions on the created JS objects. 24 class ObjectBackedNativeHandler : public NativeHandler { 25 public: 26 explicit ObjectBackedNativeHandler(ChromeV8Context* context); 27 virtual ~ObjectBackedNativeHandler(); 28 29 // Create an object with bindings to the native functions defined through 30 // RouteFunction(). 31 virtual v8::Handle<v8::Object> NewInstance() OVERRIDE; 32 33 protected: 34 typedef base::Callback<void(const v8::FunctionCallbackInfo<v8::Value>&)> 35 HandlerFunction; 36 37 // Installs a new 'route' from |name| to |handler_function|. This means that 38 // NewInstance()s of this ObjectBackedNativeHandler will have a property 39 // |name| which will be handled by |handler_function|. 40 void RouteFunction(const std::string& name, 41 const HandlerFunction& handler_function); 42 43 ChromeV8Context* context() const { return context_; } 44 45 virtual void Invalidate() OVERRIDE; 46 47 private: 48 // Callback for RouteFunction which routes the V8 call to the correct 49 // base::Bound callback. 50 static void Router(const v8::FunctionCallbackInfo<v8::Value>& args); 51 52 // When RouteFunction is called we create a v8::Object to hold the data we 53 // need when handling it in Router() - this is the base::Bound function to 54 // route to. 55 // 56 // We need a v8::Object because it's possible for v8 to outlive the 57 // base::Bound function; the lifetime of an ObjectBackedNativeHandler is the 58 // lifetime of webkit's involvement with it, not the life of the v8 context. 59 // A scenario when v8 will outlive us is if a frame holds onto the 60 // contentWindow of an iframe after it's removed. 61 // 62 // So, we use v8::Objects here to hold that data, effectively refcounting 63 // the data. When |this| is destroyed we remove the base::Bound function from 64 // the object to indicate that it shoudn't be called. 65 // 66 // Storing UnsafePersistents is safe here, because the corresponding 67 // Persistent handle is created in RouteFunction(), and it keeps the data 68 // pointed by the UnsafePersistent alive. It's not made weak or disposed, and 69 // nobody else has access to it. The Persistent is then disposed in 70 // Invalidate(). 71 typedef std::vector<UnsafePersistent<v8::Object> > RouterData; 72 RouterData router_data_; 73 74 ChromeV8Context* context_; 75 76 ScopedPersistent<v8::ObjectTemplate> object_template_; 77 78 DISALLOW_COPY_AND_ASSIGN(ObjectBackedNativeHandler); 79 }; 80 81 } // namespace extensions 82 83 #endif // CHROME_RENDERER_EXTENSIONS_OBJECT_BACKED_NATIVE_HANDLER_H_ 84