wiki:WebKitGTK/AddingNewWebKit2API
Last modified 16 months ago Last modified on 03/21/13 12:25:28

Adding new API to WebKit2 GTK+

  • Patches including new public API should be approved by at least two GTK+ reviewers
  • Patches should include API documentation for new methods, properties, signals, etc.
  • Patches should always include unit tests for new API when possible
  • If the patch adds a new public header
  • Follow coding style guidelines
    • Use GNOME coding style for public headers and generated code (get_type(), init() and class_init() methods)
    • Use WebKit coding style for all other code, including unit tests, See http://www.webkit.org/coding/coding-style.html
    • You can use check-webkit-style script to make sure your patch follows the WebKit coding style
  • Use WEBKIT_DEFINE_ macros instead of G_DEFINE_ ones. There some small differences:
    • The private struct is allocated by the macro using the placement new syntax, so you can use smart pointers in the private struct.
    • You only need to define a class_init method but not init() nor finalize().
    • Don't call g_type_class_add_private() in class_init() since it's already done by the macro.
    • If you need to add some initialization for instances, override GObjectClass::constructor() or use the private struct constructor
      struct _WebKitSettingsPrivate {
          _WebKitSettingsPrivate()
              : preferences(WebPreferences::create())
          {
              defaultFontFamily = preferences->standardFontFamily().utf8();
              monospaceFontFamily = preferences->fixedFontFamily().utf8();
              serifFontFamily = preferences->serifFontFamily().utf8();
              sansSerifFontFamily = preferences->sansSerifFontFamily().utf8();
              cursiveFontFamily = preferences->cursiveFontFamily().utf8();
              fantasyFontFamily = preferences->fantasyFontFamily().utf8();
              pictographFontFamily = preferences->pictographFontFamily().utf8();
              defaultCharset = preferences->defaultTextEncodingName().utf8();
          }
      
          RefPtr<WebPreferences> preferences;
          CString defaultFontFamily;
          CString monospaceFontFamily;
          CString serifFontFamily;
          CString sansSerifFontFamily;
          CString cursiveFontFamily;
          CString fantasyFontFamily;
          CString pictographFontFamily;
          CString defaultCharset;
          CString userAgent;
          bool allowModalDialogs;
          bool zoomTextOnly;
      };
      
    • The same way, if you need to add destruction code, you can override GObjectClass::dispose() or use the private struct destructor. Note that dispose can be called multiple times, so if you want to make sure the destruction code is only called once, use the private struct destructor.
      struct _WebKitCookieManagerPrivate {
          ~_WebKitCookieManagerPrivate()
          {
              webCookieManager->stopObservingCookieChanges();
          }
      
          RefPtr<WebCookieManagerProxy> webCookieManager;
      };
      
  • Use wtf classes (CString, HashMap, etc.) and GRefPtr/GOwnPtr for attributes so that they are automatically freed by the private structure destructor
  • Don't make private structures public in Private.h headers, keep them in the corresponding .cpp file and add private API for accessing them when needed.
  • Add always public get/set methods even for attributes that are GObject properties
  • Protect arguments of public methods using g_return_if_fail() and g_return_val_if_fail() macros
    • For private methods use ASSERT or g_assert() instead, but only when it's really needed
  • Protect public headers so that they can't be included directly in client code, adding the following code at the top of the file (after the license text):
    #if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
    #error "Only <webkit2/webkit2.h> can be included directly."
    #endif
    
    #ifndef WebKitFoo_h
    #define WebKitFoo_h
    .......
    
  • Don't use the C API except for the C client callbacks
    • Use toImpl() to pass C API pointers to other methods from the client callbacks
    • Use toAPI() to pass objects back to C client callbacks
      static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef, WKDictionaryRef wkWindowFeatures, WKEventModifiers, WKEventMouseButton, const void* clientInfo)
      {
          return static_cast<WKPageRef>(toAPI(webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(clientInfo), toImpl(wkWindowFeatures))));
      }
      
  • Don't expose the C API in public API or headers
  • Including other headers:
    • Use always the angle-bracket form of #include directive in public headers
    • In private headers or .cpp files
      • Use the angle-bracket form for header files from other libraries, including WebCore, JavaScriptCore or the WebKit2 C API
      • Use the quoted form for header files of WebKit2