⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlhttprequest.cpp

📁 最新Nokia手机浏览器全套源代码完美版。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *  This file is part of the KDE libraries
 *  Copyright (C) 2004 Apple Computer, Inc.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "xmlhttprequest.h"

#include "xmlhttprequest.lut.h"
#include "kjs_window.h"
#include "kjs_events.h"

#include "dom/dom_doc.h"
#include "dom/dom_exception.h"
#include "dom/dom_string.h"
#include "misc/loader.h"
#include "html/html_documentimpl.h"
#include "xml/dom2_eventsimpl.h"

#include "khtml_part.h"
#include "khtmlview.h"

#include <kdebug.h>
#include <kio/job.h>
#include <qobject.h>
#include <qregexp.h>

#ifdef APPLE_CHANGES
#include "KWQLoader.h"
#endif

using namespace KJS;
using khtml::Decoder;

////////////////////// XMLHttpRequest Object ////////////////////////

/* Source for XMLHttpRequestProtoTable.
@begin XMLHttpRequestProtoTable 7
  abort         XMLHttpRequest::Abort           DontDelete|Function 0
  getAllResponseHeaders XMLHttpRequest::GetAllResponseHeaders   DontDelete|Function 0
  getResponseHeader XMLHttpRequest::GetResponseHeader   DontDelete|Function 1
  open          XMLHttpRequest::Open            DontDelete|Function 5
  overrideMimeType      XMLHttpRequest::OverrideMIMEType        DontDelete|Function 1
  send          XMLHttpRequest::Send            DontDelete|Function 1
  setRequestHeader  XMLHttpRequest::SetRequestHeader    DontDelete|Function 2
@end
*/
DEFINE_PROTOTYPE("XMLHttpRequest",XMLHttpRequestProto)
IMPLEMENT_PROTOFUNC(XMLHttpRequestProtoFunc)
IMPLEMENT_PROTOTYPE(XMLHttpRequestProto,XMLHttpRequestProtoFunc)

namespace KJS {

XMLHttpRequestQObject::XMLHttpRequestQObject(XMLHttpRequest *_jsObject) 
{
  jsObject = _jsObject; 
}

#if APPLE_CHANGES
void XMLHttpRequestQObject::slotData( KIO::Job* job, const char *data, int size )
{
  jsObject->slotData(job, data, size);
}
#else
void XMLHttpRequestQObject::slotData( KIO::Job* job, const QByteArray &data )
{
  jsObject->slotData(job, data);
}
#endif

void XMLHttpRequestQObject::slotFinished( KIO::Job* job )
{
  jsObject->slotFinished(job); 
}

void XMLHttpRequestQObject::slotRedirection( KIO::Job* job, const KURL& url)
{ 
  jsObject->slotRedirection( job, url ); 
}

XMLHttpRequestConstructorImp::XMLHttpRequestConstructorImp(ExecState *, const DOM::Document &d)
    : doc(d)
{
}

bool XMLHttpRequestConstructorImp::implementsConstruct() const
{
  return true;
}

Object XMLHttpRequestConstructorImp::construct(ExecState *exec, const List &)
{
  return Object(new XMLHttpRequest(exec, doc));
}

const ClassInfo XMLHttpRequest::info = { "XMLHttpRequest", 0, &XMLHttpRequestTable, 0 };

/* Source for XMLHttpRequestTable.
@begin XMLHttpRequestTable 7
  readyState        XMLHttpRequest::ReadyState      DontDelete|ReadOnly
  responseText      XMLHttpRequest::ResponseText        DontDelete|ReadOnly
  responseXML       XMLHttpRequest::ResponseXML     DontDelete|ReadOnly
  status        XMLHttpRequest::Status          DontDelete|ReadOnly
  statusText        XMLHttpRequest::StatusText      DontDelete|ReadOnly
  onreadystatechange    XMLHttpRequest::Onreadystatechange  DontDelete
  onload        XMLHttpRequest::Onload          DontDelete
@end
*/

Value XMLHttpRequest::tryGet(ExecState *exec, const Identifier &propertyName) const
{
  return DOMObjectLookupGetValue<XMLHttpRequest,DOMObject>(exec, propertyName, &XMLHttpRequestTable, this);
}

Value XMLHttpRequest::getValueProperty(ExecState *exec, int token) const
{
  switch (token) {
  case ReadyState:
    return Number(state);
  case ResponseText:
    return getStringOrNull(DOM::DOMString(response));
  case ResponseXML:
    if (state != Completed) {
      return Undefined();
    }
    if (!createdDocument) {
      QString mimeType;
      
      if (MIMETypeOverride.isEmpty()) {
        Value header = getResponseHeader("Content-Type");
        if (header.type() == UndefinedType) {
          mimeType = "text/xml";
        } else {
      mimeType = QStringList::split(";", header.toString(exec).qstring())[0].stripWhiteSpace();
        }
      } else {
        mimeType = MIMETypeOverride;
      }
      
      if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "application/xhtml+xml" ||
          mimeType == "text/xsl" || mimeType == "application/rss+xml" || mimeType == "application/atom+xml") {
    responseXML = DOM::Document(doc->implementation()->createDocument());

    DOM::DocumentImpl *docImpl = static_cast<DOM::DocumentImpl *>(responseXML.handle());
    
    docImpl->open();
    docImpl->write(response);
    docImpl->finishParsing();
    docImpl->close();
    typeIsXML = true;
      } else {
    typeIsXML = false;
      }
      createdDocument = true;
    }

    if (!typeIsXML) {
      return Undefined();
    }

    return getDOMNode(exec,responseXML);
  case Status:
    return getStatus();
  case StatusText:
    return getStatusText();
  case Onreadystatechange:
   if (onReadyStateChangeListener.notNull() && onReadyStateChangeListener->listenerObjImp()) {
     return onReadyStateChangeListener->listenerObj();
   } else {
     return Null();
   }
  case Onload:
   if (onLoadListener.notNull() && onLoadListener->listenerObjImp()) {
     return onLoadListener->listenerObj();
   } else {
     return Null();
   }
  default:
    kdWarning() << "XMLHttpRequest::getValueProperty unhandled token " << token << endl;
    return Value();
  }
}

void XMLHttpRequest::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
  DOMObjectLookupPut<XMLHttpRequest,DOMObject>(exec, propertyName, value, attr, &XMLHttpRequestTable, this );
}

void XMLHttpRequest::putValue(ExecState *exec, int token, const Value& value, int /*attr*/)
{
  switch(token) {
  case Onreadystatechange:
    onReadyStateChangeListener.reset(Window::retrieveActive(exec)->getJSUnprotectedEventListener(value, true));
    break;
  case Onload:
    onLoadListener.reset(Window::retrieveActive(exec)->getJSUnprotectedEventListener(value, true));
    break;
  default:
    kdWarning() << "HTMLDocument::putValue unhandled token " << token << endl;
  }
}

void XMLHttpRequest::mark()
{
  DOMObject::mark();

  if (onReadyStateChangeListener.notNull())
    onReadyStateChangeListener->mark();

  if (onLoadListener.notNull())
    onLoadListener->mark();
}


XMLHttpRequest::XMLHttpRequest(ExecState *exec, const DOM::Document &d)
  : qObject(new XMLHttpRequestQObject(this)),
    doc(static_cast<DOM::DocumentImpl*>(d.handle())),
    async(true),
    job(0),
    state(Uninitialized),
    decoder(0),
    createdDocument(false),
    aborted(false)
{
  setPrototype(XMLHttpRequestProto::self(exec));
#if NOKIA_CHANGES
  ValueImp *imp = exec->dynamicInterpreter()->globalObject().imp();
  if(imp) {
    Window* window = static_cast<KJS::Window*>(imp);
    decoder = new Decoder;
    decoder->setEncoding(KWQ(window->part())->encoding().ascii(), Decoder::DefaultEncoding);
  }
#endif
}

XMLHttpRequest::~XMLHttpRequest()
{
  delete qObject;
  delete decoder;
}

void XMLHttpRequest::changeState(XMLHttpRequestState newState)
{
  if (state != newState) {
    state = newState;
    
    if (doc && doc->part() && onReadyStateChangeListener.notNull()) {
      DOM::Event ev = doc->part()->document().createEvent("HTMLEvents");
      ev.initEvent("readystatechange", true, true);
      onReadyStateChangeListener->handleEvent(ev, true);
    }
    
    if (doc && doc->part() && state == Completed && onLoadListener.notNull()) {
      DOM::Event ev = doc->part()->document().createEvent("HTMLEvents");
      ev.initEvent("load", true, true);
      onLoadListener->handleEvent(ev, true);
    }
  }
}

bool XMLHttpRequest::urlMatchesDocumentDomain(const KURL& _url) const
{
  KURL documentURL(doc->URL());

  // a local file can load anything
  if (documentURL.protocol().lower() == "file") {
    return true;
  }

  // but a remote document can only load from the same port on the server
  if (documentURL.protocol().lower() == _url.protocol().lower() &&
      documentURL.host().lower() == _url.host().lower() &&
      documentURL.port() == _url.port()) {
    return true;
  }

  return false;
}

void XMLHttpRequest::open(const QString& _method, const KURL& _url, bool _async)
{
  abort();
  aborted = false;

  // clear stuff from possible previous load
  requestHeaders = QString();
  responseHeaders = QString();
  response = QString();
  createdDocument = false;
  responseXML = DOM::Document();

  changeState(Uninitialized);

  if (aborted) {
    return;
  }

  if (!urlMatchesDocumentDomain(_url)) {
    return;
  }

  
  method = _method;
  url = _url;
  async = _async;

  changeState(Loading);
}

void XMLHttpRequest::send(const QString& _body)
{
  if (!doc)
    return;

  // FIXME: Should this abort instead if we already have a job going?
  if (job)
    return;

  aborted = false;

#if !APPLE_CHANGES
  if (!async) {
    return;
  }
#endif

  if (method.lower() == "post" && (url.protocol().lower() == "http" || url.protocol().lower() == "https") ) {
      // FIXME: determine post encoding correctly by looking in headers for charset
      job = KIO::http_post( url, _body.utf8(), false );
  }
  else
  {
     job = KIO::get( url, false, false );
  }
  if (requestHeaders.length() > 0) {
    job->addMetaData("customHTTPHeader", requestHeaders);
  }

#if APPLE_CHANGES
  if (!async) {
    QByteArray data;
    KURL finalURL;
    QString headers;

    data = KWQServeSynchronousRequest(khtml::Cache::loader(), doc->docLoader(), job, finalURL, headers);
    job = 0;
    processSyncLoadResults(data, finalURL, headers);
    
    return;
  }
#endif

  {
    InterpreterLock lock;
    gcProtect(this);
#if !USE_CONSERVATIVE_GC
    ref();
#endif
  }
  
  qObject->connect( job, SIGNAL( result( KIO::Job* ) ),
            SLOT( slotFinished( KIO::Job* ) ) );
#if APPLE_CHANGES
  qObject->connect( job, SIGNAL( data( KIO::Job*, const char*, int ) ),
            SLOT( slotData( KIO::Job*, const char*, int ) ) );
#else
  qObject->connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
            SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
#endif
  qObject->connect( job, SIGNAL(redirection(KIO::Job*, const KURL& ) ),
            SLOT( slotRedirection(KIO::Job*, const KURL&) ) );

  addToRequestsByDocument();

#ifdef APPLE_CHANGES
  KWQServeRequest(khtml::Cache::loader(), doc->docLoader(), job);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -