Difference between revisions of "Development:Third-Party Preference Panes"

From Camino Wiki
Jump to navigation Jump to search
(more updates)
(→‎Working with Gecko preferences: <code>-ify code examples)
 
(12 intermediate revisions by the same user not shown)
Line 4: Line 4:
  
 
==Who should read this document?==
 
==Who should read this document?==
Camino, per our mission statement, "is an open source web browser developed with a focus on providing the best possible experience for Mac OS X users." This, along with the limited time available for our all-volunteer programming team to implement features, means that certain choices have to be made about what should and shouldn't be part of the Camino application itself. As with Firefox extensions, there are many opportunities for third-party developers to step in and provide niche features or UI for things that Camino doesn't provide by default. This document is intended to provide a jumping-off point for third-party developers interested in developing additional preference panes for Camino.
+
This documentation is intended for third-party developers interested in writing preference panes for Camino using Apple's Cocoa APIs, and assumes a basic working knowledge of Xcode, Cocoa, and Objective-C programming.
 +
 
 +
Camino, per our mission statement, "is an open source web browser developed with a focus on providing the best possible experience for Mac OS X users." This, along with the limited time available for our all-volunteer programming team to implement features, means that certain choices have to be made about what should and shouldn't be part of the Camino application itself. There are many opportunities for third-party developers to step in and provide niche features or UI for things that Camino doesn't provide by default.
 +
 
 +
For example, while Camino does not provide any UI (other than about:config) for changing the user-agent string passed by the browser to a Web server, the basic hooks are present for a third-party developer to write a preference pane that puts UI on this ability, and the [http://pimpmycamino.com/parts/user-agent UserAgent preference pane] does exactly that.
  
 
==Getting started==
 
==Getting started==
Line 13: Line 17:
  
 
===Disclaimer===
 
===Disclaimer===
These instructions are presented in good faith, but we make no guarantees as to the stability of Camino's APIs (even across minor versions), and we cannot guarantee preference panes developed using this guide will not set your cat -- or your users' cats, or both -- on fire.
+
These instructions are presented in good faith, but we cannot guarantee preference panes developed using this guide will not set your cat -- or your users' cats, or both -- on fire.
 +
 
 +
We do make every effort to ensure the compatibility and stability of methods in PreferencePaneBase.
  
 
==Creating the Xcode project==
 
==Creating the Xcode project==
In Xcode's New Project Assistant, scroll down and expand the "Standard Apple Plug-ins" group and select "PreferencePane", then click Next.
+
 
 +
We've put together a [CBSamplePane.zip sample Xcode project] (download size) for developers to use when writing preference panes for Camino. Feel free to use this project as a starting point, or make your own as follows.
 +
 
 +
===Making the new PreferencePane project===
 +
In Xcode's New Project Assistant (see below), scroll down and expand the "Standard Apple Plug-ins" group and select "PreferencePane", then click Next and continue through the Assistant.
 +
 
 +
[[Image:Newproject.png]]
 +
 
 +
===Changing the creator code===
  
 
Camino's preference panes are standard Apple PreferencePanes with a small twist: their creator code is <code>MOZC</code> (Camino's creator code) instead of the default <code>????</code>. Go to Xcode's Project menu and select "Edit Active Target", which will bring up the Target Info window. Click on the Properties tab and you'll be able to change the creator code, as seen in the screenshot below:
 
Camino's preference panes are standard Apple PreferencePanes with a small twist: their creator code is <code>MOZC</code> (Camino's creator code) instead of the default <code>????</code>. Go to Xcode's Project menu and select "Edit Active Target", which will bring up the Target Info window. Click on the Properties tab and you'll be able to change the creator code, as seen in the screenshot below:
Line 22: Line 36:
 
[[Image:Properties.png]]
 
[[Image:Properties.png]]
  
 +
===Changing the bundle ID===
 +
If you use the provided project, make sure you change your preference pane's bundle identifier from <code>org.mozilla.caminoprefpane</code>, as bundle ID conflicts can prevent your pane from loading. Bundle identifiers generally take the form of <code>tld.developer.productname</code>, so your preference pane might be <code>com.johndoe.awesomeprefs</code>, for example. You should make a reasonable effort to ensure that this bundle ID is unique across all Camino preference panes.
  
We've put together a [CBSamplePane.zip sample Xcode project] (download size) for developers to use when writing preference panes for Camino. Feel free to use this project as a starting point, or make your own.
+
===Changing the class names===
 
+
You should also ensure that your classes have unique names, as class name conflicts can also be a problem. Continuing with the above example, your preference pane's class might be <code>ComJohnDoeAwesomePrefs</code>. As with the bundle ID, you should make a reasonable effort to ensure class names are unique not only within your project, but across all Camino preference panes.
If you use the provided project, make sure you change your preference pane's bundle identifier from <code>org.mozilla.caminoprefpane</code>, as bundle ID conflicts can prevent your pane from loading. Bundle identifiers generally take the form of <code>tld.developer.productname</code>, so your preference pane might be <code>com.johndoe.awesomeprefs</code>, for example.
 
  
You should also ensure that your classes have unique names, as class name conflicts can also be a problem. Continuing with the above example, your preference pane's class would be <code>ComJohndoeAwesomeprefs</code>.
+
For more on avoiding naming conflicts and the potential consequences of such conflicts, see [http://developer.apple.com/documentation/UserExperience/Conceptual/PreferencePanes/Tasks/Conflicts.html Apple's "Preventing Name Conflicts" documentation].
  
 
==Laying out the UI==
 
==Laying out the UI==
Line 35: Line 50:
 
==Using Camino methods==
 
==Using Camino methods==
  
If you plan to use any of Camino's methods directly, your preference pane should subclass Camino's <code>PreferencePaneBase</code> class (which is, in turn, a subclass of the standard AppKit NSPreferencePane class). This means that <code>PreferencePaneBase.h</code> is a required header. If you plan to deploy your preference pane on Camino 1.5.x, you'll also need to compile <code>PreferencePaneBase.mm</code> (in the Compile Sources phase of the target). This step is unnecessary if you plan to deploy your preference pane ''only'' for Camino 1.6 or higher.
+
If you plan to use any of Camino's methods directly, your preference pane should subclass Camino's <code>PreferencePaneBase</code> class (which is, in turn, a subclass of the standard AppKit NSPreferencePane class). Using Camino methods other than those defined in PreferencePaneBase is explicitly discouraged; other classes can and do change without notice and should ''not'' be relied on to be stable across Camino versions.
 +
 
 +
Logically, it follows that <code>PreferencePaneBase.h</code> is a required header if you decide to use any of its methods. If you plan to deploy your preference pane on Camino 1.5.x, you'll also need to compile <code>PreferencePaneBase.mm</code> (in the Compile Sources phase of the target). This step is unnecessary if you plan to deploy your preference pane ''only'' for Camino 1.6 or higher.
  
 
You'll also need to tell the linker where it can find a Camino application. Using the Target Info window, point the linker's "Bundle Loader" to a copy of Camino on your hard disk. For example, if Camino is in your Applications folder, it would look like this:
 
You'll also need to tell the linker where it can find a Camino application. Using the Target Info window, point the linker's "Bundle Loader" to a copy of Camino on your hard disk. For example, if Camino is in your Applications folder, it would look like this:
Line 42: Line 59:
  
 
If you have multiple copies of Camino, point it to the oldest one you plan to support with your preference pane.
 
If you have multiple copies of Camino, point it to the oldest one you plan to support with your preference pane.
 
You'll also need to copy over any Camino header files for methods you're using in your preference pane. You can add them to the Copy Headers phase of the project, like this:
 
 
[[Image:Adding-files.png]]
 
  
 
That's it! You should be able to build the project and test your preference pane with Camino. Remember to re-launch Camino after placing the preference pane in <code>[~]/Library/Application Suppport/Camino/PreferencePanes/</code>.
 
That's it! You should be able to build the project and test your preference pane with Camino. Remember to re-launch Camino after placing the preference pane in <code>[~]/Library/Application Suppport/Camino/PreferencePanes/</code>.
Line 53: Line 66:
 
Calling Gecko functions directly from a third-party preference pane is somewhat more involved. You'll still need to link against the appropriate libraries, but rather than copying the headers, which is likely to be a big headache (there are a great number of interdependencies amongst Gecko's header files, and it's easy to miss one), you'll probably be better off adding appropriate paths to the HEADER_SEARCH_PATHS parameter in Xcode's Target Info window. ''[An example here would be great. -cl]''
 
Calling Gecko functions directly from a third-party preference pane is somewhat more involved. You'll still need to link against the appropriate libraries, but rather than copying the headers, which is likely to be a big headache (there are a great number of interdependencies amongst Gecko's header files, and it's easy to miss one), you'll probably be better off adding appropriate paths to the HEADER_SEARCH_PATHS parameter in Xcode's Target Info window. ''[An example here would be great. -cl]''
  
If there's something in Gecko you really need to use that simply doesn't have a Cocoa wrapper on it in Camino, please bring it to our attention. We may be willing to add wrapper code for it, since one architectural goal we have for Camino is to hide Gecko from our developers as much as possible.
+
If there's something in Gecko you really need to use that simply doesn't have a Cocoa wrapper on it in Camino, please bring it to our attention by [https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html filing a bug report] (with severity of "Enhancement"). We may be willing to add wrapper code for it, since one architectural goal we have for Camino is to hide Gecko from our developers as much as possible.
 +
 
 +
==Working with Gecko preferences==
 +
 
 +
There are a number of points to keep in mind when dealing with the Gecko preferences (as opposed to Apple's NSUserDefaults) system. First and foremost, it's easy for preferences UI to get out of sync with reality, since there are a number of Gecko preferences that have UI in multiple locations within Camino.
 +
 
 +
For example, there are at least three places to edit the <code>security.warn_viewing_mixed</code> preference in Camino:
 +
 
 +
* the Security preference pane;
 +
* the warning sheet that comes up when entering a secure page containing insecure elements; and
 +
* <code>about:config</code>.
 +
 
 +
If your preference pane will edit preferences that can be changed outside the Preferences window, you should read {{Bug|358318}}, {{Bug|373158}}, and {{Bug|411189}} (and possibly {{Bug|371266}} as well) and ensure you have a thorough understanding of the underlying issues behind them. The sample preference pane provided above has comments in the code that should help you to avoid the pref synchronization bugs we've encountered over the course of Camino development.
 +
 
 +
Some preferences require further action to toggle on or off than <code>about:config</code> by itself is capable of performing. Again, as an example, both Flashblock and Camino's built-in ad-blocking need to (re)load a stylesheet in order to take effect. You should expect advanced users to know about and use <code>about:config</code>, so if your preference pane will deal with preferences like this, you should use the Camino PreferenceManager's <code>-addObserver:forPref:</code> method to trigger notifications when the preferences change in <code>about:config</code>. (Don't forget to <code>-removeObserver:forPref:</code> when you're done!) {{Bug|384689}} contains a real-world example of how to use this code.
  
 
==Other potential gotchas and caveats==
 
==Other potential gotchas and caveats==
  
 
* Anything with C++ code in it built by gcc 4 won't run on Mac OS versions prior to 10.3.9. If you need to deploy on 10.3.8 or lower, you'll need to select an earlier gcc version.
 
* Anything with C++ code in it built by gcc 4 won't run on Mac OS versions prior to 10.3.9. If you need to deploy on 10.3.8 or lower, you'll need to select an earlier gcc version.

Latest revision as of 17:54, 2 October 2008

DRAFT
This page is not complete.

See Bug 384800 for more information on the status of this page. The current how-to should not be attempted by people unfamiliar with Xcode and its related tools or the Camino codebase.

Who should read this document?

This documentation is intended for third-party developers interested in writing preference panes for Camino using Apple's Cocoa APIs, and assumes a basic working knowledge of Xcode, Cocoa, and Objective-C programming.

Camino, per our mission statement, "is an open source web browser developed with a focus on providing the best possible experience for Mac OS X users." This, along with the limited time available for our all-volunteer programming team to implement features, means that certain choices have to be made about what should and shouldn't be part of the Camino application itself. There are many opportunities for third-party developers to step in and provide niche features or UI for things that Camino doesn't provide by default.

For example, while Camino does not provide any UI (other than about:config) for changing the user-agent string passed by the browser to a Web server, the basic hooks are present for a third-party developer to write a preference pane that puts UI on this ability, and the UserAgent preference pane does exactly that.

Getting started

These instructions assume a basic working knowledge of Apple's Developer Tools, including Xcode and Interface Builder, as well as the Objective-C language itself. If you are unfamiliar with these, Apple Developer Connection is an excellent place to start learning. You'll also want to be familiar with the basics of preference pane development, for which Apple has provided an excellent tutorial as well.

Applicability and support

These instructions can be used by anyone developing preference panes on Mac OS X 10.4 or higher, with Xcode 2.4.x or higher and Interface Builder 2.x or higher, to be deployed on any version of Camino from 1.5 onward. Developers may choose to support only Mac OS X 10.4+ or Camino 2.0pre+, but this is highly discouraged unless certain limitations of the Mac OS or Camino/Gecko code make supporting Mac OS X 10.3.9 or the Camino 1.5 branch impossible.

Disclaimer

These instructions are presented in good faith, but we cannot guarantee preference panes developed using this guide will not set your cat -- or your users' cats, or both -- on fire.

We do make every effort to ensure the compatibility and stability of methods in PreferencePaneBase.

Creating the Xcode project

We've put together a [CBSamplePane.zip sample Xcode project] (download size) for developers to use when writing preference panes for Camino. Feel free to use this project as a starting point, or make your own as follows.

Making the new PreferencePane project

In Xcode's New Project Assistant (see below), scroll down and expand the "Standard Apple Plug-ins" group and select "PreferencePane", then click Next and continue through the Assistant.

Error creating thumbnail: Unable to save thumbnail to destination

Changing the creator code

Camino's preference panes are standard Apple PreferencePanes with a small twist: their creator code is MOZC (Camino's creator code) instead of the default ????. Go to Xcode's Project menu and select "Edit Active Target", which will bring up the Target Info window. Click on the Properties tab and you'll be able to change the creator code, as seen in the screenshot below:

Error creating thumbnail: Unable to save thumbnail to destination

Changing the bundle ID

If you use the provided project, make sure you change your preference pane's bundle identifier from org.mozilla.caminoprefpane, as bundle ID conflicts can prevent your pane from loading. Bundle identifiers generally take the form of tld.developer.productname, so your preference pane might be com.johndoe.awesomeprefs, for example. You should make a reasonable effort to ensure that this bundle ID is unique across all Camino preference panes.

Changing the class names

You should also ensure that your classes have unique names, as class name conflicts can also be a problem. Continuing with the above example, your preference pane's class might be ComJohnDoeAwesomePrefs. As with the bundle ID, you should make a reasonable effort to ensure class names are unique not only within your project, but across all Camino preference panes.

For more on avoiding naming conflicts and the potential consequences of such conflicts, see Apple's "Preventing Name Conflicts" documentation.

Laying out the UI

In order to keep the UI of your preference panes as consistent as possible with the preference panes shipped with Camino itself, please use our Nib Editing Guide as a reference for laying out the UI when developing preference panes for Camino.

Using Camino methods

If you plan to use any of Camino's methods directly, your preference pane should subclass Camino's PreferencePaneBase class (which is, in turn, a subclass of the standard AppKit NSPreferencePane class). Using Camino methods other than those defined in PreferencePaneBase is explicitly discouraged; other classes can and do change without notice and should not be relied on to be stable across Camino versions.

Logically, it follows that PreferencePaneBase.h is a required header if you decide to use any of its methods. If you plan to deploy your preference pane on Camino 1.5.x, you'll also need to compile PreferencePaneBase.mm (in the Compile Sources phase of the target). This step is unnecessary if you plan to deploy your preference pane only for Camino 1.6 or higher.

You'll also need to tell the linker where it can find a Camino application. Using the Target Info window, point the linker's "Bundle Loader" to a copy of Camino on your hard disk. For example, if Camino is in your Applications folder, it would look like this:

Error creating thumbnail: Unable to save thumbnail to destination

If you have multiple copies of Camino, point it to the oldest one you plan to support with your preference pane.

That's it! You should be able to build the project and test your preference pane with Camino. Remember to re-launch Camino after placing the preference pane in [~]/Library/Application Suppport/Camino/PreferencePanes/.

Using Gecko functions and methods

Calling Gecko functions directly from a third-party preference pane is somewhat more involved. You'll still need to link against the appropriate libraries, but rather than copying the headers, which is likely to be a big headache (there are a great number of interdependencies amongst Gecko's header files, and it's easy to miss one), you'll probably be better off adding appropriate paths to the HEADER_SEARCH_PATHS parameter in Xcode's Target Info window. [An example here would be great. -cl]

If there's something in Gecko you really need to use that simply doesn't have a Cocoa wrapper on it in Camino, please bring it to our attention by filing a bug report (with severity of "Enhancement"). We may be willing to add wrapper code for it, since one architectural goal we have for Camino is to hide Gecko from our developers as much as possible.

Working with Gecko preferences

There are a number of points to keep in mind when dealing with the Gecko preferences (as opposed to Apple's NSUserDefaults) system. First and foremost, it's easy for preferences UI to get out of sync with reality, since there are a number of Gecko preferences that have UI in multiple locations within Camino.

For example, there are at least three places to edit the security.warn_viewing_mixed preference in Camino:

  • the Security preference pane;
  • the warning sheet that comes up when entering a secure page containing insecure elements; and
  • about:config.

If your preference pane will edit preferences that can be changed outside the Preferences window, you should read Bug 358318, Bug 373158, and Bug 411189 (and possibly Bug 371266 as well) and ensure you have a thorough understanding of the underlying issues behind them. The sample preference pane provided above has comments in the code that should help you to avoid the pref synchronization bugs we've encountered over the course of Camino development.

Some preferences require further action to toggle on or off than about:config by itself is capable of performing. Again, as an example, both Flashblock and Camino's built-in ad-blocking need to (re)load a stylesheet in order to take effect. You should expect advanced users to know about and use about:config, so if your preference pane will deal with preferences like this, you should use the Camino PreferenceManager's -addObserver:forPref: method to trigger notifications when the preferences change in about:config. (Don't forget to -removeObserver:forPref: when you're done!) Bug 384689 contains a real-world example of how to use this code.

Other potential gotchas and caveats

  • Anything with C++ code in it built by gcc 4 won't run on Mac OS versions prior to 10.3.9. If you need to deploy on 10.3.8 or lower, you'll need to select an earlier gcc version.