[webkit-dev] New loader class to allow workers to do xhr

Darin Adler darin at apple.com
Tue Dec 30 12:07:31 PST 2008

I have a few thoughts on this. The general approach seems OK.

On Dec 30, 2008, at 11:11 AM, David Levin wrote:

>     class ScriptResourceLoader {

I'm not sure "Script" is the right word here, but I don't have a  
better one. Up until now Script has meant "interface to the JavaScript  
interpreter" rather than objects outside that that are intended for  
use by script. But prefixes like "Programmatic" are uglier, so maybe  
we should stick with Script. Lets see if we can  think of a better  

How were you planning on handling synchronous loads? Maybe the  
function for that should be here too as a static member function?

>     public:
>         static PassRefPtr<ScriptResourceLoader>  
> create(ScriptExecutionContext*, ScriptResourceLoaderClient*, const  
> ResourceRequest&, bool skipCanLoadCheck, bool  
> sendResourceLoadCallbacks, bool shouldContentSniff);

Despite their use in existing code I think booleans are a lousy way to  
handle options like these.

I think we can omit skipCanLoadCheck, since it's always false for  
XMLHttpRequest. For the other two I would prefer something easier to  
read at the call site, either named enums or a flags word. The best  
example I could find of the named enum approach is EChildrenOnly in  
markup.h, although the use of an "E" prefix isn't desirable. I  
couldn't find a good example of a flags word.

But this may be in appropriate, since we already use booleans for this  
purpose and you're just refactoring.

>         virtual ~ScriptResourceLoader() {}

ScriptResourceLoader should have a protected destructor instead of a  
public one. There's no legitimate reason for someone who created an  
object using create to call the destructor. Instead only the deref  
function should do that, and since it's virtual it will be a deref  
function specific to a particular derived class.

>         virtual void ref() = 0;
>         virtual void deref() = 0;

I'll need to see more of a design to be sure that the virtual ref/ 
deref design is the best one for this. I understand it can be helpful  
to use ThreadSafeShared rather than RefCounted (or whatever those  
classes are named), but there are other approaches too; it's basically  
an implementation detail, though, not really part of the interface.  
I'll wait to see work that's further along.

>         virtual ~ScriptResourceLoaderClient() {}

This destructor should be protected rather than public. Nobody should  
ever delete a ScriptResourceLoaderClient given a pointer of that  
class. I believe the lifetime rule for these objects is that they are  
responsible for deleting themselves. That's a little hard to program  
with, but if we're sticking with it then the protected destructor  
helps make it clear. But the rules about when it's safe/needed for a  
client to delete itself should be defined as clearly as possible. I  
believe that certain client functions are guaranteed to be the last  
one received, and also if you call cancel() you're guaranteed to not  
get any more client function calls, but I'm not sure. This kind of  
lifetime rule is one of the most important things about an interface  
like this. I presume you'll just keep the current design.

>         virtual void didSendData(unsigned long long bytesSent,  
> unsigned long long totalBytesToBeSent) { }

It's a little strange that each didSendData call repeatedly passes the  
total bytes to be sent; not terrible, but strange. Like other aspects  
of this class it's no doubt just echoing the existing resource loader  

>         virtual void didReceiveData(const char*, int) { }

I think the "int" here needs an argument name to make clear it's the  
size of the data.

>         virtual void didFinishLoading(int resourceIdentifer) { }

Does XMLHttpRequest need to know about the resource identifier? If so,  
how could it possibly know which identifiers to expect? Should we just  
omit that from this interface? Or is this part of the inspector  
interface? It's pretty confusing with the current name, I think.

>         virtual void didFail(bool isCancellation) { }

I think that the cancellation and non-cancellation functions should be  
separate rather than having a single call with a boolean. Like other  
aspects of this class it's no doubt just echoing the existing resource  
loader design.

>         virtual void securityOriginDenyRequest() { }

You're adding a new call here to indicate that the request was denied  
due to the security origin. It's important to use the past tense, so  
it's clear you're not telling the client to deny the request, but  
rather notifying the client that the request was already denied. A  
name like "didFailDueToSecurityOrigin" might be appropriate to fit in  
with the other client calls.

Also, the name needs to express what's different about this failure  
that matters to the client. The practical difference in XMLHttpRequest  
seems to be only the call to internalAbort(), so the fact that this  
failure is due to a security origin check may not be the salient  
difference. It's possible that the important difference is the timing  
of the failure and the name should reflect that. Or maybe all failures  
could call internalAbort(), in which case this can just be didFail()  
and not require a separate function.

>         virtual void receivedCancellation(const ResourceResponse&) { }

This needs "authentication" in its name; the original function  
arguably doesn't need that in its name because its  
AuthenticationChallenge argument makes it clear what kind of  
cancellation we are hearing about.

I don't understand our mix of "did" in some calls and "received" in  
others. We should be more consistent in our naming. If "did" is our  
way to emphasize this is a client function then it should be  
"didReceiveAuthenticationCancellation" or "didCancelAuthentication".

We could dump the "did" prefix if we have a better naming scheme for  
client functions as a group.

     -- Darin

More information about the webkit-dev mailing list