зеркало из https://github.com/mozilla/pjs.git
Form submission performance / maintability improvements (bug 120682) r=alexsavulov,r=sicking,sr=jst
This commit is contained in:
Родитель
2afd472bc6
Коммит
fe1d4d2f35
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
nsIForm.h
|
||||
nsIFormControl.h
|
||||
nsIFormSubmission.h
|
||||
nsILink.h
|
||||
nsIOptionElement.h
|
||||
nsIScriptElement.h
|
||||
|
|
|
@ -40,6 +40,7 @@ EXPORTS = \
|
|||
nsIOptionElement.h \
|
||||
nsITextControlElement.h \
|
||||
nsIScriptElement.h \
|
||||
nsIFormSubmission.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -32,6 +32,7 @@ EXPORTS= \
|
|||
nsIOptionElement.h \
|
||||
nsIScriptElement.h \
|
||||
nsITextControlElement.h \
|
||||
nsIFormSubmission.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE=content
|
||||
|
|
|
@ -45,6 +45,7 @@ class nsIPresState;
|
|||
class nsIContent;
|
||||
class nsString;
|
||||
class nsIFormProcessor;
|
||||
class nsIFormSubmission;
|
||||
|
||||
#define NS_FORM_BROWSE 0
|
||||
#define NS_FORM_BUTTON_BUTTON 1
|
||||
|
@ -97,6 +98,8 @@ public:
|
|||
/**
|
||||
* Set the form for this form control.
|
||||
* @param aForm the form
|
||||
* @param aRemoveFromForm set false if you do not want this element removed
|
||||
* from the form. (Used by evil DemoteForm() method.)
|
||||
* @return NS_OK
|
||||
*/
|
||||
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm,
|
||||
|
@ -109,16 +112,21 @@ public:
|
|||
*/
|
||||
NS_IMETHOD GetType(PRInt32* aType) = 0;
|
||||
|
||||
/**
|
||||
* Reset this form control
|
||||
*/
|
||||
NS_IMETHOD Reset() = 0;
|
||||
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval) = 0;
|
||||
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval) = 0;
|
||||
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames) = 0;
|
||||
/**
|
||||
* Tells the form control to submit its names and values to the form
|
||||
* submission object
|
||||
* @param aFormSubmission the form submission to notify of names/values/files
|
||||
* to submit
|
||||
* @param aSubmitElement the element that was pressed to submit (possibly
|
||||
* null)
|
||||
*/
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement) = 0;
|
||||
|
||||
/**
|
||||
* Save to presentation state
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef nsIFormSubmission_h___
|
||||
#define nsIFormSubmission_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
class nsAString;
|
||||
class nsACString;
|
||||
class nsIURI;
|
||||
class nsIInputStream;
|
||||
class nsIForm;
|
||||
class nsIPresContext;
|
||||
class nsIContent;
|
||||
class nsIFormControl;
|
||||
class nsIDOMHTMLElement;
|
||||
|
||||
#define NS_IFORMSUBMITTER_IID \
|
||||
{ 0x7ee38e3a, 0x1dd2, 0x11b2, \
|
||||
{0x89, 0x6f, 0xab, 0x28, 0x03, 0x96, 0x25, 0xa9} }
|
||||
|
||||
/**
|
||||
* Interface for form submissions; encompasses the function to call to submit as
|
||||
* well as the form submission name/value pairs
|
||||
*/
|
||||
class nsIFormSubmission : public nsISupports
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFORMSUBMITTER_IID)
|
||||
|
||||
/**
|
||||
* Find out whether or not this form submission accepts files
|
||||
*
|
||||
* @param aAcceptsFiles the boolean output
|
||||
*/
|
||||
NS_IMETHOD AcceptsFiles(PRBool* aAcceptsFiles) = 0;
|
||||
|
||||
/**
|
||||
* Call to perform the submission
|
||||
*
|
||||
* @param aActionURL the URL to submit to (may be modified with GET contents)
|
||||
* @param aTarget the target window
|
||||
* @param aSource the element responsible for the submission (for web shell)
|
||||
* @param aPresContext the presentation context
|
||||
*/
|
||||
NS_IMETHOD SubmitTo(nsIURI* aActionURL, const nsAString& aTarget,
|
||||
nsIContent* aSource, nsIPresContext* aPresContext) = 0;
|
||||
|
||||
/**
|
||||
* Submit a name/value pair
|
||||
*
|
||||
* @param aSource the control sending the parameter
|
||||
* @param aName the name of the parameter
|
||||
* @param aValue the value of the parameter
|
||||
*/
|
||||
NS_IMETHOD AddNameValuePair(nsIDOMHTMLElement* aSource,
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue) = 0;
|
||||
|
||||
/**
|
||||
* Submit a name/file pair
|
||||
*
|
||||
* @param aSource the control sending the parameter
|
||||
* @param aName the name of the parameter
|
||||
* @param aFilename the name of the file (pass null to provide no name)
|
||||
* @param aStream the stream containing the file data to be sent
|
||||
* @param aContentType the content-type of the file data being sent
|
||||
* @param aMoreFilesToCome true if another name/file pair with the same name
|
||||
* will be sent soon
|
||||
*/
|
||||
NS_IMETHOD AddNameFilePair(nsIDOMHTMLElement* aSource,
|
||||
const nsAString& aName,
|
||||
const nsAString& aFilename,
|
||||
nsIInputStream* aStream,
|
||||
const nsACString& aContentType,
|
||||
PRBool aMoreFilesToCome) = 0;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// Factory methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Get a submission object based on attributes in the form (ENCTYPE and METHOD)
|
||||
*
|
||||
* @param aForm the form to get a submission object based on
|
||||
* @param aPresContext the presentation context
|
||||
* @param aFormSubmission the form submission object (out param)
|
||||
*/
|
||||
nsresult GetSubmissionFromForm(nsIForm* aForm, nsIPresContext* aPresContext,
|
||||
nsIFormSubmission** aFormSubmission);
|
||||
|
||||
|
||||
#endif /* nsIFormSubmission_h___ */
|
|
@ -59,7 +59,7 @@ CPPSRCS = \
|
|||
nsGenericHTMLElement.cpp \
|
||||
nsGenericDOMHTMLCollection.cpp \
|
||||
GenericElementCollection.cpp \
|
||||
nsFormSubmitter.cpp \
|
||||
nsFormSubmission.cpp \
|
||||
nsHTMLAnchorElement.cpp \
|
||||
nsHTMLAppletElement.cpp \
|
||||
nsHTMLAreaElement.cpp \
|
||||
|
|
|
@ -65,7 +65,7 @@ CPP_OBJS= \
|
|||
.\$(OBJDIR)\nsGenericHTMLElement.obj \
|
||||
.\$(OBJDIR)\nsGenericDOMHTMLCollection.obj \
|
||||
.\$(OBJDIR)\GenericElementCollection.obj \
|
||||
.\$(OBJDIR)\nsFormSubmitter.obj \
|
||||
.\$(OBJDIR)\nsFormSubmission.obj \
|
||||
.\$(OBJDIR)\nsHTMLAnchorElement.obj \
|
||||
.\$(OBJDIR)\nsHTMLAppletElement.obj \
|
||||
.\$(OBJDIR)\nsHTMLAreaElement.obj \
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -48,6 +48,7 @@
|
|||
#include "nsIPresContext.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#include "nsIFrame.h"
|
||||
|
@ -90,12 +91,8 @@ public:
|
|||
// overrided nsIFormControl method
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
// nsIContent overrides...
|
||||
NS_IMETHOD GetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
|
@ -126,7 +123,6 @@ private:
|
|||
// The analogue of defaultValue in the DOM for input and textarea
|
||||
nsresult SetDefaultValue(const nsAReadableString& aDefaultValue);
|
||||
nsresult GetDefaultValue(nsAWritableString& aDefaultValue);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -582,63 +578,56 @@ nsHTMLButtonElement::SetDefaultValue(const nsAReadableString& aDefaultValue)
|
|||
return SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::value, aDefaultValue, PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsHTMLButtonElement::Reset()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLButtonElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
//
|
||||
// We only submit if we were the button pressed
|
||||
//
|
||||
if (aSubmitElement != this) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if it's disabled, it won't submit
|
||||
//
|
||||
// Disabled elements don't submit
|
||||
//
|
||||
PRBool disabled;
|
||||
nsresult rv = GetDisabled(&disabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (disabled) {
|
||||
return NS_OK;
|
||||
rv = GetDisabled(&disabled);
|
||||
if (NS_FAILED(rv) || disabled) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If there is no name, it won't submit
|
||||
nsAutoString val;
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, val);
|
||||
*_retval = rv != NS_CONTENT_ATTR_NOT_THERE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 1, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// We'll of course use the name of the control for the submit
|
||||
//
|
||||
// Get the name (if no name, no submit)
|
||||
//
|
||||
nsAutoString name;
|
||||
nsresult rv = GetName(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
if (NS_FAILED(rv) || rv == NS_CONTENT_ATTR_NOT_THERE) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the value
|
||||
//
|
||||
nsAutoString value;
|
||||
rv = GetValue(value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aNames[0] = name;
|
||||
aValues[0] = value;
|
||||
aNumValues = 1;
|
||||
return NS_OK;
|
||||
//
|
||||
// Submit
|
||||
//
|
||||
rv = aFormSubmission->AddNameValuePair(this, name, value);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -75,10 +75,8 @@ public:
|
|||
// nsIFormControl
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues,
|
||||
nsString* aValues, nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
#ifdef DEBUG
|
||||
// nsIContent
|
||||
|
@ -208,27 +206,9 @@ nsHTMLFieldSetElement::Reset()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFieldSetElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFieldSetElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFieldSetElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFieldSetElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
aNumValues = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include "nsIForm.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIFormManager.h"
|
||||
#include "nsFormSubmitter.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMNSHTMLFormElement.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
|
@ -63,7 +63,18 @@
|
|||
#include "nsHashtable.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
// form submission
|
||||
#include "nsIFormSubmitObserver.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
|
||||
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
|
||||
|
||||
|
@ -131,16 +142,72 @@ protected:
|
|||
nsresult DoSubmitOrReset(nsIPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
PRInt32 aMessage);
|
||||
nsresult DoReset();
|
||||
|
||||
NS_IMETHOD OnReset(nsIPresContext* aPresContext);
|
||||
nsresult RemoveSelfAsWebProgressListener();
|
||||
//
|
||||
// Submit Helpers
|
||||
//
|
||||
//
|
||||
/**
|
||||
* Actually perform the submit (called by DoSubmitOrReset)
|
||||
*
|
||||
* @param aPresContext the presentation context
|
||||
* @param aEvent the DOM event that was passed to us for the submit
|
||||
*/
|
||||
nsresult DoSubmit(nsIPresContext* aPresContext, nsEvent* aEvent);
|
||||
/**
|
||||
* Walk over the form elements and call SubmitNamesValues() on them to get
|
||||
* their data pumped into the FormSubmitter.
|
||||
*
|
||||
* @param aFormSubmission the form submission object
|
||||
* @param aSubmitElement the element that was clicked on (nsnull if none)
|
||||
*/
|
||||
nsresult WalkFormElements(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
/**
|
||||
* Get the full URL to submit to. Do not submit if the returned URL is null.
|
||||
*
|
||||
* @param aActionURL the full, unadulterated URL you'll be submitting to
|
||||
*/
|
||||
nsresult GetActionURL(nsIURI** aActionURL);
|
||||
/**
|
||||
* Notify any submit observsers of the submit.
|
||||
*
|
||||
* @param aActionURL the URL being submitted to
|
||||
* @param aCancelSubmit out param where submit observers can specify that the
|
||||
* submit should be cancelled.
|
||||
*/
|
||||
nsresult NotifySubmitObservers(nsIURI* aActionURL, PRBool* aCancelSubmit);
|
||||
|
||||
/**
|
||||
* Compare two nodes in the same tree (Negative result means a < b, 0 ==,
|
||||
* positive >). This function may fail if the nodes are not in a tree
|
||||
* or are in different trees.
|
||||
*
|
||||
* @param a the first node
|
||||
* @param b the second node
|
||||
* @param retval whether a < b (negative), a == b (0), or a > b (positive)
|
||||
*/
|
||||
static nsresult CompareNodes(nsIDOMNode* a,
|
||||
nsIDOMNode* b,
|
||||
PRInt32* retval);
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
nsFormControlList *mControls;
|
||||
PRPackedBool mGeneratingSubmit;
|
||||
PRPackedBool mGeneratingReset;
|
||||
PRPackedBool mDemotingForm;
|
||||
|
||||
protected:
|
||||
// Detection of first form to notify observers
|
||||
static PRBool gFirstFormSubmitted;
|
||||
};
|
||||
|
||||
PRBool nsHTMLFormElement::gFirstFormSubmitted = PR_FALSE;
|
||||
|
||||
|
||||
// nsFormControlList
|
||||
class nsFormControlList : public nsIDOMNSHTMLFormControlList,
|
||||
public nsIDOMHTMLCollection
|
||||
|
@ -324,9 +391,7 @@ nsHTMLFormElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
|
|||
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
|
||||
|
||||
nsresult rv = it->Init(mNodeInfo);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
CopyInnerTo(this, it, aDeep);
|
||||
|
||||
|
@ -520,7 +585,8 @@ nsHTMLFormElement::HandleDOMEvent(nsIPresContext* aPresContext,
|
|||
nsresult
|
||||
nsHTMLFormElement::DoSubmitOrReset(nsIPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
PRInt32 aMessage) {
|
||||
PRInt32 aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPresContext);
|
||||
|
||||
// Make sure the presentation is up-to-date
|
||||
|
@ -535,27 +601,16 @@ nsHTMLFormElement::DoSubmitOrReset(nsIPresContext* aPresContext,
|
|||
// Submit or Reset the form
|
||||
nsresult rv = NS_OK;
|
||||
if (NS_FORM_RESET == aMessage) {
|
||||
rv = OnReset(aPresContext);
|
||||
rv = DoReset();
|
||||
}
|
||||
else if (NS_FORM_SUBMIT == aMessage) {
|
||||
nsIContent *originatingElement = nsnull;
|
||||
|
||||
// Get the originating frame (failure is non-fatal)
|
||||
if (aEvent) {
|
||||
if (NS_FORM_EVENT == aEvent->eventStructType) {
|
||||
originatingElement = ((nsFormEvent *)aEvent)->originator;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the form originator
|
||||
rv = nsFormSubmitter::OnSubmit(this, aPresContext, originatingElement);
|
||||
rv = DoSubmit(aPresContext, aEvent);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// JBK moved from nsFormFrame - bug 34297
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFormElement::OnReset(nsIPresContext* aPresContext)
|
||||
nsresult
|
||||
nsHTMLFormElement::DoReset()
|
||||
{
|
||||
// JBK walk the elements[] array instead of form frame controls - bug 34297
|
||||
PRUint32 numElements;
|
||||
|
@ -571,6 +626,326 @@ nsHTMLFormElement::OnReset(nsIPresContext* aPresContext)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::DoSubmit(nsIPresContext* aPresContext, nsEvent* aEvent)
|
||||
{
|
||||
nsIContent *originatingElement = nsnull;
|
||||
|
||||
// Get the originating frame (failure is non-fatal)
|
||||
if (aEvent) {
|
||||
if (NS_FORM_EVENT == aEvent->eventStructType) {
|
||||
originatingElement = ((nsFormEvent *)aEvent)->originator;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get the submission object
|
||||
//
|
||||
nsCOMPtr<nsIFormSubmission> submission;
|
||||
nsresult rv = GetSubmissionFromForm(this, aPresContext,
|
||||
getter_AddRefs(submission));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
//
|
||||
// Dump the data into the submission object
|
||||
//
|
||||
rv = WalkFormElements(submission, originatingElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
//
|
||||
// Get the action and target
|
||||
//
|
||||
nsCOMPtr<nsIURI> actionURI;
|
||||
rv = GetActionURL(getter_AddRefs(actionURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (actionURI) {
|
||||
nsAutoString target;
|
||||
rv = GetTarget(target);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
//
|
||||
// Notify observers of submit
|
||||
//
|
||||
PRBool aCancelSubmit = PR_FALSE;
|
||||
rv = NotifySubmitObservers(actionURI, &aCancelSubmit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!aCancelSubmit) {
|
||||
//
|
||||
// Submit
|
||||
//
|
||||
rv = submission->SubmitTo(actionURI, target, this, aPresContext);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
|
||||
PRBool* aCancelSubmit)
|
||||
{
|
||||
// If this is the first form, bring alive the first form submit
|
||||
// category observers
|
||||
if (!gFirstFormSubmitted) {
|
||||
gFirstFormSubmitted = PR_TRUE;
|
||||
NS_CreateServicesFromCategory(NS_FIRST_FORMSUBMIT_CATEGORY,
|
||||
nsnull,
|
||||
NS_FIRST_FORMSUBMIT_CATEGORY);
|
||||
}
|
||||
|
||||
// Notify observers that the form is being submitted.
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIObserverService> service =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> theEnum;
|
||||
rv = service->EnumerateObservers(NS_FORMSUBMIT_SUBJECT,
|
||||
getter_AddRefs(theEnum));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (theEnum) {
|
||||
nsCOMPtr<nsISupports> inst;
|
||||
*aCancelSubmit = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> globalObject;
|
||||
mDocument->GetScriptGlobalObject(getter_AddRefs(globalObject));
|
||||
nsCOMPtr<nsIDOMWindowInternal> window = do_QueryInterface(globalObject);
|
||||
|
||||
PRBool loop = PR_TRUE;
|
||||
while (NS_SUCCEEDED(theEnum->HasMoreElements(&loop)) && loop) {
|
||||
theEnum->GetNext(getter_AddRefs(inst));
|
||||
|
||||
nsCOMPtr<nsIFormSubmitObserver> formSubmitObserver(
|
||||
do_QueryInterface(inst));
|
||||
if (formSubmitObserver) {
|
||||
rv = formSubmitObserver->Notify(this,
|
||||
window,
|
||||
aActionURL,
|
||||
aCancelSubmit);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (*aCancelSubmit) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsHTMLFormElement::CompareNodes(nsIDOMNode* a, nsIDOMNode* b, PRInt32* retval)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentA;
|
||||
PRInt32 indexA;
|
||||
rv = a->GetParentNode(getter_AddRefs(parentA));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!parentA) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
{
|
||||
// To get the index, we must turn them both into contents
|
||||
// and do IndexOf(). Ick.
|
||||
nsCOMPtr<nsIContent> parentA(do_QueryInterface(parentA));
|
||||
nsCOMPtr<nsIContent> contentA(do_QueryInterface(a));
|
||||
if (!parentA && !contentA) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
rv = parentA->IndexOf(contentA, indexA);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentB;
|
||||
PRInt32 indexB;
|
||||
rv = b->GetParentNode(getter_AddRefs(parentB));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!parentB) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
{
|
||||
// To get the index, we must turn them both into contents
|
||||
// and do IndexOf(). Ick.
|
||||
nsCOMPtr<nsIContent> parentB(do_QueryInterface(parentB));
|
||||
nsCOMPtr<nsIContent> bContent(do_QueryInterface(b));
|
||||
if (!parentB && !bContent) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
rv = parentB->IndexOf(bContent, indexB);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
*retval = ComparePoints(parentA, indexA, parentB, indexB);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::WalkFormElements(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
//
|
||||
// If the submitter is an input type=image element, it is not in the
|
||||
// form.elements[] array. So we get the DOMNode pointer to it here so that
|
||||
// later we can determine its proper position in the submit order.
|
||||
//
|
||||
nsCOMPtr<nsIDOMNode> imageElementNode;
|
||||
{
|
||||
nsCOMPtr<nsIFormControl> submitControl = do_QueryInterface(aSubmitElement);
|
||||
if (submitControl) {
|
||||
PRInt32 type;
|
||||
submitControl->GetType(&type);
|
||||
if (type == NS_FORM_INPUT_IMAGE) {
|
||||
imageElementNode = do_QueryInterface(aSubmitElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Walk the list of nodes and call SubmitNamesValues() on the controls
|
||||
//
|
||||
PRUint32 numElements;
|
||||
GetElementCount(&numElements);
|
||||
|
||||
PRUint32 elementX;
|
||||
for (elementX = 0; elementX < numElements; elementX++) {
|
||||
nsCOMPtr<nsIFormControl> control;
|
||||
GetElementAt(elementX, getter_AddRefs(control));
|
||||
|
||||
// Determine whether/when to submit the image element, which is not in
|
||||
// the list of form.elements[]
|
||||
if (imageElementNode) {
|
||||
// If the input type=image element is before this element, submit it
|
||||
// instead
|
||||
nsCOMPtr<nsIDOMNode> controlNode(do_QueryInterface(control));
|
||||
PRInt32 comparison;
|
||||
CompareNodes(imageElementNode, controlNode, &comparison);
|
||||
if (comparison < 0) {
|
||||
nsCOMPtr<nsIFormControl> image = do_QueryInterface(imageElementNode);
|
||||
image->SubmitNamesValues(aFormSubmission, aSubmitElement);
|
||||
imageElementNode = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the control to submit its name/value pairs to the submission
|
||||
control->SubmitNamesValues(aFormSubmission, aSubmitElement);
|
||||
}
|
||||
|
||||
// The image appeared after all other controls
|
||||
if (imageElementNode) {
|
||||
nsCOMPtr<nsIFormControl> image = do_QueryInterface(imageElementNode);
|
||||
image->SubmitNamesValues(aFormSubmission, aSubmitElement);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::GetActionURL(nsIURI** aActionURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
*aActionURL = nsnull;
|
||||
|
||||
//
|
||||
// Grab the URL string
|
||||
//
|
||||
nsAutoString action;
|
||||
GetAction(action);
|
||||
|
||||
//
|
||||
// Form the full action URL
|
||||
//
|
||||
|
||||
// Get the document to form the URL.
|
||||
// We'll also need it later to get the DOM window when notifying form submit
|
||||
// observers (bug 33203)
|
||||
if (!mDocument) {
|
||||
return NS_OK; // No doc means don't submit, see Bug 28988
|
||||
}
|
||||
|
||||
// Get base URL
|
||||
nsCOMPtr<nsIURI> docURL;
|
||||
mDocument->GetBaseURL(*getter_AddRefs(docURL));
|
||||
NS_ASSERTION(docURL, "No Base URL found in Form Submit!\n");
|
||||
if (!docURL) {
|
||||
return NS_OK; // No base URL -> exit early, see Bug 30721
|
||||
}
|
||||
|
||||
// If an action is not specified and we are inside
|
||||
// a HTML document then reload the URL. This makes us
|
||||
// compatible with 4.x browsers.
|
||||
// If we are in some other type of document such as XML or
|
||||
// XUL, do nothing. This prevents undesirable reloading of
|
||||
// a document inside XUL.
|
||||
|
||||
nsCOMPtr<nsIURI> actionURL;
|
||||
if (action.IsEmpty()) {
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
|
||||
if (!htmlDoc) {
|
||||
// Must be a XML, XUL or other non-HTML document type
|
||||
// so do nothing.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = docURL->Clone(getter_AddRefs(actionURL));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
rv = NS_NewURI(getter_AddRefs(actionURL), action, docURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
//
|
||||
// Verify the URL should be reached
|
||||
//
|
||||
// Get security manager, check to see if access to action URI is allowed.
|
||||
//
|
||||
// XXX This code has not been tested. mailto: does not work in forms.
|
||||
//
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = securityManager->CheckLoadURI(docURL, actionURL,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLCString scheme;
|
||||
PRBool isMailto = PR_FALSE;
|
||||
if (actionURL && NS_FAILED(rv = actionURL->SchemeIs("mailto", &isMailto))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (isMailto) {
|
||||
PRBool enabled;
|
||||
rv = securityManager->IsCapabilityEnabled("UniversalSendMail", &enabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!enabled) {
|
||||
// Form submit to a mailto: URI requires UniversalSendMail privilege
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Assign to the output
|
||||
//
|
||||
*aActionURL = actionURL;
|
||||
NS_ADDREF(*aActionURL);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// nsIForm
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsIHTMLAttributes.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsIGfxTextControlFrame.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
@ -91,6 +92,14 @@
|
|||
|
||||
#include "nsRuleNode.h"
|
||||
|
||||
// input type=file
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
|
||||
|
||||
// XXX align=left, hspace, vspace, border? other nav4 attrs
|
||||
|
||||
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
||||
|
@ -142,12 +151,8 @@ public:
|
|||
// Overriden nsIFormControl methods
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState);
|
||||
NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);
|
||||
|
||||
|
@ -218,8 +223,7 @@ public:
|
|||
|
||||
protected:
|
||||
// Helper method
|
||||
void SetPresStateChecked(nsIHTMLContent * aHTMLContent,
|
||||
PRBool aValue);
|
||||
void SetPresStateChecked(nsIHTMLContent * aHTMLContent, PRBool aValue);
|
||||
NS_IMETHOD SetValueSecure(const nsAReadableString& aValue,
|
||||
nsIGfxTextControlFrame2* aFrame,
|
||||
PRBool aCheckSecurity);
|
||||
|
@ -244,6 +248,8 @@ protected:
|
|||
|
||||
void FireOnChange();
|
||||
|
||||
static nsresult GetContentType(const char* aPathName, char** aContentType);
|
||||
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
|
||||
PRInt8 mType;
|
||||
|
@ -1848,132 +1854,71 @@ nsHTMLInputElement::Reset()
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLInputElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// if it's disabled, it won't submit
|
||||
//
|
||||
// Disabled elements don't submit
|
||||
//
|
||||
PRBool disabled;
|
||||
nsresult rv = GetDisabled(&disabled);
|
||||
if (disabled) {
|
||||
return NS_OK;
|
||||
rv = GetDisabled(&disabled);
|
||||
if (NS_FAILED(rv) || disabled) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the type (many ops depend on the type)
|
||||
//
|
||||
PRInt32 type;
|
||||
GetType(&type);
|
||||
rv = GetType(&type);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// if it dosn't have a name it we don't submit
|
||||
if (type != NS_FORM_INPUT_IMAGE) {
|
||||
nsAutoString val;
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, val);
|
||||
if (rv == NS_CONTENT_ATTR_NOT_THERE) {
|
||||
return NS_OK;
|
||||
//
|
||||
// For type=reset, and type=button, we just never submit, period.
|
||||
//
|
||||
if (type == NS_FORM_INPUT_RESET || type == NS_FORM_INPUT_BUTTON) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// For type=image and type=button, we only submit if we were the button
|
||||
// pressed
|
||||
//
|
||||
if ((type == NS_FORM_INPUT_SUBMIT || type == NS_FORM_INPUT_IMAGE)
|
||||
&& aSubmitElement != this) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// For type=radio and type=checkbox, we only submit if checked=true
|
||||
//
|
||||
if (type == NS_FORM_INPUT_RADIO || type == NS_FORM_INPUT_CHECKBOX) {
|
||||
PRBool checked;
|
||||
rv = GetChecked(&checked);
|
||||
if (NS_FAILED(rv) || !checked) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NS_FORM_INPUT_CHECKBOX:
|
||||
case NS_FORM_INPUT_RADIO:
|
||||
{
|
||||
GetChecked(_retval);
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_HIDDEN:
|
||||
case NS_FORM_INPUT_PASSWORD:
|
||||
case NS_FORM_INPUT_TEXT:
|
||||
case NS_FORM_INPUT_FILE:
|
||||
{
|
||||
*_retval = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_RESET:
|
||||
case NS_FORM_INPUT_BUTTON:
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_SUBMIT:
|
||||
case NS_FORM_INPUT_IMAGE:
|
||||
{
|
||||
*_retval = (this == aSubmitElement);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLInputElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
PRInt32 type;
|
||||
GetType(&type);
|
||||
if (type == NS_FORM_INPUT_IMAGE) {
|
||||
//
|
||||
// Get the name
|
||||
//
|
||||
nsAutoString name;
|
||||
nsAutoString value;
|
||||
GetName(name);
|
||||
GetValue(value);
|
||||
if (name.IsEmpty() || value.IsEmpty()) {
|
||||
*_retval = 2;
|
||||
} else {
|
||||
*_retval = 3;
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
*_retval = 1;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLInputElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 type;
|
||||
GetType(&type);
|
||||
|
||||
switch (type) {
|
||||
case NS_FORM_INPUT_CHECKBOX:
|
||||
case NS_FORM_INPUT_RADIO:
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 1, NS_ERROR_UNEXPECTED);
|
||||
|
||||
GetName(aNames[0]);
|
||||
GetValue(aValues[0]);
|
||||
aNumValues = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_HIDDEN:
|
||||
case NS_FORM_INPUT_PASSWORD:
|
||||
case NS_FORM_INPUT_TEXT:
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 1, NS_ERROR_UNEXPECTED);
|
||||
|
||||
GetName(aNames[0]);
|
||||
GetValue(aValues[0]);
|
||||
aNumValues = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_FILE:
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 1, NS_ERROR_UNEXPECTED);
|
||||
|
||||
GetName(aNames[0]);
|
||||
GetValue(aValues[0]);
|
||||
aNumValues = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_IMAGE:
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 2, NS_ERROR_UNEXPECTED);
|
||||
PRBool nameThere = (rv != NS_CONTENT_ATTR_NOT_THERE);
|
||||
|
||||
//
|
||||
// Submit .x, .y for input type=image
|
||||
//
|
||||
if (type == NS_FORM_INPUT_IMAGE) {
|
||||
// Go to the frame to find out where it was clicked. This is the only
|
||||
// case where I can actually see using the frame, because you're talking
|
||||
// about a value--mouse click--that is rightfully the domain of the frame.
|
||||
|
@ -1989,67 +1934,136 @@ nsHTMLInputElement::GetNamesValues(PRInt32 aMaxNumValues,
|
|||
if (imageControlFrame) {
|
||||
imageControlFrame->GetClickedX(&clickedX);
|
||||
imageControlFrame->GetClickedY(&clickedY);
|
||||
} else {
|
||||
aNumValues = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Convert the values to strings for submission
|
||||
char buf[20];
|
||||
sprintf(&buf[0], "%d", clickedX);
|
||||
aValues[0].AssignWithConversion(&buf[0]);
|
||||
nsAutoString xVal = NS_ConvertASCIItoUCS2(buf);
|
||||
sprintf(&buf[0], "%d", clickedY);
|
||||
aValues[1].AssignWithConversion(&buf[0]);
|
||||
nsAutoString yVal = NS_ConvertASCIItoUCS2(buf);
|
||||
|
||||
// Figure out the proper name of the x and y values
|
||||
nsAutoString name;
|
||||
rv = GetName(name);
|
||||
if (!name.IsEmpty()) {
|
||||
aNames[0] = name;
|
||||
aNames[0].Append(NS_LITERAL_STRING(".x"));
|
||||
aNames[1] = name;
|
||||
aNames[1].Append(NS_LITERAL_STRING(".y"));
|
||||
nsAutoString value;
|
||||
rv = GetValue(value);
|
||||
if (!value.IsEmpty()) {
|
||||
aNames[2] = name;
|
||||
aValues[2] = value;
|
||||
aNumValues = 3;
|
||||
} else {
|
||||
aNumValues = 2;
|
||||
}
|
||||
aFormSubmission->AddNameValuePair(this,
|
||||
name + NS_LITERAL_STRING(".x"), xVal);
|
||||
aFormSubmission->AddNameValuePair(this,
|
||||
name + NS_LITERAL_STRING(".y"), yVal);
|
||||
} else {
|
||||
// If the Image Element has no name, simply return x and y
|
||||
// to Nav and IE compatability.
|
||||
aNames[0] = NS_LITERAL_STRING("x");
|
||||
aNames[1] = NS_LITERAL_STRING("y");
|
||||
aNumValues = 2;
|
||||
aFormSubmission->AddNameValuePair(this, NS_LITERAL_STRING("x"), xVal);
|
||||
aFormSubmission->AddNameValuePair(this, NS_LITERAL_STRING("y"), yVal);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_RESET:
|
||||
case NS_FORM_INPUT_BUTTON:
|
||||
{
|
||||
aNumValues = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case NS_FORM_INPUT_SUBMIT:
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 1, NS_ERROR_UNEXPECTED);
|
||||
|
||||
GetName(aNames[0]);
|
||||
GetValue(aValues[0]);
|
||||
aNumValues = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
//
|
||||
// Submit name=value
|
||||
//
|
||||
|
||||
// If name not there, don't submit
|
||||
if (!nameThere) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Get the value
|
||||
nsAutoString value;
|
||||
rv = GetValue(value);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Submit file if it's input type=file and this encoding method accepts files
|
||||
//
|
||||
PRBool submittedValue = PR_FALSE;
|
||||
if (type == NS_FORM_INPUT_FILE) {
|
||||
|
||||
//
|
||||
// Open the file
|
||||
//
|
||||
nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID,
|
||||
&rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = file->InitWithUnicodePath(value.get());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
||||
//
|
||||
// Get the leaf path name (to be submitted as the value)
|
||||
//
|
||||
PRUnichar* leafNameChars = nsnull;
|
||||
rv = file->GetUnicodeLeafName(&leafNameChars);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (leafNameChars) {
|
||||
nsAutoString filename;
|
||||
filename.Adopt(leafNameChars);
|
||||
|
||||
PRBool acceptsFiles = PR_FALSE;
|
||||
aFormSubmission->AcceptsFiles(&acceptsFiles);
|
||||
|
||||
if (acceptsFiles) {
|
||||
//
|
||||
// Get content type
|
||||
//
|
||||
nsCOMPtr<nsIMIMEService> MIMEService =
|
||||
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char * contentTypeChars = nsnull;
|
||||
rv = MIMEService->GetTypeFromFile(file, &contentTypeChars);
|
||||
|
||||
nsCAutoString contentType;
|
||||
if (contentTypeChars) {
|
||||
contentType.Adopt(contentTypeChars);
|
||||
} else {
|
||||
contentType = NS_LITERAL_CSTRING("application/octet-stream");
|
||||
}
|
||||
|
||||
//
|
||||
// Get input stream
|
||||
//
|
||||
nsCOMPtr<nsIInputStream> rawStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(rawStream), file);
|
||||
if (rawStream) {
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
rawStream, 8192);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
//
|
||||
// Submit
|
||||
//
|
||||
aFormSubmission->AddNameFilePair(this, name, filename,
|
||||
bufferedStream, contentType,
|
||||
PR_FALSE);
|
||||
submittedValue = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If we don't submit as a file, at least submit the truncated filename.
|
||||
//
|
||||
if (!submittedValue) {
|
||||
aFormSubmission->AddNameValuePair(this, name, filename);
|
||||
submittedValue = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!submittedValue) {
|
||||
// Submit
|
||||
// (for type=image, only submit if value is non-null)
|
||||
if (type != NS_FORM_INPUT_IMAGE || !value.IsEmpty()) {
|
||||
rv = aFormSubmission->AddNameValuePair(this, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLInputElement::SaveState(nsIPresContext* aPresContext,
|
||||
nsIPresState** aState)
|
||||
|
@ -2109,4 +2123,3 @@ nsHTMLInputElement::RestoreState(nsIPresContext* aPresContext,
|
|||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,12 +172,8 @@ public:
|
|||
// nsIFormControl
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
// nsIContent
|
||||
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
|
||||
|
@ -420,27 +416,9 @@ nsHTMLLabelElement::Reset()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLLabelElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLLabelElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLLabelElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLLabelElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
aNumValues = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -75,12 +75,8 @@ public:
|
|||
// nsIFormControl
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
// nsIContent
|
||||
NS_IMETHOD StringToAttribute(nsIAtom* aAttribute,
|
||||
|
@ -253,27 +249,9 @@ nsHTMLLegendElement::Reset()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLLegendElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLLegendElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLLegendElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLLegendElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
aNumValues = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsIPresContext.h"
|
||||
#include "nsIHTMLAttributes.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDOMHTMLOptionElement.h"
|
||||
#include "nsIDOMHTMLOptGroupElement.h"
|
||||
|
@ -175,12 +176,8 @@ public:
|
|||
// Overriden nsIFormControl methods
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
|
||||
// nsISelectElement
|
||||
NS_DECL_NSISELECTELEMENT
|
||||
|
@ -1977,59 +1974,36 @@ nsHTMLSelectElement::InitializeOption(nsIDOMHTMLOptionElement * aOption,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Since this is multivalued, IsSuccessful here only really says whether
|
||||
// we're *allowed* to submit options here. There still may be no successful
|
||||
// options and nothing will submit.
|
||||
nsresult
|
||||
nsHTMLSelectElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLSelectElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
// if it's disabled, it won't submit
|
||||
PRBool disabled;
|
||||
nsresult rv = GetDisabled(&disabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (disabled) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
//
|
||||
// Disabled elements don't submit
|
||||
//
|
||||
PRBool disabled;
|
||||
rv = GetDisabled(&disabled);
|
||||
if (NS_FAILED(rv) || disabled) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If there is no name, it won't submit
|
||||
nsAutoString val;
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, val);
|
||||
*_retval = rv != NS_CONTENT_ATTR_NOT_THERE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLSelectElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
PRUint32 length;
|
||||
nsresult rv = GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*_retval = length;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLSelectElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
//
|
||||
// Get the name (if no name, no submit)
|
||||
//
|
||||
nsAutoString name;
|
||||
nsresult rv = GetName(name);
|
||||
|
||||
PRInt32 sentOptions = 0;
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
if (NS_FAILED(rv) || rv == NS_CONTENT_ATTR_NOT_THERE) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Submit
|
||||
//
|
||||
PRUint32 len;
|
||||
GetLength(&len);
|
||||
|
||||
// We loop through the cached list of selected items because it's
|
||||
// hella faster than looping through all options
|
||||
for (PRUint32 optIndex = 0; optIndex < len; optIndex++) {
|
||||
// Don't send disabled options
|
||||
PRBool disabled;
|
||||
|
@ -2040,30 +2014,24 @@ nsHTMLSelectElement::GetNamesValues(PRInt32 aMaxNumValues,
|
|||
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> option;
|
||||
mOptions->ItemAsOption(optIndex, getter_AddRefs(option));
|
||||
if (option) {
|
||||
NS_ENSURE_TRUE(option, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRBool isSelected;
|
||||
rv = option->GetSelected(&isSelected);
|
||||
if (NS_FAILED(rv) || !isSelected) {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!isSelected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIOptionElement> optionElement = do_QueryInterface(option);
|
||||
if (optionElement) {
|
||||
NS_ENSURE_TRUE(optionElement, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAutoString value;
|
||||
rv = optionElement->GetValueOrText(value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the value is not there
|
||||
if (sentOptions < aMaxNumValues) {
|
||||
aNames[sentOptions] = name;
|
||||
aValues[sentOptions] = value;
|
||||
sentOptions++;
|
||||
rv = aFormSubmission->AddNameValuePair(this, name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aNumValues = sentOptions;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIForm.h"
|
||||
#include "nsIFormSubmission.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
|
@ -106,12 +107,8 @@ public:
|
|||
// nsIFormControl
|
||||
NS_IMETHOD GetType(PRInt32* aType);
|
||||
NS_IMETHOD Reset();
|
||||
NS_IMETHOD IsSuccessful(nsIContent* aSubmitElement, PRBool *_retval);
|
||||
NS_IMETHOD GetMaxNumValues(PRInt32 *_retval);
|
||||
NS_IMETHOD GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames);
|
||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement);
|
||||
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState);
|
||||
NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);
|
||||
|
||||
|
@ -874,55 +871,48 @@ nsHTMLTextAreaElement::Reset()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::IsSuccessful(nsIContent* aSubmitElement,
|
||||
PRBool *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTextAreaElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||
nsIContent* aSubmitElement)
|
||||
{
|
||||
// if it's disabled, it won't submit
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
//
|
||||
// Disabled elements don't submit
|
||||
//
|
||||
PRBool disabled;
|
||||
nsresult rv = GetDisabled(&disabled);
|
||||
if (disabled) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
rv = GetDisabled(&disabled);
|
||||
if (NS_FAILED(rv) || disabled) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// if it dosn't have a name it we don't submit
|
||||
nsAutoString val;
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, val);
|
||||
*_retval = rv != NS_CONTENT_ATTR_NOT_THERE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::GetMaxNumValues(PRInt32 *_retval)
|
||||
{
|
||||
*_retval = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTextAreaElement::GetNamesValues(PRInt32 aMaxNumValues,
|
||||
PRInt32& aNumValues,
|
||||
nsString* aValues,
|
||||
nsString* aNames)
|
||||
{
|
||||
NS_ENSURE_TRUE(aMaxNumValues >= 1, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// We'll of course use the name of the control for the submit
|
||||
//
|
||||
// Get the name (if no name, no submit)
|
||||
//
|
||||
nsAutoString name;
|
||||
nsresult rv = GetName(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
|
||||
if (NS_FAILED(rv) || rv == NS_CONTENT_ATTR_NOT_THERE) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the value
|
||||
//
|
||||
nsAutoString value;
|
||||
rv = GetValue(value);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aNames[0] = name;
|
||||
aValues[0] = value;
|
||||
aNumValues = 1;
|
||||
return NS_OK;
|
||||
//
|
||||
// Submit
|
||||
//
|
||||
rv = aFormSubmission->AddNameValuePair(this, name, value);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTextAreaElement::SaveState(nsIPresContext* aPresContext,
|
||||
nsIPresState** aState)
|
||||
|
|
|
@ -8,6 +8,7 @@ nsIChannel.idl
|
|||
nsIFileChannel.idl
|
||||
nsIDownloader.idl
|
||||
nsIFileTransportService.idl
|
||||
nsIMIMEInputStream.idl
|
||||
nsIPasswordManager.idl
|
||||
nsIPrompt.idl
|
||||
nsIProtocolProxyService.idl
|
||||
|
|
|
@ -38,6 +38,7 @@ XPIDLSRCS = \
|
|||
nsIFileTransportService.idl \
|
||||
nsIIOService.idl \
|
||||
nsILoadGroup.idl \
|
||||
nsIMIMEInputStream.idl \
|
||||
nsINetModRegEntry.idl \
|
||||
nsINetModuleMgr.idl \
|
||||
nsINetNotify.idl \
|
||||
|
|
|
@ -40,6 +40,7 @@ XPIDLSRCS = \
|
|||
.\nsIFileTransportService.idl \
|
||||
.\nsIIOService.idl \
|
||||
.\nsILoadGroup.idl \
|
||||
.\nsIMIMEInputStream.idl \
|
||||
.\nsINetModRegEntry.idl \
|
||||
.\nsINetModuleMgr.idl \
|
||||
.\nsINetNotify.idl \
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is frightening to behold.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIInputStream.idl"
|
||||
|
||||
/**
|
||||
* The MIME stream separates headers and a datastream. It also allows
|
||||
* automatic creation of the content-length header.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(dcbce63c-1dd1-11b2-b94d-91f6d49a3161)]
|
||||
interface nsIMIMEInputStream : nsIInputStream
|
||||
{
|
||||
/**
|
||||
* When true a "Content-Length" header is automatically added to the
|
||||
* stream. The value of the content-length is automatically calculated
|
||||
* using the available() method on the data stream. The value is
|
||||
* recalculated every time the stream is rewinded to the start.
|
||||
* Not allowed to be changed once the stream has been started to be read.
|
||||
*/
|
||||
attribute boolean addContentLength;
|
||||
|
||||
/**
|
||||
* Adds an additional header to the stream on the form "name: value". May
|
||||
* not be called once the stream has been started to be read.
|
||||
* @param name name of the header
|
||||
* @param value value of the header
|
||||
*/
|
||||
void addHeader([const] in string name, [const] in string value);
|
||||
|
||||
/**
|
||||
* Sets data-stream. May not be called once the stream has been started
|
||||
* to be read.
|
||||
* The cursor of the new stream should be located at the beginning of the
|
||||
* stream if the implementation of the nsIMIMEInputStream also is used as
|
||||
* an nsISeekableStream.
|
||||
* @param stream stream containing the data for the stream
|
||||
*/
|
||||
void setData(in nsIInputStream stream);
|
||||
};
|
|
@ -49,6 +49,7 @@ CPPSRCS = \
|
|||
nsInputStreamChannel.cpp \
|
||||
nsIOService.cpp \
|
||||
nsLoadGroup.cpp \
|
||||
nsMIMEInputStream.cpp \
|
||||
nsNetModRegEntry.cpp \
|
||||
nsNetModuleMgr.cpp \
|
||||
nsProtocolProxyService.cpp \
|
||||
|
|
|
@ -54,6 +54,7 @@ CPP_OBJS = \
|
|||
.\$(OBJDIR)\nsURLParsers.obj \
|
||||
.\$(OBJDIR)\nsStandardURL.obj \
|
||||
.\$(OBJDIR)\nsSimpleURI.obj \
|
||||
.\$(OBJDIR)\nsMIMEInputStream.obj \
|
||||
.\$(OBJDIR)\nsNetModuleMgr.obj \
|
||||
.\$(OBJDIR)\nsNetModRegEntry.obj \
|
||||
.\$(OBJDIR)\nsLoadGroup.obj \
|
||||
|
|
|
@ -251,8 +251,13 @@ nsBufferedInputStream::Close()
|
|||
NS_IMETHODIMP
|
||||
nsBufferedInputStream::Available(PRUint32 *result)
|
||||
{
|
||||
*result = mFillPoint - mCursor;
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
*result = 0;
|
||||
if (mStream) {
|
||||
rv = Source()->Available(result);
|
||||
}
|
||||
*result += (mFillPoint - mCursor);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is frightening to behold.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The MIME stream separates headers and a datastream. It also allows
|
||||
* automatic creation of the content-length header.
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIMultiplexInputStream.h"
|
||||
#include "nsIMIMEInputStream.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsIStringStream.h"
|
||||
|
||||
class nsMIMEInputStream : public nsIMIMEInputStream,
|
||||
public nsISeekableStream
|
||||
{
|
||||
public:
|
||||
nsMIMEInputStream();
|
||||
virtual ~nsMIMEInputStream();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINPUTSTREAM
|
||||
NS_DECL_NSIMIMEINPUTSTREAM
|
||||
NS_DECL_NSISEEKABLESTREAM
|
||||
|
||||
NS_METHOD Init();
|
||||
|
||||
private:
|
||||
|
||||
void InitStreams();
|
||||
|
||||
struct ReadSegmentsState {
|
||||
nsIInputStream* mThisStream;
|
||||
nsWriteSegmentFun mWriter;
|
||||
void* mClosure;
|
||||
};
|
||||
static NS_METHOD ReadSegCb(nsIInputStream* aIn, void* aClosure,
|
||||
const char* aFromRawSegment, PRUint32 aToOffset,
|
||||
PRUint32 aCount, PRUint32 *aWriteCount);
|
||||
|
||||
nsCString mHeaders;
|
||||
nsCOMPtr<nsIStringInputStream> mHeaderStream;
|
||||
|
||||
nsCString mContentLength;
|
||||
nsCOMPtr<nsIStringInputStream> mCLStream;
|
||||
|
||||
nsCOMPtr<nsIInputStream> mData;
|
||||
nsCOMPtr<nsIMultiplexInputStream> mStream;
|
||||
PRPackedBool mAddContentLength;
|
||||
PRPackedBool mStartedReading;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsMIMEInputStream,
|
||||
nsIMIMEInputStream,
|
||||
nsIInputStream,
|
||||
nsISeekableStream);
|
||||
|
||||
nsMIMEInputStream::nsMIMEInputStream() : mAddContentLength(PR_FALSE),
|
||||
mStartedReading(PR_FALSE)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsMIMEInputStream::~nsMIMEInputStream()
|
||||
{
|
||||
}
|
||||
|
||||
NS_METHOD nsMIMEInputStream::Init()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
mStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1",
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHeaderStream = do_CreateInstance("@mozilla.org/io/string-input-stream;1",
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mCLStream = do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIInputStream> headerStream = do_QueryInterface(mHeaderStream);
|
||||
nsCOMPtr<nsIInputStream> clStream = do_QueryInterface(mCLStream);
|
||||
rv = mStream->AppendStream(headerStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mStream->AppendStream(clStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* attribute boolean addContentLength; */
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInputStream::GetAddContentLength(PRBool *aAddContentLength)
|
||||
{
|
||||
*aAddContentLength = mAddContentLength;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInputStream::SetAddContentLength(PRBool aAddContentLength)
|
||||
{
|
||||
NS_ENSURE_FALSE(mStartedReading, NS_ERROR_FAILURE);
|
||||
mAddContentLength = aAddContentLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void addHeader ([const] in string name, [const] in string value); */
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInputStream::AddHeader(const char *aName, const char *aValue)
|
||||
{
|
||||
NS_ENSURE_FALSE(mStartedReading, NS_ERROR_FAILURE);
|
||||
mHeaders.Append(aName);
|
||||
mHeaders.Append(": ");
|
||||
mHeaders.Append(aValue);
|
||||
mHeaders.Append("\r\n");
|
||||
|
||||
// Just in case someone somehow uses our stream, lets at least
|
||||
// let the stream have a valid pointer. The stream will be properly
|
||||
// initialized in nsMIMEInputStream::InitStreams
|
||||
mHeaderStream->ShareData(mHeaders.get(), 0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void setData (in nsIInputStream stream); */
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInputStream::SetData(nsIInputStream *aStream)
|
||||
{
|
||||
NS_ENSURE_FALSE(mStartedReading, NS_ERROR_FAILURE);
|
||||
// Remove the old stream if there is one
|
||||
if (mData)
|
||||
mStream->RemoveStream(2);
|
||||
|
||||
mData = aStream;
|
||||
if (aStream)
|
||||
mStream->AppendStream(mData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// set up the internal streams
|
||||
void nsMIMEInputStream::InitStreams()
|
||||
{
|
||||
NS_ASSERTION(!mStartedReading,
|
||||
"Don't call initStreams twice without rewinding");
|
||||
|
||||
mStartedReading = PR_TRUE;
|
||||
|
||||
// We'll use the content-length stream to add the final \r\n
|
||||
if (mAddContentLength && mData) {
|
||||
PRUint32 cl;
|
||||
mData->Available(&cl);
|
||||
if (!cl) {
|
||||
mContentLength = "\r\n";
|
||||
}
|
||||
else {
|
||||
mContentLength = "Content-Length: ";
|
||||
mContentLength.AppendInt((PRInt32)cl);
|
||||
mContentLength.Append("\r\n\r\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
mContentLength = "\r\n";
|
||||
}
|
||||
mCLStream->ShareData(mContentLength.get(), -1);
|
||||
mHeaderStream->ShareData(mHeaders.get(), -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define INITSTREAMS \
|
||||
if (!mStartedReading) { \
|
||||
InitStreams(); \
|
||||
}
|
||||
|
||||
// Reset mStartedReading when Seek-ing to start
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInputStream::Seek(PRInt32 whence, PRInt32 offset)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);
|
||||
if (whence == NS_SEEK_SET && offset == 0) {
|
||||
rv = stream->Seek(whence, offset);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mStartedReading = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
INITSTREAMS;
|
||||
rv = stream->Seek(whence, offset);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Proxy ReadSegments since we need to be a good little nsIInputStream
|
||||
NS_IMETHODIMP nsMIMEInputStream::ReadSegments(nsWriteSegmentFun aWriter,
|
||||
void *aClosure, PRUint32 aCount,
|
||||
PRUint32 *_retval)
|
||||
{
|
||||
INITSTREAMS;
|
||||
ReadSegmentsState state;
|
||||
state.mThisStream = this;
|
||||
state.mWriter = aWriter;
|
||||
state.mClosure = aClosure;
|
||||
return mStream->ReadSegments(ReadSegCb, &state, aCount, _retval);
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsMIMEInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
|
||||
const char* aFromRawSegment,
|
||||
PRUint32 aToOffset, PRUint32 aCount,
|
||||
PRUint32 *aWriteCount)
|
||||
{
|
||||
ReadSegmentsState* state = (ReadSegmentsState*)aClosure;
|
||||
return (state->mWriter)(state->mThisStream,
|
||||
state->mClosure,
|
||||
aFromRawSegment,
|
||||
aToOffset,
|
||||
aCount,
|
||||
aWriteCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward everything else to the mStream after calling InitStreams()
|
||||
*/
|
||||
|
||||
// nsIInputStream
|
||||
NS_IMETHODIMP nsMIMEInputStream::Close(void) { INITSTREAMS; return mStream->Close(); }
|
||||
NS_IMETHODIMP nsMIMEInputStream::Available(PRUint32 *_retval) { INITSTREAMS; return mStream->Available(_retval); }
|
||||
NS_IMETHODIMP nsMIMEInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval) { INITSTREAMS; return mStream->Read(buf, count, _retval); }
|
||||
NS_IMETHODIMP nsMIMEInputStream::GetNonBlocking(PRBool *aNonBlocking) { INITSTREAMS; return mStream->GetNonBlocking(aNonBlocking); }
|
||||
NS_IMETHODIMP nsMIMEInputStream::GetObserver(nsIInputStreamObserver * *aObserver) { INITSTREAMS; return mStream->GetObserver(aObserver); }
|
||||
NS_IMETHODIMP nsMIMEInputStream::SetObserver(nsIInputStreamObserver * aObserver) { INITSTREAMS; return mStream->SetObserver(aObserver); }
|
||||
|
||||
// nsISeekableStream
|
||||
NS_IMETHODIMP nsMIMEInputStream::Tell(PRUint32 *_retval)
|
||||
{
|
||||
INITSTREAMS;
|
||||
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);
|
||||
return stream->Tell(_retval);
|
||||
}
|
||||
NS_IMETHODIMP nsMIMEInputStream::SetEOF(void) {
|
||||
INITSTREAMS;
|
||||
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStream);
|
||||
return stream->SetEOF();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory method used by do_CreateInstance
|
||||
*/
|
||||
|
||||
NS_METHOD
|
||||
nsMIMEInputStreamConstructor(nsISupports *outer, REFNSIID iid, void **result)
|
||||
{
|
||||
*result = nsnull;
|
||||
|
||||
if (outer)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsMIMEInputStream *inst;
|
||||
NS_NEWXPCOM(inst, nsMIMEInputStream);
|
||||
if (!inst)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(inst);
|
||||
|
||||
nsresult rv = inst->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(inst);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = inst->QueryInterface(iid, result);
|
||||
NS_RELEASE(inst);
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is frightening to behold.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The MIME stream separates headers and a datastream. It also allows
|
||||
* automatic creation of the content-length header.
|
||||
*/
|
||||
|
||||
#ifndef _nsMIMEInputStream_h_
|
||||
#define _nsMIMEInputStream_h_
|
||||
|
||||
#include "nsIMIMEInputStream.h"
|
||||
|
||||
#define NS_MIMEINPUTSTREAM_CLASSNAME "nsMIMEInputStream"
|
||||
#define NS_MIMEINPUTSTREAM_CONTRACTID "@mozilla.org/network/mime-input-stream;1"
|
||||
#define NS_MIMEINPUTSTREAM_CID \
|
||||
{ /* 58a1c31c-1dd2-11b2-a3f6-d36949d48268 */ \
|
||||
0x58a1c31c, \
|
||||
0x1dd2, \
|
||||
0x11b2, \
|
||||
{0xa3, 0xf6, 0xd3, 0x69, 0x49, 0xd4, 0x82, 0x68} \
|
||||
}
|
||||
|
||||
extern NS_METHOD nsMIMEInputStreamConstructor(nsISupports *outer,
|
||||
REFNSIID iid,
|
||||
void **result);
|
||||
|
||||
#endif // _nsMIMEInputStream_h_
|
|
@ -56,6 +56,7 @@
|
|||
#include "nsAsyncStreamListener.h"
|
||||
#include "nsFileStreams.h"
|
||||
#include "nsBufferedStreams.h"
|
||||
#include "nsMIMEInputStream.h"
|
||||
#include "nsProtocolProxyService.h"
|
||||
#include "nsSOCKSSocketProvider.h"
|
||||
#include "nsSOCKS4SocketProvider.h"
|
||||
|
@ -724,6 +725,10 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
|
|||
NS_BUFFEREDOUTPUTSTREAM_CID,
|
||||
NS_BUFFEREDOUTPUTSTREAM_CONTRACTID,
|
||||
nsBufferedOutputStream::Create },
|
||||
{ NS_MIMEINPUTSTREAM_CLASSNAME,
|
||||
NS_MIMEINPUTSTREAM_CID,
|
||||
NS_MIMEINPUTSTREAM_CONTRACTID,
|
||||
nsMIMEInputStreamConstructor },
|
||||
{ "Protocol Proxy Service",
|
||||
NS_PROTOCOLPROXYSERVICE_CID,
|
||||
"@mozilla.org/network/protocol-proxy-service;1",
|
||||
|
|
|
@ -1058,6 +1058,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -1664,6 +1671,11 @@
|
|||
<PATH>nsLoadGroup.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -3056,6 +3068,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -3662,6 +3681,11 @@
|
|||
<PATH>nsLoadGroup.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -5054,6 +5078,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -5646,6 +5677,11 @@
|
|||
<PATH>nsLoadGroup.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -7028,6 +7064,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -7620,6 +7663,11 @@
|
|||
<PATH>nsLoadGroup.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsInputStreamChannel.cpp</PATH>
|
||||
|
@ -8080,6 +8128,12 @@
|
|||
<PATH>nsLoadGroup.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>Necko.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMIMEInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>Necko.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
|
|
@ -1414,6 +1414,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMIMEInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIResumableChannel.idl</PATH>
|
||||
|
@ -1840,6 +1847,11 @@
|
|||
<PATH>nsIFileProtocolHandler.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMIMEInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIResumableChannel.idl</PATH>
|
||||
|
@ -3206,6 +3218,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMIMEInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIResumableChannel.idl</PATH>
|
||||
|
@ -3627,6 +3646,11 @@
|
|||
<PATH>nsIFileProtocolHandler.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMIMEInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIResumableChannel.idl</PATH>
|
||||
|
@ -4004,6 +4028,12 @@
|
|||
<PATH>nsIUploadChannel.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMIMEInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</GROUP>
|
||||
<GROUP><NAME>mimetype</NAME>
|
||||
<FILEREF>
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsMultiplexInputStream.h"
|
||||
|
||||
#include "nsFastLoadService.h"
|
||||
|
||||
|
@ -278,6 +279,7 @@ static const nsModuleComponentInfo components[] = {
|
|||
COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create),
|
||||
|
||||
COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor),
|
||||
COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor),
|
||||
|
||||
COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create),
|
||||
COMPONENT(VARIANT, nsVariantConstructor),
|
||||
|
|
|
@ -10,6 +10,7 @@ nsIInputStream.idl
|
|||
nsIInputStreamTee.idl
|
||||
nsILineInputStream.idl
|
||||
nsILocalFile.idl
|
||||
nsIMultiplexInputStream.idl
|
||||
nsIObjectInputStream.idl
|
||||
nsIObjectOutputStream.idl
|
||||
nsIOutputStream.idl
|
||||
|
|
|
@ -50,6 +50,7 @@ CPPSRCS = \
|
|||
nsLinebreakConverter.cpp \
|
||||
nsLocalFileCommon.cpp \
|
||||
nsLocalFileUnicode.cpp \
|
||||
nsMultiplexInputStream.cpp \
|
||||
nsPipe2.cpp \
|
||||
nsScriptableInputStream.cpp \
|
||||
nsSegmentedBuffer.cpp \
|
||||
|
@ -119,6 +120,7 @@ XPIDLSRCS = \
|
|||
nsIInputStreamTee.idl \
|
||||
nsILineInputStream.idl \
|
||||
nsILocalFile.idl \
|
||||
nsIMultiplexInputStream.idl \
|
||||
nsIObjectInputStream.idl \
|
||||
nsIObjectOutputStream.idl \
|
||||
nsIOutputStream.idl \
|
||||
|
|
|
@ -62,6 +62,7 @@ XPIDLSRCS = \
|
|||
.\nsIInputStreamTee.idl \
|
||||
.\nsILineInputStream.idl \
|
||||
.\nsILocalFile.idl \
|
||||
.\nsIMultiplexInputStream.idl \
|
||||
.\nsIObjectInputStream.idl \
|
||||
.\nsIObjectOutputStream.idl \
|
||||
.\nsIOutputStream.idl \
|
||||
|
@ -97,6 +98,7 @@ CPP_OBJS = \
|
|||
.\$(OBJDIR)\nsLinebreakConverter.obj \
|
||||
.\$(OBJDIR)\nsLocalFileCommon.obj \
|
||||
.\$(OBJDIR)\nsLocalFileWin.obj \
|
||||
.\$(OBJDIR)\nsMultiplexInputStream.obj \
|
||||
.\$(OBJDIR)\nsPipe2.obj \
|
||||
.\$(OBJDIR)\nsScriptableInputStream.obj \
|
||||
.\$(OBJDIR)\nsSegmentedBuffer.obj \
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is frightening to behold.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIInputStream.idl"
|
||||
|
||||
/**
|
||||
* The multiplex stream concatinates a list of input streams into a single
|
||||
* stream.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(a076fd12-1dd1-11b2-b19a-d53b5dffaade)]
|
||||
interface nsIMultiplexInputStream : nsIInputStream
|
||||
{
|
||||
/**
|
||||
* Number of streams in this multiplex-stream
|
||||
*/
|
||||
readonly attribute unsigned long count;
|
||||
|
||||
/**
|
||||
* Appends a stream to the end of the streams. The cursor of the stream
|
||||
* should be located at the beginning of the stream if the implementation
|
||||
* of this nsIMultiplexInputStream also is used as an nsISeekableStream.
|
||||
* @param stream stream to append
|
||||
*/
|
||||
void appendStream(in nsIInputStream stream);
|
||||
|
||||
/**
|
||||
* Insert a stream at specified index. If the cursor of this stream is at
|
||||
* the beginning of the stream at index, the cursor will be placed at the
|
||||
* beginning of the inserted stream instead.
|
||||
* The cursor of the new stream should be located at the beginning of the
|
||||
* stream if the implementation of this nsIMultiplexInputStream also is
|
||||
* used as an nsISeekableStream.
|
||||
* @param stream stream to insert
|
||||
* @param index index to insert stream at, must be <= count
|
||||
*/
|
||||
void insertStream(in nsIInputStream stream, in unsigned long index);
|
||||
|
||||
/**
|
||||
* Remove stream at specified index. If this stream is the one currently
|
||||
* being read the readcursor is moved to the beginning of the next
|
||||
* stream
|
||||
* @param index remove stream at this index, must be < count
|
||||
*/
|
||||
void removeStream(in unsigned long index);
|
||||
|
||||
/**
|
||||
* Get stream at specified index.
|
||||
* @param index return stream at this index, must be < count
|
||||
* @return stream at specified index
|
||||
*/
|
||||
nsIInputStream getStream(in unsigned long index);
|
||||
};
|
|
@ -0,0 +1,393 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is frightening to behold.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The multiplex stream concatenates a list of input streams into a single
|
||||
* stream.
|
||||
*/
|
||||
|
||||
#include "nsMultiplexInputStream.h"
|
||||
#include "nsIMultiplexInputStream.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsSupportsArray.h"
|
||||
|
||||
class nsMultiplexInputStream : public nsIMultiplexInputStream,
|
||||
public nsISeekableStream
|
||||
{
|
||||
public:
|
||||
nsMultiplexInputStream();
|
||||
virtual ~nsMultiplexInputStream();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINPUTSTREAM
|
||||
NS_DECL_NSIMULTIPLEXINPUTSTREAM
|
||||
NS_DECL_NSISEEKABLESTREAM
|
||||
|
||||
static NS_METHOD Create(nsISupports *outer, REFNSIID iid, void **result);
|
||||
|
||||
private:
|
||||
|
||||
struct ReadSegmentsState {
|
||||
nsIInputStream* mThisStream;
|
||||
PRUint32 mOffset;
|
||||
nsWriteSegmentFun mWriter;
|
||||
void* mClosure;
|
||||
PRBool mDone;
|
||||
};
|
||||
|
||||
static NS_METHOD ReadSegCb(nsIInputStream* aIn, void* aClosure,
|
||||
const char* aFromRawSegment, PRUint32 aToOffset,
|
||||
PRUint32 aCount, PRUint32 *aWriteCount);
|
||||
|
||||
nsSupportsArray mStreams;
|
||||
PRUint32 mCurrentStream;
|
||||
PRBool mStartedReadingCurrent;
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsMultiplexInputStream,
|
||||
nsIMultiplexInputStream,
|
||||
nsIInputStream,
|
||||
nsISeekableStream);
|
||||
|
||||
nsMultiplexInputStream::nsMultiplexInputStream()
|
||||
: mCurrentStream(0),
|
||||
mStartedReadingCurrent(PR_FALSE)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsMultiplexInputStream::~nsMultiplexInputStream()
|
||||
{
|
||||
}
|
||||
|
||||
/* readonly attribute unsigned long count; */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::GetCount(PRUint32 *aCount)
|
||||
{
|
||||
mStreams.Count(aCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void appendStream (in nsIInputStream stream); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::AppendStream(nsIInputStream *aStream)
|
||||
{
|
||||
return mStreams.AppendElement(aStream);
|
||||
}
|
||||
|
||||
/* void insertStream (in nsIInputStream stream, in unsigned long index); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::InsertStream(nsIInputStream *aStream, PRUint32 aIndex)
|
||||
{
|
||||
nsresult rv = mStreams.InsertElementAt(aStream, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mCurrentStream > aIndex ||
|
||||
(mCurrentStream == aIndex && mStartedReadingCurrent))
|
||||
++mCurrentStream;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* void removeStream (in unsigned long index); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
|
||||
{
|
||||
nsresult rv = mStreams.RemoveElementAt(aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mCurrentStream > aIndex)
|
||||
--mCurrentStream;
|
||||
else if (mCurrentStream == aIndex)
|
||||
mStartedReadingCurrent = PR_FALSE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* nsIInputStream getStream (in unsigned long index); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::GetStream(PRUint32 aIndex, nsIInputStream **_retval)
|
||||
{
|
||||
return mStreams.QueryElementAt(aIndex,
|
||||
NS_GET_IID(nsIInputStream),
|
||||
(void**)_retval);
|
||||
}
|
||||
|
||||
/* void close (); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::Close()
|
||||
{
|
||||
PRUint32 len, i;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
mStreams.Count(&len);
|
||||
for (i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
|
||||
nsresult rv2 = stream->Close();
|
||||
// We still want to close all streams, but we should return an error
|
||||
if (NS_FAILED(rv2))
|
||||
rv = rv2;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* unsigned long available (); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::Available(PRUint32 *_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 i, len, avail = 0;
|
||||
|
||||
mStreams.Count(&len);
|
||||
for (i = mCurrentStream; i < len; i++) {
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
|
||||
|
||||
PRUint32 streamAvail;
|
||||
rv = stream->Available(&streamAvail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
avail += streamAvail;
|
||||
}
|
||||
*_retval = avail;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] unsigned long read (in charPtr buf, in unsigned long count); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 len;
|
||||
|
||||
mStreams.Count(&len);
|
||||
PRUint32 read = 0;
|
||||
while (mCurrentStream < len && aCount > 0) {
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
|
||||
mCurrentStream));
|
||||
rv = stream->Read(aBuf, aCount, _retval);
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
*_retval = read;
|
||||
return read == 0 ? NS_BASE_STREAM_WOULD_BLOCK : NS_OK;
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!*_retval) {
|
||||
// we're done with this stream, proceed to next
|
||||
++mCurrentStream;
|
||||
mStartedReadingCurrent = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
read += *_retval;
|
||||
aBuf += *_retval;
|
||||
aCount -= *_retval;
|
||||
mStartedReadingCurrent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
*_retval = read;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun writer,
|
||||
* in voidPtr closure,
|
||||
* in unsigned long count); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
|
||||
PRUint32 aCount, PRUint32 *_retval)
|
||||
{
|
||||
NS_ASSERTION(aWriter, "missing aWriter");
|
||||
|
||||
nsresult rv;
|
||||
ReadSegmentsState state;
|
||||
state.mThisStream = this;
|
||||
state.mOffset = 0;
|
||||
state.mWriter = aWriter;
|
||||
state.mClosure = aClosure;
|
||||
state.mDone = PR_FALSE;
|
||||
|
||||
PRUint32 len;
|
||||
mStreams.Count(&len);
|
||||
while (mCurrentStream < len) {
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
|
||||
mCurrentStream));
|
||||
PRUint32 read;
|
||||
rv = stream->ReadSegments(ReadSegCb, &state, aCount, &read);
|
||||
// If we got an NS_BASE_STREAM_WOULD_BLOCK error since the reader
|
||||
// didn't want any more data. This might not be an error for us if
|
||||
// data was read from a previous stream in this run
|
||||
if (state.mDone && rv == NS_BASE_STREAM_WOULD_BLOCK &&
|
||||
!read && state.mOffset)
|
||||
break;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(aCount >= read, "Read more then requested");
|
||||
mStartedReadingCurrent = PR_TRUE;
|
||||
state.mOffset += read;
|
||||
aCount -= read;
|
||||
if (state.mDone || !aCount)
|
||||
break;
|
||||
|
||||
++mCurrentStream;
|
||||
mStartedReadingCurrent = PR_FALSE;
|
||||
}
|
||||
*_retval = state.mOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsMultiplexInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
|
||||
const char* aFromRawSegment,
|
||||
PRUint32 aToOffset, PRUint32 aCount,
|
||||
PRUint32 *aWriteCount)
|
||||
{
|
||||
nsresult rv;
|
||||
ReadSegmentsState* state = (ReadSegmentsState*)aClosure;
|
||||
rv = (state->mWriter)(state->mThisStream,
|
||||
state->mClosure,
|
||||
aFromRawSegment,
|
||||
aToOffset + state->mOffset,
|
||||
aCount,
|
||||
aWriteCount);
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK ||
|
||||
(NS_SUCCEEDED(rv) && *aWriteCount == 0 && aCount != 0))
|
||||
state->mDone = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* readonly attribute boolean nonBlocking; */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::GetNonBlocking(PRBool *aNonBlocking)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 i, len;
|
||||
|
||||
mStreams.Count(&len);
|
||||
for (i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
|
||||
rv = stream->GetNonBlocking(aNonBlocking);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// If one is non-blocking the entire stream becomes non-blocking
|
||||
if (*aNonBlocking)
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIInputStreamObserver observer; */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::GetObserver(nsIInputStreamObserver * *aObserver)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::SetObserver(nsIInputStreamObserver * aObserver)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void seek (in PRInt32 whence, in PRInt32 offset); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt32 aOffset)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// rewinding to start is easy, and should be the most common case
|
||||
if (aWhence == NS_SEEK_SET && aOffset == 0)
|
||||
{
|
||||
PRUint32 i, last;
|
||||
last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
|
||||
for (i = 0; i < last; ++i) {
|
||||
nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
|
||||
NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
|
||||
|
||||
rv = stream->Seek(NS_SEEK_SET, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mCurrentStream = 0;
|
||||
mStartedReadingCurrent = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// other Seeks not implemented yet
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* PRUint32 tell (); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::Tell(PRUint32 *_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
*_retval = 0;
|
||||
PRUint32 i, last;
|
||||
last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
|
||||
for (i = 0; i < last; ++i) {
|
||||
nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
|
||||
NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
|
||||
|
||||
PRUint32 pos;
|
||||
rv = stream->Tell(&pos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*_retval += pos;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void setEOF (); */
|
||||
NS_IMETHODIMP
|
||||
nsMultiplexInputStream::SetEOF()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsMultiplexInputStreamConstructor(nsISupports *outer,
|
||||
REFNSIID iid,
|
||||
void **result)
|
||||
{
|
||||
*result = nsnull;
|
||||
|
||||
if (outer)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsMultiplexInputStream *inst;
|
||||
NS_NEWXPCOM(inst, nsMultiplexInputStream);
|
||||
if (!inst)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(inst);
|
||||
nsresult rv = inst->QueryInterface(iid, result);
|
||||
NS_RELEASE(inst);
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is frightening to behold.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* The multiplex stream concatinates a list of input streams into a single
|
||||
* stream.
|
||||
*/
|
||||
|
||||
#ifndef _nsMultiplexInputStream_h_
|
||||
#define _nsMultiplexInputStream_h_
|
||||
|
||||
#include "nsIMultiplexInputStream.h"
|
||||
|
||||
#define NS_MULTIPLEXINPUTSTREAM_CLASSNAME "nsMultiplexInputStream"
|
||||
#define NS_MULTIPLEXINPUTSTREAM_CONTRACTID "@mozilla.org/io/multiplex-input-stream;1"
|
||||
#define NS_MULTIPLEXINPUTSTREAM_CID \
|
||||
{ /* 565e3a2c-1dd2-11b2-8da1-b4cef17e568d */ \
|
||||
0x565e3a2c, \
|
||||
0x1dd2, \
|
||||
0x11b2, \
|
||||
{0x8d, 0xa1, 0xb4, 0xce, 0xf1, 0x7e, 0x56, 0x8d} \
|
||||
}
|
||||
|
||||
extern NS_METHOD nsMultiplexInputStreamConstructor(nsISupports *outer,
|
||||
REFNSIID iid,
|
||||
void **result);
|
||||
|
||||
#endif // _nsMultiplexInputStream_h_
|
|
@ -1277,6 +1277,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMultiplexInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -1634,6 +1641,11 @@
|
|||
<PATH>nsIStringStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMultiplexInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
<TARGET>
|
||||
|
@ -2860,6 +2872,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMultiplexInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS></FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -3217,6 +3236,11 @@
|
|||
<PATH>nsIStringStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMultiplexInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
</TARGETLIST>
|
||||
|
@ -3653,6 +3677,12 @@
|
|||
<PATH>nsIStringStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>headers</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsIMultiplexInputStream.idl</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</GROUPLIST>
|
||||
|
||||
</PROJECT>
|
||||
|
|
|
@ -1709,6 +1709,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMultiplexInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMemoryImpl.cpp</PATH>
|
||||
|
@ -2371,6 +2378,11 @@
|
|||
<PATH>nsLocalFileCommon.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMultiplexInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMemoryImpl.cpp</PATH>
|
||||
|
@ -4161,6 +4173,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMultiplexInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMemoryImpl.cpp</PATH>
|
||||
|
@ -4828,6 +4847,11 @@
|
|||
<PATH>nsLocalFileCommon.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMultiplexInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMemoryImpl.cpp</PATH>
|
||||
|
@ -5466,6 +5490,12 @@
|
|||
<PATH>nsLocalFileCommon.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>xpcom.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsMultiplexInputStream.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>xpcom.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
|
Загрузка…
Ссылка в новой задаче