Berkelium

Patrick Horn

Over the past three months, we’ve been working on a new BSD-licensed browser engine called Berkelium. Berkelium is a library that provides off-screen browser rendering via Google’s open source Chromium and takes advantage of Chromium’s multi-process rendering engine, allowing us to safely isolate browser instances.  Best of all, it is independent of Sirikata—you can incorporate it into any project to get a simple, easy to use API for off-screen web browsers.  We’ve started using it in Sirikata to allow arbitrary 3d objects to contain browsers, and in the future, objects may be able to run a user interfaces and even entire object scripts within the sandbox of a browser window.

Berkelium should support plugins, but currently that support is limited to Flash (on all platforms). Hopefully many needs will be addressed by new features in HTML5. For those that aren’t, we believe Flash is able to fill the gap. (For the curious with some spare time, it may be possible to use a hooked HDC on Windows, and to use the X11 Composite extension to render plugins to OpenGL on Linux. However, we suspect enabling arbitrary plugins and programs in this way would take a good month of work to get right.)

And, of course, we wouldn’t leave you without a demo of the browser in action in Sirikata:


60 Responses to “Berkelium”

  • Neil Canham Says:

    Congratulations and thanks for releasing this. I look forward to trying it, I have many potential uses for server-side and in-memory browser rendering. I'm intrigued though – I thought I saw a few Sirikata mailing list comments about Awesomium – does Berkelium fill the same role as Awesomium? What differences are there? They look to cover the same ground using the same unerlying engine.

    • Ewen CheslackPostava Says:

      Neil – They do fill a very similar need. Berkelium uses a layer of Chromium built on top of WebKit instead of using some of the WebKit code directly. There are a couple of benefits to this. The two primary ones are that, first, the API for this layer is much more stable than the one that Awesomium uses, which makes it much less of a hassle to track the main Chromium tree, and second, that by using this layer we get the multiprocess rendering almost for free, which is great for isolating pages from each other from both a security and performance point of view.

      So from a technical perspective they are different solutions to the same problem with different tradeoffs. Beyond that, we also prefer libraries that are developed in the open and that are easier for us to participate in the development of. While Awesomium has a similar feature list, and in fact has quite a few features Berkelium doesn't, it didn't feel like quite the right fit for our project. Just like in the browser space, we think its worthwhile exploring a number of different avenues of development before settling on a long term solution.

  • Neil Canham Says:

    OK, thanks for that – a very comprehensive and comprehendable reply. Do you know if anyone right now is likely to be working on any C# bindings for Berkelium? I appreciate that it isn't quite that kind of component yet, being open source with no binary distribution, but I thought I'd ask anyway :-)

    • Ewen CheslackPostava Says:

      Neil – I don't think anybody is currently working on bindings, but the API is currently pretty thin (see the small set of files in the berkelium/include/ directory) so I think it would be pretty easy to get a binding up and running.

    • Kevin Gadd Says:

      I hacked together a C++/CLI wrapper for Berkelium along with a simple example in C# that implements a mostly working browser.

      You can check out the source at http://code.google.com/p/berkelium-sharp/ if you're interested. It seems pretty likely that this could be taken all the way for fully functional embedding.

      • benjoTLV Says:

        Very cool! I am still evaluating if to go and invest time in Berkelium (I need a WPF based webkit component) and this layer is definitely a good thing for me. Thanks.
        Do you happen to have a simple demo exe that includes the necessary dlls I could test? I would rather test that before going to build chromium and berkelium… Thanks a bunch!

  • Thinking in the overlap | Sirikata Says:

    […] have been pretty excited about our embedded browser Berkelium and it was good to see Patrick pull the trigger on it. Within our group there is an emerging sense that this technology is going to mean something and I […]

  • Ronen Says:

    Is there a binary distribution available? Or are there any plans to make one available? Building Chromium is a pain and if one can avoid it, it is a blessing…

  • benjoTLV Says:

    Hi,
    It seems pretty nice!
    I am currently using Awesomium 1.08 (the latest open source version…) and I have few problems with it, especially one: Clicking on Flash files only works if the action is handled by the flash itself (like clicking on "play" in youtube). If the click is supposed to trigger a browser event (navigate to URL) then click on Flash does not work…

    Can you tell me if this is also the case with Berkelium? Do you have any demo app I can install in order to try by myself (I would like to avoid compiling, building a demo app and so on at this stage!)
    Last, same question as above… any binaries available?

    Thanks!

  • This Week in OpenSim Dev - week ending Saturday 2nd January 2010 | justincc.org Says:

    […] client stack.  This would allow a Sirikata viewer, such as one based upon their new browser engine Berkelium, to connect with […]

  • Daniel Says:

    Hi benjo
    Sorry for the delayed response, but you can see Berkelium in action through our nightly builds and downloading an empty scene file with just a camera
    I've done so here
    http://graphics.stanford.edu/~danielrh/SirikataBe
    download, unzip and use the + on the browser bar to make a new window… It doesn't show the window in 3d yet, but it does reside on a texture so we could just as easily translate it around… making a more flashy prebuilt demo like the one you saw the video of for windows is not on the radar right now, but you can download the source and build it if you wish. Otherwise this should let you know if the feature you need is supported yet
    -Daniel

    • simos Says:

      Hi Daniel and thank you and your team for great Berkelium :)

      I tried SirikataBerkelium demo. First i tried to run proximite.exe and then space.exe and after that i runned cppoh.exe. Sirikata window opened but i got only blue screen with grey box. Grey box is where the Chromium addressbar should be. If i click this grey area the demo crashes. Do you have any clues where the problem could be? Am I doing all the reguired steps to start the demo?

      • Daniel Says:

        Your steps sound right… What a gray box means is that berkelium loaded but when it tried to spawn the browser subprocesses something wrong happened–maybe the subprocesses didn't have the right resources available or maybe there were windows permission problems.
        Generally when that fails so, too, does double clicking berkelium.exe, which should launch a full-featured chrome browser.
        What happens when you double click berkelium.exe? Also maybe sending your console output during the run would be helpful– the blue screen is expected since no objects were in the test scene I zipped

      • Patrick Horn Says:

        For Berkelium to work in Windows Vista and Windows 7, you need an extra wrapper program for the sandbox to work. I don't think our install script installs this yet.

        You can download it directly from the chromium source tree here:
        http://src.chromium.org/svn/trunk/src/sandbox/wow

        Then, put it into the same binary directory as berkelium.exe and all the dlls.

  • Daniel Says:

    Ronen: yes there is a binary Berkelium SDK for windows that lets you avoid building the whole thing yourself
    http://sirikatawin32.googlecode.com/svn/trunk/ber

    the other platforms have automated build scripts that come with the berkelium source, so you just hit make and it does the rest (downloading, etc)

  • benjoTLV Says:

    Thanks for the reply and links!
    One more question though (even if it might sound like a newbie one:-)!):
    Awesomium is 8Mb (unzipped) and I needed as well icudt38.dll which was another 8Mb so all together I have an overhead of 16Mb in my app. I see that the SDK is 56.5Mb! So my question is what is the minimum overhead I can get to have a functional browser? do I need the all 56Mb in release?

    Thanks

    • Daniel Says:

      Awesomium avoids the chrome layer and merely routes around it, using only the webkit internals (which is why it was so difficult to keep it up to date with the bug and security fixes of chrome). We need a fully functioning chrome browser so that you can execute the new process in berkelium.exe
      Note that if you double click berkelium.exe you get a full featured chrome browser: this is necessary to have the multiprocess work and bring with it all the safety and futureproofing that multiprocess gets you. You probablby can strip down the .pak files somewhat, and only include english locales, etc depending on your target audience. Let me know how far you get in your experimentation with stripping down the .pak files. Also however the chrome team packs up chrome we can probably do the same thing for berkelium since we include a virtually unmodified browser in the berkelium.exe dll–and I think they've gotten it way down below 56 megabytes–so maybe the place to go is investigation of the chrome setup/install tools

      • benjoTLV Says:

        Thank you Daniel for the explaination. I will play with it as you suggested.
        As you pointed out, it is really great to have a full embed-able browser already… I'll worry about the size later! :-)

  • Ronen Says:

    Thank you Daniel! This is great. Any thoughts about getting Silverlight to work in addition to Flash?

  • Daniel Says:

    I played with silverlight a bit–it does not apparently respect the ordering constraints that you can ask Flash to respect— by asking Flash to remain in the proper ordering with the rest of the webpage it coordinates well with Chrome and delivers a buffer past the interprocess mark that's got all the correct pixels for the webpage+flash.
    Apparently silverlight ignores this ordering request and hence expects berkelium to hand it a hWnd and then composite it manually into a memory buffer after the interprocess layer. I'm not exactly sure how to get this offscreen hWnd in windows, being primarily a linux dev. If someone has the wherewithal to help with silverlight and java plugins, I'm sure it's possible to get it working, but it will need some windows dev smarts.

  • James Says:

    Looks great! Can't wait to dig into the further. The demo still leaves me with a question though, does berkelium support transparency?

  • Ewen CheslackPostava Says:

    It supports transparency in the sense that you can munge the data before passing it to your rendering pipeline. For instance, you could easily filter a special color, marking the alpha channel as 0 for those pixels. I'm not sure about not fully opaque output directly from Berkelium, but that's more a matter of whether Chromium supports transparency rather than Berkelium. If you're curious about the equivalent of transparency in Awesomium, that was accomplished by filtering a special color, which isn't built into Berkelium but is trivial to implement.

    • Daniel Says:

      I do believe there is an option per window to turn on full fledged translucency for that window (certain webpages look really bad with transparency but we can use it for drag and drop/other things)
      I remember I had a javascript test webpage up that was transparent.
      In fact that's one of our small patches to chrome to fix their white-padded RGB channel to actually have transparency if you wanted it.

  • jusas Says:

    I've been playing around with the source for a while now and I finally got it to compile *almost* properly (in Windows). Release build works fine, I've only tested the ppmrender example but it worked just fine. Unfortunately debug builds are a real pain in the arse.
    The first brick wall I hit was the annoying DCHECK macros in Chromium debug build. This could be solved by redefining the macros to actually work like they do in Release builds (shows an error dialog but then continues execution). After this little tweak and recompilation of Chromium source the Berkelium subprocess now runs. Unfortunately another problem surfaced straight away, the ppmrender example crashes straight away after Berkelium::Window::create() when we actually try to do something with the window. I'm not entirely sure where to put my finger on that one but the error being an access violation without a sensible call stack I'm guessing it might have something to do with memory allocation, after all Chromium uses tcmalloc itself and ppmrender probably (?) does not and in the end links to the default libcmt, causing problems. The strange thing is that Release build works just fine but Debug does not! I'm not quite sure how to deal with it, I've tried fiddling with /NODEFAULTLIB with no success.

    Has anyone else run into these problems? Perhaps I'm just dumb in this department and the solution is obvious, if that is the case then please educate me ;)

    I love the library, it has a nice minimal interface with full Chrome awesomeness but the whole build process is unfortunately quite painful…

  • Daniel Says:

    We ran into the same problems, and never resolved them. However you'll note that in visual studio the release builds work fine with a debug app since the API consists of C-like calls (const char *'s and integers rather than std::strings)

    so feel free to link against the release builds. If you get any crashes cus of it let us know, but we've tested our very huge app against berkelium in Debug and Release, both linking against a Berkelium Release and it worked snappy

  • jusas Says:

    Ah, good to know :) I never even thought about mixing debug and release since it's usually such a no-no. Thanks for the tip Daniel! :)

  • jusas Says:

    Ugh, unfortunately it does not seem as easy as it first sounded. Simply linking to the release version of Berkelium in the ppmrender debug build doesn't work, it produces the same problem as before.

    Exacly what settings do you have to successfully build and run ppmrender_d.exe linked against release Berkelium?

    • jusas Says:

      The strange thing is that when I enable optimizations /O2 the build works (except that I can't obviously debug it anymore) and when optimizations are disabled ppmrender crashes. :(

    • jusas Says:

      Replying to my own post: I think I've found the source of the problems with the ppmrender debug build:
      The WindowImpl constructor in Berkelium

      Like I explained the error gets traced into Window::create() which leads to the WindowImpl constructor, this code:

      WindowImpl::WindowImpl(const Context*otherContext):
      Window(otherContext),
      mController(this, profile())
      {

      }

      This I changed to:

      WindowImpl::WindowImpl(const Context*otherContext)
      {
      mContext = (otherContext->clone());
      mController = new NavigationController(this, profile()); // mController changed to a pointer

      }

      The compiler reports a warning from the first code snippet and for a reason: this is where it ultimately crashes. Now, changing mController from NavigationController to a pointer and then creating it with _new_ (did this because it was easier than changing the constructor code and/or creating a copy constructor) _inside the constructor body_ ultimately solved the crash problem.

      I also built a wrapper to completely isolate the DLL to work on its own, loaded with LoadLibrary on demand with a pure virtual interface, not sure if that had something to do with the end result. However the isolated DLL crashed just like in my previous attempts until I found the culprit in WindowImpl and fixed it.

  • Patrick Horn Says:

    Thanks, I've pushed the fix to master. I'm worried that this was not the source of the crash (perhaps it was nondeterministic or related to the act of rebuilding), but nonetheless, using 'this' in an argument list is very shaky ground, since one small mistake in one of the dependent classes can cause a bug like this.

  • Ronen Says:

    I have been playing with it for the last couple of weeks and have been very impressed from Berkelium's stability over Awesomium which kept crashing for me every once in a while. The one issue I came across to date is the inability to correctly render pages from crackle.com. The flash video does not show while I do hear the audio. This does not happen when I run berkelium.exe, just the demo. Any idea?

    • Patrick Horn Says:

      The reason is that we add a parameter called wmode="transparent" onto flash videos in order to tell them to render directly into the browser window, unless the website already set a wmode parameter.

      Without wmode="transparent", the plugin doesn't render onto the browser's canvas and instead goes into a child window that in normal browsers gets positioned in exactly the right place. In our case, that isn't possible since the browser isn't necessarily on-screen. On Linux, we popup the plugin as a separate window–on Windows, this is taken care of by the renderer process, so the plugin just doesn't render (a hidden HWND).

      It seems that crackle.com seems to explicitly specify wmode="window", which puts us in a hard position. Do we ignore the webmaster's explicit request to make the Flash plugin windowed, or do we not display the plugin?

      We have a patch to chromium sources at patches/chromium_wmode_opaque.patch
      The file it changes is "chrome/renderer/webplugin_delegate_proxy.cc" inside chromium/src. If you want to experiment, you could go to line 268 in that file, in the for loop, and add:
      arg_values[i] = "transparent"
      so as to always override the webmaster's default (I think "opaque" should work too.)

      • Ronen Says:

        Thanks. I would love to experiment but have not yet figured how to build Chromium on Windows. If by any chance you can somehow provide a binary with this patch, I would love to test it.

        Thanks again for the detailed explanation!

  • Neil Canham Says:

    Thinking about trying to build Berkelium on a linux vps, but wondering how much disk space you need during the build? ONe comment on the sirikata wiki about building Awesomium says you need 10s of Gb to build Chrome?

  • Ewen CheslackPostava Says:

    Neil – A fairly recent build on my computer shows about 3.4 GB used. Not sure where the 10s of GB figure is coming from, maybe from Windows or maybe we're not checking out and building everything in Chromium anymore (e.g. omitting tests).

    One current caveat is that we aren't doing an install-style step on Chromium, so it just lives in the directory it was built in, meaning that currently none of the space is recovered after you're finished building.

  • Neil Canham Says:

    OK, well that isn't too bad so maybe I'll give it a go – thanks.

  • Ronen Says:

    Just came across a crash in berkelium.dll on the page http://www.nfl.com/videos/nfl-game-highlights/090… This happen consistently when playing the ad before the video (ad says "welcome to the now network, 3 skiers are…" then crash), when the ad does not come up and the actual video plays the crash does not occur so reproducing it might not be trivial. When running berkelium.exe as standalone app the crash does not occur either.

    • Ronen Says:

      Sorry that was a false alarm, please ignore.

    • Ronen Says:

      In fact it is crashing when injecting a click due to the fact that clicking on an ad pops up a window and when that happens berkelium crashes. I think I saw somewhere that this is a known issue. Is there any way to silently ignore these windows and avoid a crash?

      • jusas Says:

        I had the same problem and it was pretty trivial to fix.

        The place to look at is in WindowImpl.hpp and cpp. You'll notice there are two overloads of CreateNewWindow(…). The other is not really implemented (it's merely a {} in the header). That's the problem. Whenever a new window is created, 1. CreateNewWindow() is called and it is followed by 2. ShowCreatedWindow(). In this case what happens is that the CreateNewWindow() that hasn't been implemented, is being called before ShowCreatedWindow() and since the method did not create a new window ShowCreatedWindow() has no new window to work with, which is why it crashes. To solve this, simply copy the CreateNewWindow implementation to the unimplemented method.

        I have no idea why the other CreateNewWindow() wasn't implemented in the first place. The funny thing is that the implemented one never even seems to get called.

  • Ronen Says:

    Just came across a crash in berkelium.dll on the page http://www.nfl.com/videos/nfl-game-highlights/090… This happen consistently when playing the ad before the video (ad says "welcome to the now network, 3 skiers are…" then crash), when the ad does not come up and the actual video plays the crash does not occur so reproducing it might not be trivial. When running berkelium.exe as standalone app the crash does not occur either.

  • A managed WebKit library: BerkeliumSharp « luminance Says:

    […] spent the past day or so hacking together a managed wrapper for Sirikata’s Berkelium library. Berkelium allows you to easily embed a WebKit-based browser into games and other applications. […]

  • Simie Says:

    Have you encountered this error on Mac OS X before?
    "LaunchApp: execvp(./berkelium) failed: Permission denied"

    It has me very confused right now. Any ideas how to fix it? The crash occurs in the demo apps too.

    (This is snow leopard)

  • Ric Says:

    Tired compiling the glut demo using the win32 sdk (http://sirikatawin32.googlecode.com/svn/trunk/). I just get a black box.

  • Gogg Says:

    Hi, I'm trying berkelium but I can't get it to call the onPaint event, this is what I'm doing:

    class HtmlDelegate : public Berkelium::WindowDelegate {
    void onPaint(Berkelium::Window *wini,
    const unsigned char *bitmap_in, const Berkelium::Rect &bitmap_rect,
    size_t num_copy_rects, const Berkelium::Rect *copy_rects,
    int dx, int dy, const Berkelium::Rect &scroll_rect) {
    cout << endl << endl << "——–PAINT————" << endl << endl << endl;
    }
    };

    Berkelium::init(Berkelium::FileString::empty());
    html_context = Berkelium::Context::create();
    html_window = Berkelium::Window::create(html_context);
    delete html_context;
    html_window->resize(512, 512);
    html_window->setDelegate( new HtmlDelegate() );
    html_window->setTransparent(true);
    html_window->focus();
    std::string url = "http://www.google.com&quot;;
    html_window->navigateTo(url.data(), url.length());

    And then in my main loop I call:

    Berkelium::update();

    …every frame. Am I missing something, or is there any way to get more information of what's going on? I wasn't able to debug inside init().

    • bearclaw Says:

      Err, are you sure you can delete the context? I'd remove the delete html_context line.
      Also check the exact signature of onPaint. Add a virtual and compile with -Woverloaded-virtual

  • Gogg Says:

    Nevermind, I realized what was going on. I hadn't copy berkelium.exe in my path. It isn't good that a library depends on an exe guys. So if a user goes to the task manager and terminates berkelium.exe my application gets crippled? Are you planning to re-architect this in a way that only a dll is required? The way it is now it's unusable for me. At least could you make it re-run berkelium.exe automatically if it's terminated. Well that wouldn't be good either, as state information would be lost. Please consider removing the exe.

  • Gogg Says:

    Me again! Here's a compromise, how about letting us know if berkelium.exe gets terminated through ErrorDelegate, so that we can finish the host application and tell the user to never terminate that process again? Know that depending on an exe would still be hackish for a library but this would make it an acceptable temporary solution. You should still consider removing it on the long term.

    Also, another simple thing to do would be to let us customize the name of the exe (maybe as a parameter to Berkelium::init()) without having to rebuild the SDK. That way we could easily rename "berkelium.exe" to the same name than our product. Say, if Starcraft used berkelium.exe, they could have named it "starcraftb.exe" and people would know that is related to the game and would not terminate the process.

    Thanks for your attention!

    • Ewen CheslackPostava Says:

      The extra executable is the model Chromium uses to sandbox its browser windows/tabs, so that's not going to go away. If you run Chromium/Chrome, you'll notice a bunch of chromium-browser processes, many of which are –type=renderer.

      It might be possible to disable the sandboxing and have it run the renderer in the same process, thus only requiring the dll. Otherwise, the callback to ErrorDelegate might be possible. I think allowing customizing the exe name wouldn't be too hard and should be able to accept parameters as well so you could use the same approach as Chromium where the renderer processes just take a special parameter. This would require you to include code similar to that used by the berkelium.exe executable.

      Your best bet is to propose an approach on the dev list (http://groups.google.com/group/platformtalk/topics).

  • vilden Says:

    First, Excellent work on this guys!

    Did some testing with the transparency support and it looks like the rgb values are premultiplied with the alpha? Thus leaving the correct alpha in the alpha channel. Removing the blending by chrome should speed things up i think.

  • bearclaw Says:

    There seem to be a bug when building under linux caused by the size of wchar_t being 4 whereas the code expects 2. I think building with -fshort-wchar should fix that.

  • toffeeman Says:

    Hi there

    This is a nice library – I wonder if someone can help solve a problem I have come across though.

    I’m trying to use berkelium to embed the facebook authorisation web pages in a C++ application and I’m finding that if the user clicks on certain links in the sign in page the library calls on onCreateWindow without a prior call to onNavigateTo. I then have to deal with this new window by assigning a delegate and handling it too, when what I want to do is control which links are to produce popups and which aren’t before it gets to this stage.

    My workaround is to call stop() on the new window in onStartLoading and delete the new window and then navigate to the same URL in the old window. Not nice!

    Have I missed something somewhere or does this sound like a bug?

    I’m using the OS X ore-built binaries dated 31st October.

    KUTGW

  • eunsuksong Says:

    Source and unity3dpackage files, please………. by e-mail. edusystem@paran.com

  • laser Says:

    I have to ask though, what version of Chromium did you use with Berkelium? I'm asking because I just pulled the latest Chromium sources and compiled them, then tried to compile Berkelium but ran into a big bunch of errors. It seems that some things have changed in Chromium and compiling it with the latest version probably won't work – the interfaces have changed. For example, ViewHostMsg_PaintRect_Params is no longer defined (or has been renamed), digging into older SVN entries shows it being there in previous versions but in the newer ones it has disappeared, I think it's now ViewHostMsg_UpdateRect_Flags (the contents of the structs look the same).

    So… if anyone is attempting to compile this with the latest Chromium, better not. You'll be wasting many hours like I did

    Would be nice to know which version is the right one to use to be able to compile Berkelium cleanly.