|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
BackgroundI have been
working on BHO for few months. It's neat to develop BHO components. On
the contrary, Firefox seems really frustrating. I guess the first reason is
that there are never enough examples and codes for you to follow. Secondly, Mozilla does not provide enough documents like Microsoft does. Well, I
don't blame them for that. It's a small company and it's free source after all.
In the
following parts, I will use an example to show you how to intercept Firefox's DOM
elements and operates like in BHO. There are two articles I strongly recommend you to read before you
scroll down this page. http://www.iosart.com/firefox/xpcom/ Creating
a XPCOM component http://www.borngeek.com/firefox/toolbar-tutorial/
Firefox toolbar tutorial The first one
teaches you how to build a component; the second teaches you how to make an
extension. The example
here is based on the example in first article. It took me two
whole weeks to learn how Firefox as well as XPCOM operate. Just use this simple
graph to demonstrate the structure: UI--> XPConnect--> XPCOM Most of the
add-ons you have seen and you can download are extensions such as a
toolbar etc. The majority of them are written with javascript. It's alright and
neat if you don't want to touch some advanced components; for instance a toolbar only navigates the window etc. But if you want to go further, you have to
call components built under XPConnect or XPCOM. Following
code is a simple cookie manager from Mozilla's official tutorial. var cookiemanager = Components.classes["@mozilla.org/1005953"> <o:p /> color: black;"> cookiemanager;1"].getService();1009012"> <o:p /> cookiemanager = cookiemanager.QueryInterface<o:p /> (Components.interfaces.nsICookieManager);1005955"> <o:p />1005956"> <o:p /> // called as part of a largerDeleteAllCookies() function1005976"> <o:p /> function FinalizeCookieDeletions() {1005960"> <o:p /> for (var c=0; c<deletedCookies.length; c++) {1005961"> <o:p /> cookiemanager.remove(deletedCookies[c].host,1005962"> <o:p /> deletedCookies[c].name,1005963"> <o:p /> deletedCookies[c].path);1005964"> <o:p /> 1005965"> <o:p /> }1005966"> <o:p /> deletedCookies.length = 0;1005967"> <o:p /> }1001113"> <o:p /> It is quite
easy to understand the procedure.
There isn't
too much technology in this part. But, how the components work is another
issue. Firefox are
based on Gecko SDK. Basically all those APIs starts with "ns" such as "nsIWebBrowser"
(similar to IWebBrowser on BHO) are from Gecko SDK. You can find the
information on www.xulplanet.com Let's get to
the point. Now, I want to build a FormFiller for firefox. Meanwhile, I do not
want to use javascript to do the job due to following reasons:
So, here are
two solutions
I go for the
second. Although registering a component is far more complicated than
registering an extension on Firefox. But it's much more secured when calling
core components and operates the data. How to do itLike BHO, there is an nsIWebBrowser that provides the APIs of any XPCOM based browsers such as SeaMonkey or NetScape.Through nsIWebBrowser, we can get nsIDOMWindow-> nsIDOMDocument->nsIDOMElement then fill in the information we want. However, this does NOT work on Firefox. The reason is very simple: Firefox does not use nsIWebBrowser. They will return some random useless stuffs when you call nsIWebBrowser via Component Manager. I have no idea why do they do that. Maybe it's because of the multi-tab structure of Firefox. So, our problem is here. We must initialize nsIDOMWindow before we move further. To save your time on googling all the information, please let me present the simple function prototype: var res = obj.Nothing(window); where Nothing is the method called for filling in forms. "window" is the browser window object that javascript naturally has. So inside your code, you have the method declared as: NS_IMETHOD Nothing(nsIDOMWindow *domWindow); //.h file NS_IMETHODIMP MyComponent::Nothing(nsIDOMWindow *domWindow) //cpp file
NS_IMETHODIMP MyComponent::Nothing(nsIDOMWindow *domWindow)
{
nsEmbedString temp(L"test");
nsEmbedString attribute(L"value");
nsEmbedString id(L"id");
nsEmbedString value(L"value");
//The above declare some strings.
/*
Please note that the string in XPCOM is declared as either nsAString or nsString or nsEmbedString Please refer to http://developer.mozilla.org/en/docs/XPCOM:Strings for more information
*/
nsIDOMWindow* window; //you can use the parameter directly
window=domWindow;
nsCOMPtr<nsIDOMDocument> domDocument;
nsCOMPtr<nsIDOMElement> element;
window->GetDocument(getter_AddRefs(domDocument)); //Get document
domDocument->GetElementById(temp,getter_AddRefs(element));
//Find target element, you also can use GetElementByTagName to get a node list. Then loop through the node list. Please refer to XULPlanet for more info //about nsIDOMDocument
element->GetAttribute(id,value);
//I get the value of "id" attribute and fill it into "value attribute"
element->SetAttribute(attribute,value);
return NS_OK;
}Ok, above is the all the code you need. How to build the projectI strongly recommend #include "nsISupports.idl" #include "nsIDOMWindow.idl" [scriptable, uuid(_YOUR_INTERFACE_GUID_)] interface IMyComponent : nsISupports { void Nothing(in nsIDOMWindow domWindow); };
Calling the componentThere are two ways to call the component
<HTML> <SCRIPT type="text/javascript"> function MyComponentTestGo() { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); const cid = "@mydomain.com/XPCOMSample/MyComponent;1"; obj = Components.classes[cid].createInstance(); obj = obj.QueryInterface(Components.interfaces.IMyComponent); } catch (err) { alert(err); return; } var res = obj.Nothing(window);} </SCRIPT> <BODY> <BUTTON ONCLICK="MyComponentTestGo();" id="go">Go</BUTTON> <input id="test" value="" /> </BODY> </HTML> ConclusionThe biggest problem of developing Firefox components is the lack of documents and codes. Even XPCOM itself has the same problem. But I think situation will get better and better. Usually, there are some skilled people on Mozillzine you can ask for help. I hope this simple article is helpful to those people who are frustrated by Firefox. If you have any comments or questions, please leave here. I will reply you as much as I can.
|
||||||||||||||||||||||