Archive for the ‘guest posts’ Category

Firefox Mobile Add-ons – One Small Step for Mankind

Thursday, June 4th, 2009

This is a re-post from Mozilla community member & add-on developer Brian King:

By small in the title, I mean small devices. One large step was taken in the Fennec add-ons ecosystem over the weekend at the Mozilla/Maemo get together in Copenhagen [pictures, tweets]. Present were a large chunk of the Fennec developement team, add-on developers, localisers, and community members. We shared the space with Maemo developers and community members, and while there was not much overlap during sessions and hacking, there were some useful discussions on how we can work better together. The weekend was a mix of sessions and hacking, with the focus more on the latter. We ported add-ons, made new ones, found bugs, and had discussions on best practices and ways to improve the user experience. Here is a mini-report of what went down, from an add-ons perspective.

Target

It might be obvious to say this, but Fennec add-ons are much different beasts than their desktop counterparts. All the goodness of the Mozilla Platform is there and available to use, but the UI is completely different. Less hooks are available simply because there is less space, but the design and UI flow provide different challenges. Sure, there are toolstrips, aka vertical bars to stick icons on to, but what would happen if every extension did that. Pretty soon yours would be lost in the mix.

Madhava Enros did a good job of explain the design behind the Fennec UI. Dialogs and context menus are just 2 things among others that are out in Fennec, and their usage is strongly discouraged. With regard to dialogs, one concern I was hearing from devs is how to show preferences. Recent builds of Fennec (get desktop builds here, or ask on irc.mozilla.org#mobile) have already taken steps to address this.

Fennec Add-ons Manager

Fennec Add-ons Manager

So as you can see, when Options is selected, the UI appears inline and not in a dialog. While there are still bugs, it is clever, but is it scalable for larger pref sets? Or should extension authors scale down?

Stepping Back

I started off my talk about porting existing extensions [Slides: PDF | PPT] by challenging authors to really think whether they should do it. Ask yourself, does it make sense in this context? Does it fit into the browsing habits of users of smaller devices, which is different than desktop usage? For example, users on the go want more information suggested to them as opposed to go hunting for it which can be cumbersome. Now I don’t want to discourage you from porting your add-on. We certainly need more. Keep in mind that it will be more work than just adding Fennec as a target application in install.rdf, and while doing it, get inspiration for new ideas. I think some of the best add-ons will be ones built from the ground up that take advantage of device capabilities such as GPS and voice.

The document story needs to get better. Mark Finkle posted last week about his documentation efforts so far, and thanks to Mark for that. It gives us a solid foundation to add more. I urge everyone working in this area to post your finding on the Mozilla wiki / Devmo / your blog / anywhere to make life easier for those who follow and help promote adoption. I’ll be personally following up with all participants to make sure they do so.

The Winners

Before the event, we offered a challenge at short notice on Mozdev to developers to propose ports of their existing work or new add-ons for Fennec. 4 entrants got to go to Copenhagen. The winners were (in no particular order):

  1. Fabrice Desre – Develop a “local guide” application leveraging the geolocation support in recent Fennec builds. The geoguide will show informations relevant for the user, like touristic information, photos, retaurants and hotel etc. using various data sources such as flickr and dbpedia. The focus here is not to rely on a cluttered map display, but to provide a clean UI : in the same spirit of the experiments going on for the “new tab” in Firefox, but for a “new place”.
  2. Chris Neale – Port Link Widgets to Fennec.
  3. Marien Zwart – Port RadialContext-mz to Fennec.
  4. Benoit BailleuxautoOpenID looks for OpenID sign-in forms and (depending on its configuration) can log-in automaticaly (or propose to) with no more than one click.

Of the four, Fabrice completed GeoGuide, Chris is almost complete, and Marien and Benoit are still working on it.


briks_fennec1

GeoGuide

GeoGuide determines your location using the Geolocation API, and with that data present you with a map view, weather, local events, images, and wikipedia articles.

And The Rest

Some other good work came out the weekend.

  • Nicolas Belloni and Mattias Rost are working on Detector which is their own words, “is an add-on to bring more fingerfriendliness to the content of webpages on Fennec. We strongly support Mozilla’s effort to make a browser adapted for mobile users. So we are aiming at adding more interaction to phone numbers, addresses and contacts’ names. The type of interaction style that we add to the content needs to be thought in order not to be destructive and to take into account the lack of contextual menu. To begin with, we want to detect phones numbers and give the possibility to users to call, save or sms this number”.
  • Jesper Hansen is working on a few things — The first is Save Image. Since Fennec has no possibility to save images, then this addon will provide a list of all images on the loaded page with name, ext, size and a single button to save it. Save Image will also provide a simple canvas dialog (or alternative) that slides up from the bottom of the screen when a onmousedown is being detected for longer than a specific time on an image. Second up, Toastercat: an add-on to monitor and display content of icanhascheezburger.com (and friends, see https://addons.mozilla.org/en-US/firefox/addon/11945) RSS feeds in a simple way without having to load the entire page but only rely on the content provided in the feed. A third add-on is related to about:config since Fennec is missing some features there.
  • Fabrice followed up the excellent GeoGuide with the equally excellent GrafiTwit. This brings a new twist to tweeting, allow you to doodle on a canvas, send the picture off to Twitpic, and post the link to your stream.
  • I ported Zemanta, a few hours of effort, and it now works as the desktop version bar a couple of bugs related to the icon in the location bar. Let me know if you want to try it out, it is not public yet.
Zemanta on Fennec

Zemanta on Fennec

There are a few more add-ons for Fennec available on Mozilla Add-ons. UPDATE: More than a few.

Lessons Learned and Bugs

One of the lessons learned is best summed up by the mantra ‘performance, performance, performance’. Things you take for granted on the desktop may bite you on the mobile device. Here are some performance related guidelines. Another important point is to try if at all possible to test on one of the mobile devices that Fennec runs on. When testing existing add-ons on Nokia developer devices, it was apparent quickly that this was not done for some existing ones. The desktop versions just don’t highlight some issues, e.g. related to touch. Another alternative is to run Maemo virtually.

Mozilla/Maemo Danish Weekend 2009

Mozilla/Maemo Danish Weekend 2009

At this point, bugs are good. If you come across any, please report them and make them block bug 492546 [Develop an extension showing a xul page in BrowserCanvas].

Mozilla in Indonesia

Monday, June 1st, 2009

This is a re-post of Gen Kanai’s article on the Add-ons for Mozilla meetup at ITS Surabaya, a university in the second-largest city in Indonesia.

In a recent post at Ken Kovash’s Blog of Metrics regarding Firefox in Latvia passing 50% market share, Indonesia was ranked at 63% market share. With such a love for Firefox, it’s also great to see that Indonesia has finally had it’s first Mozilla event last month.

Romi Hardiyanto, Mozilla’s localizer for Bahasa Indonesia, led an afternoon of presentations on Add-ons for Mozilla at ITS Surabaya, a university in the second-largest city in Indonesia. Romi has a great write-up of the event, Mozilla Day at ITS, at the brand new Mozilla Indonesia blog.

A photo of the students

The People


HΛniF: Hadits, Now in Firefox

HΛniF Presentation

Photos from the event are available at Romi’s Flickr, Aini-san’s Picasa and Kiki’s Facebook.

I would like to take a moment to thank Romi Hardiyanto, Mozilla’s tireless Bahasa Indonesia localizer for Firefox who, in addition to localizing Firefox for Indonesians, is also working to spread Firefox farther in Indonesia. Thank you Romi!

This event would also not have happened without the support and coordination of Nur’ Aini Rakhmawati of ITS Surabaya who hosted the event. Thank you Aini-san!

Thank you also goes to Mary Colvig who provided support from Marketing/Events.

Since there has been so much interest in Add-ons in Indonesia, we would like to explore the possibility of doing a similar or related Mozilla-focused event in Jakarta later this year, after the launch of Firefox 3.5. If you would like to have a Mozilla event in Jakarta, please feel free to comment and leave your email so we can contact you. We are looking for people in Jakarta who would volunteer to help us with some of the organizational work to create such an event.

Here is Romi Hardiyanto’s presentation on Add-ons (in Bahasa Indonesia, not English.)

Purezilla

Here is Kiki Ahmadi’s presentation on the PureZilla add-on.

Thank you Romi and Aini-san and everyone who made Mozilla’s first event in Indonesia a success!

Romi Hardiyanto

Firefox Mobile Add-ons Challenge

Tuesday, May 12th, 2009

Mozdev and Mozilla Europe are teaming up to sponsor a contest for mobile add-ons. The following post is from the Mozdev blog.


Here at Mozdev, we want to see more add-ons for Firefox Mobile (aka Fennec), so we are teaming up with Mozilla Europe to make a challenge. The task is straightforward. You need only at this time to propose porting your existing add-on to Fennec, or write a new one, with a commitment to finishing it (or at least having a solid proof-of-concept) in time for the Mozilla Maemo Danish Weekend on 30-31 May.

REQUIREMENTS
(We are on a tight schedule and have logistics constraints, so apologise for the deadline and geographical restrictions)

  • Write a short proposal stating what your add-on name and current install location, why you think it would be useful to mobile browser users, and how you plan on going about implementing it. Send it to brian@mozdev.org by Friday 15 May, at 12:00 CET.
  • This challenge is only open to developers living in Europe.
  • The challenge open to current Mozdev project owners, and other developers who host their projects elsewhere.

PRIZE

USEFUL RESOURCES
http://wiki.maemo.org/MozillaMaemoDanishWeekend
http://www.mozilla.org/projects/fennec/1.0b1/releasenotes/
https://wiki.mozilla.org/Mobile/Fennec/Extensions
https://wiki.mozilla.org/Mobile/Fennec/Architecture
http://starkravingfinkle.org/blog/tags/mobile/
http://www.mozdev.org/projects/applications/Fennec.html
https://addons.mozilla.org/en-US/fennec/

An Invitation to Create Firefox Extensions for Good Causes

Monday, February 23rd, 2009

The following is a guest post from Joe Solomon, Director of Social Actions’ Change the Web Challenge.


Today we are launching Social Actions’ Change the Web Challenge – a contest to build new web apps that help people make a difference on the millions of websites we visit everyday. There will also be $10,000 in prizes. We are extremely excited to be partnering with Mozilla on this project!

Over at Social Actions we’ve created an open database of 60,000+ actions from 40+ sites- including GlobalGiving, Change.org, DonorsChoose.org, Kiva.org, Nabuur, TakingITGlobal, Idealist.org, and VolunteerMatch.

What the Change the Web Challenge is about is getting these actions out there – by helping people find and share actions on the websites, blogs and social networks that we all visit everyday.

What makes Mozilla and Firefox add-ons in particular such a powerful platform for social change is that you can change the way people browse the web. You can add an intimate and direct layer of social change to the browsing experience. You can, with so many different possibilities, help people make a difference on any website.

For example, Marnie Webb created an Ubiquity command that lets you highlight any phrase on any site and find related ways to take action from Social Actions’ 40+ action sources.

Our community members have also imagined (read: not built) an extension that replaces ads with actions (a la AddArt), to another extension that would alert you to relevant actions as you browse the web (possibly like Collactive), to a browser-based feed reader with the latest actions categorized by cause (by re-skinning ObamaFox).

We hope you’ll join us in envisioning and building new Firefox extensions that combine the aggregated actions of Social Actions with the powerful reach and impact of Mozilla Firefox.

You can find out more about the Change the Web Challenge, including how to submit your project here.

More links:

How to develop a Firefox extension

Wednesday, January 28th, 2009

Reposted with permission from Robert Nyman:

Admit that you have always wanted to know how to develop a Firefox extension but never had the time to learn. :-) Here I will walk you through and at the end of the article we will have created a fully functional Firefox extension!

Our objective

We will create a Firefox extension to find all links in the current web page, highlight those which have a target attribute and alert you how many links it found. The good part is that once you have done this, you have both an understanding of Firefox extension development as well as a blueprint for any extension you would want to develop in the future.

(more…)

Know Thy Add-on User

Tuesday, January 20th, 2009

Mark Cramer is a guest writer for the AMO blog. He is CEO of SurfCanyon, the creators of the SurfCanyon Firefox add-on.

Creating software in a vacuum is incredibly difficult. While all add-on developers have a general idea of the value they’d like to deliver to their users, without copious and constant feedback it’s like flying in the dark. Knowing what your users want and what they don’t find interesting is incredibly important. It also helps to know what, if anything, they’re seeking and how they perceive what it is that your add-on does and how it works. Even if you’re delivering a valuable add-on, compatibility can also be a major issue since end users’ machines all look different and testing the limitless combinations of add-ons, desktop software and personal configurations is virtually impossible.

Listening and reacting to the people in the trenches can therefore make the difference between success and failure.

While it may seem daunting, you can take heart in the fact that users, when nurtured properly, can be an incredible resource for feedback, helpful advice, technical assistance and, on many occasions, even quality assurance. They can certainly be abrasive sometimes, but with a thick skin you can get tremendous value out of their “tough love.” In the spirit of trying to share a few thoughts, here are some humbly submitted, common sense ideas, along with a few tricks, that might help make the difference.

1. Actively Seek Feedback

The AMO page for every add-on enables users to leave comments. Check once a day for new feedback, post responses whenever appropriate and, when possible, follow up with the commenter if more information is needed. As a general rule, when communicating with users, keep it positive and constructive and control your emotions. While on occasion it might seem otherwise, malicious intent is extremely rare. Most people want to help, so always respond with that in mind.

The AMO page, however, should only be the beginning. For most add-ons, the percentage of people who download and then return to leave a comment is small. Finding other ways to elicit feedback is therefore imperative. Nevertheless, the challenge can be particularly difficult since it is not obviously when, where or how to ask for feedback. You could try to incorporate a feedback mechanism into the add-ons itself, but be careful about being overly intrusive. Real estate is very precious and most people don’t want things popping up at them. We have found, however, that one excellent way to resolve these issues is with an uninstall survey.

A survey page can be launched using an uninstall script. For actually running the survey and collecting the data, SurveyMonkey provides an excellent service. If you don’t mind having to erase the responses and start over every time you get 100 replies, you could run it for free. Keeping the survey very short will help conversion greatly. You might even consider one simple multiple-choice question: “Please tell us why you are uninstalling this add-on.” Allow for an open-ended response and consider making one of the answers “Temporary issue – I’ll be back!” While few people will leave an email, make sure to ask for it as those that do leave one will normally turn out to be very helpful.

Remember to keep your uninstall survey up to date. The open-ended responses will enable users to give whatever feedback they want, but if you use multiple-choice questions, make sure to keep the selections current with the functionality of your add-on. Moving the questions and responses around a bit will also help to remove “position bias” – people have a tendency to select the first choices.

We’ve found that the moment the user chooses to uninstall an add-on turns out to be an opportune time to request feedback. He or she has had an opportunity to evaluate the application and has just made a decision: to uninstall. Unfortunately this doesn’t afford a lot of opportunity for positive feedback (people who love the application will generally leave it installed and thus won’t ever see the survey, so you’ll have to find another mechanism for getting the positive reviews), but hearing from people who uninstall is what you really need to improve your add-on.

2. Meticulously Pursue All Leads

The majority of feedback, whether through the AMO page, the add-on’s website or the uninstall script, will not include contact information for the user. For obvious reasons, people are very reluctant to share their emails. In many cases, this can make the job of debugging or improving your application very difficult, especially when the feedback isn’t anything more than “it didn’t work.” Therefore, whenever a user is gracious enough to provide contact information along with the feedback, it’s important to capitalize on that opportunity to learn everything that you can. People who submit their email addresses are doing so for follow up, so don’t be afraid to contact them. That being said, restrict the communication to the subject matter at hand (their feedback) and don’t send them sales pitches or add them to any mailing lists.

Take pains to profusely express gratitude for their feedback at every opportunity. Pointing out how valuable their contributions are to resolving issues and improving your application, and then thanking them for their effort, turns out to be very helpful. It’s also the right thing to do. As a consequence, we’ve found that some people can be incredibly generous with their time and assistance. In order to debug issues, we’ve had people create new profiles for testing, uninstall and deactivate add-ons one at a time to find compatibility problems and install testing software as well as beta versions of our add-on. We even had one user send a video in order to demonstrate a particular thing he was experiencing.

Many people love problem solving and will look at providing you with useful information as a personal challenge. By offering them avenues for giving feedback, demonstrating respect for their time and offering them encouragement, AMO users will be an amazingly valuable resource for improving your add-on.

3. Relentlessly Make Improvements

Now that you’ve got the feedback and have an army of users helping you out, it’s naturally important to implement improvements as a result. New features and enhancements can take time to realize, but responding to your users should always be a top priority. That being said, just because one user asks for something doesn’t mean that you need to drop everything to deliver it, but with enough feedback you’ll begin to identify patterns. Keep in mind that if five people give similar feedback there might be hundreds out there that are thinking the same thing.

Compatibility issues can also be tricky to resolve since they typically involve other people’s software, although once again, other developers can be very helpful. If you reach out to developers with whom you have issues you’ll most likely find that most are eager to provide assistance. Add-on incompatibility issues work both ways, so it’s in everyone’s interest to work together. If another add-on developer were to contact you, I’m sure you’d do the same. Even if other developers are unable to modify their application in a timely fashion, perhaps they could help suggest a temporary work-around. We’ve found that the odds of not getting some form of assistance is very small and that most developers are enthusiastic about collaborating.

Finally, don’t hesitate to reach out to the AMO community for technical assistance. Many issues relating to the development of add-ons are tricky and a lot of the “art” is still being fashioned. Post questions to forums or send emails to other add-on developers. If you have a little bit of money to dedicate to something particular, RentACoder can be a cost-effective means of finding vetted developers with very specific talents.

I’m sure there are many other techniques for working with AMO users, but these suggestions might be a helpful place to get started. If other people have ideas, we’d love to hear them, so please post below. Everyone is always looking for ways to improve!

Firefox Extensions: Global Namespace Pollution

Friday, January 16th, 2009

Reposted with permission from Jan Odvarko (AKA Honza):

I have been recently asked by couple of developers how to properly design architecture of a Firefox extension. The first thing that immediately came to my mind at that point was a problem with global variables defined by extensions in ChromeWindow scope.

This problem can easily cause collisions among various extensions. Something that should be always avoided (and is also part of AMO review process) since this kind of issues is very hard to find. Yes, global variables are still evil, especially in OOP world.

I don’t want to describe how to develop a new extension from scratch. For this there is already bunch of detailed articles. I am rather concentrating on effective tactics how to make Firefox extension architecture maintainable and well designed.

So, read more if you are interested…

Namespace Architecture

Defining global variables is a way how to risk collisions with other extensions. I think that creating just one global variable per extension that is unique enough (composed e.g. from the name of the extension, domain URL, etc.) is sufficient strategy how to avoid undesirable collisions.

The architecture for namespaces used in Firebug, is based (more or less) on well known module pattern (originally described by Douglas Crockford). It’s really simple and transparent so, I hadn’t understand how it actually works for a long time. I believe other extension developers can utilize this approach as well.

The basic idea is to wrap content of every JS file into its own scope that is represented by a function so, there are no global objects. See following snippet.

function() {

// TODO: entire JS code in this file is here
}

This is what I am going to call a namespace.

The first question is how to ensure that the function is actually called and the code executed at the right time. The second question is how to share objects among more files (see Sharing among namespaces chapter below). Firebug solves this by registering every namespace and executing all when Firefox chrome UI is ready. See modified example.

myExtension.ns(function() {

// TODO: entire JS code in this file is here
});

The namespace (regular function) is passed as a parameter to myExtension.ns function. The myExtension object is the only global object that is defined by the extension. This is the singleton object that represents entire extension. Don’t worry if the name is long, there’ll be a shortcut for it (in real application it could be e.g. comSoftwareIsHardMyExtension).

The ns function is simple. Every function is pushed into an array.

var namespaces = [];

this.ns = function(fn) {
    var ns = {};

    namespaces.push(fn, ns);
    return ns;
};

Actual execution of registered namespaces (functions) is only matter of calling apply on them.

this.initialize = function() {
    for (var i=0; i<namespaces.length; i+=2) {

        var fn = namespaces[i];
        var ns = namespaces[i+1];

        fn.apply(ns);
    }
};

Now, let’s put all together and see how the global extension (singleton) object is defined and initialized.

The following source code snippet represents a browserOverlay.js file that is included into an overlay (browserOverlay.xul)

// The only global object for this extension.
var myExtension = {};

(function() {
// Registration
var namespaces = [];

this.ns = function(fn) {
    var ns = {};
    namespaces.push(fn, ns);

    return ns;
};
// Initialization
this.initialize = function() {

    for (var i=0; i<namespaces.length; i+=2) {
        var fn = namespaces[i];

        var ns = namespaces[i+1];
        fn.apply(ns);

    }

};
// Clean up
this.shutdown = function() {
    window.removeEventListener("load", myExtension.initialize, false);

    window.removeEventListener("unload", myExtension.shutdown, false);
};
// Register handlers to maintain extension life cycle.
window.addEventListener("load", myExtension.initialize, false);

window.addEventListener("unload", myExtension.shutdown, false);
}).apply(myExtension);

As I mentioned above, there is just one global object myExtension.

To summarize, the object implements following methods:

  • ns – register a new namespace.
  • initialize – initialize all namespaces.
  • shutdown – clean up.

And also, the code makes sure that initialize and shutdown methods are called at the right time. This is why event handlers are registered.

The browserOverlay.xul looks as follows now.

<?xml version="1.0"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <script src="chrome://namespace/content/browserOverlay.js" type="application/x-javascript"/>
    <script src="chrome://namespace/content/Module1.js" type="application/x-javascript"/>

    <script src="chrome://namespace/content/Module2.js" type="application/x-javascript"/>
</overlay>

And the Module1.js and Module2.js files are both the same.

myExtension.ns(function() {
// TODO: entire JS code in this file is here
});

Sharing among namespaces

Now, when we have our script within a local scope(s), let’s answer the question how to share functionality and data among individual namespaces. The general idea is to use the one global object we have – myExtension.

First of all, see the following source code (lib.js file).

myExtension.LIB = {

    // Shared APIs
    getCurrentURI: function() {
        return window.location.href;

    },

    // Extension singleton shortcut
    theApp: myExtension,

    // XPCOM shortcuts
    Cc: Components.classes,

    Ci: Components.interfaces,

    // Etc.
};

You can see that a new LIB property is created within our global myExtension singleton. This objects represents a library of functions that should be shared among all modules in our extension. At this point, you can also get inspiration from Java Packaging and create whole tree of namespaces within the global singleton (just like e.g. YUI does)

The lib.js file is included in browserOvelay.xul (just after browserOverlay.js)

<?xml version="1.0"?>

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <script src="chrome://myextension/content/browserOverlay.js" type="application/x-javascript"/>

    <script src="chrome://myextension/content/lib.js" type="application/x-javascript"/>
    <script src="chrome://myextension/content/Module1.js" type="application/x-javascript"/>

    <script src="chrome://myextension/content/Module2.js" type="application/x-javascript"/>
</overlay>

Let’s also improve our module script a bit.

myExtension.ns(function() { with (myExtension.LIB) {
// TODO: entire JS code in this file is here

var moduleVariable = "Accessible only from withing this module";

dump("myExtension.Module initialization " + getCurrentURI() + "\n");

}});

By utilizing with statement we can simply access all library functions as if they would be a global functions.

In case we want to access our singleton global object we can also utilize theApp shortcut (useful especially if the name is long) as follows:

myExtension.ns(function() { with (myExtension.LIB) {
// TODO: entire JS code in this file is here

theApp.sharedValue = "A new shared property";

}});

Here is how the architecture look like from UML perspective.

Namespaces within a Firefox extension.

Download example extension here.

Successfully Getting your Addon Reviewed

Wednesday, January 14th, 2009

Thanks to AMO Editor Cesar Oliveira for allowing us to repost this here:

As the addon review queue grows beyond 600 nominated and updated addons, it is more important than ever to make sure your extension passes review the first time around. Editors have a review guide, and a well hidden but publicly viewable set of policies. But here is a quick list of the most cited reasons for addon refusal :

  1. Addon should have at least 3 user reviews before being nominated. External reviews count too, but you have to mention them in your nomination message. Softpedia reviews do not count.
  2. Wrap your loose variables. All objects, variables, and anything that your addon makes global should be wrapped to avoid conflicts with other addons.
  3. Look at the error console. Is your extension throwing up javascript errors? Fix it. There are some options you can set in about:config to help you with this.
  4. You break functionality in the host application (Firefox, Thunderbird, etc.).
  5. Your extension doesn’t work properly, or showing unexpected results. This is what user reviews are expected to catch, but you really should get someone who wasn’t involved to test and report bugs.

There are other less common things that can get you busted too. I’ll just list them here for completeness sake :

  1. Including remote javascript/css or other files, anywhere. Include them in your xpi file instead.
  2. CSS warnings on the error console if your submitting a theme.

If you have any doubts, check the public policies page linked above.

And don’t ask when your extension will be reviewed in the comments. Because every answer will be the same : When someone gets around to it. It could be sooner if you’d help!