如何请求一个url, form数据如何发送过去?
gtk版本的webkit是用soup库来请求资源, 在webCore/platform/network/soup/ResouceHandlerSoup.cpp:static bool startHTTPRequest(ResourceHandle* handle)中对资源请求。ResourceHandle中有这样一个函数ResourceRequest& firstRequest(),返回ResourceRequest类,它是维护http请求信息的并且继承ResourceRequestBase类。ResourceRequestBase类有这些数据:
KURL m_url;
ResourceRequestCachePolicy m_cachePolicy;
double m_timeoutInterval; // 0 is a magic value for platform default on platforms that have one.
KURL m_firstPartyForCookies;
String m_httpMethod;
HTTPHeaderMap m_httpHeaderFields;
Vector<String> m_responseContentDispositionEncodingFallbackArray;
RefPtr<FormData> m_httpBody;
bool m_allowCookies;
mutable bool m_resourceRequestUpdated;
mutable bool m_platformRequestUpdated;
bool m_reportUploadProgress;
bool m_reportLoadTiming;
bool m_reportRawHeaders;
ResourceLoadPriority m_priority;
TargetType m_targetType;
主要有url, httpMethod, httpHeader, httpBody。
下面以提交sina weibo的表单, 围绕这个ResourceRequest类, 查看它是怎么创建和初始化的。
WebCore::startHTTPRequest() at ResourceHandleSoup.cpp:565 0xc1568d
WebCore::ResourceHandle::start() at ResourceHandleSoup.cpp:667 0xc160f6
WebCore::ResourceHandle::create() at ResourceHandle.cpp:71 0xc0c21d
WebCore::MainResourceLoader::loadNow() at MainResourceLoader.cpp:586 0xac282a
WebCore::MainResourceLoader::load() at MainResourceLoader.cpp:613 0xac2af2
WebCore::DocumentLoader::startLoadingMainResource() at DocumentLoader.cpp:828 0xa7e753
WebCore::FrameLoader::continueLoadAfterWillSubmitForm() at FrameLoader.cpp:2,286 0xa9338d
WebCore::FrameLoader::continueLoadAfterNavigationPolicy() at FrameLoader.cpp:2,807 0xa956df
WebCore::FrameLoader::callContinueLoadAfterNavigationPolicy() at FrameLoader.cpp:2,680 0xa94efa
WebCore::PolicyCallback::call() at PolicyCallback.cpp:103 0xac517b
WebCore::PolicyChecker::continueAfterNavigationPolicy() at PolicyChecker.cpp:164 0xac5f77
webkit_web_policy_decision_use() at webkitwebpolicydecision.cpp:88 0x4c6a74
WebKit::FrameLoaderClient::dispatchDecidePolicyForNavigationAction() at FrameLoaderClientGtk.cpp:608 0x4a1d8a
WebCore::PolicyChecker::checkNavigationPolicy() at PolicyChecker.cpp:89 0xac59d9
WebCore::FrameLoader::loadWithDocumentLoader() at FrameLoader.cpp:1,360 0xa8f56b
WebCore::FrameLoader::load() at FrameLoader.cpp:1,307 0xa8f0b4
WebCore::FrameLoader::load() at FrameLoader.cpp:1,243 0xa8ebc4
WebCore::FrameLoader::load() at FrameLoader.cpp:1,230 0xa8ea22
webkit_web_frame_load_uri() at webkitwebframe.cpp:542 0x4c09c1
webkit_web_view_load_uri() at webkitwebview.cpp:3,835 0x4d784c
main() at main.c:437 0x804b0c6
在WebCore::DocumentLoader::startLoadingMainResource() at DocumentLoader.cpp:828 0xa7e753中DocumentLoader类把自己ResourceRequest放在startLoadingMainResource函数中调用, 可见DocumentLoader维护了这个类。接下来查看DocumentLoader中的ResourceRequest类是如何在DocumentLoader类中创建和初始化的。有两处DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData& substituteData)
void DocumentLoader::setRequest(const ResourceRequest& req)
把断点定在这两处WebCore::DocumentLoader::DocumentLoader() at DocumentLoader.cpp:100 0xa7bd16
WebKit::DocumentLoader::DocumentLoader() at DocumentLoaderGtk.cpp:44 0x48e3df
WebKit::DocumentLoader::create() at DocumentLoaderGtk.h:48 0x4a6f6b
WebKit::FrameLoaderClient::createDocumentLoader() at FrameLoaderClientGtk.cpp:299 0x4a07b2
WebCore::FrameLoader::loadWithNavigationAction() at FrameLoader.cpp:1,264 0xa8ed73
WebCore::FrameLoader::loadPostRequest() at FrameLoader.cpp:2,554 0xa9458b
WebCore::FrameLoader::loadFrameRequest() at FrameLoader.cpp:1,145 0xa8e0cb
WebCore::ScheduledFormSubmission::fire() at NavigationScheduler.cpp:235 0xacaefa
在WebCore::FrameLoader::loadFrameRequest() at FrameLoader.cpp:1,145 0xa8e0cb中调用 loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
这个request.resourceRequest()是resourceRequest类型, request是FrameLoadRequest类型。下面要查看FrameLoadRequest在函数fire中有FrameLoadRequest frameRequest(requestingFrame->document()->securityOrigin());
m_submission->populateFrameLoadRequest(frameRequest);
frame->loader()->loadFrameRequest(frameRequest, lockHistory(), lockBackForwardList(), m_submission->event(), m_submission->state(), SendReferrer);
FrameLoadRequest类是在m_submission->populateFrameLoadRequest(frameRequest);初始化的。查看m_submission是FormSubmission类型, 它有数据
Method m_method;
KURL m_action;
String m_target;
String m_contentType;
RefPtr<FormState> m_formState;
RefPtr<FormData> m_formData;
String m_boundary;
bool m_lockHistory;
RefPtr<Event> m_event;
String m_referrer;
String m_origin;
一个 Method m_method; KURL m_action;RefPtr<FormData> m_formData;
可见它是存储表单数据的类型。这些数据的初始化是在PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger)
函数中, 一个是HTMLFormElement* form, 另一个是Attributes& attributes。
url来自
formData来自efPtr<DOMFormData> domFormData, 而domFormData来自
for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
FormAssociatedElement* control = form->associatedElements()[i];
HTMLElement* element = toHTMLElement(control);
if (!element->disabled())
control->appendFormData(*domFormData, isMultiPartForm);
if (element->hasLocalName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(control);
if (input->isTextField()) {
formValues.append(pair<String, String>(input->name().string(), input->value()));
if (input->isSearchField())
input->addSearchResult();
}
}
}
这样一个语句control->appendFormData(*domFormData, isMultiPartForm);它是一个virtual method, 通过跟踪是它是调用了HTMLInputElement类的函数。
class HTMLFormControlElement : public HTMLElement, public FormAssociatedElement 所以HTMLInputElement是HTMLElement又是FormAssociatedElement
HTMLInputElement中有一个Vector<FormAssociatedElement*> m_associatedElements容器, 所以语句中form->associatedElements()[i];取出存放的指针FormAssociatedElement* control, 其实是HTMLInputElement*类型的。在函数control->appendFormData(*domFormData, isMultiPartForm);中把HTMLInputElement数据m_name和m_valueIfDirty(也就是post数据时的name=value)转存出来。得到formData
通过函数调用stack
WebCore::FormSubmission::create() at FormSubmission.cpp:139 0xa888d2
WebCore::HTMLFormElement::submit() at HTMLFormElement.cpp:336 0x91d3a5
WebCore::HTMLFormElement::submitFromJavaScript() at HTMLFormElement.cpp:298 0x91d1b7
WebCore::jsHTMLFormElementPrototypeFunctionSubmit() at JSHTMLFormElement.cpp:428 0x10b4c82
0x5089cf1
JSC::JITCode::execute() at JITCode.h:80 0x2c0d07c
找到WebCore::jsHTMLFormElementPrototypeFunctionSubmit() at JSHTMLFormElement.cpp:428 0x10b4c82EncodedJSValue JSC_HOST_CALL jsHTMLFormElementPrototypeFunctionSubmit(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
if (!thisValue.inherits(&JSHTMLFormElement::s_info))
return throwVMTypeError(exec);
JSHTMLFormElement* castedThis = static_cast<JSHTMLFormElement*>(asObject(thisValue));
ASSERT_GC_OBJECT_INHERITS(castedThis, &JSHTMLFormElement::s_info);
HTMLFormElement* imp = static_cast<HTMLFormElement*>(castedThis->impl());
imp->submitFromJavaScript();
return JSValue::encode(jsUndefined());
}
找到HTMLFormElement的生成过程。将thisValue.u.asBits.playload转换成JSHTMLFormElement*类型
再将JSHTMLFormElement.JSHTMLElement.JSElement.JSNode.m_impl.m_ptr转换成HTMLFormElement*。就可以得到了。至于thisValuse怎么从exec->hostThisValue();得到, 还不清楚。这个EncodedJSValue JSC_HOST_CALL jsHTMLFormElementPrototypeFunctionSubmit(ExecState* exec)函数怎么被调用的, 在函数栈中找不到调用的语句。。。。那位大牛可以请教???????????????
WebCore::HTMLInputElement::setValue() at HTMLInputElement.cpp:994 0x92c5b8
WebCore::setJSHTMLInputElementValue() at JSHTMLInputElement.cpp:906 0x10c5e27
JSC::lookupPut<WebCore::JSHTMLInputElement>() at Lookup.h:319 0x10c75d9
JSC::lookupPut<WebCore::JSHTMLInputElement, WebCore::JSHTMLElement>() at Lookup.h:333 0x10c72b4
WebCore::JSHTMLInputElement::put() at JSHTMLInputElement.cpp:665 0x10c4fad
JSC::JSValue::put() at JSObject.h:810 0x2c0cc86
JSC::cti_op_put_by_id_generic() at JITStubs.cpp:1,385 0x2c41697
JSC::JITThunks::tryCacheGetByID() at JITStubs.cpp:941 0x2c4095c
0x2ed0ff4
JSC::JITCode::execute() at JITCode.h:80 0x2c0d07c