Integrating with Sparkle (mac) for enabling autoupdate feature.

620 views
Skip to first unread message

Viatcheslav Gachkaylo

unread,
May 13, 2011, 1:32:32 AM5/13/11
to Chromium-dev
Hello.

We are using our own branch of Chromium, which will contain autoupdate
feature for mac and win (our own server). As it is complex to
implement full keystone functionality by ourselves, we decided to use
Sparkle framework for Mac OS X updates. My question is what is a
proper way to include third party framework, like Sparkle, to Chromium
mac project? Which gypi files may be modified for this? Also, what
needs to be done to add Chromium's Info.plist entries?

Thanks for your help.
Viatcheslav Gachkaylo, Crystalnix

Robert Sesek

unread,
May 13, 2011, 10:40:08 AM5/13/11
to vgach...@gmail.com, Chromium-dev
You'll want to add the framework to third_party/sparkle, create a .gyp file for it (see OCMock for an example), and then set it to be copied to Chromium.app/Contents/Frameworks. There's a similar example of how to do this in chrome/chrome_dll.gypi for "Keystone Registration.framework", but that copies it to Chromium Framework.framework/Frameworks. You may also need to set include paths and link settings for it in chrome/chrome_browser.gypi.

Chrome's Info.plists live in chrome/app. You'll probably want to modify app-Info.plist.

- Robert
 

Viatcheslav Gachkaylo

unread,
May 13, 2011, 12:19:39 PM5/13/11
to Chromium-dev


On May 13, 9:40 pm, Robert Sesek <rse...@chromium.org> wrote:
> On Fri, May 13, 2011 at 1:32 AM, Viatcheslav Gachkaylo <vgachka...@gmail.com
Thank you, Robert. You were very helpful. I wish there would be
a .xcodeproj -> .gyp
conversion feature, but I didn't find any.

Viatcheslav Gachkaylo

unread,
May 14, 2011, 7:44:25 AM5/14/11
to Chromium-dev
On May 13, 11:19 pm, Viatcheslav Gachkaylo <vgachka...@gmail.com>
wrote:
I have an action in chrome_dll.gypi file:
{
'postbuild_name': 'Copy Sparkle.framework',
'action': [
'tools/build/mac/copy_framework_unversioned',
'../Sparkle/build/Release/Sparkle.framework',
'${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/
Frameworks',
],
},
which I made by example of copying Keystone framework.
Why is there a copy_framework_unversioned script used? It must be
somehow connected with symbolic links presence in source library. What
additional steps need to be done to make an unversioned framework work
with Chromium Framework when I linked it as a versioned framework? Now
it outputs:

dyld: Library not loaded: @loader_path/../Frameworks/Sparkle.framework/
Versions/A/Sparkle
Referenced from: /Users/admin/dev/treeoflife/src/chrome/../
xcodebuild/Release/Chromium.app/Contents/MacOS/../Versions/13.0.760.0/
Chromium Framework.framework/Chromium Framework
Reason: image not found
Trace/BPT trap

The Sparkle framework copied is unversioned and there is no path .../
Versions/A/Sparkle.
What if I use versioned framework copy - can I still use the scripts
preparing delta updates .dmg for an .app bundle?

Mark Mentovai

unread,
May 14, 2011, 1:11:13 PM5/14/11
to vgach...@gmail.com, Chromium-dev

If you want to use unversioned frameworks, you should read the
copy_framework_unversioned script, which explains what it does, why we
use it, and how to get the best results from it. Whether or not you
want to use unversioned frameworks is your own decision, but the
comments will at least help you make an informed decision, and explain
why I made the decision to go unversioned.

In this case, if you’re linking Chromium Framework directly against
Sparkle, you’ll need to adjust Sparkle’s “install name” before you
link Chromium Framework. You can handle this by changing the setting
of LD_DYLIB_INSTALL_NAME as instructed by the comments in
copy_framework_unversioned. If you’re building Sparkle using a
GYP-generated .xcodeproj, you’d put LD_DYLIB_INSTALL_NAME inside an
xcode_settings section. You can find an example of this in
chrome_dll.gypi, within the chrome_dll target. If you’re using
Sparkle’s own .xcodeproj, you can set LD_DYLIB_INSTALL_NAME in the
framework target’s Build tab within its settings window. If you’re
using a prebuilt copy of Sparkle, you can run install_name_tool
manually to set LD_DYLIB_INSTALL_NAME properly before you link
Chromium Framework against it.

> What if I use versioned framework copy - can I still use the scripts
> preparing delta updates .dmg for an .app bundle?

Whether or not the framework is versioned won’t have any impact on
your ability to use our scripts to handle delta updates. However, if
you’re not using Keystone, I’m not sure how useful our existing delta
update support will be for you. Our support for this depends on being
able to run a script at update time, and I don’t know if Sparkle or
other update systems can be made to work that way. For that matter,
even non-delta updates of Chrome are updated by script, much more than
just a simple copy. A lot of the details of our on-disk layout were
influenced by the updater design. This may not be helpful, or may even
prove troublesome, for updaters that behave differently behind the
scenes than Keystone as used by Chrome.

If you haven’t seen this already, here’s some background reading that
explains how our update scheme works, how we’ve laid things out on
disk to make everything operate smoothly, answers a lot of other “why”
questions, and will probably save you some time.
http://an.enduringcolumn.com/2011/04/keeping-up.html

Some additional background material: while not all of Keystone’s
source is available publicly, much of it is, at
http://update-engine.googlecode.com/ .

Viatcheslav Gachkaylo

unread,
May 16, 2011, 9:29:27 AM5/16/11
to Chromium-dev
> questions, and will probably save you some time.http://an.enduringcolumn.com/2011/04/keeping-up.html
>
> Some additional background material: while not all of Keystone’s
> source is available publicly, much of it is, athttp://update-engine.googlecode.com/.

Thanks Mark, your help was invaluable.

Now I managed to create a user preference, allowing to chose whether
to use automatic updates or manual ones. It is showing up properly in
chrome://settings screen and now I want the changes of that property
to be observed and an action must be launched when it changes. I've
added a line to the bottom of Browser::RegisterUserPrefs()

prefs->RegisterBooleanPref(prefs::kAutomaticUpdatesEnabled, true);

As I see there's

virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);

in subtle::PrefMemberBase.
How do I properly use it to monitor property changes?

Robert Sesek

unread,
May 16, 2011, 9:58:36 AM5/16/11
to vgach...@gmail.com, Chromium-dev
On Mon, May 16, 2011 at 9:29 AM, Viatcheslav Gachkaylo <vgach...@gmail.com> wrote:
Now I managed to create a user preference, allowing to chose whether
to use automatic updates or manual ones. It is showing up properly in
chrome://settings screen and now I want the changes of that property
to be observed and an action must be launched when it changes. I've
added a line to the bottom of Browser::RegisterUserPrefs()

prefs->RegisterBooleanPref(prefs::kAutomaticUpdatesEnabled, true);

As I see there's

 virtual void Observe(NotificationType type,
                      const NotificationSource& source,
                      const NotificationDetails& details);

in subtle::PrefMemberBase.
How do I properly use it to monitor property changes?

You need a C++ class that extends NotificationObserver, which can be an observer of NotificationType::PREF_CHANGED. The |details| are a std::string of the preference name. This is basically a C++ equivalent to NSNotification/NSNotificationCenter in Cocoa.


But it looks like there's already a NotificationObserver for the WebUI settings: http://codesearch.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/chrome/browser/ui/webui/options/core_options_handler.cc&q=PREF_CHANGED%20webui&exact_package=chromium&sa=N&cd=7&ct=rc&l=101 . I don't know how this interacts with the JS on the preferences page, though. But if you do some stepping in the debugger, it should be easy to find out.

rsesek / @chromium.org

Viatcheslav Gachkaylo

unread,
May 17, 2011, 10:06:45 AM5/17/11
to Chromium-dev


On May 16, 8:58 pm, Robert Sesek <rse...@chromium.org> wrote:
> On Mon, May 16, 2011 at 9:29 AM, Viatcheslav Gachkaylo <vgachka...@gmail.com
>
>
>
>
>
> > wrote:
> > Now I managed to create a user preference, allowing to chose whether
> > to use automatic updates or manual ones. It is showing up properly in
> > chrome://settings screen and now I want the changes of that property
> > to be observed and an action must be launched when it changes. I've
> > added a line to the bottom of Browser::RegisterUserPrefs()
>
> > prefs->RegisterBooleanPref(prefs::kAutomaticUpdatesEnabled, true);
>
> > As I see there's
>
> >  virtual void Observe(NotificationType type,
> >                       const NotificationSource& source,
> >                       const NotificationDetails& details);
>
> > in subtle::PrefMemberBase.
> > How do I properly use it to monitor property changes?
>
> You need a C++ class that extends NotificationObserver, which can be an
> observer of NotificationType::PREF_CHANGED. The |details| are a std::string
> of the preference name. This is basically a C++ equivalent to
> NSNotification/NSNotificationCenter in Cocoa.
>
> There's an example of this in a Cocoa context here:http://codesearch.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/chrom...
>
> But it looks like there's already a NotificationObserver for the WebUI
> settings:http://codesearch.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/chrom....
> I don't know how this interacts with the JS on the preferences page,
> though. But if you do some stepping in the debugger, it should be easy to
> find out.
>
> rsesek / @chromium.org

Thanks, Robert. I implemented observing the property change on
settings page and call Sparkle's method to change property, contolling
automatic updates download. Now I need to do it backwards, i.e. when
the Sparkle's property changes - I need to change value of profile's
prefservice boolean variable. I plan to use Objective-C KVO for this.
So, where is the right place in Chromium's code to add observer for an
Objective-C object's property? The object is instantiated through nib
file for main menu (MainMenu.nib).

Thank you.
Viatcheslav Gachkaylo, Crystalnix

Robert Sesek

unread,
May 17, 2011, 10:50:01 AM5/17/11
to vgach...@gmail.com, Chromium-dev
I'd probably stick it in AppController, which is our NSApp delegate and instantiated through MainMenu.xib.

rsesek / @chromium.org 

Viatcheslav Gachkaylo

unread,
May 20, 2011, 10:18:51 AM5/20/11
to Chromium-dev
Thanks, Robert, for your answer.

Now I made browser updates install via my edited keystone_install.sh,
which is not using keystone, so it's not able to use system
authorization rights for updating, but it operates the same way as
original script.
What I seek for now is to re-use upgrade detection code in chrome/
browser/upgrade_detector.cc

There are these lines:
#elif defined(OS_MACOSX)
installed_version.reset(
Version::GetVersionFromString(UTF16ToASCII(
keystone_glue::CurrentlyInstalledVersion())));

As I understand, after keystone_install.sh has done its work, the
Contents/Resources/Info.plist in main bundle directory contains newly
installed version. Can I just get the on-disk version in Info.plist
here? If so, is there a built-in API to do this?

Thank you,
Viatcheslav Gachkaylo, Crystalnix

Robert Sesek

unread,
May 20, 2011, 10:22:13 AM5/20/11
to vgach...@gmail.com, Chromium-dev
On Fri, May 20, 2011 at 10:18 AM, Viatcheslav Gachkaylo <vgach...@gmail.com> wrote:
As I understand, after keystone_install.sh has done its work, the
Contents/Resources/Info.plist in main bundle directory contains newly
installed version. Can I just get the on-disk version in Info.plist
here? If so, is there a built-in API to do this?

Mark Mentovai

unread,
May 20, 2011, 10:40:30 AM5/20/11
to vgach...@gmail.com, Chromium-dev
Viatcheslav Gachkaylo wrote:
> What I seek for now is to re-use upgrade detection code in chrome/
> browser/upgrade_detector.cc
>
> There are these lines:
> #elif defined(OS_MACOSX)
>    installed_version.reset(
>        Version::GetVersionFromString(UTF16ToASCII(
>            keystone_glue::CurrentlyInstalledVersion())));
>
> As I understand, after keystone_install.sh has done its work, the
> Contents/Resources/Info.plist in main bundle directory contains newly
> installed version. Can I just get the on-disk version in Info.plist
> here? If so, is there a built-in API to do this?

Take a look at what keystone_glue::CurrentlyInstalledVersion() in
chrome/browser/cocoa/keystone_glue.mm does. It’s just this:

KeystoneGlue* keystoneGlue = [KeystoneGlue defaultKeystoneGlue];
NSString* version = [keystoneGlue currentlyInstalledVersion];
return base::SysNSStringToUTF16(version);

and all -[KeystoneGlue currentlyInstalledVersion] does is:

NSString* appInfoPlistPath = [self appInfoPlistPath];
NSDictionary* infoPlist =
[NSDictionary dictionaryWithContentsOfFile:appInfoPlistPath];
return [infoPlist objectForKey:@"CFBundleShortVersionString"];

-[KeystoneGlue appInfoPlistPath] is:

// NSBundle ought to have a way to access this path directly, but it
// doesn't.
return [[appPath_ stringByAppendingPathComponent:@"Contents"]
stringByAppendingPathComponent:@"Info.plist"];

appPath_ is [[NSBundle mainBundle] bundlePath].

The deal here is that the installed version is determined by looking
at the Info.plist’s CFBundleShortVersionString. In order to avoid
getting a cached CFBundleShortVersionString that probably corresponds
to the running app, this code needs to actually consult the Info.plist
file on disk. As you point out, the version contained in that file
will reflect that an update has been applied. That’s why this code
uses +[NSDictionary dictionaryWithContentsOfFile:] instead of
-[NSBundle infoDictionary], -[NSBundle objectForInfoDictionaryKey:],
or any other NSBundle method.

I would stay away from the FileVersionInfo interface here. Chrome code
generally uses it to get the running framework’s version (via
FileVersionInfo::CreateFileVersionInfoForCurrentModule()) and it is
implemented using -[NSBundle objectForInfoDictionaryKey:].

Viatcheslav Gachkaylo

unread,
May 20, 2011, 12:19:57 PM5/20/11
to Chromium-dev
Thanks, Mark, Robert.

Is the chrome/browser/platform_util.h (conditional platform func
definition), platform_util_mac.mm the right place for adding the
suggested code sequence, or is there a better place? Sorry for such
trivial question, but I really want to understand Chromium's code
structure better and do things the right way.

Best regards,
Viatcheslav Gachkaylo, Crystalnix.

Mark Mentovai

unread,
May 21, 2011, 11:56:12 AM5/21/11
to vgach...@gmail.com, Chromium-dev
Viatcheslav Gachkaylo wrote:
> Is the chrome/browser/platform_util.h (conditional platform func
> definition), platform_util_mac.mm the right place for adding the
> suggested code sequence, or is there a better place? Sorry for such
> trivial question, but I really want to understand Chromium's code
> structure better and do things the right way.

platform_util.h sounds fine to me, but since I’m not sure what your
plans for upstreaming your changes are or even if upstreaming would be
appropriate, my opinion shouldn’t be terribly important.

Viatcheslav Gachkaylo

unread,
May 25, 2011, 9:25:35 AM5/25/11
to Chromium-dev
Hi everyone,

Mark wrote:
> while not all of Keystone’s
> source is available publicly, much of it is, at
> http://update-engine.googlecode.com/ .

Can you tell me what exactly update-engine is missing, compared to
Keystone,
specifically features used by Chrome's updater,
and whether it can be used with minor modifications for Chromium
updates, using
keystone_install.sh script?

Wuggly Juggly

unread,
Jul 30, 2013, 1:48:10 PM7/30/13
to chromi...@chromium.org, vgach...@gmail.com

Hi  Viatcheslav Gachkaylo ,

I know this too late question, but curious, is this problem of updating through sparkle is completely solved, as I'm also working on similar lines. Just referring this email for the solution.


Thank You
Reply all
Reply to author
Forward
0 new messages