2001-02-17 09:53:29 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2006-04-26 19:53:27 +00:00
|
|
|
* vim: set ts=2 sw=2 et tw=78:
|
2001-02-17 09:53:29 +00:00
|
|
|
*
|
2004-04-17 21:52:36 +00:00
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
2001-02-17 09:53:29 +00:00
|
|
|
*
|
2004-04-17 21:52:36 +00:00
|
|
|
* 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.
|
2001-02-17 09:53:29 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code, released
|
|
|
|
* March 31, 1998.
|
|
|
|
*
|
2004-04-17 21:52:36 +00:00
|
|
|
* 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.
|
2001-02-17 09:53:29 +00:00
|
|
|
*
|
2002-06-25 20:03:06 +00:00
|
|
|
* Contributor(s):
|
|
|
|
* Johnny Stenback <jst@netscape.com>
|
|
|
|
* Christopher A. Aillon <christopher@aillon.com>
|
2001-02-17 09:53:29 +00:00
|
|
|
*
|
2004-04-17 21:52:36 +00:00
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of 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 ***** */
|
2001-02-17 09:53:29 +00:00
|
|
|
|
|
|
|
/* A namespace class for static layout utilities. */
|
|
|
|
|
2011-06-09 08:12:21 +00:00
|
|
|
#include "jsapi.h"
|
|
|
|
#include "jsdbgapi.h"
|
2010-03-17 19:55:45 +00:00
|
|
|
|
2004-04-13 03:21:50 +00:00
|
|
|
#include "nsJSUtils.h"
|
2001-02-17 09:53:29 +00:00
|
|
|
#include "nsCOMPtr.h"
|
2003-05-30 00:21:01 +00:00
|
|
|
#include "nsAString.h"
|
|
|
|
#include "nsPrintfCString.h"
|
|
|
|
#include "nsUnicharUtils.h"
|
2004-11-24 22:48:45 +00:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2001-02-17 09:53:29 +00:00
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsIScriptContext.h"
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
#include "nsIDOMScriptObjectFactory.h"
|
|
|
|
#include "nsDOMCID.h"
|
2001-02-17 09:53:29 +00:00
|
|
|
#include "nsContentUtils.h"
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
#include "nsIXPConnect.h"
|
|
|
|
#include "nsIContent.h"
|
2010-05-05 18:18:05 +00:00
|
|
|
#include "mozilla/dom/Element.h"
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsINodeInfo.h"
|
2002-06-11 23:23:12 +00:00
|
|
|
#include "nsReadableUtils.h"
|
2002-07-15 19:25:27 +00:00
|
|
|
#include "nsIDOMDocument.h"
|
2002-12-04 05:18:39 +00:00
|
|
|
#include "nsIDOMNodeList.h"
|
2004-08-04 19:48:55 +00:00
|
|
|
#include "nsIDOMNode.h"
|
2003-07-08 05:35:04 +00:00
|
|
|
#include "nsIIOService.h"
|
|
|
|
#include "nsNetCID.h"
|
|
|
|
#include "nsNetUtil.h"
|
2002-07-15 19:25:27 +00:00
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsDOMError.h"
|
2005-09-02 18:02:51 +00:00
|
|
|
#include "nsPIDOMWindow.h"
|
2002-04-12 10:11:00 +00:00
|
|
|
#include "nsIJSContextStack.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocShellTreeItem.h"
|
2002-11-19 13:39:20 +00:00
|
|
|
#include "nsParserCIID.h"
|
2006-06-05 20:32:48 +00:00
|
|
|
#include "nsIParser.h"
|
|
|
|
#include "nsIFragmentContentSink.h"
|
|
|
|
#include "nsIContentSink.h"
|
2008-02-08 22:07:51 +00:00
|
|
|
#include "nsIHTMLContentSink.h"
|
|
|
|
#include "nsIXMLContentSink.h"
|
2006-06-05 20:32:48 +00:00
|
|
|
#include "nsHTMLParts.h"
|
2002-11-19 13:39:20 +00:00
|
|
|
#include "nsIParserService.h"
|
|
|
|
#include "nsIServiceManager.h"
|
2003-01-22 03:25:51 +00:00
|
|
|
#include "nsIAttribute.h"
|
2005-02-02 23:16:02 +00:00
|
|
|
#include "nsContentList.h"
|
2003-05-30 00:21:01 +00:00
|
|
|
#include "nsIHTMLDocument.h"
|
|
|
|
#include "nsIDOMHTMLDocument.h"
|
|
|
|
#include "nsIDOMHTMLCollection.h"
|
|
|
|
#include "nsIDOMHTMLFormElement.h"
|
2008-09-08 16:09:35 +00:00
|
|
|
#include "nsIDOMNSHTMLElement.h"
|
2003-05-30 00:21:01 +00:00
|
|
|
#include "nsIForm.h"
|
|
|
|
#include "nsIFormControl.h"
|
2007-01-30 00:06:41 +00:00
|
|
|
#include "nsGkAtoms.h"
|
2006-12-26 17:47:52 +00:00
|
|
|
#include "nsISupportsPrimitives.h"
|
2004-03-09 03:57:51 +00:00
|
|
|
#include "imgIDecoderObserver.h"
|
|
|
|
#include "imgIRequest.h"
|
2004-07-30 06:04:57 +00:00
|
|
|
#include "imgIContainer.h"
|
2004-03-09 03:57:51 +00:00
|
|
|
#include "imgILoader.h"
|
2009-11-09 18:00:53 +00:00
|
|
|
#include "nsDocShellCID.h"
|
2004-07-30 06:04:57 +00:00
|
|
|
#include "nsIImageLoadingContent.h"
|
|
|
|
#include "nsIInterfaceRequestor.h"
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
2004-03-09 03:57:51 +00:00
|
|
|
#include "nsILoadGroup.h"
|
2010-02-24 19:14:14 +00:00
|
|
|
#include "nsIObserver.h"
|
|
|
|
#include "nsIObserverService.h"
|
2004-03-09 03:57:51 +00:00
|
|
|
#include "nsContentPolicyUtils.h"
|
2004-06-25 12:26:02 +00:00
|
|
|
#include "nsNodeInfoManager.h"
|
2006-08-15 15:55:45 +00:00
|
|
|
#include "nsIXBLService.h"
|
2004-07-25 12:12:39 +00:00
|
|
|
#include "nsCRT.h"
|
2005-10-10 18:38:57 +00:00
|
|
|
#include "nsIDOMEvent.h"
|
|
|
|
#include "nsIDOMEventTarget.h"
|
|
|
|
#include "nsIPrivateDOMEvent.h"
|
2004-10-07 20:59:53 +00:00
|
|
|
#ifdef MOZ_XTF
|
|
|
|
#include "nsIXTFService.h"
|
|
|
|
static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
|
|
|
#endif
|
2005-02-03 17:23:35 +00:00
|
|
|
#include "nsIMIMEService.h"
|
2005-08-22 03:00:06 +00:00
|
|
|
#include "nsLWBrkCIID.h"
|
|
|
|
#include "nsILineBreaker.h"
|
|
|
|
#include "nsIWordBreaker.h"
|
2005-09-02 18:02:51 +00:00
|
|
|
#include "jsdbgapi.h"
|
2005-09-24 02:33:33 +00:00
|
|
|
#include "nsIJSRuntimeService.h"
|
2005-10-18 20:33:35 +00:00
|
|
|
#include "nsIDOMDocumentXBL.h"
|
2007-02-16 23:02:08 +00:00
|
|
|
#include "nsBindingManager.h"
|
2005-10-18 20:33:35 +00:00
|
|
|
#include "nsIURI.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "nsXBLBinding.h"
|
|
|
|
#include "nsXBLPrototypeBinding.h"
|
|
|
|
#include "nsEscape.h"
|
|
|
|
#include "nsICharsetConverterManager.h"
|
2006-02-07 14:34:10 +00:00
|
|
|
#include "nsIEventListenerManager.h"
|
2006-05-16 14:51:52 +00:00
|
|
|
#include "nsAttrName.h"
|
2006-06-02 13:28:14 +00:00
|
|
|
#include "nsIDOMUserDataHandler.h"
|
2006-09-15 19:54:45 +00:00
|
|
|
#include "nsContentCreatorFunctions.h"
|
2006-11-02 19:33:10 +00:00
|
|
|
#include "nsTPtrArray.h"
|
2007-04-02 17:17:36 +00:00
|
|
|
#include "nsGUIEvent.h"
|
|
|
|
#include "nsMutationEvent.h"
|
2007-05-02 15:34:35 +00:00
|
|
|
#include "nsIMEStateManager.h"
|
2007-06-12 21:56:06 +00:00
|
|
|
#include "nsContentErrors.h"
|
2007-07-02 23:36:59 +00:00
|
|
|
#include "nsUnicharUtilCIID.h"
|
2007-11-12 01:51:31 +00:00
|
|
|
#include "nsCompressedCharMap.h"
|
2007-12-18 05:41:56 +00:00
|
|
|
#include "nsINativeKeyBindings.h"
|
|
|
|
#include "nsIDOMNSUIEvent.h"
|
|
|
|
#include "nsIDOMNSEvent.h"
|
|
|
|
#include "nsIPrivateDOMEvent.h"
|
2008-02-08 20:23:05 +00:00
|
|
|
#include "nsXULPopupManager.h"
|
2008-01-16 21:54:33 +00:00
|
|
|
#include "nsIPermissionManager.h"
|
2010-08-19 23:12:46 +00:00
|
|
|
#include "nsIContentPrefService.h"
|
2008-02-27 02:03:27 +00:00
|
|
|
#include "nsIScriptObjectPrincipal.h"
|
2008-03-14 23:08:57 +00:00
|
|
|
#include "nsIRunnable.h"
|
|
|
|
#include "nsDOMJSUtils.h"
|
2008-06-22 23:12:40 +00:00
|
|
|
#include "nsGenericHTMLElement.h"
|
|
|
|
#include "nsAttrValue.h"
|
2008-06-25 01:55:01 +00:00
|
|
|
#include "nsReferencedElement.h"
|
2008-07-02 16:28:43 +00:00
|
|
|
#include "nsIUGenCategory.h"
|
2008-08-27 12:07:27 +00:00
|
|
|
#include "nsIDragService.h"
|
2008-09-08 01:13:02 +00:00
|
|
|
#include "nsIChannelEventSink.h"
|
2010-08-05 02:15:55 +00:00
|
|
|
#include "nsIAsyncVerifyRedirectCallback.h"
|
2008-09-08 01:13:02 +00:00
|
|
|
#include "nsIInterfaceRequestor.h"
|
2008-10-20 04:12:25 +00:00
|
|
|
#include "nsIOfflineCacheUpdate.h"
|
|
|
|
#include "nsCPrefetchService.h"
|
2008-11-14 00:00:11 +00:00
|
|
|
#include "nsIChromeRegistry.h"
|
2011-05-09 19:33:03 +00:00
|
|
|
#include "nsEventDispatcher.h"
|
2008-12-17 02:11:07 +00:00
|
|
|
#include "nsIMIMEHeaderParam.h"
|
2009-06-30 07:56:40 +00:00
|
|
|
#include "nsIDOMXULCommandEvent.h"
|
2009-06-24 17:12:33 +00:00
|
|
|
#include "nsIDOMDragEvent.h"
|
|
|
|
#include "nsDOMDataTransfer.h"
|
2009-06-28 22:44:22 +00:00
|
|
|
#include "nsHtml5Module.h"
|
2009-08-01 15:53:40 +00:00
|
|
|
#include "nsPresContext.h"
|
2009-08-14 19:00:24 +00:00
|
|
|
#include "nsLayoutStatics.h"
|
2010-05-18 04:04:22 +00:00
|
|
|
#include "nsLayoutUtils.h"
|
|
|
|
#include "nsFrameManager.h"
|
|
|
|
#include "BasicLayers.h"
|
2010-04-21 20:17:41 +00:00
|
|
|
#include "nsFocusManager.h"
|
|
|
|
#include "nsTextEditorState.h"
|
2010-06-10 16:42:16 +00:00
|
|
|
#include "nsIPluginHost.h"
|
|
|
|
#include "nsICategoryManager.h"
|
2010-11-16 07:47:10 +00:00
|
|
|
#include "nsAHtml5FragmentParser.h"
|
2011-03-01 16:15:23 +00:00
|
|
|
#include "nsIViewManager.h"
|
2006-08-12 04:46:43 +00:00
|
|
|
|
2006-08-08 05:14:52 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
#include "nsIBidiKeyboard.h"
|
|
|
|
#endif
|
2007-01-04 22:31:26 +00:00
|
|
|
#include "nsCycleCollectionParticipant.h"
|
2002-04-12 10:11:00 +00:00
|
|
|
|
2004-09-14 17:26:35 +00:00
|
|
|
// for ReportToConsole
|
|
|
|
#include "nsIStringBundle.h"
|
|
|
|
#include "nsIScriptError.h"
|
|
|
|
#include "nsIConsoleService.h"
|
|
|
|
|
2008-04-11 17:29:06 +00:00
|
|
|
#include "mozAutoDocUpdate.h"
|
2009-07-08 05:23:20 +00:00
|
|
|
#include "imgICache.h"
|
2010-04-11 13:55:24 +00:00
|
|
|
#include "xpcprivate.h"
|
|
|
|
#include "nsScriptSecurityManager.h"
|
2010-05-20 20:08:02 +00:00
|
|
|
#include "nsIChannelPolicy.h"
|
|
|
|
#include "nsChannelPolicy.h"
|
|
|
|
#include "nsIContentSecurityPolicy.h"
|
2010-06-10 16:42:16 +00:00
|
|
|
#include "nsContentDLF.h"
|
2010-08-23 01:40:21 +00:00
|
|
|
#ifdef MOZ_MEDIA
|
2010-06-10 18:11:11 +00:00
|
|
|
#include "nsHTMLMediaElement.h"
|
2010-08-23 01:40:21 +00:00
|
|
|
#endif
|
2011-04-26 12:30:17 +00:00
|
|
|
#include "nsDOMTouchEvent.h"
|
2008-04-11 17:29:06 +00:00
|
|
|
|
2011-05-25 06:31:59 +00:00
|
|
|
#include "mozilla/Preferences.h"
|
|
|
|
|
2010-04-30 13:12:05 +00:00
|
|
|
using namespace mozilla::dom;
|
2010-07-15 21:08:10 +00:00
|
|
|
using namespace mozilla::layers;
|
2011-05-25 06:31:59 +00:00
|
|
|
using namespace mozilla;
|
2010-04-30 13:12:05 +00:00
|
|
|
|
2006-06-15 20:30:44 +00:00
|
|
|
const char kLoadAsData[] = "loadAsData";
|
|
|
|
|
2003-05-27 03:49:22 +00:00
|
|
|
static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
|
2005-09-11 10:08:43 +00:00
|
|
|
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
|
2006-06-05 20:32:48 +00:00
|
|
|
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
|
|
|
nsIDOMScriptObjectFactory *nsContentUtils::sDOMScriptObjectFactory = nsnull;
|
2005-09-11 10:08:43 +00:00
|
|
|
nsIXPConnect *nsContentUtils::sXPConnect;
|
|
|
|
nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
|
|
|
|
nsIThreadJSContextStack *nsContentUtils::sThreadJSContextStack;
|
2002-11-19 13:39:20 +00:00
|
|
|
nsIParserService *nsContentUtils::sParserService = nsnull;
|
2005-09-11 10:08:43 +00:00
|
|
|
nsINameSpaceManager *nsContentUtils::sNameSpaceManager;
|
|
|
|
nsIIOService *nsContentUtils::sIOService;
|
2004-10-07 20:59:53 +00:00
|
|
|
#ifdef MOZ_XTF
|
|
|
|
nsIXTFService *nsContentUtils::sXTFService = nsnull;
|
|
|
|
#endif
|
2005-09-11 10:08:43 +00:00
|
|
|
imgILoader *nsContentUtils::sImgLoader;
|
2009-07-08 05:23:20 +00:00
|
|
|
imgICache *nsContentUtils::sImgCache;
|
2004-09-14 17:26:35 +00:00
|
|
|
nsIConsoleService *nsContentUtils::sConsoleService;
|
2010-06-22 18:12:12 +00:00
|
|
|
nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nsnull;
|
|
|
|
nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nsnull;
|
|
|
|
nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nsnull;
|
2004-09-14 17:26:35 +00:00
|
|
|
nsIStringBundleService *nsContentUtils::sStringBundleService;
|
|
|
|
nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
|
2005-08-19 15:00:01 +00:00
|
|
|
nsIContentPolicy *nsContentUtils::sContentPolicyService;
|
2005-08-23 21:00:00 +00:00
|
|
|
PRBool nsContentUtils::sTriedToGetContentPolicy = PR_FALSE;
|
2005-09-11 10:08:43 +00:00
|
|
|
nsILineBreaker *nsContentUtils::sLineBreaker;
|
|
|
|
nsIWordBreaker *nsContentUtils::sWordBreaker;
|
2008-07-02 16:28:43 +00:00
|
|
|
nsIUGenCategory *nsContentUtils::sGenCat;
|
2007-03-02 13:34:14 +00:00
|
|
|
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
|
|
|
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
2007-10-29 13:45:07 +00:00
|
|
|
PRUint32 nsContentUtils::sJSGCThingRootCount;
|
2006-08-08 05:14:52 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
|
|
|
|
#endif
|
2008-03-14 23:08:57 +00:00
|
|
|
PRUint32 nsContentUtils::sScriptBlockerCount = 0;
|
2011-05-09 19:33:04 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
PRUint32 nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
|
|
|
|
#endif
|
2008-03-14 23:08:57 +00:00
|
|
|
nsCOMArray<nsIRunnable>* nsContentUtils::sBlockedScriptRunners = nsnull;
|
|
|
|
PRUint32 nsContentUtils::sRunnersCountAtFirstBlocker = 0;
|
2010-01-11 21:45:20 +00:00
|
|
|
PRUint32 nsContentUtils::sScriptBlockerCountWhereRunnersPrevented = 0;
|
2008-09-08 01:13:02 +00:00
|
|
|
nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nsnull;
|
2004-09-14 17:26:35 +00:00
|
|
|
|
2010-04-24 10:40:48 +00:00
|
|
|
PRBool nsContentUtils::sIsHandlingKeyBoardEvent = PR_FALSE;
|
2010-11-23 08:50:55 +00:00
|
|
|
PRBool nsContentUtils::sAllowXULXBL_for_file = PR_FALSE;
|
2010-04-24 10:40:48 +00:00
|
|
|
|
2003-10-30 02:53:08 +00:00
|
|
|
PRBool nsContentUtils::sInitialized = PR_FALSE;
|
|
|
|
|
2006-02-07 14:34:10 +00:00
|
|
|
static PLDHashTable sEventListenerManagersHash;
|
|
|
|
|
|
|
|
class EventListenerManagerMapEntry : public PLDHashEntryHdr
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
EventListenerManagerMapEntry(const void *aKey)
|
|
|
|
: mKey(aKey)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~EventListenerManagerMapEntry()
|
|
|
|
{
|
2006-04-18 20:59:28 +00:00
|
|
|
NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const void *mKey; // must be first, to look like PLDHashEntryStub
|
|
|
|
|
|
|
|
public:
|
|
|
|
nsCOMPtr<nsIEventListenerManager> mListenerManager;
|
|
|
|
};
|
|
|
|
|
2008-10-10 15:04:34 +00:00
|
|
|
static PRBool
|
2006-02-07 14:34:10 +00:00
|
|
|
EventListenerManagerHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
|
|
|
|
const void *key)
|
|
|
|
{
|
|
|
|
// Initialize the entry with placement new
|
|
|
|
new (entry) EventListenerManagerMapEntry(key);
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-10-10 15:04:34 +00:00
|
|
|
static void
|
2006-02-07 14:34:10 +00:00
|
|
|
EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|
|
|
{
|
|
|
|
EventListenerManagerMapEntry *lm =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<EventListenerManagerMapEntry *>(entry);
|
2006-02-07 14:34:10 +00:00
|
|
|
|
|
|
|
// Let the EventListenerManagerMapEntry clean itself up...
|
|
|
|
lm->~EventListenerManagerMapEntry();
|
|
|
|
}
|
|
|
|
|
2008-09-08 01:13:02 +00:00
|
|
|
class nsSameOriginChecker : public nsIChannelEventSink,
|
|
|
|
public nsIInterfaceRequestor
|
|
|
|
{
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSICHANNELEVENTSINK
|
|
|
|
NS_DECL_NSIINTERFACEREQUESTOR
|
|
|
|
};
|
|
|
|
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::Init()
|
|
|
|
{
|
2003-10-30 02:53:08 +00:00
|
|
|
if (sInitialized) {
|
|
|
|
NS_WARNING("Init() called twice");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2010-04-11 13:55:24 +00:00
|
|
|
nsresult rv = NS_GetNameSpaceManager(&sNameSpaceManager);
|
2003-10-30 02:53:08 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-04-11 13:55:24 +00:00
|
|
|
nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
|
|
|
|
NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
|
2003-10-30 02:53:08 +00:00
|
|
|
|
2010-04-11 13:55:24 +00:00
|
|
|
sXPConnect = xpconnect;
|
|
|
|
sThreadJSContextStack = xpconnect;
|
|
|
|
|
|
|
|
sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
|
|
|
|
if(!sSecurityManager)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
NS_ADDREF(sSecurityManager);
|
2002-07-18 05:53:28 +00:00
|
|
|
|
2003-07-08 05:35:04 +00:00
|
|
|
rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
|
|
|
|
if (NS_FAILED(rv)) {
|
2003-10-30 02:53:08 +00:00
|
|
|
// This makes life easier, but we can live without it.
|
|
|
|
|
2003-07-08 05:35:04 +00:00
|
|
|
sIOService = nsnull;
|
|
|
|
}
|
2002-11-29 23:44:07 +00:00
|
|
|
|
2005-08-22 03:00:06 +00:00
|
|
|
rv = CallGetService(NS_LBRK_CONTRACTID, &sLineBreaker);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2008-07-02 16:28:43 +00:00
|
|
|
rv = CallGetService(NS_UNICHARCATEGORY_CONTRACTID, &sGenCat);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2007-04-02 17:17:36 +00:00
|
|
|
if (!InitializeEventTable())
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2006-02-07 14:34:10 +00:00
|
|
|
if (!sEventListenerManagersHash.ops) {
|
|
|
|
static PLDHashTableOps hash_table_ops =
|
|
|
|
{
|
|
|
|
PL_DHashAllocTable,
|
|
|
|
PL_DHashFreeTable,
|
|
|
|
PL_DHashVoidPtrKeyStub,
|
|
|
|
PL_DHashMatchEntryStub,
|
|
|
|
PL_DHashMoveEntryStub,
|
|
|
|
EventListenerManagerHashClearEntry,
|
|
|
|
PL_DHashFinalizeStub,
|
|
|
|
EventListenerManagerHashInitEntry
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops,
|
|
|
|
nsnull, sizeof(EventListenerManagerMapEntry), 16)) {
|
|
|
|
sEventListenerManagersHash.ops = nsnull;
|
|
|
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-14 23:08:57 +00:00
|
|
|
sBlockedScriptRunners = new nsCOMArray<nsIRunnable>;
|
|
|
|
NS_ENSURE_TRUE(sBlockedScriptRunners, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
2011-05-28 23:42:57 +00:00
|
|
|
Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
|
|
|
|
"dom.allow_XUL_XBL_for_file");
|
2010-11-23 08:50:55 +00:00
|
|
|
|
2003-10-30 02:53:08 +00:00
|
|
|
sInitialized = PR_TRUE;
|
2002-08-09 08:45:30 +00:00
|
|
|
|
2003-10-30 02:53:08 +00:00
|
|
|
return NS_OK;
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
2001-02-17 09:53:29 +00:00
|
|
|
|
2010-07-02 21:15:52 +00:00
|
|
|
bool nsContentUtils::sImgLoaderInitialized;
|
|
|
|
|
|
|
|
void
|
|
|
|
nsContentUtils::InitImgLoader()
|
|
|
|
{
|
|
|
|
sImgLoaderInitialized = true;
|
|
|
|
|
|
|
|
// Ignore failure and just don't load images
|
|
|
|
nsresult rv = CallGetService("@mozilla.org/image/loader;1", &sImgLoader);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// no image loading for us. Oh, well.
|
|
|
|
sImgLoader = nsnull;
|
|
|
|
sImgCache = nsnull;
|
|
|
|
} else {
|
|
|
|
if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache )))
|
|
|
|
sImgCache = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-02 17:17:36 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::InitializeEventTable() {
|
2010-06-22 18:12:12 +00:00
|
|
|
NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
|
|
|
|
NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");
|
|
|
|
|
|
|
|
static const EventNameMapping eventArray[] = {
|
|
|
|
{ nsGkAtoms::onmousedown, NS_MOUSE_BUTTON_DOWN, EventNameType_All, NS_MOUSE_EVENT },
|
|
|
|
{ nsGkAtoms::onmouseup, NS_MOUSE_BUTTON_UP, EventNameType_All, NS_MOUSE_EVENT },
|
|
|
|
{ nsGkAtoms::onclick, NS_MOUSE_CLICK, EventNameType_All, NS_MOUSE_EVENT },
|
|
|
|
{ nsGkAtoms::ondblclick, NS_MOUSE_DOUBLECLICK, EventNameType_HTMLXUL, NS_MOUSE_EVENT },
|
|
|
|
{ nsGkAtoms::onmouseover, NS_MOUSE_ENTER_SYNTH, EventNameType_All, NS_MOUSE_EVENT },
|
|
|
|
{ nsGkAtoms::onmouseout, NS_MOUSE_EXIT_SYNTH, EventNameType_All, NS_MOUSE_EVENT },
|
2010-06-28 06:04:05 +00:00
|
|
|
{ nsGkAtoms::onMozMouseHittest, NS_MOUSE_MOZHITTEST, EventNameType_None, NS_MOUSE_EVENT },
|
2010-06-22 18:12:12 +00:00
|
|
|
{ nsGkAtoms::onmousemove, NS_MOUSE_MOVE, EventNameType_All, NS_MOUSE_EVENT },
|
|
|
|
{ nsGkAtoms::oncontextmenu, NS_CONTEXTMENU, EventNameType_HTMLXUL, NS_MOUSE_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onkeydown, NS_KEY_DOWN, EventNameType_HTMLXUL, NS_KEY_EVENT },
|
|
|
|
{ nsGkAtoms::onkeyup, NS_KEY_UP, EventNameType_HTMLXUL, NS_KEY_EVENT },
|
|
|
|
{ nsGkAtoms::onkeypress, NS_KEY_PRESS, EventNameType_HTMLXUL, NS_KEY_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onfocus, NS_FOCUS_CONTENT, EventNameType_HTMLXUL, NS_FOCUS_EVENT },
|
|
|
|
{ nsGkAtoms::onblur, NS_BLUR_CONTENT, EventNameType_HTMLXUL, NS_FOCUS_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onoffline, NS_OFFLINE, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::ononline, NS_ONLINE, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onsubmit, NS_FORM_SUBMIT, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onreset, NS_FORM_RESET, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onchange, NS_FORM_CHANGE, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onselect, NS_FORM_SELECTED, EventNameType_HTMLXUL, NS_EVENT },
|
2010-08-18 18:28:08 +00:00
|
|
|
{ nsGkAtoms::oninvalid, NS_FORM_INVALID, EventNameType_HTMLXUL, NS_EVENT },
|
2010-06-22 18:12:12 +00:00
|
|
|
{ nsGkAtoms::onload, NS_LOAD, EventNameType_All, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onpopstate, NS_POPSTATE, EventNameType_HTMLXUL, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onunload, NS_PAGE_UNLOAD,
|
|
|
|
(EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
|
|
|
|
{ nsGkAtoms::onhashchange, NS_HASHCHANGE, EventNameType_HTMLXUL, NS_EVENT },
|
2010-06-24 01:12:07 +00:00
|
|
|
{ nsGkAtoms::onreadystatechange, NS_READYSTATECHANGE, EventNameType_HTMLXUL },
|
2010-06-22 18:12:12 +00:00
|
|
|
{ nsGkAtoms::onbeforeunload, NS_BEFORE_PAGE_UNLOAD, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onabort, NS_IMAGE_ABORT,
|
|
|
|
(EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
|
|
|
|
{ nsGkAtoms::onerror, NS_LOAD_ERROR,
|
|
|
|
(EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
|
2010-09-16 08:48:47 +00:00
|
|
|
{ nsGkAtoms::onbeforescriptexecute, NS_BEFORE_SCRIPT_EXECUTE, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onafterscriptexecute, NS_AFTER_SCRIPT_EXECUTE, EventNameType_HTMLXUL, NS_EVENT },
|
2010-06-22 18:12:12 +00:00
|
|
|
|
|
|
|
{ nsGkAtoms::onDOMAttrModified, NS_MUTATION_ATTRMODIFIED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMCharacterDataModified, NS_MUTATION_CHARACTERDATAMODIFIED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMNodeInserted, NS_MUTATION_NODEINSERTED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMNodeRemoved, NS_MUTATION_NODEREMOVED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMNodeInsertedIntoDocument, NS_MUTATION_NODEINSERTEDINTODOCUMENT, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMNodeRemovedFromDocument, NS_MUTATION_NODEREMOVEDFROMDOCUMENT, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMSubtreeModified, NS_MUTATION_SUBTREEMODIFIED, EventNameType_HTMLXUL, NS_MUTATION_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onDOMActivate, NS_UI_ACTIVATE, EventNameType_HTMLXUL, NS_UI_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMFocusIn, NS_UI_FOCUSIN, EventNameType_HTMLXUL, NS_UI_EVENT },
|
|
|
|
{ nsGkAtoms::onDOMFocusOut, NS_UI_FOCUSOUT, EventNameType_HTMLXUL, NS_UI_EVENT },
|
|
|
|
{ nsGkAtoms::oninput, NS_FORM_INPUT, EventNameType_HTMLXUL, NS_UI_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onDOMMouseScroll, NS_MOUSE_SCROLL, EventNameType_HTMLXUL, NS_MOUSE_SCROLL_EVENT },
|
|
|
|
{ nsGkAtoms::onMozMousePixelScroll, NS_MOUSE_PIXEL_SCROLL, EventNameType_HTMLXUL, NS_MOUSE_SCROLL_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onpageshow, NS_PAGE_SHOW, EventNameType_HTML, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onpagehide, NS_PAGE_HIDE, EventNameType_HTML, NS_EVENT },
|
2010-11-17 13:46:00 +00:00
|
|
|
{ nsGkAtoms::onMozBeforeResize, NS_BEFORERESIZE_EVENT, EventNameType_None, NS_EVENT },
|
2010-06-22 18:12:12 +00:00
|
|
|
{ nsGkAtoms::onresize, NS_RESIZE_EVENT,
|
|
|
|
(EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
|
|
|
|
{ nsGkAtoms::onscroll, NS_SCROLL_EVENT,
|
|
|
|
(EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::oncopy, NS_COPY, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::oncut, NS_CUT, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onpaste, NS_PASTE, EventNameType_HTMLXUL, NS_EVENT },
|
2011-05-22 21:30:07 +00:00
|
|
|
{ nsGkAtoms::onopen, NS_OPEN, EventNameType_None, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onmessage, NS_MESSAGE, EventNameType_None, NS_EVENT },
|
2007-04-02 17:17:36 +00:00
|
|
|
// XUL specific events
|
2010-06-22 18:12:12 +00:00
|
|
|
{ nsGkAtoms::ontext, NS_TEXT_TEXT, EventNameType_XUL, NS_EVENT_NULL },
|
|
|
|
|
|
|
|
{ nsGkAtoms::oncompositionstart, NS_COMPOSITION_START, EventNameType_XUL, NS_COMPOSITION_EVENT },
|
|
|
|
{ nsGkAtoms::oncompositionend, NS_COMPOSITION_END, EventNameType_XUL, NS_COMPOSITION_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::oncommand, NS_XUL_COMMAND, EventNameType_XUL, NS_INPUT_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onclose, NS_XUL_CLOSE, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onpopupshowing, NS_XUL_POPUP_SHOWING, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onpopupshown, NS_XUL_POPUP_SHOWN, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onpopuphiding, NS_XUL_POPUP_HIDING, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onpopuphidden, NS_XUL_POPUP_HIDDEN, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onbroadcast, NS_XUL_BROADCAST, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::oncommandupdate, NS_XUL_COMMAND_UPDATE, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
|
|
|
|
{ nsGkAtoms::ondragenter, NS_DRAGDROP_ENTER, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondragover, NS_DRAGDROP_OVER_SYNTH, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondragexit, NS_DRAGDROP_EXIT_SYNTH, EventNameType_XUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondragdrop, NS_DRAGDROP_DRAGDROP, EventNameType_XUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondraggesture, NS_DRAGDROP_GESTURE, EventNameType_XUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondrag, NS_DRAGDROP_DRAG, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondragend, NS_DRAGDROP_END, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondragstart, NS_DRAGDROP_START, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondragleave, NS_DRAGDROP_LEAVE_SYNTH, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
{ nsGkAtoms::ondrop, NS_DRAGDROP_DROP, EventNameType_HTMLXUL, NS_DRAG_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onoverflow, NS_SCROLLPORT_OVERFLOW, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onunderflow, NS_SCROLLPORT_UNDERFLOW, EventNameType_XUL, NS_EVENT_NULL},
|
|
|
|
{ nsGkAtoms::onSVGLoad, NS_SVG_LOAD, EventNameType_None, NS_SVG_EVENT },
|
|
|
|
{ nsGkAtoms::onSVGUnload, NS_SVG_UNLOAD, EventNameType_None, NS_SVG_EVENT },
|
|
|
|
{ nsGkAtoms::onSVGAbort, NS_SVG_ABORT, EventNameType_None, NS_SVG_EVENT },
|
|
|
|
{ nsGkAtoms::onSVGError, NS_SVG_ERROR, EventNameType_None, NS_SVG_EVENT },
|
|
|
|
{ nsGkAtoms::onSVGResize, NS_SVG_RESIZE, EventNameType_None, NS_SVG_EVENT },
|
|
|
|
{ nsGkAtoms::onSVGScroll, NS_SVG_SCROLL, EventNameType_None, NS_SVG_EVENT },
|
|
|
|
|
|
|
|
{ nsGkAtoms::onSVGZoom, NS_SVG_ZOOM, EventNameType_None, NS_SVGZOOM_EVENT },
|
|
|
|
|
|
|
|
// This is a bit hackish, but SVG's event names are weird.
|
|
|
|
{ nsGkAtoms::onzoom, NS_SVG_ZOOM, EventNameType_SVGSVG, NS_EVENT_NULL },
|
2010-07-31 07:02:52 +00:00
|
|
|
#ifdef MOZ_SMIL
|
|
|
|
{ nsGkAtoms::onbegin, NS_SMIL_BEGIN, EventNameType_SMIL, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onbeginEvent, NS_SMIL_BEGIN, EventNameType_None, NS_SMIL_TIME_EVENT },
|
|
|
|
{ nsGkAtoms::onend, NS_SMIL_END, EventNameType_SMIL, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onendEvent, NS_SMIL_END, EventNameType_None, NS_SMIL_TIME_EVENT },
|
|
|
|
{ nsGkAtoms::onrepeat, NS_SMIL_REPEAT, EventNameType_SMIL, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onrepeatEvent, NS_SMIL_REPEAT, EventNameType_None, NS_SMIL_TIME_EVENT },
|
|
|
|
#endif // MOZ_SMIL
|
2010-06-22 18:12:12 +00:00
|
|
|
#ifdef MOZ_MEDIA
|
|
|
|
{ nsGkAtoms::onloadstart, NS_LOADSTART, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onprogress, NS_PROGRESS, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onsuspend, NS_SUSPEND, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onemptied, NS_EMPTIED, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onstalled, NS_STALLED, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onplay, NS_PLAY, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onpause, NS_PAUSE, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onloadedmetadata, NS_LOADEDMETADATA, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onloadeddata, NS_LOADEDDATA, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onwaiting, NS_WAITING, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onplaying, NS_PLAYING, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::oncanplay, NS_CANPLAY, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::oncanplaythrough, NS_CANPLAYTHROUGH, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onseeking, NS_SEEKING, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onseeked, NS_SEEKED, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::ontimeupdate, NS_TIMEUPDATE, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onended, NS_ENDED, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onratechange, NS_RATECHANGE, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::ondurationchange, NS_DURATIONCHANGE, EventNameType_HTML, NS_EVENT_NULL },
|
|
|
|
{ nsGkAtoms::onvolumechange, NS_VOLUMECHANGE, EventNameType_HTML, NS_EVENT_NULL },
|
2010-08-25 13:10:00 +00:00
|
|
|
{ nsGkAtoms::onMozAudioAvailable, NS_MOZAUDIOAVAILABLE, EventNameType_None, NS_EVENT_NULL },
|
2010-06-22 18:12:12 +00:00
|
|
|
#endif // MOZ_MEDIA
|
|
|
|
{ nsGkAtoms::onMozAfterPaint, NS_AFTERPAINT, EventNameType_None, NS_EVENT },
|
2010-08-11 21:05:27 +00:00
|
|
|
{ nsGkAtoms::onMozBeforePaint, NS_BEFOREPAINT, EventNameType_None, NS_EVENT_NULL },
|
2010-06-22 18:12:12 +00:00
|
|
|
|
|
|
|
{ nsGkAtoms::onMozScrolledAreaChanged, NS_SCROLLEDAREACHANGED, EventNameType_None, NS_SCROLLAREA_EVENT },
|
2008-10-23 20:15:20 +00:00
|
|
|
|
|
|
|
// Simple gesture events
|
2010-06-22 18:12:12 +00:00
|
|
|
{ nsGkAtoms::onMozSwipeGesture, NS_SIMPLE_GESTURE_SWIPE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozMagnifyGestureStart, NS_SIMPLE_GESTURE_MAGNIFY_START, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozMagnifyGestureUpdate, NS_SIMPLE_GESTURE_MAGNIFY_UPDATE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozMagnifyGesture, NS_SIMPLE_GESTURE_MAGNIFY, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozRotateGestureStart, NS_SIMPLE_GESTURE_ROTATE_START, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozRotateGestureUpdate, NS_SIMPLE_GESTURE_ROTATE_UPDATE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozRotateGesture, NS_SIMPLE_GESTURE_ROTATE, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozTapGesture, NS_SIMPLE_GESTURE_TAP, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
{ nsGkAtoms::onMozPressTapGesture, NS_SIMPLE_GESTURE_PRESSTAP, EventNameType_None, NS_SIMPLE_GESTURE_EVENT },
|
|
|
|
|
2010-08-02 13:34:54 +00:00
|
|
|
{ nsGkAtoms::onMozTouchDown, NS_MOZTOUCH_DOWN, EventNameType_None, NS_MOZTOUCH_EVENT },
|
|
|
|
{ nsGkAtoms::onMozTouchMove, NS_MOZTOUCH_MOVE, EventNameType_None, NS_MOZTOUCH_EVENT },
|
|
|
|
{ nsGkAtoms::onMozTouchUp, NS_MOZTOUCH_UP, EventNameType_None, NS_MOZTOUCH_EVENT },
|
|
|
|
|
2011-06-20 23:47:09 +00:00
|
|
|
{ nsGkAtoms::ontransitionend, NS_TRANSITION_END, EventNameType_None, NS_TRANSITION_EVENT },
|
2011-04-12 06:18:44 +00:00
|
|
|
{ nsGkAtoms::onanimationstart, NS_ANIMATION_START, EventNameType_None, NS_ANIMATION_EVENT },
|
|
|
|
{ nsGkAtoms::onanimationend, NS_ANIMATION_END, EventNameType_None, NS_ANIMATION_EVENT },
|
2011-05-14 12:03:58 +00:00
|
|
|
{ nsGkAtoms::onanimationiteration, NS_ANIMATION_ITERATION, EventNameType_None, NS_ANIMATION_EVENT },
|
|
|
|
{ nsGkAtoms::onbeforeprint, NS_BEFOREPRINT, EventNameType_HTMLXUL, NS_EVENT },
|
|
|
|
{ nsGkAtoms::onafterprint, NS_AFTERPRINT, EventNameType_HTMLXUL, NS_EVENT }
|
2007-04-02 17:17:36 +00:00
|
|
|
};
|
|
|
|
|
2010-06-22 18:12:12 +00:00
|
|
|
sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>;
|
|
|
|
sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>;
|
|
|
|
sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
|
|
|
|
|
|
|
|
if (!sAtomEventTable || !sStringEventTable || !sUserDefinedEvents ||
|
|
|
|
!sAtomEventTable->Init(int(NS_ARRAY_LENGTH(eventArray) / 0.75) + 1) ||
|
|
|
|
!sStringEventTable->Init(int(NS_ARRAY_LENGTH(eventArray) / 0.75) + 1)) {
|
|
|
|
delete sAtomEventTable;
|
|
|
|
sAtomEventTable = nsnull;
|
|
|
|
delete sStringEventTable;
|
|
|
|
sStringEventTable = nsnull;
|
|
|
|
delete sUserDefinedEvents;
|
|
|
|
sUserDefinedEvents = nsnull;
|
2007-04-02 17:17:36 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventArray); ++i) {
|
2010-06-22 18:12:12 +00:00
|
|
|
if (!sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]) ||
|
|
|
|
!sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
|
|
|
|
eventArray[i])) {
|
|
|
|
delete sAtomEventTable;
|
|
|
|
sAtomEventTable = nsnull;
|
|
|
|
delete sStringEventTable;
|
|
|
|
sStringEventTable = nsnull;
|
2007-04-02 17:17:36 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-04-26 12:30:17 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::InitializeTouchEventTable()
|
|
|
|
{
|
|
|
|
static PRBool sEventTableInitialized = PR_FALSE;
|
|
|
|
if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
|
|
|
|
sEventTableInitialized = PR_TRUE;
|
|
|
|
static const EventNameMapping touchEventArray[] = {
|
|
|
|
{ nsGkAtoms::ontouchstart, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
|
|
|
|
{ nsGkAtoms::ontouchend, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
|
|
|
|
{ nsGkAtoms::ontouchmove, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
|
|
|
|
{ nsGkAtoms::ontouchenter, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
|
|
|
|
{ nsGkAtoms::ontouchleave, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
|
|
|
|
{ nsGkAtoms::ontouchcancel, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT }
|
|
|
|
};
|
|
|
|
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(touchEventArray); ++i) {
|
|
|
|
if (!sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]) ||
|
|
|
|
!sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
|
|
|
|
touchEventArray[i])) {
|
|
|
|
delete sAtomEventTable;
|
|
|
|
sAtomEventTable = nsnull;
|
|
|
|
delete sStringEventTable;
|
|
|
|
sStringEventTable = nsnull;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-19 13:39:20 +00:00
|
|
|
/**
|
|
|
|
* Access a cached parser service. Don't addref. We need only one
|
|
|
|
* reference to it and this class has that one.
|
|
|
|
*/
|
|
|
|
/* static */
|
|
|
|
nsIParserService*
|
2005-09-11 10:08:43 +00:00
|
|
|
nsContentUtils::GetParserService()
|
2002-11-19 13:39:20 +00:00
|
|
|
{
|
|
|
|
// XXX: This isn't accessed from several threads, is it?
|
2003-07-08 05:35:04 +00:00
|
|
|
if (!sParserService) {
|
2002-11-19 13:39:20 +00:00
|
|
|
// Lock, recheck sCachedParserService and aquire if this should be
|
|
|
|
// safe for multiple threads.
|
2003-07-08 05:35:04 +00:00
|
|
|
nsresult rv = CallGetService(kParserServiceCID, &sParserService);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
sParserService = nsnull;
|
|
|
|
}
|
2002-11-19 13:39:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sParserService;
|
|
|
|
}
|
|
|
|
|
2004-10-07 21:23:52 +00:00
|
|
|
#ifdef MOZ_XTF
|
2004-10-07 20:59:53 +00:00
|
|
|
nsIXTFService*
|
2005-09-11 10:08:43 +00:00
|
|
|
nsContentUtils::GetXTFService()
|
2004-10-07 20:59:53 +00:00
|
|
|
{
|
|
|
|
if (!sXTFService) {
|
|
|
|
nsresult rv = CallGetService(kXTFServiceCID, &sXTFService);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
sXTFService = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sXTFService;
|
|
|
|
}
|
2004-10-07 21:23:52 +00:00
|
|
|
#endif
|
2004-10-07 20:59:53 +00:00
|
|
|
|
2006-08-08 05:14:52 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
nsIBidiKeyboard*
|
|
|
|
nsContentUtils::GetBidiKeyboard()
|
|
|
|
{
|
|
|
|
if (!sBidiKeyboard) {
|
|
|
|
nsresult rv = CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
sBidiKeyboard = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sBidiKeyboard;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-18 05:53:28 +00:00
|
|
|
template <class OutputIterator>
|
2001-02-17 09:53:29 +00:00
|
|
|
struct NormalizeNewlinesCharTraits {
|
|
|
|
public:
|
|
|
|
typedef typename OutputIterator::value_type value_type;
|
|
|
|
|
|
|
|
public:
|
|
|
|
NormalizeNewlinesCharTraits(OutputIterator& aIterator) : mIterator(aIterator) { }
|
|
|
|
void writechar(typename OutputIterator::value_type aChar) {
|
|
|
|
*mIterator++ = aChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
OutputIterator mIterator;
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
|
|
|
|
|
|
|
|
template <class CharT>
|
|
|
|
struct NormalizeNewlinesCharTraits<CharT*> {
|
|
|
|
public:
|
|
|
|
typedef CharT value_type;
|
|
|
|
|
2002-07-18 05:53:28 +00:00
|
|
|
public:
|
2001-02-17 09:53:29 +00:00
|
|
|
NormalizeNewlinesCharTraits(CharT* aCharPtr) : mCharPtr(aCharPtr) { }
|
|
|
|
void writechar(CharT aChar) {
|
|
|
|
*mCharPtr++ = aChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
CharT* mCharPtr;
|
2002-07-18 05:53:28 +00:00
|
|
|
};
|
2001-02-17 09:53:29 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
NS_SPECIALIZE_TEMPLATE
|
|
|
|
struct NormalizeNewlinesCharTraits<char*> {
|
|
|
|
public:
|
|
|
|
typedef char value_type;
|
|
|
|
|
2002-07-18 05:53:28 +00:00
|
|
|
public:
|
2001-02-17 09:53:29 +00:00
|
|
|
NormalizeNewlinesCharTraits(char* aCharPtr) : mCharPtr(aCharPtr) { }
|
|
|
|
void writechar(char aChar) {
|
|
|
|
*mCharPtr++ = aChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
char* mCharPtr;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_SPECIALIZE_TEMPLATE
|
|
|
|
struct NormalizeNewlinesCharTraits<PRUnichar*> {
|
|
|
|
public:
|
|
|
|
typedef PRUnichar value_type;
|
|
|
|
|
2002-07-18 05:53:28 +00:00
|
|
|
public:
|
2001-02-17 09:53:29 +00:00
|
|
|
NormalizeNewlinesCharTraits(PRUnichar* aCharPtr) : mCharPtr(aCharPtr) { }
|
|
|
|
void writechar(PRUnichar aChar) {
|
|
|
|
*mCharPtr++ = aChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
PRUnichar* mCharPtr;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2002-07-18 05:53:28 +00:00
|
|
|
template <class OutputIterator>
|
2001-02-17 09:53:29 +00:00
|
|
|
class CopyNormalizeNewlines
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef typename OutputIterator::value_type value_type;
|
|
|
|
|
|
|
|
public:
|
2002-07-18 05:53:28 +00:00
|
|
|
CopyNormalizeNewlines(OutputIterator* aDestination,
|
|
|
|
PRBool aLastCharCR=PR_FALSE) :
|
2001-07-05 22:20:34 +00:00
|
|
|
mLastCharCR(aLastCharCR),
|
2001-02-17 09:53:29 +00:00
|
|
|
mDestination(aDestination),
|
2002-07-18 05:53:28 +00:00
|
|
|
mWritten(0)
|
2001-02-17 09:53:29 +00:00
|
|
|
{ }
|
2002-07-18 05:53:28 +00:00
|
|
|
|
|
|
|
PRUint32 GetCharsWritten() {
|
|
|
|
return mWritten;
|
2001-02-17 09:53:29 +00:00
|
|
|
}
|
|
|
|
|
2001-07-05 22:20:34 +00:00
|
|
|
PRBool IsLastCharCR() {
|
|
|
|
return mLastCharCR;
|
|
|
|
}
|
|
|
|
|
2008-01-04 00:07:06 +00:00
|
|
|
void write(const typename OutputIterator::value_type* aSource, PRUint32 aSourceLength) {
|
2002-07-18 05:53:28 +00:00
|
|
|
|
2001-06-18 21:18:37 +00:00
|
|
|
const typename OutputIterator::value_type* done_writing = aSource + aSourceLength;
|
2002-07-18 05:53:28 +00:00
|
|
|
|
2001-02-17 09:53:29 +00:00
|
|
|
// If the last source buffer ended with a CR...
|
|
|
|
if (mLastCharCR) {
|
|
|
|
// ..and if the next one is a LF, then skip it since
|
|
|
|
// we've already written out a newline
|
|
|
|
if (aSourceLength && (*aSource == value_type('\n'))) {
|
2001-06-18 21:18:37 +00:00
|
|
|
++aSource;
|
2001-02-17 09:53:29 +00:00
|
|
|
}
|
|
|
|
mLastCharCR = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32 num_written = 0;
|
|
|
|
while ( aSource < done_writing ) {
|
|
|
|
if (*aSource == value_type('\r')) {
|
|
|
|
mDestination->writechar('\n');
|
2001-06-18 21:18:37 +00:00
|
|
|
++aSource;
|
2001-02-17 09:53:29 +00:00
|
|
|
// If we've reached the end of the buffer, record
|
|
|
|
// that we wrote out a CR
|
|
|
|
if (aSource == done_writing) {
|
|
|
|
mLastCharCR = PR_TRUE;
|
|
|
|
}
|
|
|
|
// If the next character is a LF, skip it
|
|
|
|
else if (*aSource == value_type('\n')) {
|
2001-06-18 21:18:37 +00:00
|
|
|
++aSource;
|
2001-02-17 09:53:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mDestination->writechar(*aSource++);
|
|
|
|
}
|
2001-06-18 21:18:37 +00:00
|
|
|
++num_written;
|
2001-02-17 09:53:29 +00:00
|
|
|
}
|
2002-07-18 05:53:28 +00:00
|
|
|
|
2001-02-17 09:53:29 +00:00
|
|
|
mWritten += num_written;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
PRBool mLastCharCR;
|
|
|
|
OutputIterator* mDestination;
|
|
|
|
PRUint32 mWritten;
|
|
|
|
};
|
|
|
|
|
|
|
|
// static
|
2002-07-18 05:53:28 +00:00
|
|
|
PRUint32
|
|
|
|
nsContentUtils::CopyNewlineNormalizedUnicodeTo(const nsAString& aSource,
|
|
|
|
PRUint32 aSrcOffset,
|
|
|
|
PRUnichar* aDest,
|
|
|
|
PRUint32 aLength,
|
2001-07-05 22:20:34 +00:00
|
|
|
PRBool& aLastCharCR)
|
2001-02-17 09:53:29 +00:00
|
|
|
{
|
|
|
|
typedef NormalizeNewlinesCharTraits<PRUnichar*> sink_traits;
|
|
|
|
|
|
|
|
sink_traits dest_traits(aDest);
|
2001-07-05 22:20:34 +00:00
|
|
|
CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits,aLastCharCR);
|
2001-02-17 09:53:29 +00:00
|
|
|
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
|
2002-07-18 05:53:28 +00:00
|
|
|
copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ),
|
|
|
|
aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ),
|
2001-07-05 22:20:34 +00:00
|
|
|
normalizer);
|
|
|
|
aLastCharCR = normalizer.IsLastCharCR();
|
2001-02-17 09:53:29 +00:00
|
|
|
return normalizer.GetCharsWritten();
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2002-07-18 05:53:28 +00:00
|
|
|
PRUint32
|
2002-03-23 23:54:46 +00:00
|
|
|
nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator<PRUnichar>& aSrcStart, const nsReadingIterator<PRUnichar>& aSrcEnd, nsAString& aDest)
|
2001-02-17 09:53:29 +00:00
|
|
|
{
|
|
|
|
typedef nsWritingIterator<PRUnichar> WritingIterator;
|
|
|
|
typedef NormalizeNewlinesCharTraits<WritingIterator> sink_traits;
|
|
|
|
|
|
|
|
WritingIterator iter;
|
|
|
|
aDest.BeginWriting(iter);
|
|
|
|
sink_traits dest_traits(iter);
|
|
|
|
CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits);
|
|
|
|
copy_string(aSrcStart, aSrcEnd, normalizer);
|
|
|
|
return normalizer.GetCharsWritten();
|
|
|
|
}
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2007-11-12 01:51:31 +00:00
|
|
|
// Replaced by precompiled CCMap (see bug 180266). To update the list
|
|
|
|
// of characters, see one of files included below. As for the way
|
|
|
|
// the original list of characters was obtained by Frank Tang, see bug 54467.
|
|
|
|
// Updated to fix the regression (bug 263411). The list contains
|
|
|
|
// characters of the following Unicode character classes : Ps, Pi, Po, Pf, Pe.
|
|
|
|
// (ref.: http://www.w3.org/TR/2004/CR-CSS21-20040225/selector.html#first-letter)
|
2008-07-02 16:28:43 +00:00
|
|
|
#include "punct_marks.x-ccmap"
|
|
|
|
DEFINE_X_CCMAP(gPuncCharsCCMapExt, const);
|
2007-11-12 01:51:31 +00:00
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool
|
2008-07-02 16:28:43 +00:00
|
|
|
nsContentUtils::IsPunctuationMark(PRUint32 aChar)
|
2007-11-12 01:51:31 +00:00
|
|
|
{
|
2008-07-02 16:28:43 +00:00
|
|
|
return CCMAP_HAS_CHAR_EXT(gPuncCharsCCMapExt, aChar);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsPunctuationMarkAt(const nsTextFragment* aFrag, PRUint32 aOffset)
|
|
|
|
{
|
|
|
|
PRUnichar h = aFrag->CharAt(aOffset);
|
|
|
|
if (!IS_SURROGATE(h)) {
|
|
|
|
return IsPunctuationMark(h);
|
|
|
|
}
|
|
|
|
if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
|
|
|
|
PRUnichar l = aFrag->CharAt(aOffset + 1);
|
|
|
|
if (NS_IS_LOW_SURROGATE(l)) {
|
|
|
|
return IsPunctuationMark(SURROGATE_TO_UCS4(h, l));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool nsContentUtils::IsAlphanumeric(PRUint32 aChar)
|
|
|
|
{
|
|
|
|
nsIUGenCategory::nsUGenCategory cat = sGenCat->Get(aChar);
|
|
|
|
|
|
|
|
return (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool nsContentUtils::IsAlphanumericAt(const nsTextFragment* aFrag, PRUint32 aOffset)
|
|
|
|
{
|
|
|
|
PRUnichar h = aFrag->CharAt(aOffset);
|
|
|
|
if (!IS_SURROGATE(h)) {
|
|
|
|
return IsAlphanumeric(h);
|
|
|
|
}
|
|
|
|
if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
|
|
|
|
PRUnichar l = aFrag->CharAt(aOffset + 1);
|
|
|
|
if (NS_IS_LOW_SURROGATE(l)) {
|
|
|
|
return IsAlphanumeric(SURROGATE_TO_UCS4(h, l));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
2007-11-12 01:51:31 +00:00
|
|
|
}
|
|
|
|
|
2008-06-11 00:27:00 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsHTMLWhitespace(PRUnichar aChar)
|
|
|
|
{
|
|
|
|
return aChar == PRUnichar(0x0009) ||
|
|
|
|
aChar == PRUnichar(0x000A) ||
|
|
|
|
aChar == PRUnichar(0x000C) ||
|
|
|
|
aChar == PRUnichar(0x000D) ||
|
|
|
|
aChar == PRUnichar(0x0020);
|
|
|
|
}
|
|
|
|
|
2010-06-25 02:01:07 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result)
|
|
|
|
{
|
|
|
|
nsAutoString marginStr(aString);
|
|
|
|
marginStr.CompressWhitespace(PR_TRUE, PR_TRUE);
|
|
|
|
if (marginStr.IsEmpty()) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 start = 0, end = 0;
|
|
|
|
for (int count = 0; count < 4; count++) {
|
2010-08-06 11:04:32 +00:00
|
|
|
if ((PRUint32)end >= marginStr.Length())
|
2010-06-25 02:01:07 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
// top, right, bottom, left
|
|
|
|
if (count < 3)
|
|
|
|
end = Substring(marginStr, start).FindChar(',');
|
|
|
|
else
|
|
|
|
end = Substring(marginStr, start).Length();
|
|
|
|
|
|
|
|
if (end <= 0)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
PRInt32 ec, val =
|
|
|
|
nsString(Substring(marginStr, start, end)).ToInteger(&ec);
|
|
|
|
if (NS_FAILED(ec))
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
switch(count) {
|
|
|
|
case 0:
|
|
|
|
result.top = val;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
result.right = val;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
result.bottom = val;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
result.left = val;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
start += end + 1;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2008-06-11 00:27:00 +00:00
|
|
|
|
2008-01-16 21:54:33 +00:00
|
|
|
/* static */
|
|
|
|
void
|
2008-11-06 00:01:07 +00:00
|
|
|
nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
|
2008-01-16 21:54:33 +00:00
|
|
|
{
|
2010-04-30 13:12:05 +00:00
|
|
|
Element* docElement = aDocument->GetRootElement();
|
2008-01-16 21:54:33 +00:00
|
|
|
if (!docElement) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString manifestSpec;
|
|
|
|
docElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
|
|
|
|
|
|
|
|
// Manifest URIs can't have fragment identifiers.
|
|
|
|
if (manifestSpec.IsEmpty() ||
|
|
|
|
manifestSpec.FindChar('#') != kNotFound) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
|
2010-04-19 15:40:15 +00:00
|
|
|
aDocument,
|
|
|
|
aDocument->GetDocBaseURI());
|
2008-01-16 21:54:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
|
|
|
|
{
|
2008-10-20 04:12:25 +00:00
|
|
|
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
|
|
|
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
|
|
|
|
if (!updateService) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool allowed;
|
2011-05-28 23:42:57 +00:00
|
|
|
nsresult rv =
|
|
|
|
updateService->OfflineAppAllowedForURI(aURI,
|
|
|
|
Preferences::GetRootBranch(),
|
|
|
|
&allowed);
|
2008-10-20 04:12:25 +00:00
|
|
|
return NS_SUCCEEDED(rv) && allowed;
|
2008-01-16 21:54:33 +00:00
|
|
|
}
|
|
|
|
|
2008-08-28 01:15:32 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
|
|
|
|
{
|
2008-10-20 04:12:25 +00:00
|
|
|
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
|
|
|
|
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
|
|
|
|
if (!updateService) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2008-08-28 01:15:32 +00:00
|
|
|
|
2008-10-20 04:12:25 +00:00
|
|
|
PRBool allowed;
|
|
|
|
nsresult rv = updateService->OfflineAppAllowed(aPrincipal,
|
2011-05-28 23:42:57 +00:00
|
|
|
Preferences::GetRootBranch(),
|
2008-10-20 04:12:25 +00:00
|
|
|
&allowed);
|
|
|
|
return NS_SUCCEEDED(rv) && allowed;
|
2008-08-28 01:15:32 +00:00
|
|
|
}
|
|
|
|
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
// static
|
|
|
|
void
|
|
|
|
nsContentUtils::Shutdown()
|
|
|
|
{
|
2003-10-30 02:53:08 +00:00
|
|
|
sInitialized = PR_FALSE;
|
|
|
|
|
2006-08-12 04:46:43 +00:00
|
|
|
NS_HTMLParanoidFragmentSinkShutdown();
|
|
|
|
NS_XHTMLParanoidFragmentSinkShutdown();
|
|
|
|
|
2005-08-19 15:00:01 +00:00
|
|
|
NS_IF_RELEASE(sContentPolicyService);
|
2005-08-23 21:00:00 +00:00
|
|
|
sTriedToGetContentPolicy = PR_FALSE;
|
2009-03-20 08:15:35 +00:00
|
|
|
PRUint32 i;
|
|
|
|
for (i = 0; i < PropertiesFile_COUNT; ++i)
|
2004-09-14 17:26:35 +00:00
|
|
|
NS_IF_RELEASE(sStringBundles[i]);
|
2010-02-08 02:49:18 +00:00
|
|
|
|
2004-09-14 17:26:35 +00:00
|
|
|
NS_IF_RELEASE(sStringBundleService);
|
|
|
|
NS_IF_RELEASE(sConsoleService);
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
NS_IF_RELEASE(sDOMScriptObjectFactory);
|
2010-04-11 13:55:24 +00:00
|
|
|
sXPConnect = nsnull;
|
|
|
|
sThreadJSContextStack = nsnull;
|
2002-07-18 05:53:28 +00:00
|
|
|
NS_IF_RELEASE(sSecurityManager);
|
2002-11-29 23:44:07 +00:00
|
|
|
NS_IF_RELEASE(sNameSpaceManager);
|
2002-11-19 13:39:20 +00:00
|
|
|
NS_IF_RELEASE(sParserService);
|
2003-07-08 05:35:04 +00:00
|
|
|
NS_IF_RELEASE(sIOService);
|
2005-08-22 03:00:06 +00:00
|
|
|
NS_IF_RELEASE(sLineBreaker);
|
|
|
|
NS_IF_RELEASE(sWordBreaker);
|
2008-07-02 16:28:43 +00:00
|
|
|
NS_IF_RELEASE(sGenCat);
|
2004-10-07 20:59:53 +00:00
|
|
|
#ifdef MOZ_XTF
|
|
|
|
NS_IF_RELEASE(sXTFService);
|
|
|
|
#endif
|
2004-03-09 03:57:51 +00:00
|
|
|
NS_IF_RELEASE(sImgLoader);
|
2009-07-08 05:23:20 +00:00
|
|
|
NS_IF_RELEASE(sImgCache);
|
2006-08-08 05:14:52 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
NS_IF_RELEASE(sBidiKeyboard);
|
|
|
|
#endif
|
2007-04-02 17:17:36 +00:00
|
|
|
|
2010-06-22 18:12:12 +00:00
|
|
|
delete sAtomEventTable;
|
|
|
|
sAtomEventTable = nsnull;
|
|
|
|
delete sStringEventTable;
|
|
|
|
sStringEventTable = nsnull;
|
|
|
|
delete sUserDefinedEvents;
|
|
|
|
sUserDefinedEvents = nsnull;
|
2007-04-02 17:17:36 +00:00
|
|
|
|
2006-02-07 14:34:10 +00:00
|
|
|
if (sEventListenerManagersHash.ops) {
|
|
|
|
NS_ASSERTION(sEventListenerManagersHash.entryCount == 0,
|
|
|
|
"Event listener manager hash not empty at shutdown!");
|
|
|
|
|
|
|
|
// See comment above.
|
|
|
|
|
2006-02-17 23:41:44 +00:00
|
|
|
// However, we have to handle this table differently. If it still
|
|
|
|
// has entries, we want to leak it too, so that we can keep it alive
|
|
|
|
// in case any elements are destroyed. Because if they are, we need
|
|
|
|
// their event listener managers to be destroyed too, or otherwise
|
|
|
|
// it could leave dangling references in DOMClassInfo's preserved
|
|
|
|
// wrapper table.
|
|
|
|
|
|
|
|
if (sEventListenerManagersHash.entryCount == 0) {
|
|
|
|
PL_DHashTableFinish(&sEventListenerManagersHash);
|
2006-09-01 00:43:23 +00:00
|
|
|
sEventListenerManagersHash.ops = nsnull;
|
2006-02-17 23:41:44 +00:00
|
|
|
}
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
2007-10-29 13:45:07 +00:00
|
|
|
|
2008-03-14 23:08:57 +00:00
|
|
|
NS_ASSERTION(!sBlockedScriptRunners ||
|
|
|
|
sBlockedScriptRunners->Count() == 0,
|
|
|
|
"How'd this happen?");
|
|
|
|
delete sBlockedScriptRunners;
|
|
|
|
sBlockedScriptRunners = nsnull;
|
|
|
|
|
2008-09-08 01:13:02 +00:00
|
|
|
NS_IF_RELEASE(sSameOriginChecker);
|
|
|
|
|
2010-04-21 20:17:41 +00:00
|
|
|
nsTextEditorState::ShutDown();
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
|
|
|
|
2007-11-15 06:16:06 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsCallerTrustedForCapability(const char* aCapability)
|
2007-07-10 04:11:11 +00:00
|
|
|
{
|
|
|
|
// The secman really should handle UniversalXPConnect case, since that
|
|
|
|
// should include UniversalBrowserRead... doesn't right now, though.
|
|
|
|
PRBool hasCap;
|
2007-11-15 06:16:06 +00:00
|
|
|
if (NS_FAILED(sSecurityManager->IsCapabilityEnabled(aCapability, &hasCap)))
|
2007-07-10 04:11:11 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
if (hasCap)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
2007-11-15 06:16:06 +00:00
|
|
|
if (NS_FAILED(sSecurityManager->IsCapabilityEnabled("UniversalXPConnect",
|
|
|
|
&hasCap)))
|
2007-07-10 04:11:11 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
return hasCap;
|
|
|
|
}
|
|
|
|
|
2002-07-18 05:53:28 +00:00
|
|
|
/**
|
|
|
|
* Checks whether two nodes come from the same origin. aTrustedNode is
|
|
|
|
* considered 'safe' in that a user can operate on it and that it isn't
|
|
|
|
* a js-object that implements nsIDOMNode.
|
|
|
|
* Never call this function with the first node provided by script, it
|
|
|
|
* must always be known to be a 'real' node!
|
|
|
|
*/
|
2002-07-15 19:25:27 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
2010-01-12 13:08:44 +00:00
|
|
|
nsContentUtils::CheckSameOrigin(nsINode *aTrustedNode,
|
2002-07-18 05:53:28 +00:00
|
|
|
nsIDOMNode *aUnTrustedNode)
|
2002-07-15 19:25:27 +00:00
|
|
|
{
|
2002-07-18 05:53:28 +00:00
|
|
|
NS_PRECONDITION(aTrustedNode, "There must be a trusted node");
|
2002-07-23 22:16:45 +00:00
|
|
|
|
2003-06-19 23:59:24 +00:00
|
|
|
PRBool isSystem = PR_FALSE;
|
2011-06-21 16:52:01 +00:00
|
|
|
nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&isSystem);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2003-06-19 23:59:24 +00:00
|
|
|
if (isSystem) {
|
|
|
|
// we're running as system, grant access to the node.
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-07-23 22:16:45 +00:00
|
|
|
/*
|
2006-02-02 20:02:34 +00:00
|
|
|
* Get hold of each node's principal
|
2002-07-23 22:16:45 +00:00
|
|
|
*/
|
2006-02-02 20:02:34 +00:00
|
|
|
nsCOMPtr<nsINode> unTrustedNode = do_QueryInterface(aUnTrustedNode);
|
2002-07-23 22:16:45 +00:00
|
|
|
|
2006-02-02 20:02:34 +00:00
|
|
|
// Make sure these are both real nodes
|
2010-01-12 13:08:44 +00:00
|
|
|
NS_ENSURE_TRUE(aTrustedNode && unTrustedNode, NS_ERROR_UNEXPECTED);
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2010-01-12 13:08:44 +00:00
|
|
|
nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
|
2006-04-27 18:21:11 +00:00
|
|
|
nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
|
2002-07-23 22:16:45 +00:00
|
|
|
|
2006-02-02 20:02:34 +00:00
|
|
|
if (trustedPrincipal == unTrustedPrincipal) {
|
2003-01-22 03:25:51 +00:00
|
|
|
return NS_OK;
|
2002-07-15 19:25:27 +00:00
|
|
|
}
|
2002-07-18 05:53:28 +00:00
|
|
|
|
2007-07-10 04:11:11 +00:00
|
|
|
PRBool equal;
|
|
|
|
// XXXbz should we actually have a Subsumes() check here instead? Or perhaps
|
|
|
|
// a separate method for that, with callers using one or the other?
|
|
|
|
if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal)) ||
|
|
|
|
!equal) {
|
|
|
|
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2002-07-15 19:25:27 +00:00
|
|
|
}
|
|
|
|
|
2008-02-27 02:03:27 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
|
|
|
|
nsIPrincipal* aPrincipal)
|
|
|
|
{
|
|
|
|
PRBool subsumes;
|
|
|
|
nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
|
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
|
|
|
|
|
|
|
if (subsumes) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The subject doesn't subsume aPrincipal. Allow access only if the subject
|
|
|
|
// has either "UniversalXPConnect" (if aPrincipal is system principal) or
|
|
|
|
// "UniversalBrowserRead" (in all other cases).
|
|
|
|
PRBool isSystem;
|
|
|
|
rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
|
|
|
|
isSystem = NS_FAILED(rv) || isSystem;
|
|
|
|
const char* capability =
|
|
|
|
NS_FAILED(rv) || isSystem ? "UniversalXPConnect" : "UniversalBrowserRead";
|
|
|
|
|
|
|
|
return IsCallerTrustedForCapability(capability);
|
|
|
|
}
|
|
|
|
|
2002-07-16 13:09:15 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
|
|
|
|
{
|
2006-02-02 20:02:34 +00:00
|
|
|
// XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
|
|
|
|
// with the system principal games? But really, there should be a simpler
|
|
|
|
// API here, dammit.
|
2002-07-30 21:26:32 +00:00
|
|
|
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
2011-06-21 16:52:22 +00:00
|
|
|
nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
2002-07-30 21:26:32 +00:00
|
|
|
|
|
|
|
if (!subjectPrincipal) {
|
|
|
|
// we're running as system, grant access to the node.
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2006-02-02 20:02:34 +00:00
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
|
|
|
NS_ENSURE_TRUE(node, PR_FALSE);
|
2002-07-16 13:09:15 +00:00
|
|
|
|
2008-02-27 02:03:27 +00:00
|
|
|
return CanCallerAccess(subjectPrincipal, node->NodePrincipal());
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::CanCallerAccess(nsPIDOMWindow* aWindow)
|
|
|
|
{
|
|
|
|
// XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
|
|
|
|
// with the system principal games? But really, there should be a simpler
|
|
|
|
// API here, dammit.
|
|
|
|
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
2011-06-21 16:52:22 +00:00
|
|
|
nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
2006-06-27 00:56:41 +00:00
|
|
|
|
2008-02-27 02:03:27 +00:00
|
|
|
if (!subjectPrincipal) {
|
|
|
|
// we're running as system, grant access to the node.
|
2006-06-27 00:56:41 +00:00
|
|
|
|
2004-06-01 20:19:22 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2002-07-16 13:09:15 +00:00
|
|
|
|
2008-02-27 02:03:27 +00:00
|
|
|
nsCOMPtr<nsIScriptObjectPrincipal> scriptObject =
|
|
|
|
do_QueryInterface(aWindow->IsOuterWindow() ?
|
|
|
|
aWindow->GetCurrentInnerWindow() : aWindow);
|
|
|
|
NS_ENSURE_TRUE(scriptObject, PR_FALSE);
|
2004-06-01 20:19:22 +00:00
|
|
|
|
2008-02-27 02:03:27 +00:00
|
|
|
return CanCallerAccess(subjectPrincipal, scriptObject->GetPrincipal());
|
2002-07-16 13:09:15 +00:00
|
|
|
}
|
|
|
|
|
2002-09-04 06:57:25 +00:00
|
|
|
//static
|
|
|
|
PRBool
|
2006-05-19 10:01:22 +00:00
|
|
|
nsContentUtils::InProlog(nsINode *aNode)
|
2002-09-04 06:57:25 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
|
|
|
|
|
2006-05-19 10:01:22 +00:00
|
|
|
nsINode* parent = aNode->GetNodeParent();
|
|
|
|
if (!parent || !parent->IsNodeOfType(nsINode::eDOCUMENT)) {
|
2002-09-04 06:57:25 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-07-08 07:08:04 +00:00
|
|
|
nsIDocument* doc = static_cast<nsIDocument*>(parent);
|
2010-04-30 13:12:05 +00:00
|
|
|
nsIContent* root = doc->GetRootElement();
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2006-05-19 10:01:22 +00:00
|
|
|
return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
|
2002-09-04 06:57:25 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 02:30:54 +00:00
|
|
|
JSContext *
|
|
|
|
nsContentUtils::GetContextFromDocument(nsIDocument *aDocument)
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
{
|
2006-04-11 03:49:44 +00:00
|
|
|
nsIScriptGlobalObject *sgo = aDocument->GetScopeObject();
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
if (!sgo) {
|
|
|
|
// No script global, no context.
|
2004-02-09 22:48:53 +00:00
|
|
|
return nsnull;
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
|
|
|
|
2006-04-11 03:49:44 +00:00
|
|
|
nsIScriptContext *scx = sgo->GetContext();
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
if (!scx) {
|
2010-12-03 16:43:25 +00:00
|
|
|
// No context left in the scope...
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2004-02-09 22:48:53 +00:00
|
|
|
return nsnull;
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
|
|
|
|
2004-02-09 22:48:53 +00:00
|
|
|
return (JSContext *)scx->GetNativeContext();
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
|
|
|
|
2006-07-29 16:02:11 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
2010-12-03 16:43:25 +00:00
|
|
|
nsContentUtils::GetContextAndScope(nsIDocument *aOldDocument,
|
|
|
|
nsIDocument *aNewDocument, JSContext **aCx,
|
|
|
|
JSObject **aNewScope)
|
2006-07-29 16:02:11 +00:00
|
|
|
{
|
|
|
|
*aCx = nsnull;
|
|
|
|
*aNewScope = nsnull;
|
|
|
|
|
2010-12-03 16:43:25 +00:00
|
|
|
JSObject *newScope = aNewDocument->GetWrapper();
|
|
|
|
JSObject *global;
|
|
|
|
if (!newScope) {
|
|
|
|
nsIScriptGlobalObject *newSGO = aNewDocument->GetScopeObject();
|
|
|
|
if (!newSGO || !(global = newSGO->GetGlobalJSObject())) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE(sXPConnect, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
|
2010-12-03 16:43:25 +00:00
|
|
|
JSContext *cx = aOldDocument ? GetContextFromDocument(aOldDocument) : nsnull;
|
2006-04-11 03:49:44 +00:00
|
|
|
if (!cx) {
|
2010-12-03 16:43:25 +00:00
|
|
|
cx = GetContextFromDocument(aNewDocument);
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2006-04-11 03:49:44 +00:00
|
|
|
if (!cx) {
|
|
|
|
// No context reachable from the old or new document, use the
|
|
|
|
// calling context, or the safe context if no caller can be
|
|
|
|
// found.
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2006-04-11 03:49:44 +00:00
|
|
|
sThreadJSContextStack->Peek(&cx);
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2006-04-11 03:49:44 +00:00
|
|
|
if (!cx) {
|
|
|
|
sThreadJSContextStack->GetSafeJSContext(&cx);
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2006-04-11 03:49:44 +00:00
|
|
|
if (!cx) {
|
|
|
|
// No safe context reachable, bail.
|
2010-01-16 14:27:51 +00:00
|
|
|
NS_WARNING("No context reachable in GetContextAndScopes()!");
|
2006-04-11 03:49:44 +00:00
|
|
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
|
2010-12-03 16:43:25 +00:00
|
|
|
if (!newScope && cx) {
|
|
|
|
jsval v;
|
|
|
|
nsresult rv = WrapNative(cx, global, aNewDocument, aNewDocument, &v);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
newScope = JSVAL_TO_OBJECT(v);
|
|
|
|
}
|
|
|
|
|
2006-07-29 16:02:11 +00:00
|
|
|
*aCx = cx;
|
|
|
|
*aNewScope = newScope;
|
|
|
|
|
|
|
|
return NS_OK;
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 16:46:42 +00:00
|
|
|
}
|
|
|
|
|
2006-04-26 19:53:27 +00:00
|
|
|
nsresult
|
2011-05-19 20:05:46 +00:00
|
|
|
nsContentUtils::ReparentContentWrappersInScope(JSContext *cx,
|
|
|
|
nsIScriptGlobalObject *aOldScope,
|
2006-04-26 19:53:27 +00:00
|
|
|
nsIScriptGlobalObject *aNewScope)
|
|
|
|
{
|
|
|
|
JSObject *oldScopeObj = aOldScope->GetGlobalJSObject();
|
|
|
|
JSObject *newScopeObj = aNewScope->GetGlobalJSObject();
|
|
|
|
|
|
|
|
if (!newScopeObj || !oldScopeObj) {
|
|
|
|
// We can't really do anything without the JSObjects.
|
|
|
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2010-03-31 11:45:46 +00:00
|
|
|
return sXPConnect->MoveWrappers(cx, oldScopeObj, newScopeObj);
|
2006-04-26 19:53:27 +00:00
|
|
|
}
|
|
|
|
|
2010-09-09 18:18:23 +00:00
|
|
|
nsPIDOMWindow *
|
|
|
|
nsContentUtils::GetWindowFromCaller()
|
|
|
|
{
|
|
|
|
JSContext *cx = nsnull;
|
|
|
|
sThreadJSContextStack->Peek(&cx);
|
|
|
|
|
|
|
|
if (cx) {
|
|
|
|
nsCOMPtr<nsPIDOMWindow> win =
|
|
|
|
do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
|
|
|
|
return win;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2004-02-09 22:48:53 +00:00
|
|
|
nsIDOMDocument *
|
|
|
|
nsContentUtils::GetDocumentFromCaller()
|
2002-09-20 13:40:53 +00:00
|
|
|
{
|
|
|
|
JSContext *cx = nsnull;
|
2010-08-20 01:12:02 +00:00
|
|
|
JSObject *obj = nsnull;
|
|
|
|
sXPConnect->GetCaller(&cx, &obj);
|
|
|
|
NS_ASSERTION(cx && obj, "Caller ensures something is running");
|
2002-09-20 13:40:53 +00:00
|
|
|
|
2011-01-25 23:06:45 +00:00
|
|
|
JSAutoEnterCompartment ac;
|
|
|
|
if (!ac.enter(cx, obj)) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2010-08-20 01:12:02 +00:00
|
|
|
nsCOMPtr<nsPIDOMWindow> win =
|
|
|
|
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, obj));
|
|
|
|
if (!win) {
|
|
|
|
return nsnull;
|
2002-09-20 13:40:53 +00:00
|
|
|
}
|
2004-02-09 22:48:53 +00:00
|
|
|
|
2010-08-20 01:12:02 +00:00
|
|
|
return win->GetExtantDocument();
|
2002-09-20 13:40:53 +00:00
|
|
|
}
|
|
|
|
|
2005-11-03 22:47:06 +00:00
|
|
|
nsIDOMDocument *
|
|
|
|
nsContentUtils::GetDocumentFromContext()
|
|
|
|
{
|
|
|
|
JSContext *cx = nsnull;
|
|
|
|
sThreadJSContextStack->Peek(&cx);
|
|
|
|
|
|
|
|
if (cx) {
|
|
|
|
nsIScriptGlobalObject *sgo = nsJSUtils::GetDynamicScriptGlobal(cx);
|
|
|
|
|
|
|
|
if (sgo) {
|
|
|
|
nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(sgo);
|
|
|
|
if (pwin) {
|
|
|
|
return pwin->GetExtantDocument();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2002-04-12 10:11:00 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsCallerChrome()
|
|
|
|
{
|
2002-07-16 13:09:15 +00:00
|
|
|
PRBool is_caller_chrome = PR_FALSE;
|
2002-07-18 05:53:28 +00:00
|
|
|
nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&is_caller_chrome);
|
2002-07-16 13:09:15 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return PR_FALSE;
|
2002-04-12 10:11:00 +00:00
|
|
|
}
|
|
|
|
|
2002-07-16 13:09:15 +00:00
|
|
|
return is_caller_chrome;
|
2002-04-12 10:11:00 +00:00
|
|
|
}
|
|
|
|
|
2006-03-26 20:57:53 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsCallerTrustedForRead()
|
|
|
|
{
|
|
|
|
return IsCallerTrustedForCapability("UniversalBrowserRead");
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsCallerTrustedForWrite()
|
|
|
|
{
|
|
|
|
return IsCallerTrustedForCapability("UniversalBrowserWrite");
|
|
|
|
}
|
|
|
|
|
2010-07-16 12:50:28 +00:00
|
|
|
// static
|
|
|
|
nsINode*
|
|
|
|
nsContentUtils::GetCrossDocParentNode(nsINode* aChild)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aChild, "The child is null!");
|
|
|
|
|
|
|
|
nsINode* parent = aChild->GetNodeParent();
|
|
|
|
if (parent || !aChild->IsNodeOfType(nsINode::eDOCUMENT))
|
|
|
|
return parent;
|
|
|
|
|
|
|
|
nsIDocument* doc = static_cast<nsIDocument*>(aChild);
|
|
|
|
nsIDocument* parentDoc = doc->GetParentDocument();
|
|
|
|
return parentDoc ? parentDoc->FindContentForSubDocument(doc) : nsnull;
|
|
|
|
}
|
|
|
|
|
2002-06-28 01:30:09 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
2010-05-11 01:12:34 +00:00
|
|
|
nsContentUtils::ContentIsDescendantOf(const nsINode* aPossibleDescendant,
|
|
|
|
const nsINode* aPossibleAncestor)
|
2002-06-28 01:30:09 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
|
|
|
|
NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (aPossibleDescendant == aPossibleAncestor)
|
|
|
|
return PR_TRUE;
|
2006-05-19 10:01:22 +00:00
|
|
|
aPossibleDescendant = aPossibleDescendant->GetNodeParent();
|
2002-06-28 01:30:09 +00:00
|
|
|
} while (aPossibleDescendant);
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-08-27 15:51:41 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
|
|
|
|
nsINode* aPossibleAncestor)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
|
|
|
|
NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (aPossibleDescendant == aPossibleAncestor)
|
|
|
|
return PR_TRUE;
|
2010-07-16 12:50:28 +00:00
|
|
|
aPossibleDescendant = GetCrossDocParentNode(aPossibleDescendant);
|
2009-08-27 15:51:41 +00:00
|
|
|
} while (aPossibleDescendant);
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2002-06-28 01:30:09 +00:00
|
|
|
|
2002-06-25 20:03:06 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
2010-04-30 11:15:09 +00:00
|
|
|
nsContentUtils::GetAncestors(nsINode* aNode,
|
|
|
|
nsTArray<nsINode*>& aArray)
|
2002-06-25 20:03:06 +00:00
|
|
|
{
|
2010-04-30 11:15:09 +00:00
|
|
|
while (aNode) {
|
|
|
|
aArray.AppendElement(aNode);
|
|
|
|
aNode = aNode->GetNodeParent();
|
|
|
|
}
|
2002-06-25 20:03:06 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode* aNode,
|
|
|
|
PRInt32 aOffset,
|
2009-03-20 08:15:35 +00:00
|
|
|
nsTArray<nsIContent*>* aAncestorNodes,
|
|
|
|
nsTArray<PRInt32>* aAncestorOffsets)
|
2002-06-25 20:03:06 +00:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aNode);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
|
|
|
|
|
|
|
if (!content) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2009-03-20 08:15:35 +00:00
|
|
|
if (!aAncestorNodes->IsEmpty()) {
|
2002-06-25 20:03:06 +00:00
|
|
|
NS_WARNING("aAncestorNodes is not empty");
|
|
|
|
aAncestorNodes->Clear();
|
|
|
|
}
|
|
|
|
|
2009-03-20 08:15:35 +00:00
|
|
|
if (!aAncestorOffsets->IsEmpty()) {
|
2002-06-25 20:03:06 +00:00
|
|
|
NS_WARNING("aAncestorOffsets is not empty");
|
|
|
|
aAncestorOffsets->Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// insert the node itself
|
|
|
|
aAncestorNodes->AppendElement(content.get());
|
2009-03-20 08:15:35 +00:00
|
|
|
aAncestorOffsets->AppendElement(aOffset);
|
2002-06-25 20:03:06 +00:00
|
|
|
|
|
|
|
// insert all the ancestors
|
2003-07-29 23:49:41 +00:00
|
|
|
nsIContent* child = content;
|
|
|
|
nsIContent* parent = child->GetParent();
|
|
|
|
while (parent) {
|
|
|
|
aAncestorNodes->AppendElement(parent);
|
2009-03-20 08:15:35 +00:00
|
|
|
aAncestorOffsets->AppendElement(parent->IndexOf(child));
|
2003-07-29 23:49:41 +00:00
|
|
|
child = parent;
|
|
|
|
parent = parent->GetParent();
|
2002-06-25 20:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode,
|
|
|
|
nsIDOMNode *aOther,
|
|
|
|
nsIDOMNode** aCommonAncestor)
|
|
|
|
{
|
|
|
|
*aCommonAncestor = nsnull;
|
|
|
|
|
2006-05-16 14:51:52 +00:00
|
|
|
nsCOMPtr<nsINode> node1 = do_QueryInterface(aNode);
|
|
|
|
nsCOMPtr<nsINode> node2 = do_QueryInterface(aOther);
|
2002-06-25 20:03:06 +00:00
|
|
|
|
2006-05-16 14:51:52 +00:00
|
|
|
NS_ENSURE_TRUE(node1 && node2, NS_ERROR_UNEXPECTED);
|
2002-06-25 20:03:06 +00:00
|
|
|
|
2006-05-16 14:51:52 +00:00
|
|
|
nsINode* common = GetCommonAncestor(node1, node2);
|
|
|
|
NS_ENSURE_TRUE(common, NS_ERROR_NOT_AVAILABLE);
|
2002-06-25 20:03:06 +00:00
|
|
|
|
2006-05-16 14:51:52 +00:00
|
|
|
return CallQueryInterface(common, aCommonAncestor);
|
2002-06-25 20:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2006-05-16 14:51:52 +00:00
|
|
|
nsINode*
|
|
|
|
nsContentUtils::GetCommonAncestor(nsINode* aNode1,
|
|
|
|
nsINode* aNode2)
|
2002-06-25 20:03:06 +00:00
|
|
|
{
|
2006-05-16 14:51:52 +00:00
|
|
|
if (aNode1 == aNode2) {
|
|
|
|
return aNode1;
|
2002-06-25 20:03:06 +00:00
|
|
|
}
|
|
|
|
|
2006-05-16 14:51:52 +00:00
|
|
|
// Build the chain of parents
|
2006-11-02 19:33:10 +00:00
|
|
|
nsAutoTPtrArray<nsINode, 30> parents1, parents2;
|
2002-06-25 20:03:06 +00:00
|
|
|
do {
|
2006-05-16 14:51:52 +00:00
|
|
|
parents1.AppendElement(aNode1);
|
|
|
|
aNode1 = aNode1->GetNodeParent();
|
|
|
|
} while (aNode1);
|
2002-06-25 20:03:06 +00:00
|
|
|
do {
|
2006-05-16 14:51:52 +00:00
|
|
|
parents2.AppendElement(aNode2);
|
|
|
|
aNode2 = aNode2->GetNodeParent();
|
|
|
|
} while (aNode2);
|
|
|
|
|
|
|
|
// Find where the parent chain differs
|
2006-11-02 19:33:10 +00:00
|
|
|
PRUint32 pos1 = parents1.Length();
|
|
|
|
PRUint32 pos2 = parents2.Length();
|
2006-05-16 14:51:52 +00:00
|
|
|
nsINode* parent = nsnull;
|
|
|
|
PRUint32 len;
|
2010-02-22 19:41:19 +00:00
|
|
|
for (len = NS_MIN(pos1, pos2); len > 0; --len) {
|
2006-11-02 19:33:10 +00:00
|
|
|
nsINode* child1 = parents1.ElementAt(--pos1);
|
|
|
|
nsINode* child2 = parents2.ElementAt(--pos2);
|
2006-05-16 14:51:52 +00:00
|
|
|
if (child1 != child2) {
|
|
|
|
break;
|
2002-06-25 20:03:06 +00:00
|
|
|
}
|
2006-05-16 14:51:52 +00:00
|
|
|
parent = child1;
|
2002-06-25 20:03:06 +00:00
|
|
|
}
|
|
|
|
|
2006-05-16 14:51:52 +00:00
|
|
|
return parent;
|
2002-06-25 20:03:06 +00:00
|
|
|
}
|
|
|
|
|
2006-10-21 01:30:54 +00:00
|
|
|
/* static */
|
|
|
|
PRInt32
|
|
|
|
nsContentUtils::ComparePoints(nsINode* aParent1, PRInt32 aOffset1,
|
2008-02-24 12:46:09 +00:00
|
|
|
nsINode* aParent2, PRInt32 aOffset2,
|
|
|
|
PRBool* aDisconnected)
|
2006-10-21 01:30:54 +00:00
|
|
|
{
|
|
|
|
if (aParent1 == aParent2) {
|
|
|
|
return aOffset1 < aOffset2 ? -1 :
|
|
|
|
aOffset1 > aOffset2 ? 1 :
|
|
|
|
0;
|
|
|
|
}
|
|
|
|
|
2007-11-11 20:35:30 +00:00
|
|
|
nsAutoTArray<nsINode*, 32> parents1, parents2;
|
2006-10-21 01:30:54 +00:00
|
|
|
nsINode* node1 = aParent1;
|
|
|
|
nsINode* node2 = aParent2;
|
|
|
|
do {
|
|
|
|
parents1.AppendElement(node1);
|
|
|
|
node1 = node1->GetNodeParent();
|
|
|
|
} while (node1);
|
|
|
|
do {
|
|
|
|
parents2.AppendElement(node2);
|
|
|
|
node2 = node2->GetNodeParent();
|
|
|
|
} while (node2);
|
|
|
|
|
|
|
|
PRUint32 pos1 = parents1.Length() - 1;
|
|
|
|
PRUint32 pos2 = parents2.Length() - 1;
|
2008-11-02 16:31:29 +00:00
|
|
|
|
|
|
|
PRBool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
|
2008-02-24 12:46:09 +00:00
|
|
|
if (aDisconnected) {
|
2008-11-02 16:31:29 +00:00
|
|
|
*aDisconnected = disconnected;
|
|
|
|
}
|
|
|
|
if (disconnected) {
|
|
|
|
NS_ASSERTION(aDisconnected, "unexpected disconnected nodes");
|
|
|
|
return 1;
|
2008-02-24 12:46:09 +00:00
|
|
|
}
|
2006-10-21 01:30:54 +00:00
|
|
|
|
|
|
|
// Find where the parent chains differ
|
|
|
|
nsINode* parent = parents1.ElementAt(pos1);
|
|
|
|
PRUint32 len;
|
2010-02-22 19:41:19 +00:00
|
|
|
for (len = NS_MIN(pos1, pos2); len > 0; --len) {
|
2006-10-21 01:30:54 +00:00
|
|
|
nsINode* child1 = parents1.ElementAt(--pos1);
|
|
|
|
nsINode* child2 = parents2.ElementAt(--pos2);
|
|
|
|
if (child1 != child2) {
|
|
|
|
return parent->IndexOf(child1) < parent->IndexOf(child2) ? -1 : 1;
|
|
|
|
}
|
|
|
|
parent = child1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// The parent chains never differed, so one of the nodes is an ancestor of
|
|
|
|
// the other
|
|
|
|
|
|
|
|
NS_ASSERTION(!pos1 || !pos2,
|
|
|
|
"should have run out of parent chain for one of the nodes");
|
|
|
|
|
|
|
|
if (!pos1) {
|
|
|
|
nsINode* child2 = parents2.ElementAt(--pos2);
|
|
|
|
return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsINode* child1 = parents1.ElementAt(--pos1);
|
|
|
|
return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
2002-06-11 23:23:12 +00:00
|
|
|
inline PRBool
|
|
|
|
IsCharInSet(const char* aSet,
|
|
|
|
const PRUnichar aChar)
|
|
|
|
{
|
|
|
|
PRUnichar ch;
|
|
|
|
while ((ch = *aSet)) {
|
|
|
|
if (aChar == PRUnichar(ch)) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
++aSet;
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method strips leading/trailing chars, in given set, from string.
|
|
|
|
*/
|
2003-02-27 00:49:36 +00:00
|
|
|
|
|
|
|
// static
|
2002-06-11 23:23:12 +00:00
|
|
|
const nsDependentSubstring
|
|
|
|
nsContentUtils::TrimCharsInSet(const char* aSet,
|
|
|
|
const nsAString& aValue)
|
|
|
|
{
|
|
|
|
nsAString::const_iterator valueCurrent, valueEnd;
|
|
|
|
|
|
|
|
aValue.BeginReading(valueCurrent);
|
|
|
|
aValue.EndReading(valueEnd);
|
|
|
|
|
2006-08-28 20:12:37 +00:00
|
|
|
// Skip characters in the beginning
|
2002-06-11 23:23:12 +00:00
|
|
|
while (valueCurrent != valueEnd) {
|
|
|
|
if (!IsCharInSet(aSet, *valueCurrent)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++valueCurrent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (valueCurrent != valueEnd) {
|
|
|
|
for (;;) {
|
|
|
|
--valueEnd;
|
|
|
|
if (!IsCharInSet(aSet, *valueEnd)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++valueEnd; // Step beyond the last character we want in the value.
|
|
|
|
}
|
|
|
|
|
|
|
|
// valueEnd should point to the char after the last to copy
|
|
|
|
return Substring(valueCurrent, valueEnd);
|
|
|
|
}
|
2002-08-09 08:45:30 +00:00
|
|
|
|
2003-02-27 00:49:36 +00:00
|
|
|
/**
|
|
|
|
* This method strips leading and trailing whitespace from a string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// static
|
2010-08-18 18:34:14 +00:00
|
|
|
template<PRBool IsWhitespace(PRUnichar)>
|
2003-02-27 00:49:36 +00:00
|
|
|
const nsDependentSubstring
|
|
|
|
nsContentUtils::TrimWhitespace(const nsAString& aStr, PRBool aTrimTrailing)
|
|
|
|
{
|
|
|
|
nsAString::const_iterator start, end;
|
|
|
|
|
|
|
|
aStr.BeginReading(start);
|
|
|
|
aStr.EndReading(end);
|
|
|
|
|
2006-08-28 20:12:37 +00:00
|
|
|
// Skip whitespace characters in the beginning
|
2010-08-18 18:34:14 +00:00
|
|
|
while (start != end && IsWhitespace(*start)) {
|
2003-02-27 00:49:36 +00:00
|
|
|
++start;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aTrimTrailing) {
|
|
|
|
// Skip whitespace characters in the end.
|
|
|
|
while (end != start) {
|
|
|
|
--end;
|
|
|
|
|
2010-08-18 18:34:14 +00:00
|
|
|
if (!IsWhitespace(*end)) {
|
2003-02-27 00:49:36 +00:00
|
|
|
// Step back to the last non-whitespace character.
|
|
|
|
++end;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return a substring for the string w/o leading and/or trailing
|
|
|
|
// whitespace
|
|
|
|
|
|
|
|
return Substring(start, end);
|
|
|
|
}
|
|
|
|
|
2010-08-18 18:34:14 +00:00
|
|
|
// Declaring the templates we are going to use avoid linking issues without
|
|
|
|
// inlining the method. Considering there is not so much spaces checking
|
|
|
|
// methods we can consider this to be better than inlining.
|
|
|
|
template
|
|
|
|
const nsDependentSubstring
|
|
|
|
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, PRBool);
|
|
|
|
template
|
|
|
|
const nsDependentSubstring
|
|
|
|
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(const nsAString&, PRBool);
|
|
|
|
|
2003-05-30 00:21:01 +00:00
|
|
|
static inline void KeyAppendSep(nsACString& aKey)
|
|
|
|
{
|
|
|
|
if (!aKey.IsEmpty()) {
|
|
|
|
aKey.Append('>');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
|
|
|
|
{
|
|
|
|
KeyAppendSep(aKey);
|
|
|
|
|
|
|
|
// Could escape separator here if collisions happen. > is not a legal char
|
|
|
|
// for a name or type attribute, so we should be safe avoiding that extra work.
|
|
|
|
|
2003-06-24 21:43:01 +00:00
|
|
|
AppendUTF16toUTF8(aString, aKey);
|
2003-05-30 00:21:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
|
|
|
|
{
|
|
|
|
KeyAppendSep(aKey);
|
2005-06-02 23:36:08 +00:00
|
|
|
|
2003-05-30 00:21:01 +00:00
|
|
|
// Could escape separator here if collisions happen. > is not a legal char
|
|
|
|
// for a name or type attribute, so we should be safe avoiding that extra work.
|
|
|
|
|
|
|
|
aKey.Append(aString);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void KeyAppendInt(PRInt32 aInt, nsACString& aKey)
|
|
|
|
{
|
|
|
|
KeyAppendSep(aKey);
|
|
|
|
|
|
|
|
aKey.Append(nsPrintfCString("%d", aInt));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
|
|
|
|
|
2010-03-08 15:45:00 +00:00
|
|
|
KeyAppendString(nsAtomCString(aAtom), aKey);
|
2003-05-30 00:21:01 +00:00
|
|
|
}
|
|
|
|
|
2010-10-07 19:19:32 +00:00
|
|
|
static inline PRBool IsAutocompleteOff(const nsIContent* aElement)
|
2003-05-30 00:21:01 +00:00
|
|
|
{
|
2010-05-09 18:32:57 +00:00
|
|
|
return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocomplete,
|
|
|
|
NS_LITERAL_STRING("off"), eIgnoreCase);
|
2003-05-30 00:21:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*static*/ nsresult
|
|
|
|
nsContentUtils::GenerateStateKey(nsIContent* aContent,
|
2010-10-07 19:19:32 +00:00
|
|
|
const nsIDocument* aDocument,
|
2003-05-30 00:21:01 +00:00
|
|
|
nsIStatefulFrame::SpecialStateID aID,
|
|
|
|
nsACString& aKey)
|
|
|
|
{
|
|
|
|
aKey.Truncate();
|
|
|
|
|
2005-01-15 17:47:23 +00:00
|
|
|
PRUint32 partID = aDocument ? aDocument->GetPartID() : 0;
|
|
|
|
|
2003-05-30 00:21:01 +00:00
|
|
|
// SpecialStateID case - e.g. scrollbars around the content window
|
2005-11-29 16:47:18 +00:00
|
|
|
// The key in this case is a special state id
|
2003-05-30 00:21:01 +00:00
|
|
|
if (nsIStatefulFrame::eNoID != aID) {
|
2005-01-15 17:47:23 +00:00
|
|
|
KeyAppendInt(partID, aKey); // first append a partID
|
2003-05-30 00:21:01 +00:00
|
|
|
KeyAppendInt(aID, aKey);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We must have content if we're not using a special state id
|
|
|
|
NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
// Don't capture state for anonymous content
|
2008-07-23 04:50:20 +00:00
|
|
|
if (aContent->IsInAnonymousSubtree()) {
|
2003-05-30 00:21:01 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-05-09 18:32:57 +00:00
|
|
|
if (IsAutocompleteOff(aContent)) {
|
2003-05-30 00:21:01 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2005-01-25 04:22:09 +00:00
|
|
|
nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(aContent->GetCurrentDoc()));
|
2003-05-30 00:21:01 +00:00
|
|
|
|
2005-01-15 17:47:23 +00:00
|
|
|
KeyAppendInt(partID, aKey); // first append a partID
|
2005-11-29 16:47:18 +00:00
|
|
|
// Make sure we can't possibly collide with an nsIStatefulFrame
|
|
|
|
// special id of some sort
|
|
|
|
KeyAppendInt(nsIStatefulFrame::eNoID, aKey);
|
2003-05-30 00:21:01 +00:00
|
|
|
PRBool generatedUniqueKey = PR_FALSE;
|
|
|
|
|
|
|
|
if (htmlDocument) {
|
2005-01-25 04:22:09 +00:00
|
|
|
// Flush our content model so it'll be up to date
|
2009-11-06 13:06:48 +00:00
|
|
|
// If this becomes unnecessary and the following line is removed,
|
|
|
|
// please also remove the corresponding flush operation from
|
|
|
|
// nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
|
2005-01-25 04:22:09 +00:00
|
|
|
aContent->GetCurrentDoc()->FlushPendingNotifications(Flush_Content);
|
2003-05-30 00:21:01 +00:00
|
|
|
|
2005-02-02 23:16:02 +00:00
|
|
|
nsContentList *htmlForms = htmlDocument->GetForms();
|
2006-06-08 04:28:20 +00:00
|
|
|
nsContentList *htmlFormControls = htmlDocument->GetFormControls();
|
2004-02-03 23:23:10 +00:00
|
|
|
|
2005-02-02 23:16:02 +00:00
|
|
|
NS_ENSURE_TRUE(htmlForms && htmlFormControls, NS_ERROR_OUT_OF_MEMORY);
|
2003-05-30 00:21:01 +00:00
|
|
|
|
2005-11-29 16:47:18 +00:00
|
|
|
// If we have a form control and can calculate form information, use that
|
|
|
|
// as the key - it is more reliable than just recording position in the
|
|
|
|
// DOM.
|
|
|
|
// XXXbz Is it, really? We have bugs on this, I think...
|
2003-05-30 00:21:01 +00:00
|
|
|
// Important to have a unique key, and tag/type/name may not be.
|
|
|
|
//
|
|
|
|
// If the control has a form, the format of the key is:
|
2005-11-29 16:47:18 +00:00
|
|
|
// f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
|
2003-05-30 00:21:01 +00:00
|
|
|
// else:
|
2005-11-29 16:47:18 +00:00
|
|
|
// d>type>IndOfControlInDoc>name
|
2003-05-30 00:21:01 +00:00
|
|
|
//
|
|
|
|
// XXX We don't need to use index if name is there
|
2005-11-29 16:47:18 +00:00
|
|
|
// XXXbz We don't? Why not? I don't follow.
|
2003-05-30 00:21:01 +00:00
|
|
|
//
|
|
|
|
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
|
|
|
|
if (control && htmlFormControls && htmlForms) {
|
|
|
|
|
|
|
|
// Append the control type
|
|
|
|
KeyAppendInt(control->GetType(), aKey);
|
|
|
|
|
|
|
|
// If in a form, add form name / index of form / index in form
|
|
|
|
PRInt32 index = -1;
|
2010-05-09 18:32:57 +00:00
|
|
|
Element *formElement = control->GetFormElement();
|
2003-05-30 00:21:01 +00:00
|
|
|
if (formElement) {
|
|
|
|
if (IsAutocompleteOff(formElement)) {
|
|
|
|
aKey.Truncate();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2005-11-29 16:47:18 +00:00
|
|
|
KeyAppendString(NS_LITERAL_CSTRING("f"), aKey);
|
|
|
|
|
2003-05-30 00:21:01 +00:00
|
|
|
// Append the index of the form in the document
|
2010-05-09 18:32:57 +00:00
|
|
|
index = htmlForms->IndexOf(formElement, PR_FALSE);
|
2003-05-30 00:21:01 +00:00
|
|
|
if (index <= -1) {
|
|
|
|
//
|
|
|
|
// XXX HACK this uses some state that was dumped into the document
|
|
|
|
// specifically to fix bug 138892. What we are trying to do is *guess*
|
|
|
|
// which form this control's state is found in, with the highly likely
|
|
|
|
// guess that the highest form parsed so far is the one.
|
|
|
|
// This code should not be on trunk, only branch.
|
|
|
|
//
|
2004-02-03 23:23:10 +00:00
|
|
|
index = htmlDocument->GetNumFormsSynchronous() - 1;
|
2003-05-30 00:21:01 +00:00
|
|
|
}
|
|
|
|
if (index > -1) {
|
|
|
|
KeyAppendInt(index, aKey);
|
|
|
|
|
|
|
|
// Append the index of the control in the form
|
|
|
|
nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
|
2008-10-09 23:31:40 +00:00
|
|
|
index = form->IndexOfControl(control);
|
2003-05-30 00:21:01 +00:00
|
|
|
|
|
|
|
if (index > -1) {
|
|
|
|
KeyAppendInt(index, aKey);
|
|
|
|
generatedUniqueKey = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append the form name
|
|
|
|
nsAutoString formName;
|
2010-05-09 18:32:57 +00:00
|
|
|
formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName);
|
2003-05-30 00:21:01 +00:00
|
|
|
KeyAppendString(formName, aKey);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2005-11-29 16:47:18 +00:00
|
|
|
KeyAppendString(NS_LITERAL_CSTRING("d"), aKey);
|
|
|
|
|
2003-05-30 00:21:01 +00:00
|
|
|
// If not in a form, add index of control in document
|
2005-06-02 23:36:08 +00:00
|
|
|
// Less desirable than indexing by form info.
|
2003-05-30 00:21:01 +00:00
|
|
|
|
|
|
|
// Hash by index of control in doc (we are not in a form)
|
|
|
|
// These are important as they are unique, and type/name may not be.
|
|
|
|
|
2007-10-03 02:04:59 +00:00
|
|
|
// We have to flush sink notifications at this point to make
|
|
|
|
// sure that htmlFormControls is up to date.
|
|
|
|
index = htmlFormControls->IndexOf(aContent, PR_TRUE);
|
2003-05-30 00:21:01 +00:00
|
|
|
if (index > -1) {
|
|
|
|
KeyAppendInt(index, aKey);
|
|
|
|
generatedUniqueKey = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append the control name
|
|
|
|
nsAutoString name;
|
2006-12-26 17:47:52 +00:00
|
|
|
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
2003-05-30 00:21:01 +00:00
|
|
|
KeyAppendString(name, aKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!generatedUniqueKey) {
|
2005-11-29 16:47:18 +00:00
|
|
|
// Either we didn't have a form control or we aren't in an HTML document so
|
2011-04-06 11:32:31 +00:00
|
|
|
// we can't figure out form info. Append the tag name if it's an element
|
|
|
|
// to avoid restoring state for one type of element on another type.
|
|
|
|
if (aContent->IsElement()) {
|
|
|
|
KeyAppendString(nsDependentAtomString(aContent->Tag()), aKey);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Append a character that is not "d" or "f" to disambiguate from
|
|
|
|
// the case when we were a form control in an HTML document.
|
|
|
|
KeyAppendString(NS_LITERAL_CSTRING("o"), aKey);
|
|
|
|
}
|
|
|
|
|
2005-11-29 16:47:18 +00:00
|
|
|
// Now start at aContent and append the indices of it and all its ancestors
|
|
|
|
// in their containers. That should at least pin down its position in the
|
|
|
|
// DOM...
|
2006-05-19 10:01:22 +00:00
|
|
|
nsINode* parent = aContent->GetNodeParent();
|
|
|
|
nsINode* content = aContent;
|
2005-11-29 16:47:18 +00:00
|
|
|
while (parent) {
|
|
|
|
KeyAppendInt(parent->IndexOf(content), aKey);
|
|
|
|
content = parent;
|
2006-05-19 10:01:22 +00:00
|
|
|
parent = content->GetNodeParent();
|
2005-11-29 16:47:18 +00:00
|
|
|
}
|
2003-05-30 00:21:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-07-15 02:07:55 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
2003-07-08 05:35:04 +00:00
|
|
|
nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
|
|
|
|
const nsAString& aSpec,
|
|
|
|
nsIDocument* aDocument,
|
|
|
|
nsIURI* aBaseURI)
|
|
|
|
{
|
2004-11-03 19:44:59 +00:00
|
|
|
return NS_NewURI(aResult, aSpec,
|
|
|
|
aDocument ? aDocument->GetDocumentCharacterSet().get() : nsnull,
|
2003-07-08 05:35:04 +00:00
|
|
|
aBaseURI, sIOService);
|
|
|
|
}
|
|
|
|
|
2003-07-15 02:07:55 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
2009-06-16 06:32:10 +00:00
|
|
|
nsContentUtils::BelongsInForm(nsIContent *aForm,
|
2003-07-15 02:07:55 +00:00
|
|
|
nsIContent *aContent)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aForm, "Must have a form");
|
|
|
|
NS_PRECONDITION(aContent, "Must have a content node");
|
|
|
|
|
2009-06-16 06:32:10 +00:00
|
|
|
if (aForm == aContent) {
|
2003-07-15 02:07:55 +00:00
|
|
|
// A form does not belong inside itself, so we return false here
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-07-28 21:09:56 +00:00
|
|
|
nsIContent* content = aContent->GetParent();
|
2003-07-15 02:07:55 +00:00
|
|
|
|
|
|
|
while (content) {
|
2009-06-16 06:32:10 +00:00
|
|
|
if (content == aForm) {
|
2003-07-15 02:07:55 +00:00
|
|
|
// aContent is contained within the form so we return true.
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2006-12-26 17:47:52 +00:00
|
|
|
if (content->Tag() == nsGkAtoms::form &&
|
2009-08-24 20:02:07 +00:00
|
|
|
content->IsHTML()) {
|
2003-07-15 02:07:55 +00:00
|
|
|
// The child is contained within a form, but not the right form
|
|
|
|
// so we ignore it.
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-07-28 21:09:56 +00:00
|
|
|
content = content->GetParent();
|
2003-07-15 02:07:55 +00:00
|
|
|
}
|
|
|
|
|
2009-06-16 06:32:10 +00:00
|
|
|
if (aForm->GetChildCount() > 0) {
|
2003-07-15 02:07:55 +00:00
|
|
|
// The form is a container but aContent wasn't inside the form,
|
|
|
|
// return false
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The form is a leaf and aContent wasn't inside any other form so
|
|
|
|
// we check whether the content comes after the form. If it does,
|
|
|
|
// return true. If it does not, then it couldn't have been inside
|
|
|
|
// the form in the HTML.
|
2009-06-16 06:32:10 +00:00
|
|
|
if (PositionIsBefore(aForm, aContent)) {
|
2003-07-15 02:07:55 +00:00
|
|
|
// We could be in this form!
|
|
|
|
// In the future, we may want to get document.forms, look at the
|
|
|
|
// form after aForm, and if aContent is after that form after
|
|
|
|
// aForm return false here....
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2005-06-02 23:36:08 +00:00
|
|
|
|
2003-07-15 02:07:55 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2004-02-10 10:58:13 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::CheckQName(const nsAString& aQualifiedName,
|
|
|
|
PRBool aNamespaceAware)
|
|
|
|
{
|
2005-09-11 10:08:43 +00:00
|
|
|
nsIParserService *parserService = GetParserService();
|
2004-02-10 10:58:13 +00:00
|
|
|
NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
const PRUnichar *colon;
|
2004-03-06 16:00:23 +00:00
|
|
|
return parserService->CheckQName(PromiseFlatString(aQualifiedName),
|
|
|
|
aNamespaceAware, &colon);
|
2004-02-10 10:58:13 +00:00
|
|
|
}
|
|
|
|
|
2005-01-01 18:02:03 +00:00
|
|
|
//static
|
|
|
|
nsresult
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
|
2005-01-01 18:02:03 +00:00
|
|
|
const nsAFlatString& aQName,
|
|
|
|
PRInt32 *aNamespace, nsIAtom **aLocalName)
|
|
|
|
{
|
2005-09-11 10:08:43 +00:00
|
|
|
nsIParserService* parserService = GetParserService();
|
2005-01-01 18:02:03 +00:00
|
|
|
NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
const PRUnichar* colon;
|
|
|
|
nsresult rv = parserService->CheckQName(aQName, PR_TRUE, &colon);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (colon) {
|
|
|
|
const PRUnichar* end;
|
|
|
|
aQName.EndReading(end);
|
|
|
|
nsAutoString nameSpace;
|
2010-04-19 15:40:16 +00:00
|
|
|
rv = aNamespaceResolver->LookupNamespaceURI(Substring(aQName.get(), colon),
|
|
|
|
nameSpace);
|
2005-01-01 18:02:03 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2005-09-11 11:24:16 +00:00
|
|
|
*aNamespace = NameSpaceManager()->GetNameSpaceID(nameSpace);
|
2005-01-01 18:02:03 +00:00
|
|
|
if (*aNamespace == kNameSpaceID_Unknown)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
*aLocalName = NS_NewAtom(Substring(colon + 1, end));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*aNamespace = kNameSpaceID_None;
|
|
|
|
*aLocalName = NS_NewAtom(aQName);
|
|
|
|
}
|
|
|
|
NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-10 10:58:13 +00:00
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aQualifiedName,
|
2004-06-25 12:26:02 +00:00
|
|
|
nsNodeInfoManager* aNodeInfoManager,
|
2011-06-14 07:56:49 +00:00
|
|
|
PRUint16 aNodeType,
|
2004-02-10 10:58:13 +00:00
|
|
|
nsINodeInfo** aNodeInfo)
|
|
|
|
{
|
2005-09-11 10:08:43 +00:00
|
|
|
nsIParserService* parserService = GetParserService();
|
2004-02-10 10:58:13 +00:00
|
|
|
NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
const nsAFlatString& qName = PromiseFlatString(aQualifiedName);
|
|
|
|
const PRUnichar* colon;
|
2004-03-06 16:00:23 +00:00
|
|
|
nsresult rv = parserService->CheckQName(qName, PR_TRUE, &colon);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2004-02-10 10:58:13 +00:00
|
|
|
|
2004-06-25 12:26:02 +00:00
|
|
|
PRInt32 nsID;
|
|
|
|
sNameSpaceManager->RegisterNameSpace(aNamespaceURI, nsID);
|
2004-02-10 10:58:13 +00:00
|
|
|
if (colon) {
|
|
|
|
const PRUnichar* end;
|
|
|
|
qName.EndReading(end);
|
|
|
|
|
2004-02-12 16:40:40 +00:00
|
|
|
nsCOMPtr<nsIAtom> prefix = do_GetAtom(Substring(qName.get(), colon));
|
2004-02-10 10:58:13 +00:00
|
|
|
|
2004-02-12 16:40:40 +00:00
|
|
|
rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix,
|
2011-06-14 07:56:49 +00:00
|
|
|
nsID, aNodeType, aNodeInfo);
|
2004-02-10 10:58:13 +00:00
|
|
|
}
|
|
|
|
else {
|
2004-06-25 12:26:02 +00:00
|
|
|
rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nsnull, nsID,
|
2011-06-14 07:56:49 +00:00
|
|
|
aNodeType, aNodeInfo);
|
2004-02-10 10:58:13 +00:00
|
|
|
}
|
2004-03-06 16:00:23 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2004-02-10 10:58:13 +00:00
|
|
|
|
2006-04-17 17:13:11 +00:00
|
|
|
return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
|
|
|
|
(*aNodeInfo)->GetPrefixAtom(),
|
|
|
|
(*aNodeInfo)->NamespaceID()) ?
|
|
|
|
NS_OK : NS_ERROR_DOM_NAMESPACE_ERR;
|
2004-02-10 10:58:13 +00:00
|
|
|
}
|
|
|
|
|
2004-12-15 15:37:23 +00:00
|
|
|
// static
|
|
|
|
void
|
|
|
|
nsContentUtils::SplitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
|
|
|
|
nsIAtom **aLocalName, PRInt32* aNameSpaceID)
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Expat can send the following:
|
|
|
|
* localName
|
|
|
|
* namespaceURI<separator>localName
|
|
|
|
* namespaceURI<separator>localName<separator>prefix
|
|
|
|
*
|
|
|
|
* and we use 0xFFFF for the <separator>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
const PRUnichar *uriEnd = nsnull;
|
|
|
|
const PRUnichar *nameEnd = nsnull;
|
|
|
|
const PRUnichar *pos;
|
|
|
|
for (pos = aExpatName; *pos; ++pos) {
|
|
|
|
if (*pos == 0xFFFF) {
|
|
|
|
if (uriEnd) {
|
|
|
|
nameEnd = pos;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uriEnd = pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const PRUnichar *nameStart;
|
|
|
|
if (uriEnd) {
|
2005-10-04 09:00:41 +00:00
|
|
|
if (sNameSpaceManager) {
|
|
|
|
sNameSpaceManager->RegisterNameSpace(nsDependentSubstring(aExpatName,
|
|
|
|
uriEnd),
|
|
|
|
*aNameSpaceID);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*aNameSpaceID = kNameSpaceID_Unknown;
|
|
|
|
}
|
2004-12-15 15:37:23 +00:00
|
|
|
|
|
|
|
nameStart = (uriEnd + 1);
|
|
|
|
if (nameEnd) {
|
|
|
|
const PRUnichar *prefixStart = nameEnd + 1;
|
2010-06-08 23:25:27 +00:00
|
|
|
*aPrefix = NS_NewAtom(Substring(prefixStart, pos));
|
2004-12-15 15:37:23 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
nameEnd = pos;
|
|
|
|
*aPrefix = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*aNameSpaceID = kNameSpaceID_None;
|
|
|
|
nameStart = aExpatName;
|
|
|
|
nameEnd = pos;
|
|
|
|
*aPrefix = nsnull;
|
|
|
|
}
|
2010-06-08 23:25:27 +00:00
|
|
|
*aLocalName = NS_NewAtom(Substring(nameStart, nameEnd));
|
2004-12-15 15:37:23 +00:00
|
|
|
}
|
|
|
|
|
2007-07-13 08:49:07 +00:00
|
|
|
// static
|
|
|
|
nsPresContext*
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::GetContextForContent(const nsIContent* aContent)
|
2007-07-13 08:49:07 +00:00
|
|
|
{
|
|
|
|
nsIDocument* doc = aContent->GetCurrentDoc();
|
|
|
|
if (doc) {
|
2010-06-25 13:59:57 +00:00
|
|
|
nsIPresShell *presShell = doc->GetShell();
|
2007-07-13 08:49:07 +00:00
|
|
|
if (presShell) {
|
|
|
|
return presShell->GetPresContext();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2004-03-09 03:57:51 +00:00
|
|
|
// static
|
2004-05-13 18:34:18 +00:00
|
|
|
PRBool
|
2004-03-09 03:57:51 +00:00
|
|
|
nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
|
2005-03-02 04:05:12 +00:00
|
|
|
nsIDocument* aLoadingDocument,
|
2007-07-03 18:45:39 +00:00
|
|
|
nsIPrincipal* aLoadingPrincipal,
|
2005-03-02 04:05:12 +00:00
|
|
|
PRInt16* aImageBlockingStatus)
|
2004-03-09 03:57:51 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aURI, "Must have a URI");
|
|
|
|
NS_PRECONDITION(aLoadingDocument, "Must have a document");
|
2007-07-03 18:45:39 +00:00
|
|
|
NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal");
|
2004-03-09 03:57:51 +00:00
|
|
|
|
2004-10-13 23:16:58 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
PRUint32 appType = nsIDocShell::APP_TYPE_UNKNOWN;
|
|
|
|
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsISupports> container = aLoadingDocument->GetContainer();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
|
|
|
|
do_QueryInterface(container);
|
|
|
|
|
|
|
|
if (docShellTreeItem) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> root;
|
|
|
|
docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
|
|
|
|
|
|
|
|
if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
|
|
|
|
appType = nsIDocShell::APP_TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (appType != nsIDocShell::APP_TYPE_EDITOR) {
|
|
|
|
// Editor apps get special treatment here, editors can load images
|
2007-07-03 18:45:39 +00:00
|
|
|
// from anywhere. This allows editor to insert images from file://
|
|
|
|
// into documents that are being edited.
|
2004-10-13 23:16:58 +00:00
|
|
|
rv = sSecurityManager->
|
2007-07-03 18:45:39 +00:00
|
|
|
CheckLoadURIWithPrincipal(aLoadingPrincipal, aURI,
|
2004-10-15 16:34:58 +00:00
|
|
|
nsIScriptSecurityManager::ALLOW_CHROME);
|
2004-10-13 23:16:58 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
2005-03-02 04:05:12 +00:00
|
|
|
if (aImageBlockingStatus) {
|
2005-03-26 02:26:58 +00:00
|
|
|
// Reject the request itself, not all requests to the relevant
|
|
|
|
// server...
|
|
|
|
*aImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
|
2005-03-02 04:05:12 +00:00
|
|
|
}
|
2004-10-13 23:16:58 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-13 18:34:18 +00:00
|
|
|
PRInt16 decision = nsIContentPolicy::ACCEPT;
|
2004-03-09 03:57:51 +00:00
|
|
|
|
2004-10-13 23:16:58 +00:00
|
|
|
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE,
|
|
|
|
aURI,
|
2007-08-08 01:16:09 +00:00
|
|
|
aLoadingPrincipal,
|
2004-10-13 23:16:58 +00:00
|
|
|
aContext,
|
|
|
|
EmptyCString(), //mime guess
|
|
|
|
nsnull, //extra
|
2005-08-19 15:00:01 +00:00
|
|
|
&decision,
|
2007-08-08 01:16:09 +00:00
|
|
|
GetContentPolicy(),
|
|
|
|
sSecurityManager);
|
2004-03-09 03:57:51 +00:00
|
|
|
|
2005-03-02 04:05:12 +00:00
|
|
|
if (aImageBlockingStatus) {
|
|
|
|
*aImageBlockingStatus =
|
|
|
|
NS_FAILED(rv) ? nsIContentPolicy::REJECT_REQUEST : decision;
|
|
|
|
}
|
2004-05-13 18:34:18 +00:00
|
|
|
return NS_FAILED(rv) ? PR_FALSE : NS_CP_ACCEPTED(decision);
|
2004-03-09 03:57:51 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 05:23:20 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsImageInCache(nsIURI* aURI)
|
|
|
|
{
|
2010-07-02 21:15:52 +00:00
|
|
|
if (!sImgLoaderInitialized)
|
|
|
|
InitImgLoader();
|
|
|
|
|
2009-07-08 05:23:20 +00:00
|
|
|
if (!sImgCache) return PR_FALSE;
|
|
|
|
|
|
|
|
// If something unexpected happened we return false, otherwise if props
|
|
|
|
// is set, the image is cached and we return true
|
|
|
|
nsCOMPtr<nsIProperties> props;
|
|
|
|
nsresult rv = sImgCache->FindEntryProperties(aURI, getter_AddRefs(props));
|
|
|
|
return (NS_SUCCEEDED(rv) && props);
|
|
|
|
}
|
|
|
|
|
2004-07-27 17:15:53 +00:00
|
|
|
// static
|
2004-03-09 03:57:51 +00:00
|
|
|
nsresult
|
|
|
|
nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
|
2007-07-03 18:45:39 +00:00
|
|
|
nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
|
|
|
|
imgIDecoderObserver* aObserver, PRInt32 aLoadFlags,
|
|
|
|
imgIRequest** aRequest)
|
2004-03-09 03:57:51 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aURI, "Must have a URI");
|
|
|
|
NS_PRECONDITION(aLoadingDocument, "Must have a document");
|
2007-07-03 18:45:39 +00:00
|
|
|
NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
|
2004-03-09 03:57:51 +00:00
|
|
|
NS_PRECONDITION(aRequest, "Null out param");
|
|
|
|
|
2010-07-08 23:26:54 +00:00
|
|
|
imgILoader* imgLoader = GetImgLoader();
|
|
|
|
if (!imgLoader) {
|
2004-03-09 03:57:51 +00:00
|
|
|
// nothing we can do here
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2005-06-02 23:36:08 +00:00
|
|
|
|
2004-03-09 03:57:51 +00:00
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
|
2006-03-30 18:40:56 +00:00
|
|
|
NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early");
|
2004-03-09 03:57:51 +00:00
|
|
|
|
|
|
|
nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
|
|
|
|
|
2010-05-20 20:08:02 +00:00
|
|
|
// check for a Content Security Policy to pass down to the channel that
|
|
|
|
// will get created to load the image
|
|
|
|
nsCOMPtr<nsIChannelPolicy> channelPolicy;
|
|
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
|
|
|
if (aLoadingPrincipal) {
|
|
|
|
nsresult rv = aLoadingPrincipal->GetCsp(getter_AddRefs(csp));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (csp) {
|
|
|
|
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
|
|
|
|
channelPolicy->SetContentSecurityPolicy(csp);
|
|
|
|
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-26 19:54:41 +00:00
|
|
|
// Make the URI immutable so people won't change it under us
|
|
|
|
NS_TryToSetImmutable(aURI);
|
|
|
|
|
2004-03-09 03:57:51 +00:00
|
|
|
// XXXbz using "documentURI" for the initialDocumentURI is not quite
|
|
|
|
// right, but the best we can do here...
|
2010-07-08 23:26:54 +00:00
|
|
|
return imgLoader->LoadImage(aURI, /* uri to load */
|
|
|
|
documentURI, /* initialDocumentURI */
|
|
|
|
aReferrer, /* referrer */
|
|
|
|
loadGroup, /* loadgroup */
|
|
|
|
aObserver, /* imgIDecoderObserver */
|
|
|
|
aLoadingDocument, /* uniquification key */
|
|
|
|
aLoadFlags, /* load flags */
|
|
|
|
nsnull, /* cache key */
|
|
|
|
nsnull, /* existing request*/
|
|
|
|
channelPolicy, /* CSP info */
|
|
|
|
aRequest);
|
2004-03-09 03:57:51 +00:00
|
|
|
}
|
|
|
|
|
2004-07-30 06:04:57 +00:00
|
|
|
// static
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-21 01:50:15 +00:00
|
|
|
already_AddRefed<imgIContainer>
|
2005-02-03 17:23:35 +00:00
|
|
|
nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
|
2005-02-07 22:20:14 +00:00
|
|
|
imgIRequest **aRequest)
|
2004-07-30 06:04:57 +00:00
|
|
|
{
|
2005-02-07 22:20:14 +00:00
|
|
|
if (aRequest) {
|
|
|
|
*aRequest = nsnull;
|
|
|
|
}
|
|
|
|
|
2004-07-30 06:04:57 +00:00
|
|
|
NS_ENSURE_TRUE(aContent, nsnull);
|
2005-06-02 23:36:08 +00:00
|
|
|
|
2004-07-30 06:04:57 +00:00
|
|
|
nsCOMPtr<imgIRequest> imgRequest;
|
|
|
|
aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(imgRequest));
|
|
|
|
if (!imgRequest) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
2005-06-02 23:36:08 +00:00
|
|
|
|
2004-07-30 06:04:57 +00:00
|
|
|
nsCOMPtr<imgIContainer> imgContainer;
|
|
|
|
imgRequest->GetImage(getter_AddRefs(imgContainer));
|
|
|
|
|
|
|
|
if (!imgContainer) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
2005-06-02 23:36:08 +00:00
|
|
|
|
2005-02-07 22:20:14 +00:00
|
|
|
if (aRequest) {
|
|
|
|
imgRequest.swap(*aRequest);
|
|
|
|
}
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-21 01:50:15 +00:00
|
|
|
return imgContainer.forget();
|
2004-07-30 06:04:57 +00:00
|
|
|
}
|
|
|
|
|
2009-12-11 04:02:13 +00:00
|
|
|
//static
|
|
|
|
already_AddRefed<imgIRequest>
|
|
|
|
nsContentUtils::GetStaticRequest(imgIRequest* aRequest)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(aRequest, nsnull);
|
|
|
|
nsCOMPtr<imgIRequest> retval;
|
|
|
|
aRequest->GetStaticRequest(getter_AddRefs(retval));
|
|
|
|
return retval.forget();
|
|
|
|
}
|
|
|
|
|
2008-09-08 16:09:35 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::ContentIsDraggable(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNSHTMLElement> htmlElement = do_QueryInterface(aContent);
|
|
|
|
if (htmlElement) {
|
|
|
|
PRBool draggable = PR_FALSE;
|
|
|
|
htmlElement->GetDraggable(&draggable);
|
|
|
|
if (draggable)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
|
2008-09-08 16:22:25 +00:00
|
|
|
nsGkAtoms::_false, eIgnoreCase))
|
2008-09-08 16:09:35 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// special handling for content area image and link dragging
|
|
|
|
return IsDraggableImage(aContent) || IsDraggableLink(aContent);
|
|
|
|
}
|
|
|
|
|
2004-07-30 06:04:57 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsDraggableImage(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aContent, "Must have content node to test");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aContent));
|
|
|
|
if (!imageContent) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<imgIRequest> imgRequest;
|
|
|
|
imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
|
|
getter_AddRefs(imgRequest));
|
|
|
|
|
|
|
|
// XXXbz It may be draggable even if the request resulted in an error. Why?
|
|
|
|
// Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
|
2005-06-02 23:36:08 +00:00
|
|
|
return imgRequest != nsnull;
|
2004-07-30 06:04:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
|
2007-01-04 10:53:59 +00:00
|
|
|
nsCOMPtr<nsIURI> absURI;
|
|
|
|
return aContent->IsLink(getter_AddRefs(absURI));
|
2004-07-30 06:04:57 +00:00
|
|
|
}
|
|
|
|
|
2010-08-19 23:12:46 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsSitePermAllow(nsIURI* aURI, const char* aType)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPermissionManager> permMgr =
|
|
|
|
do_GetService("@mozilla.org/permissionmanager;1");
|
|
|
|
NS_ENSURE_TRUE(permMgr, PR_FALSE);
|
|
|
|
|
|
|
|
PRUint32 perm;
|
|
|
|
nsresult rv = permMgr->TestPermission(aURI, aType, &perm);
|
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
|
|
|
|
|
|
|
return perm == nsIPermissionManager::ALLOW_ACTION;
|
|
|
|
}
|
|
|
|
|
2006-06-13 03:07:47 +00:00
|
|
|
static const char *gEventNames[] = {"event"};
|
|
|
|
static const char *gSVGEventNames[] = {"evt"};
|
|
|
|
// for b/w compat, the first name to onerror is still 'event', even though it
|
|
|
|
// is actually the error message. (pre this code, the other 2 were not avail.)
|
|
|
|
// XXXmarkh - a quick lxr shows no affected code - should we correct this?
|
|
|
|
static const char *gOnErrorNames[] = {"event", "source", "lineno"};
|
2004-07-22 16:38:05 +00:00
|
|
|
|
|
|
|
// static
|
2006-06-13 03:07:47 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::GetEventArgNames(PRInt32 aNameSpaceID,
|
|
|
|
nsIAtom *aEventName,
|
|
|
|
PRUint32 *aArgCount,
|
|
|
|
const char*** aArgArray)
|
|
|
|
{
|
|
|
|
#define SET_EVENT_ARG_NAMES(names) \
|
|
|
|
*aArgCount = sizeof(names)/sizeof(names[0]); \
|
|
|
|
*aArgArray = names;
|
|
|
|
|
|
|
|
// nsJSEventListener is what does the arg magic for onerror, and it does
|
|
|
|
// not seem to take the namespace into account. So we let onerror in all
|
|
|
|
// namespaces get the 3 arg names.
|
2006-12-26 17:47:52 +00:00
|
|
|
if (aEventName == nsGkAtoms::onerror) {
|
2006-06-13 03:07:47 +00:00
|
|
|
SET_EVENT_ARG_NAMES(gOnErrorNames);
|
|
|
|
} else if (aNameSpaceID == kNameSpaceID_SVG) {
|
|
|
|
SET_EVENT_ARG_NAMES(gSVGEventNames);
|
|
|
|
} else {
|
|
|
|
SET_EVENT_ARG_NAMES(gEventNames);
|
|
|
|
}
|
2004-07-22 16:38:05 +00:00
|
|
|
}
|
|
|
|
|
2007-10-01 10:02:32 +00:00
|
|
|
nsCxPusher::nsCxPusher()
|
2009-02-16 14:11:41 +00:00
|
|
|
: mScriptIsRunning(PR_FALSE),
|
|
|
|
mPushedSomething(PR_FALSE)
|
2006-03-22 18:36:36 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCxPusher::~nsCxPusher()
|
|
|
|
{
|
|
|
|
Pop();
|
|
|
|
}
|
|
|
|
|
2006-06-06 21:37:32 +00:00
|
|
|
static PRBool
|
|
|
|
IsContextOnStack(nsIJSContextStack *aStack, JSContext *aContext)
|
|
|
|
{
|
|
|
|
JSContext *ctx = nsnull;
|
|
|
|
aStack->Peek(&ctx);
|
|
|
|
if (!ctx)
|
|
|
|
return PR_FALSE;
|
|
|
|
if (ctx == aContext)
|
|
|
|
return PR_TRUE;
|
2006-06-07 17:15:51 +00:00
|
|
|
|
2006-06-06 21:37:32 +00:00
|
|
|
nsCOMPtr<nsIJSContextStackIterator>
|
|
|
|
iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
|
|
|
|
NS_ENSURE_TRUE(iterator, PR_FALSE);
|
|
|
|
|
|
|
|
nsresult rv = iterator->Reset(aStack);
|
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
2006-06-07 17:15:51 +00:00
|
|
|
|
2006-06-06 21:37:32 +00:00
|
|
|
PRBool done;
|
|
|
|
while (NS_SUCCEEDED(iterator->Done(&done)) && !done) {
|
|
|
|
rv = iterator->Prev(&ctx);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Broken iterator implementation");
|
|
|
|
|
2006-06-07 17:15:51 +00:00
|
|
|
if (!ctx) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-06-06 21:37:32 +00:00
|
|
|
if (nsJSUtils::GetDynamicScriptContext(ctx) && ctx == aContext)
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-10-01 10:02:32 +00:00
|
|
|
PRBool
|
2008-10-08 11:35:29 +00:00
|
|
|
nsCxPusher::Push(nsPIDOMEventTarget *aCurrentTarget)
|
2002-08-09 08:45:30 +00:00
|
|
|
{
|
2009-02-16 14:11:41 +00:00
|
|
|
if (mPushedSomething) {
|
2002-08-09 08:45:30 +00:00
|
|
|
NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
|
|
|
|
|
2007-10-01 10:02:32 +00:00
|
|
|
return PR_FALSE;
|
2002-08-09 08:45:30 +00:00
|
|
|
}
|
|
|
|
|
2008-10-08 11:35:29 +00:00
|
|
|
NS_ENSURE_TRUE(aCurrentTarget, PR_FALSE);
|
2009-04-24 09:18:37 +00:00
|
|
|
nsresult rv;
|
|
|
|
nsIScriptContext* scx =
|
|
|
|
aCurrentTarget->GetContextForEventHandlers(&rv);
|
2008-07-19 15:11:37 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
2009-02-16 18:53:11 +00:00
|
|
|
|
|
|
|
if (!scx) {
|
2010-05-18 12:28:37 +00:00
|
|
|
// The target may have a special JS context for event handlers.
|
|
|
|
JSContext* cx = aCurrentTarget->GetJSContextForEventHandlers();
|
|
|
|
if (cx) {
|
|
|
|
DoPush(cx);
|
|
|
|
}
|
|
|
|
|
2009-02-16 18:53:11 +00:00
|
|
|
// Nothing to do here, I guess. Have to return true so that event firing
|
|
|
|
// will still work correctly even if there is no associated JSContext
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-07-19 15:11:37 +00:00
|
|
|
JSContext* cx = nsnull;
|
2008-03-14 23:08:57 +00:00
|
|
|
|
2008-07-19 15:11:37 +00:00
|
|
|
if (scx) {
|
|
|
|
cx = static_cast<JSContext*>(scx->GetNativeContext());
|
|
|
|
// Bad, no JSContext from script context!
|
2007-10-01 10:02:32 +00:00
|
|
|
NS_ENSURE_TRUE(cx, PR_FALSE);
|
2002-08-09 08:45:30 +00:00
|
|
|
}
|
|
|
|
|
2008-03-14 23:08:57 +00:00
|
|
|
// If there's no native context in the script context it must be
|
|
|
|
// in the process or being torn down. We don't want to notify the
|
|
|
|
// script context about scripts having been evaluated in such a
|
|
|
|
// case, calling with a null cx is fine in that case.
|
|
|
|
return Push(cx);
|
|
|
|
}
|
|
|
|
|
2009-05-14 07:03:15 +00:00
|
|
|
PRBool
|
|
|
|
nsCxPusher::RePush(nsPIDOMEventTarget *aCurrentTarget)
|
|
|
|
{
|
|
|
|
if (!mPushedSomething) {
|
|
|
|
return Push(aCurrentTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aCurrentTarget) {
|
|
|
|
nsresult rv;
|
|
|
|
nsIScriptContext* scx =
|
|
|
|
aCurrentTarget->GetContextForEventHandlers(&rv);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
Pop();
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have the same script context and native context is still
|
|
|
|
// alive, no need to Pop/Push.
|
|
|
|
if (scx && scx == mScx &&
|
|
|
|
scx->GetNativeContext()) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Pop();
|
|
|
|
return Push(aCurrentTarget);
|
|
|
|
}
|
|
|
|
|
2008-03-14 23:08:57 +00:00
|
|
|
PRBool
|
2010-05-18 12:28:37 +00:00
|
|
|
nsCxPusher::Push(JSContext *cx, PRBool aRequiresScriptContext)
|
2008-03-14 23:08:57 +00:00
|
|
|
{
|
2009-02-16 14:11:41 +00:00
|
|
|
if (mPushedSomething) {
|
2008-03-14 23:08:57 +00:00
|
|
|
NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-02-16 14:11:41 +00:00
|
|
|
if (!cx) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2008-03-14 23:08:57 +00:00
|
|
|
|
2009-02-16 14:11:41 +00:00
|
|
|
// Hold a strong ref to the nsIScriptContext, just in case
|
|
|
|
// XXXbz do we really need to? If we don't get one of these in Pop(), is
|
|
|
|
// that really a problem? Or do we need to do this to effectively root |cx|?
|
|
|
|
mScx = GetScriptContextFromJSContext(cx);
|
2010-05-18 12:28:37 +00:00
|
|
|
if (!mScx && aRequiresScriptContext) {
|
2009-02-16 14:11:41 +00:00
|
|
|
// Should probably return PR_FALSE. See bug 416916.
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2002-08-09 08:45:30 +00:00
|
|
|
|
2009-02-16 14:11:41 +00:00
|
|
|
return DoPush(cx);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsCxPusher::DoPush(JSContext* cx)
|
|
|
|
{
|
|
|
|
nsIThreadJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
|
|
|
|
if (!stack) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cx && IsContextOnStack(stack, cx)) {
|
|
|
|
// If the context is on the stack, that means that a script
|
|
|
|
// is running at the moment in the context.
|
|
|
|
mScriptIsRunning = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(stack->Push(cx))) {
|
|
|
|
mScriptIsRunning = PR_FALSE;
|
|
|
|
mScx = nsnull;
|
|
|
|
return PR_FALSE;
|
2002-08-09 08:45:30 +00:00
|
|
|
}
|
2009-02-16 14:11:41 +00:00
|
|
|
|
|
|
|
mPushedSomething = PR_TRUE;
|
|
|
|
#ifdef DEBUG
|
|
|
|
mPushedContext = cx;
|
|
|
|
#endif
|
2007-10-01 10:02:32 +00:00
|
|
|
return PR_TRUE;
|
2002-08-09 08:45:30 +00:00
|
|
|
}
|
|
|
|
|
2009-02-16 14:11:41 +00:00
|
|
|
PRBool
|
|
|
|
nsCxPusher::PushNull()
|
|
|
|
{
|
|
|
|
return DoPush(nsnull);
|
|
|
|
}
|
|
|
|
|
2002-08-09 08:45:30 +00:00
|
|
|
void
|
|
|
|
nsCxPusher::Pop()
|
|
|
|
{
|
2008-10-08 11:35:29 +00:00
|
|
|
nsIThreadJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
|
2009-02-16 14:11:41 +00:00
|
|
|
if (!mPushedSomething || !stack) {
|
2002-08-09 08:45:30 +00:00
|
|
|
mScx = nsnull;
|
2009-02-16 14:11:41 +00:00
|
|
|
mPushedSomething = PR_FALSE;
|
2002-08-09 08:45:30 +00:00
|
|
|
|
|
|
|
NS_ASSERTION(!mScriptIsRunning, "Huh, this can't be happening, "
|
|
|
|
"mScriptIsRunning can't be set here!");
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSContext *unused;
|
2008-10-08 11:35:29 +00:00
|
|
|
stack->Pop(&unused);
|
2002-08-09 08:45:30 +00:00
|
|
|
|
2009-02-16 14:11:41 +00:00
|
|
|
NS_ASSERTION(unused == mPushedContext, "Unexpected context popped");
|
|
|
|
|
|
|
|
if (!mScriptIsRunning && mScx) {
|
2006-06-06 21:37:32 +00:00
|
|
|
// No JS is running in the context, but executing the event handler might have
|
2002-08-09 08:45:30 +00:00
|
|
|
// caused some JS to run. Tell the script context that it's done.
|
|
|
|
|
|
|
|
mScx->ScriptEvaluated(PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
mScx = nsnull;
|
|
|
|
mScriptIsRunning = PR_FALSE;
|
2009-02-16 14:11:41 +00:00
|
|
|
mPushedSomething = PR_FALSE;
|
2002-08-09 08:45:30 +00:00
|
|
|
}
|
2004-09-14 17:26:35 +00:00
|
|
|
|
2004-12-17 20:40:48 +00:00
|
|
|
static const char gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT][56] = {
|
2004-09-14 17:26:35 +00:00
|
|
|
// Must line up with the enum values in |PropertiesFile| enum.
|
|
|
|
"chrome://global/locale/css.properties",
|
|
|
|
"chrome://global/locale/xbl.properties",
|
2004-11-23 17:45:37 +00:00
|
|
|
"chrome://global/locale/xul.properties",
|
2004-12-17 20:40:48 +00:00
|
|
|
"chrome://global/locale/layout_errors.properties",
|
2005-02-22 17:30:08 +00:00
|
|
|
"chrome://global/locale/layout/HtmlForm.properties",
|
2004-12-17 20:40:48 +00:00
|
|
|
"chrome://global/locale/printing.properties",
|
2005-04-03 17:16:28 +00:00
|
|
|
"chrome://global/locale/dom/dom.properties",
|
2006-07-27 11:58:05 +00:00
|
|
|
"chrome://global/locale/svg/svg.properties",
|
2006-02-14 02:06:48 +00:00
|
|
|
"chrome://branding/locale/brand.properties",
|
|
|
|
"chrome://global/locale/commonDialogs.properties"
|
2004-09-14 17:26:35 +00:00
|
|
|
};
|
|
|
|
|
2004-12-17 20:40:48 +00:00
|
|
|
/* static */ nsresult
|
|
|
|
nsContentUtils::EnsureStringBundle(PropertiesFile aFile)
|
|
|
|
{
|
|
|
|
if (!sStringBundles[aFile]) {
|
|
|
|
if (!sStringBundleService) {
|
|
|
|
nsresult rv =
|
|
|
|
CallGetService(NS_STRINGBUNDLE_CONTRACTID, &sStringBundleService);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
nsIStringBundle *bundle;
|
|
|
|
nsresult rv =
|
|
|
|
sStringBundleService->CreateBundle(gPropertiesFiles[aFile], &bundle);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
sStringBundles[aFile] = bundle; // transfer ownership
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
|
|
|
|
const char* aKey,
|
2005-01-18 23:46:59 +00:00
|
|
|
nsXPIDLString& aResult)
|
2004-12-17 20:40:48 +00:00
|
|
|
{
|
|
|
|
nsresult rv = EnsureStringBundle(aFile);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsIStringBundle *bundle = sStringBundles[aFile];
|
|
|
|
|
2006-02-03 14:18:39 +00:00
|
|
|
return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
|
2005-01-18 23:46:59 +00:00
|
|
|
getter_Copies(aResult));
|
2004-12-17 20:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult nsContentUtils::FormatLocalizedString(PropertiesFile aFile,
|
|
|
|
const char* aKey,
|
|
|
|
const PRUnichar **aParams,
|
|
|
|
PRUint32 aParamsLength,
|
2005-01-18 23:46:59 +00:00
|
|
|
nsXPIDLString& aResult)
|
2004-12-17 20:40:48 +00:00
|
|
|
{
|
|
|
|
nsresult rv = EnsureStringBundle(aFile);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsIStringBundle *bundle = sStringBundles[aFile];
|
|
|
|
|
2006-02-03 14:18:39 +00:00
|
|
|
return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
|
2005-01-18 23:46:59 +00:00
|
|
|
aParams, aParamsLength,
|
|
|
|
getter_Copies(aResult));
|
2004-12-17 20:40:48 +00:00
|
|
|
}
|
|
|
|
|
2004-09-14 17:26:35 +00:00
|
|
|
/* static */ nsresult
|
|
|
|
nsContentUtils::ReportToConsole(PropertiesFile aFile,
|
|
|
|
const char *aMessageName,
|
|
|
|
const PRUnichar **aParams,
|
|
|
|
PRUint32 aParamsLength,
|
|
|
|
nsIURI* aURI,
|
2004-11-23 17:45:37 +00:00
|
|
|
const nsAFlatString& aSourceLine,
|
2004-09-14 17:26:35 +00:00
|
|
|
PRUint32 aLineNumber,
|
|
|
|
PRUint32 aColumnNumber,
|
|
|
|
PRUint32 aErrorFlags,
|
2010-12-20 16:21:58 +00:00
|
|
|
const char *aCategory,
|
|
|
|
PRUint64 aWindowId)
|
2004-09-14 17:26:35 +00:00
|
|
|
{
|
2005-09-24 17:38:20 +00:00
|
|
|
NS_ASSERTION((aParams && aParamsLength) || (!aParams && !aParamsLength),
|
|
|
|
"Supply either both parameters and their number or no"
|
|
|
|
"parameters and 0.");
|
|
|
|
|
2004-09-14 17:26:35 +00:00
|
|
|
nsresult rv;
|
2004-12-17 20:40:48 +00:00
|
|
|
if (!sConsoleService) { // only need to bother null-checking here
|
|
|
|
rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2004-09-14 17:26:35 +00:00
|
|
|
}
|
|
|
|
|
2005-01-18 23:46:59 +00:00
|
|
|
nsXPIDLString errorText;
|
2005-09-24 17:38:20 +00:00
|
|
|
if (aParams) {
|
|
|
|
rv = FormatLocalizedString(aFile, aMessageName, aParams, aParamsLength,
|
|
|
|
errorText);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rv = GetLocalizedString(aFile, aMessageName, errorText);
|
|
|
|
}
|
2004-09-14 17:26:35 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCAutoString spec;
|
|
|
|
if (aURI)
|
|
|
|
aURI->GetSpec(spec);
|
|
|
|
|
2010-12-20 16:21:58 +00:00
|
|
|
nsCOMPtr<nsIScriptError2> errorObject =
|
2004-09-14 17:26:35 +00:00
|
|
|
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2010-12-20 16:21:58 +00:00
|
|
|
|
|
|
|
rv = errorObject->InitWithWindowID(errorText.get(),
|
|
|
|
NS_ConvertUTF8toUTF16(spec).get(), // file name
|
|
|
|
aSourceLine.get(),
|
|
|
|
aLineNumber, aColumnNumber,
|
|
|
|
aErrorFlags, aCategory, aWindowId);
|
2004-09-14 17:26:35 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-12-20 16:21:58 +00:00
|
|
|
nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
|
|
|
|
return sConsoleService->LogMessage(logError);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ nsresult
|
|
|
|
nsContentUtils::ReportToConsole(PropertiesFile aFile,
|
|
|
|
const char *aMessageName,
|
|
|
|
const PRUnichar **aParams,
|
|
|
|
PRUint32 aParamsLength,
|
|
|
|
nsIURI* aURI,
|
|
|
|
const nsAFlatString& aSourceLine,
|
|
|
|
PRUint32 aLineNumber,
|
|
|
|
PRUint32 aColumnNumber,
|
|
|
|
PRUint32 aErrorFlags,
|
|
|
|
const char *aCategory,
|
|
|
|
nsIDocument* aDocument)
|
|
|
|
{
|
|
|
|
nsIURI* uri = aURI;
|
|
|
|
PRUint64 windowID = 0;
|
|
|
|
if (aDocument) {
|
|
|
|
if (!uri) {
|
|
|
|
uri = aDocument->GetDocumentURI();
|
|
|
|
}
|
|
|
|
windowID = aDocument->OuterWindowID();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ReportToConsole(aFile, aMessageName, aParams, aParamsLength, uri,
|
|
|
|
aSourceLine, aLineNumber, aColumnNumber, aErrorFlags,
|
|
|
|
aCategory, windowID);
|
2004-09-14 17:26:35 +00:00
|
|
|
}
|
2005-05-10 02:06:29 +00:00
|
|
|
|
2005-06-02 23:36:08 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
|
|
|
|
{
|
2006-04-27 18:21:11 +00:00
|
|
|
if (!aDocument) {
|
2005-06-02 23:36:08 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2006-04-27 18:21:11 +00:00
|
|
|
|
2005-06-02 23:36:08 +00:00
|
|
|
nsCOMPtr<nsIPrincipal> systemPrincipal;
|
|
|
|
sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
|
|
|
|
|
2006-04-27 18:21:11 +00:00
|
|
|
return aDocument->NodePrincipal() == systemPrincipal;
|
2005-06-02 23:36:08 +00:00
|
|
|
}
|
2005-07-06 15:46:12 +00:00
|
|
|
|
2009-10-15 02:20:50 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsChildOfSameType(nsIDocument* aDoc)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsISupports> container = aDoc->GetContainer();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(container));
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
|
|
|
|
if (docShellAsItem) {
|
|
|
|
docShellAsItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
|
|
|
|
}
|
|
|
|
return sameTypeParent != nsnull;
|
|
|
|
}
|
|
|
|
|
2008-11-14 00:00:11 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument *aDocument,
|
|
|
|
nsIURI *aURI,
|
|
|
|
nsACString& aScriptURI)
|
|
|
|
{
|
|
|
|
PRBool scriptFileNameModified = PR_FALSE;
|
|
|
|
aURI->GetSpec(aScriptURI);
|
|
|
|
|
|
|
|
if (IsChromeDoc(aDocument)) {
|
|
|
|
nsCOMPtr<nsIChromeRegistry> chromeReg =
|
2010-05-14 09:24:41 +00:00
|
|
|
mozilla::services::GetChromeRegistryService();
|
2008-11-14 00:00:11 +00:00
|
|
|
|
|
|
|
if (!chromeReg) {
|
|
|
|
// If we're running w/o a chrome registry we won't modify any
|
|
|
|
// script file names.
|
|
|
|
|
|
|
|
return scriptFileNameModified;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool docWrappersEnabled =
|
|
|
|
chromeReg->WrappersEnabled(aDocument->GetDocumentURI());
|
|
|
|
|
|
|
|
PRBool uriWrappersEnabled = chromeReg->WrappersEnabled(aURI);
|
|
|
|
|
|
|
|
nsIURI *docURI = aDocument->GetDocumentURI();
|
|
|
|
|
|
|
|
if (docURI && docWrappersEnabled && !uriWrappersEnabled) {
|
|
|
|
// aURI is a script from a URL that doesn't get wrapper
|
|
|
|
// automation. aDocument is a chrome document that does get
|
|
|
|
// wrapper automation. Prepend the chrome document's URI
|
|
|
|
// followed by the string " -> " to the URI of the script we're
|
|
|
|
// loading here so that script in that URI gets the same wrapper
|
|
|
|
// automation that the chrome document expects.
|
|
|
|
nsCAutoString spec;
|
|
|
|
docURI->GetSpec(spec);
|
|
|
|
spec.AppendASCII(" -> ");
|
|
|
|
spec.Append(aScriptURI);
|
|
|
|
|
|
|
|
aScriptURI = spec;
|
|
|
|
|
|
|
|
scriptFileNameModified = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return scriptFileNameModified;
|
|
|
|
}
|
|
|
|
|
2008-09-28 19:14:28 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsInChromeDocshell(nsIDocument *aDocument)
|
|
|
|
{
|
|
|
|
if (!aDocument) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-10-04 20:00:09 +00:00
|
|
|
if (aDocument->GetDisplayDocument()) {
|
|
|
|
return IsInChromeDocshell(aDocument->GetDisplayDocument());
|
|
|
|
}
|
|
|
|
|
2008-09-28 19:14:28 +00:00
|
|
|
nsCOMPtr<nsISupports> docContainer = aDocument->GetContainer();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(docContainer));
|
|
|
|
PRInt32 itemType = nsIDocShellTreeItem::typeContent;
|
|
|
|
if (docShell) {
|
|
|
|
docShell->GetItemType(&itemType);
|
|
|
|
}
|
|
|
|
|
|
|
|
return itemType == nsIDocShellTreeItem::typeChrome;
|
|
|
|
}
|
|
|
|
|
2005-08-23 21:00:00 +00:00
|
|
|
// static
|
|
|
|
nsIContentPolicy*
|
|
|
|
nsContentUtils::GetContentPolicy()
|
|
|
|
{
|
|
|
|
if (!sTriedToGetContentPolicy) {
|
|
|
|
CallGetService(NS_CONTENTPOLICY_CONTRACTID, &sContentPolicyService);
|
|
|
|
// It's OK to not have a content policy service
|
|
|
|
sTriedToGetContentPolicy = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sContentPolicyService;
|
|
|
|
}
|
2005-09-24 02:33:33 +00:00
|
|
|
|
2007-04-02 17:17:36 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
|
|
|
|
{
|
2010-03-08 15:45:00 +00:00
|
|
|
const PRUnichar* name = aName->GetUTF16String();
|
2007-04-02 17:17:36 +00:00
|
|
|
if (name[0] != 'o' || name[1] != 'n')
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
EventNameMapping mapping;
|
2010-06-22 18:12:12 +00:00
|
|
|
return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
|
2007-04-02 17:17:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
PRUint32
|
|
|
|
nsContentUtils::GetEventId(nsIAtom* aName)
|
|
|
|
{
|
|
|
|
EventNameMapping mapping;
|
2010-06-22 18:12:12 +00:00
|
|
|
if (sAtomEventTable->Get(aName, &mapping))
|
2007-04-02 17:17:36 +00:00
|
|
|
return mapping.mId;
|
|
|
|
|
|
|
|
return NS_USER_DEFINED_EVENT;
|
|
|
|
}
|
|
|
|
|
2011-04-18 20:57:32 +00:00
|
|
|
// static
|
|
|
|
PRUint32
|
|
|
|
nsContentUtils::GetEventCategory(const nsAString& aName)
|
|
|
|
{
|
|
|
|
EventNameMapping mapping;
|
|
|
|
if (sStringEventTable->Get(aName, &mapping))
|
|
|
|
return mapping.mStructType;
|
|
|
|
|
|
|
|
return NS_EVENT;
|
|
|
|
}
|
|
|
|
|
2010-06-22 18:12:12 +00:00
|
|
|
nsIAtom*
|
|
|
|
nsContentUtils::GetEventIdAndAtom(const nsAString& aName,
|
|
|
|
PRUint32 aEventStruct,
|
|
|
|
PRUint32* aEventID)
|
|
|
|
{
|
|
|
|
EventNameMapping mapping;
|
|
|
|
if (sStringEventTable->Get(aName, &mapping)) {
|
|
|
|
*aEventID =
|
|
|
|
mapping.mStructType == aEventStruct ? mapping.mId : NS_USER_DEFINED_EVENT;
|
|
|
|
return mapping.mAtom;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have cached lots of user defined event names, clear some of them.
|
|
|
|
if (sUserDefinedEvents->Count() > 127) {
|
|
|
|
while (sUserDefinedEvents->Count() > 64) {
|
|
|
|
nsIAtom* first = sUserDefinedEvents->ObjectAt(0);
|
|
|
|
sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
|
|
|
|
sUserDefinedEvents->RemoveObjectAt(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*aEventID = NS_USER_DEFINED_EVENT;
|
|
|
|
nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aName);
|
|
|
|
sUserDefinedEvents->AppendObject(atom);
|
|
|
|
mapping.mAtom = atom;
|
|
|
|
mapping.mId = NS_USER_DEFINED_EVENT;
|
|
|
|
mapping.mType = EventNameType_None;
|
|
|
|
mapping.mStructType = NS_EVENT_NULL;
|
|
|
|
sStringEventTable->Put(aName, mapping);
|
|
|
|
return mapping.mAtom;
|
|
|
|
}
|
|
|
|
|
2009-03-06 18:12:20 +00:00
|
|
|
static
|
|
|
|
nsresult GetEventAndTarget(nsIDocument* aDoc, nsISupports* aTarget,
|
|
|
|
const nsAString& aEventName,
|
|
|
|
PRBool aCanBubble, PRBool aCancelable,
|
|
|
|
nsIDOMEvent** aEvent,
|
|
|
|
nsIDOMEventTarget** aTargetOut)
|
2005-10-10 18:38:57 +00:00
|
|
|
{
|
2011-05-23 16:46:36 +00:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
|
2005-10-10 18:38:57 +00:00
|
|
|
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(aTarget));
|
2011-05-23 16:46:36 +00:00
|
|
|
NS_ENSURE_TRUE(domDoc && target, NS_ERROR_INVALID_ARG);
|
2005-10-10 18:38:57 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
|
|
|
nsresult rv =
|
2011-05-23 16:46:36 +00:00
|
|
|
domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
|
2005-10-10 18:38:57 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
|
|
|
|
NS_ENSURE_TRUE(privateEvent, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
rv = event->InitEvent(aEventName, aCanBubble, aCancelable);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
rv = privateEvent->SetTrusted(PR_TRUE);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2009-03-06 18:12:20 +00:00
|
|
|
rv = privateEvent->SetTarget(target);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
event.forget(aEvent);
|
|
|
|
target.forget(aTargetOut);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
|
|
|
|
const nsAString& aEventName,
|
|
|
|
PRBool aCanBubble, PRBool aCancelable,
|
|
|
|
PRBool *aDefaultAction)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target;
|
|
|
|
nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
|
|
|
|
aCancelable, getter_AddRefs(event),
|
|
|
|
getter_AddRefs(target));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2005-10-10 18:38:57 +00:00
|
|
|
PRBool dummy;
|
|
|
|
return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy);
|
|
|
|
}
|
2005-10-18 20:33:35 +00:00
|
|
|
|
2009-02-22 19:09:10 +00:00
|
|
|
nsresult
|
|
|
|
nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
|
|
|
|
nsISupports *aTarget,
|
|
|
|
const nsAString& aEventName,
|
|
|
|
PRBool aCanBubble, PRBool aCancelable,
|
|
|
|
PRBool *aDefaultAction)
|
|
|
|
{
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
2009-03-06 18:12:20 +00:00
|
|
|
nsCOMPtr<nsIDOMEventTarget> target;
|
|
|
|
nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
|
|
|
|
aCancelable, getter_AddRefs(event),
|
|
|
|
getter_AddRefs(target));
|
2009-02-22 19:09:10 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2009-03-06 18:12:20 +00:00
|
|
|
NS_ASSERTION(aDoc, "GetEventAndTarget lied?");
|
2009-03-10 21:58:00 +00:00
|
|
|
if (!aDoc->GetWindow())
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2010-05-18 12:28:37 +00:00
|
|
|
|
|
|
|
nsPIDOMEventTarget* piTarget = aDoc->GetWindow()->GetChromeEventHandler();
|
|
|
|
if (!piTarget)
|
2009-03-10 21:58:00 +00:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
2009-02-22 19:09:10 +00:00
|
|
|
|
2010-05-18 12:28:37 +00:00
|
|
|
nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
|
|
|
|
if (flo) {
|
|
|
|
nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
|
|
|
|
if (fl) {
|
|
|
|
nsPIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
|
|
|
|
piTarget = t ? t : piTarget;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-22 19:09:10 +00:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2010-05-18 12:28:37 +00:00
|
|
|
rv = piTarget->DispatchDOMEvent(nsnull, event, nsnull, &status);
|
2009-02-22 19:09:10 +00:00
|
|
|
if (aDefaultAction) {
|
|
|
|
*aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2005-11-16 02:55:29 +00:00
|
|
|
/* static */
|
2010-05-14 17:04:51 +00:00
|
|
|
Element*
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::MatchElementId(nsIContent *aContent, const nsIAtom* aId)
|
2005-10-18 20:33:35 +00:00
|
|
|
{
|
2010-05-14 17:04:51 +00:00
|
|
|
for (nsIContent* cur = aContent;
|
|
|
|
cur;
|
|
|
|
cur = cur->GetNextNode(aContent)) {
|
|
|
|
if (aId == cur->GetID()) {
|
|
|
|
return cur->AsElement();
|
|
|
|
}
|
2005-10-18 20:33:35 +00:00
|
|
|
}
|
|
|
|
|
2010-05-14 17:04:51 +00:00
|
|
|
return nsnull;
|
2005-10-18 20:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
2010-05-14 17:04:51 +00:00
|
|
|
Element *
|
2005-10-18 20:33:35 +00:00
|
|
|
nsContentUtils::MatchElementId(nsIContent *aContent, const nsAString& aId)
|
|
|
|
{
|
2005-10-21 15:17:15 +00:00
|
|
|
NS_PRECONDITION(!aId.IsEmpty(), "Will match random elements");
|
|
|
|
|
|
|
|
// ID attrs are generally stored as atoms, so just atomize this up front
|
|
|
|
nsCOMPtr<nsIAtom> id(do_GetAtom(aId));
|
|
|
|
if (!id) {
|
|
|
|
// OOM, so just bail
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2005-11-16 02:55:29 +00:00
|
|
|
return MatchElementId(aContent, id);
|
2005-10-18 20:33:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the string from the given charset to Unicode.
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::ConvertStringFromCharset(const nsACString& aCharset,
|
|
|
|
const nsACString& aInput,
|
|
|
|
nsAString& aOutput)
|
|
|
|
{
|
|
|
|
if (aCharset.IsEmpty()) {
|
|
|
|
// Treat the string as UTF8
|
|
|
|
CopyUTF8toUTF16(aInput, aOutput);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsICharsetConverterManager> ccm =
|
|
|
|
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIUnicodeDecoder> decoder;
|
|
|
|
rv = ccm->GetUnicodeDecoder(PromiseFlatCString(aCharset).get(),
|
|
|
|
getter_AddRefs(decoder));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsPromiseFlatCString flatInput(aInput);
|
|
|
|
PRInt32 srcLen = flatInput.Length();
|
|
|
|
PRInt32 dstLen;
|
|
|
|
rv = decoder->GetMaxLength(flatInput.get(), srcLen, &dstLen);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
PRUnichar *ustr = (PRUnichar *)nsMemory::Alloc((dstLen + 1) *
|
|
|
|
sizeof(PRUnichar));
|
|
|
|
if (!ustr)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
rv = decoder->Convert(flatInput.get(), &srcLen, ustr, &dstLen);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
ustr[dstLen] = 0;
|
|
|
|
aOutput.Assign(ustr, dstLen);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsMemory::Free(ustr);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-12-27 21:45:03 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::CheckForBOM(const unsigned char* aBuffer, PRUint32 aLength,
|
2008-12-06 19:08:26 +00:00
|
|
|
nsACString& aCharset, PRBool *bigEndian)
|
2007-12-27 21:45:03 +00:00
|
|
|
{
|
|
|
|
PRBool found = PR_TRUE;
|
|
|
|
aCharset.Truncate();
|
|
|
|
if (aLength >= 3 &&
|
|
|
|
aBuffer[0] == 0xEF &&
|
|
|
|
aBuffer[1] == 0xBB &&
|
|
|
|
aBuffer[2] == 0xBF) {
|
|
|
|
aCharset = "UTF-8";
|
|
|
|
}
|
|
|
|
else if (aLength >= 2 &&
|
|
|
|
aBuffer[0] == 0xFE && aBuffer[1] == 0xFF) {
|
2008-12-06 19:08:26 +00:00
|
|
|
aCharset = "UTF-16";
|
|
|
|
if (bigEndian)
|
|
|
|
*bigEndian = PR_TRUE;
|
2007-12-27 21:45:03 +00:00
|
|
|
}
|
|
|
|
else if (aLength >= 2 &&
|
|
|
|
aBuffer[0] == 0xFF && aBuffer[1] == 0xFE) {
|
2008-12-06 19:08:26 +00:00
|
|
|
aCharset = "UTF-16";
|
|
|
|
if (bigEndian)
|
|
|
|
*bigEndian = PR_FALSE;
|
2007-12-27 21:45:03 +00:00
|
|
|
} else {
|
|
|
|
found = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2010-02-24 19:14:14 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 16:59:13 +00:00
|
|
|
mozilla::services::GetObserverService();
|
2010-02-24 19:14:14 +00:00
|
|
|
if (observerService) {
|
|
|
|
observerService->AddObserver(aObserver,
|
|
|
|
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
|
|
|
PR_FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 16:59:13 +00:00
|
|
|
mozilla::services::GetObserverService();
|
2010-02-24 19:14:14 +00:00
|
|
|
if (observerService) {
|
|
|
|
observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-18 04:09:33 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, PRInt32 aNameSpaceID,
|
2006-01-18 04:09:33 +00:00
|
|
|
nsIAtom* aName)
|
|
|
|
{
|
2006-12-26 17:47:52 +00:00
|
|
|
static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::_empty, nsnull};
|
2006-01-18 04:09:33 +00:00
|
|
|
return aContent->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters)
|
|
|
|
== nsIContent::ATTR_VALUE_NO_MATCH;
|
|
|
|
}
|
2006-02-07 14:34:10 +00:00
|
|
|
|
2006-04-24 19:52:21 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
2006-06-02 00:58:04 +00:00
|
|
|
nsContentUtils::HasMutationListeners(nsINode* aNode,
|
2007-07-04 20:39:10 +00:00
|
|
|
PRUint32 aType,
|
|
|
|
nsINode* aTargetForSubtreeModified)
|
2006-04-24 19:52:21 +00:00
|
|
|
{
|
2006-06-02 00:58:04 +00:00
|
|
|
nsIDocument* doc = aNode->GetOwnerDoc();
|
|
|
|
if (!doc) {
|
2006-04-24 19:52:21 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// global object will be null for documents that don't have windows.
|
2008-12-03 09:22:39 +00:00
|
|
|
nsPIDOMWindow* window = doc->GetInnerWindow();
|
2008-04-11 22:44:48 +00:00
|
|
|
// This relies on nsEventListenerManager::AddEventListener, which sets
|
|
|
|
// all mutation bits when there is a listener for DOMSubtreeModified event.
|
2006-04-24 19:52:21 +00:00
|
|
|
if (window && !window->HasMutationListeners(aType)) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-04-11 22:44:48 +00:00
|
|
|
if (aNode->IsNodeOfType(nsINode::eCONTENT) &&
|
|
|
|
static_cast<nsIContent*>(aNode)->IsInNativeAnonymousSubtree()) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
|
|
|
|
|
2006-04-24 19:52:21 +00:00
|
|
|
// If we have a window, we can check it for mutation listeners now.
|
2009-01-31 12:34:01 +00:00
|
|
|
if (aNode->IsInDoc()) {
|
|
|
|
nsCOMPtr<nsPIDOMEventTarget> piTarget(do_QueryInterface(window));
|
|
|
|
if (piTarget) {
|
2009-06-23 11:23:52 +00:00
|
|
|
nsIEventListenerManager* manager = piTarget->GetListenerManager(PR_FALSE);
|
2009-01-31 12:34:01 +00:00
|
|
|
if (manager) {
|
|
|
|
PRBool hasListeners = PR_FALSE;
|
|
|
|
manager->HasMutationListeners(&hasListeners);
|
|
|
|
if (hasListeners) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2006-04-24 19:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a window, we know a mutation listener is registered, but it
|
|
|
|
// might not be in our chain. If we don't have a window, we might have a
|
|
|
|
// mutation listener. Check quickly to see.
|
2006-06-02 00:58:04 +00:00
|
|
|
while (aNode) {
|
2009-06-23 11:23:52 +00:00
|
|
|
nsIEventListenerManager* manager = aNode->GetListenerManager(PR_FALSE);
|
2006-06-02 00:58:04 +00:00
|
|
|
if (manager) {
|
|
|
|
PRBool hasListeners = PR_FALSE;
|
|
|
|
manager->HasMutationListeners(&hasListeners);
|
|
|
|
if (hasListeners) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2006-04-24 19:52:21 +00:00
|
|
|
}
|
2007-08-22 06:48:47 +00:00
|
|
|
|
|
|
|
if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
|
|
|
|
nsIContent* content = static_cast<nsIContent*>(aNode);
|
|
|
|
nsIContent* insertionParent =
|
|
|
|
doc->BindingManager()->GetInsertionParent(content);
|
|
|
|
if (insertionParent) {
|
|
|
|
aNode = insertionParent;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2006-06-02 00:58:04 +00:00
|
|
|
aNode = aNode->GetNodeParent();
|
2006-04-24 19:52:21 +00:00
|
|
|
}
|
|
|
|
|
2006-06-02 00:58:04 +00:00
|
|
|
return PR_FALSE;
|
2006-04-24 19:52:21 +00:00
|
|
|
}
|
|
|
|
|
2011-05-09 19:33:03 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::HasMutationListeners(nsIDocument* aDocument,
|
|
|
|
PRUint32 aType)
|
|
|
|
{
|
|
|
|
nsPIDOMWindow* window = aDocument ?
|
|
|
|
aDocument->GetInnerWindow() : nsnull;
|
|
|
|
|
|
|
|
// This relies on nsEventListenerManager::AddEventListener, which sets
|
|
|
|
// all mutation bits when there is a listener for DOMSubtreeModified event.
|
|
|
|
return !window || window->HasMutationListeners(aType);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
|
|
|
|
nsIDocument* aOwnerDoc)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aChild, "Missing child");
|
|
|
|
NS_PRECONDITION(aChild->GetNodeParent() == aParent, "Wrong parent");
|
|
|
|
NS_PRECONDITION(aChild->GetOwnerDoc() == aOwnerDoc, "Wrong owner-doc");
|
|
|
|
|
2011-05-09 19:33:04 +00:00
|
|
|
// This checks that IsSafeToRunScript is true since we don't want to fire
|
|
|
|
// events when that is false. We can't rely on nsEventDispatcher to assert
|
|
|
|
// this in this situation since most of the time there are no mutation
|
|
|
|
// event listeners, in which case we won't even attempt to dispatch events.
|
|
|
|
// However this also allows for two exceptions. First off, we don't assert
|
|
|
|
// if the mutation happens to native anonymous content since we never fire
|
|
|
|
// mutation events on such content anyway.
|
|
|
|
// Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
|
|
|
|
// that is a know case when we'd normally fire a mutation event, but can't
|
|
|
|
// make that safe and so we suppress it at this time. Ideally this should
|
|
|
|
// go away eventually.
|
2011-05-09 19:33:03 +00:00
|
|
|
NS_ASSERTION(aChild->IsNodeOfType(nsINode::eCONTENT) &&
|
|
|
|
static_cast<nsIContent*>(aChild)->
|
|
|
|
IsInNativeAnonymousSubtree() ||
|
2011-05-09 19:33:04 +00:00
|
|
|
IsSafeToRunScript() ||
|
|
|
|
sDOMNodeRemovedSuppressCount,
|
2011-05-09 19:33:03 +00:00
|
|
|
"Want to fire DOMNodeRemoved event, but it's not safe");
|
|
|
|
|
|
|
|
// Having an explicit check here since it's an easy mistake to fall into,
|
|
|
|
// and there might be existing code with problems. We'd rather be safe
|
2011-05-09 19:33:04 +00:00
|
|
|
// than fire DOMNodeRemoved in all corner cases. We also rely on it for
|
|
|
|
// nsAutoScriptBlockerSuppressNodeRemoved.
|
2011-05-09 19:33:03 +00:00
|
|
|
if (!IsSafeToRunScript()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HasMutationListeners(aChild,
|
|
|
|
NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
|
|
|
|
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
|
|
|
|
mutation.mRelatedNode = do_QueryInterface(aParent);
|
|
|
|
|
|
|
|
mozAutoSubtreeModified subtree(aOwnerDoc, aParent);
|
|
|
|
nsEventDispatcher::Dispatch(aChild, nsnull, &mutation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-07 14:34:10 +00:00
|
|
|
/* static */
|
2007-01-04 22:31:26 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::TraverseListenerManager(nsINode *aNode,
|
|
|
|
nsCycleCollectionTraversalCallback &cb)
|
|
|
|
{
|
|
|
|
if (!sEventListenerManagersHash.ops) {
|
|
|
|
// We're already shut down, just return.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventListenerManagerMapEntry *entry =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<EventListenerManagerMapEntry *>
|
|
|
|
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
|
2007-01-04 22:31:26 +00:00
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
2008-03-17 23:11:08 +00:00
|
|
|
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via hash] mListenerManager");
|
2007-01-04 22:31:26 +00:00
|
|
|
cb.NoteXPCOMChild(entry->mListenerManager);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-23 11:23:52 +00:00
|
|
|
nsIEventListenerManager*
|
2006-05-15 07:03:15 +00:00
|
|
|
nsContentUtils::GetListenerManager(nsINode *aNode,
|
2009-06-23 11:23:52 +00:00
|
|
|
PRBool aCreateIfNotFound)
|
2006-02-07 14:34:10 +00:00
|
|
|
{
|
2007-02-15 23:04:33 +00:00
|
|
|
if (!aCreateIfNotFound && !aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
|
2009-06-23 11:23:52 +00:00
|
|
|
return nsnull;
|
2007-02-15 23:04:33 +00:00
|
|
|
}
|
|
|
|
|
2006-02-07 14:34:10 +00:00
|
|
|
if (!sEventListenerManagersHash.ops) {
|
|
|
|
// We're already shut down, don't bother creating an event listener
|
|
|
|
// manager.
|
|
|
|
|
2009-06-23 11:23:52 +00:00
|
|
|
return nsnull;
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
|
2006-03-07 17:08:51 +00:00
|
|
|
if (!aCreateIfNotFound) {
|
|
|
|
EventListenerManagerMapEntry *entry =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<EventListenerManagerMapEntry *>
|
|
|
|
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
|
2006-03-07 17:08:51 +00:00
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
2009-06-23 11:23:52 +00:00
|
|
|
return entry->mListenerManager;
|
2006-03-07 17:08:51 +00:00
|
|
|
}
|
2009-06-23 11:23:52 +00:00
|
|
|
return nsnull;
|
2006-03-07 17:08:51 +00:00
|
|
|
}
|
|
|
|
|
2006-02-07 14:34:10 +00:00
|
|
|
EventListenerManagerMapEntry *entry =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<EventListenerManagerMapEntry *>
|
|
|
|
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
|
2006-02-07 14:34:10 +00:00
|
|
|
PL_DHASH_ADD));
|
|
|
|
|
|
|
|
if (!entry) {
|
2009-06-23 11:23:52 +00:00
|
|
|
return nsnull;
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!entry->mListenerManager) {
|
|
|
|
nsresult rv =
|
|
|
|
NS_NewEventListenerManager(getter_AddRefs(entry->mListenerManager));
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
PL_DHashTableRawRemove(&sEventListenerManagersHash, entry);
|
|
|
|
|
2009-06-23 11:23:52 +00:00
|
|
|
return nsnull;
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
|
2006-05-15 07:03:15 +00:00
|
|
|
entry->mListenerManager->SetListenerTarget(aNode);
|
2006-02-07 14:34:10 +00:00
|
|
|
|
2007-02-15 23:04:33 +00:00
|
|
|
aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
|
2009-06-23 11:23:52 +00:00
|
|
|
return entry->mListenerManager;
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
2006-05-15 07:03:15 +00:00
|
|
|
nsContentUtils::RemoveListenerManager(nsINode *aNode)
|
2006-02-07 14:34:10 +00:00
|
|
|
{
|
|
|
|
if (sEventListenerManagersHash.ops) {
|
2006-04-18 20:59:28 +00:00
|
|
|
EventListenerManagerMapEntry *entry =
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<EventListenerManagerMapEntry *>
|
|
|
|
(PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
|
2006-04-18 20:59:28 +00:00
|
|
|
PL_DHASH_LOOKUP));
|
|
|
|
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
|
|
|
nsCOMPtr<nsIEventListenerManager> listenerManager;
|
|
|
|
listenerManager.swap(entry->mListenerManager);
|
|
|
|
// Remove the entry and *then* do operations that could cause further
|
|
|
|
// modification of sEventListenerManagersHash. See bug 334177.
|
|
|
|
PL_DHashTableRawRemove(&sEventListenerManagersHash, entry);
|
|
|
|
if (listenerManager) {
|
|
|
|
listenerManager->Disconnect();
|
|
|
|
}
|
|
|
|
}
|
2006-02-07 14:34:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-17 17:13:11 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix,
|
|
|
|
PRInt32 aNamespaceID)
|
|
|
|
{
|
2006-10-03 02:22:22 +00:00
|
|
|
if (aNamespaceID == kNameSpaceID_Unknown) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2006-04-17 17:13:11 +00:00
|
|
|
if (!aPrefix) {
|
|
|
|
// If the prefix is null, then either the QName must be xmlns or the
|
|
|
|
// namespace must not be XMLNS.
|
|
|
|
return (aLocalName == nsGkAtoms::xmlns) ==
|
|
|
|
(aNamespaceID == kNameSpaceID_XMLNS);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the prefix is non-null then the namespace must not be null.
|
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the namespace is the XMLNS namespace then the prefix must be xmlns,
|
|
|
|
// but the localname must not be xmlns.
|
|
|
|
if (aNamespaceID == kNameSpaceID_XMLNS) {
|
|
|
|
return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the namespace is not the XMLNS namespace then the prefix must not be
|
|
|
|
// xmlns.
|
|
|
|
// If the namespace is the XML namespace then the prefix can be anything.
|
|
|
|
// If the namespace is not the XML namespace then the prefix must not be xml.
|
|
|
|
return aPrefix != nsGkAtoms::xmlns &&
|
|
|
|
(aNamespaceID == kNameSpaceID_XML || aPrefix != nsGkAtoms::xml);
|
|
|
|
}
|
2006-06-02 13:28:14 +00:00
|
|
|
|
2006-06-05 20:32:48 +00:00
|
|
|
/* static */
|
|
|
|
nsresult
|
2010-04-24 10:41:02 +00:00
|
|
|
nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
|
2006-06-05 20:32:48 +00:00
|
|
|
const nsAString& aFragment,
|
2008-03-06 20:14:33 +00:00
|
|
|
PRBool aWillOwnFragment,
|
2006-06-05 20:32:48 +00:00
|
|
|
nsIDOMDocumentFragment** aReturn)
|
|
|
|
{
|
|
|
|
*aReturn = nsnull;
|
2010-04-24 10:41:02 +00:00
|
|
|
NS_ENSURE_ARG(aContextNode);
|
2006-06-05 20:32:48 +00:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// If we don't have a document here, we can't get the right security context
|
|
|
|
// for compiling event handlers... so just bail out.
|
2010-04-24 10:41:02 +00:00
|
|
|
nsCOMPtr<nsIDocument> document = aContextNode->GetOwnerDoc();
|
2006-06-05 20:32:48 +00:00
|
|
|
NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE);
|
2009-06-28 22:44:22 +00:00
|
|
|
|
2010-04-24 10:41:02 +00:00
|
|
|
PRBool isHTML = document->IsHTML();
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(document);
|
|
|
|
NS_ASSERTION(!isHTML || htmlDoc, "Should have HTMLDocument here!");
|
|
|
|
#endif
|
2009-06-28 22:44:22 +00:00
|
|
|
|
2009-07-15 11:30:33 +00:00
|
|
|
if (isHTML && nsHtml5Module::sEnabled) {
|
2009-06-28 22:44:22 +00:00
|
|
|
// See if the document has a cached fragment parser. nsHTMLDocument is the
|
|
|
|
// only one that should really have one at the moment.
|
|
|
|
nsCOMPtr<nsIParser> parser = document->GetFragmentParser();
|
|
|
|
if (parser) {
|
|
|
|
// Get the parser ready to use.
|
|
|
|
parser->Reset();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Create a new parser for this operation.
|
|
|
|
parser = nsHtml5Module::NewHtml5Parser();
|
|
|
|
if (!parser) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMDocumentFragment> frag;
|
|
|
|
rv = NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager());
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
|
2010-04-30 13:12:05 +00:00
|
|
|
if (contextAsContent && !contextAsContent->IsElement()) {
|
2009-06-28 22:44:22 +00:00
|
|
|
contextAsContent = contextAsContent->GetParent();
|
2010-04-30 13:12:05 +00:00
|
|
|
if (contextAsContent && !contextAsContent->IsElement()) {
|
2009-06-28 22:44:22 +00:00
|
|
|
// can this even happen?
|
|
|
|
contextAsContent = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-16 07:47:10 +00:00
|
|
|
nsAHtml5FragmentParser* asFragmentParser =
|
|
|
|
static_cast<nsAHtml5FragmentParser*> (parser.get());
|
2010-07-21 16:03:21 +00:00
|
|
|
nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
|
2010-09-01 11:41:07 +00:00
|
|
|
if (contextAsContent &&
|
|
|
|
!(nsGkAtoms::html == contextAsContent->Tag() &&
|
|
|
|
contextAsContent->IsHTML())) {
|
2010-11-16 07:47:10 +00:00
|
|
|
asFragmentParser->ParseHtml5Fragment(aFragment,
|
|
|
|
fragment,
|
|
|
|
contextAsContent->Tag(),
|
|
|
|
contextAsContent->GetNameSpaceID(),
|
|
|
|
(document->GetCompatibilityMode() ==
|
|
|
|
eCompatibility_NavQuirks),
|
|
|
|
PR_FALSE);
|
2009-06-28 22:44:22 +00:00
|
|
|
} else {
|
2010-11-16 07:47:10 +00:00
|
|
|
asFragmentParser->ParseHtml5Fragment(aFragment,
|
|
|
|
fragment,
|
|
|
|
nsGkAtoms::body,
|
|
|
|
kNameSpaceID_XHTML,
|
|
|
|
(document->GetCompatibilityMode() ==
|
|
|
|
eCompatibility_NavQuirks),
|
|
|
|
PR_FALSE);
|
2009-06-28 22:44:22 +00:00
|
|
|
}
|
|
|
|
|
2010-04-24 10:41:02 +00:00
|
|
|
frag.swap(*aReturn);
|
2010-04-21 11:53:57 +00:00
|
|
|
document->SetFragmentParser(parser);
|
2009-06-28 22:44:22 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2006-06-05 20:32:48 +00:00
|
|
|
|
2008-04-11 04:38:25 +00:00
|
|
|
nsAutoTArray<nsString, 32> tagStack;
|
2007-11-13 01:41:40 +00:00
|
|
|
nsAutoString uriStr, nameStr;
|
2008-02-07 15:11:29 +00:00
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode);
|
2007-12-18 21:24:54 +00:00
|
|
|
// just in case we have a text node
|
2010-04-30 13:12:05 +00:00
|
|
|
if (content && !content->IsElement())
|
2007-12-18 21:24:54 +00:00
|
|
|
content = content->GetParent();
|
|
|
|
|
2010-04-30 13:12:05 +00:00
|
|
|
while (content && content->IsElement()) {
|
2008-04-11 04:38:25 +00:00
|
|
|
nsString& tagName = *tagStack.AppendElement();
|
2007-11-13 01:41:40 +00:00
|
|
|
NS_ENSURE_TRUE(&tagName, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
2011-05-05 16:26:33 +00:00
|
|
|
tagName = content->NodeInfo()->QualifiedName();
|
2007-11-13 01:41:40 +00:00
|
|
|
|
|
|
|
// see if we need to add xmlns declarations
|
|
|
|
PRUint32 count = content->GetAttrCount();
|
|
|
|
PRBool setDefaultNamespace = PR_FALSE;
|
|
|
|
if (count > 0) {
|
|
|
|
PRUint32 index;
|
|
|
|
|
|
|
|
for (index = 0; index < count; index++) {
|
|
|
|
const nsAttrName* name = content->GetAttrNameAt(index);
|
|
|
|
if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
|
|
|
|
content->GetAttr(kNameSpaceID_XMLNS, name->LocalName(), uriStr);
|
|
|
|
|
|
|
|
// really want something like nsXMLContentSerializer::SerializeAttr
|
|
|
|
tagName.Append(NS_LITERAL_STRING(" xmlns")); // space important
|
|
|
|
if (name->GetPrefix()) {
|
|
|
|
tagName.Append(PRUnichar(':'));
|
|
|
|
name->LocalName()->ToString(nameStr);
|
|
|
|
tagName.Append(nameStr);
|
|
|
|
} else {
|
|
|
|
setDefaultNamespace = PR_TRUE;
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
2007-11-13 01:41:40 +00:00
|
|
|
tagName.Append(NS_LITERAL_STRING("=\"") + uriStr +
|
|
|
|
NS_LITERAL_STRING("\""));
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-13 01:41:40 +00:00
|
|
|
}
|
2006-06-05 20:32:48 +00:00
|
|
|
|
2007-11-13 01:41:40 +00:00
|
|
|
if (!setDefaultNamespace) {
|
|
|
|
nsINodeInfo* info = content->NodeInfo();
|
|
|
|
if (!info->GetPrefixAtom() &&
|
|
|
|
info->NamespaceID() != kNameSpaceID_None) {
|
|
|
|
// We have no namespace prefix, but have a namespace ID. Push
|
|
|
|
// default namespace attr in, so that our kids will be in our
|
|
|
|
// namespace.
|
|
|
|
info->GetNamespaceURI(uriStr);
|
|
|
|
tagName.Append(NS_LITERAL_STRING(" xmlns=\"") + uriStr +
|
|
|
|
NS_LITERAL_STRING("\""));
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-13 01:41:40 +00:00
|
|
|
|
|
|
|
content = content->GetParent();
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
|
|
|
|
2007-11-13 01:41:40 +00:00
|
|
|
nsCAutoString contentType;
|
|
|
|
nsAutoString buf;
|
|
|
|
document->GetContentType(buf);
|
|
|
|
LossyCopyUTF16toASCII(buf, contentType);
|
2008-02-08 22:07:51 +00:00
|
|
|
|
|
|
|
// See if the document has a cached fragment parser. nsHTMLDocument is the
|
|
|
|
// only one that should really have one at the moment.
|
|
|
|
nsCOMPtr<nsIParser> parser = document->GetFragmentParser();
|
|
|
|
if (parser) {
|
|
|
|
// Get the parser ready to use.
|
|
|
|
parser->Reset();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Create a new parser for this operation.
|
|
|
|
parser = do_CreateInstance(kCParserCID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if the parser already has a content sink that we can reuse.
|
2007-11-13 01:41:40 +00:00
|
|
|
nsCOMPtr<nsIFragmentContentSink> sink;
|
2008-02-08 22:07:51 +00:00
|
|
|
nsCOMPtr<nsIContentSink> contentsink = parser->GetContentSink();
|
|
|
|
if (contentsink) {
|
|
|
|
// Make sure it's the correct type.
|
2009-07-15 11:30:33 +00:00
|
|
|
if (isHTML) {
|
2008-02-08 22:07:51 +00:00
|
|
|
nsCOMPtr<nsIHTMLContentSink> htmlsink = do_QueryInterface(contentsink);
|
|
|
|
sink = do_QueryInterface(htmlsink);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsCOMPtr<nsIXMLContentSink> xmlsink = do_QueryInterface(contentsink);
|
|
|
|
sink = do_QueryInterface(xmlsink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sink) {
|
|
|
|
// Either there was no cached content sink or it was the wrong type. Make a
|
|
|
|
// new one.
|
2009-07-15 11:30:33 +00:00
|
|
|
if (isHTML) {
|
2008-02-08 22:07:51 +00:00
|
|
|
rv = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
|
|
|
|
} else {
|
|
|
|
rv = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
|
|
|
|
}
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
contentsink = do_QueryInterface(sink);
|
|
|
|
NS_ASSERTION(contentsink, "Sink doesn't QI to nsIContentSink!");
|
|
|
|
|
|
|
|
parser->SetContentSink(contentsink);
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
|
|
|
|
2007-11-13 01:41:40 +00:00
|
|
|
sink->SetTargetDocument(document);
|
|
|
|
|
|
|
|
nsDTDMode mode = eDTDMode_autodetect;
|
|
|
|
switch (document->GetCompatibilityMode()) {
|
|
|
|
case eCompatibility_NavQuirks:
|
|
|
|
mode = eDTDMode_quirks;
|
|
|
|
break;
|
|
|
|
case eCompatibility_AlmostStandards:
|
|
|
|
mode = eDTDMode_almost_standards;
|
|
|
|
break;
|
|
|
|
case eCompatibility_FullStandards:
|
|
|
|
mode = eDTDMode_full_standards;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_NOTREACHED("unknown mode");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = parser->ParseFragment(aFragment, nsnull, tagStack,
|
2009-07-15 11:30:33 +00:00
|
|
|
!isHTML, contentType, mode);
|
2007-11-13 01:41:40 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2008-03-06 20:14:33 +00:00
|
|
|
rv = sink->GetFragment(aWillOwnFragment, aReturn);
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
|
|
|
|
2008-02-08 22:07:51 +00:00
|
|
|
document->SetFragmentParser(parser);
|
|
|
|
|
2009-01-16 19:19:27 +00:00
|
|
|
return rv;
|
2006-06-05 20:32:48 +00:00
|
|
|
}
|
2006-06-15 20:30:44 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::CreateDocument(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aQualifiedName,
|
|
|
|
nsIDOMDocumentType* aDoctype,
|
|
|
|
nsIURI* aDocumentURI, nsIURI* aBaseURI,
|
|
|
|
nsIPrincipal* aPrincipal,
|
2007-10-01 10:02:32 +00:00
|
|
|
nsIScriptGlobalObject* aEventObject,
|
2006-06-15 20:30:44 +00:00
|
|
|
nsIDOMDocument** aResult)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_NewDOMDocument(aResult, aNamespaceURI, aQualifiedName,
|
2007-10-01 10:02:32 +00:00
|
|
|
aDoctype, aDocumentURI, aBaseURI, aPrincipal,
|
|
|
|
PR_TRUE);
|
2006-06-15 20:30:44 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2007-10-01 10:02:32 +00:00
|
|
|
nsCOMPtr<nsIDocument> document = do_QueryInterface(*aResult);
|
|
|
|
document->SetScriptHandlingObject(aEventObject);
|
2009-01-09 17:12:09 +00:00
|
|
|
|
|
|
|
// created documents are immediately "complete" (ready to use)
|
|
|
|
document->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
|
2006-06-15 20:30:44 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2006-09-15 19:54:45 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::SetNodeTextContent(nsIContent* aContent,
|
|
|
|
const nsAString& aValue,
|
|
|
|
PRBool aTryReuse)
|
|
|
|
{
|
2011-05-09 19:33:03 +00:00
|
|
|
// Fire DOMNodeRemoved mutation events before we do anything else.
|
|
|
|
nsCOMPtr<nsIContent> owningContent;
|
|
|
|
|
|
|
|
// Batch possible DOMSubtreeModified events.
|
|
|
|
mozAutoSubtreeModified subtree(nsnull, nsnull);
|
|
|
|
|
|
|
|
// Scope firing mutation events so that we don't carry any state that
|
|
|
|
// might be stale
|
|
|
|
{
|
|
|
|
// We're relying on mozAutoSubtreeModified to keep a strong reference if
|
|
|
|
// needed.
|
|
|
|
nsIDocument* doc = aContent->GetOwnerDoc();
|
|
|
|
|
|
|
|
// Optimize the common case of there being no observers
|
|
|
|
if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
|
|
|
|
subtree.UpdateTarget(doc, nsnull);
|
|
|
|
owningContent = aContent;
|
|
|
|
nsCOMPtr<nsINode> child;
|
|
|
|
bool skipFirst = aTryReuse;
|
|
|
|
for (child = aContent->GetFirstChild();
|
|
|
|
child && child->GetNodeParent() == aContent;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
if (skipFirst && child->IsNodeOfType(nsINode::eTEXT)) {
|
|
|
|
skipFirst = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
nsContentUtils::MaybeFireNodeRemoved(child, aContent, doc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-15 19:54:45 +00:00
|
|
|
// Might as well stick a batch around this since we're performing several
|
|
|
|
// mutations.
|
|
|
|
mozAutoDocUpdate updateBatch(aContent->GetCurrentDoc(),
|
|
|
|
UPDATE_CONTENT_MODEL, PR_TRUE);
|
|
|
|
|
|
|
|
PRUint32 childCount = aContent->GetChildCount();
|
|
|
|
|
|
|
|
if (aTryReuse && !aValue.IsEmpty()) {
|
|
|
|
PRUint32 removeIndex = 0;
|
|
|
|
|
|
|
|
// i is unsigned, so i >= is always true
|
|
|
|
for (PRUint32 i = 0; i < childCount; ++i) {
|
|
|
|
nsIContent* child = aContent->GetChildAt(removeIndex);
|
2009-05-15 03:16:04 +00:00
|
|
|
if (removeIndex == 0 && child && child->IsNodeOfType(nsINode::eTEXT)) {
|
2006-09-15 19:54:45 +00:00
|
|
|
nsresult rv = child->SetText(aValue, PR_TRUE);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
removeIndex = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aContent->RemoveChildAt(removeIndex, PR_TRUE);
|
|
|
|
}
|
|
|
|
}
|
2011-05-09 19:33:03 +00:00
|
|
|
|
2006-09-15 19:54:45 +00:00
|
|
|
if (removeIndex == 1) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// i is unsigned, so i >= is always true
|
|
|
|
for (PRUint32 i = childCount; i-- != 0; ) {
|
|
|
|
aContent->RemoveChildAt(i, PR_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aValue.IsEmpty()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> textContent;
|
|
|
|
nsresult rv = NS_NewTextNode(getter_AddRefs(textContent),
|
|
|
|
aContent->NodeInfo()->NodeInfoManager());
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
textContent->SetText(aValue, PR_TRUE);
|
|
|
|
|
|
|
|
return aContent->AppendChildTo(textContent, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void AppendNodeTextContentsRecurse(nsINode* aNode, nsAString& aResult)
|
|
|
|
{
|
|
|
|
nsIContent* child;
|
|
|
|
PRUint32 i;
|
|
|
|
for (i = 0; (child = aNode->GetChildAt(i)); ++i) {
|
2010-04-30 13:12:05 +00:00
|
|
|
if (child->IsElement()) {
|
2006-09-15 19:54:45 +00:00
|
|
|
AppendNodeTextContentsRecurse(child, aResult);
|
|
|
|
}
|
|
|
|
else if (child->IsNodeOfType(nsINode::eTEXT)) {
|
|
|
|
child->AppendTextTo(aResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::AppendNodeTextContent(nsINode* aNode, PRBool aDeep,
|
|
|
|
nsAString& aResult)
|
|
|
|
{
|
|
|
|
if (aNode->IsNodeOfType(nsINode::eTEXT)) {
|
2007-07-08 07:08:04 +00:00
|
|
|
static_cast<nsIContent*>(aNode)->AppendTextTo(aResult);
|
2006-09-15 19:54:45 +00:00
|
|
|
}
|
|
|
|
else if (aDeep) {
|
|
|
|
AppendNodeTextContentsRecurse(aNode, aResult);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsIContent* child;
|
|
|
|
PRUint32 i;
|
|
|
|
for (i = 0; (child = aNode->GetChildAt(i)); ++i) {
|
|
|
|
if (child->IsNodeOfType(nsINode::eTEXT)) {
|
|
|
|
child->AppendTextTo(aResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-11-09 00:02:21 +00:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::HasNonEmptyTextContent(nsINode* aNode)
|
|
|
|
{
|
|
|
|
nsIContent* child;
|
|
|
|
PRUint32 i;
|
|
|
|
for (i = 0; (child = aNode->GetChildAt(i)); ++i) {
|
|
|
|
if (child->IsNodeOfType(nsINode::eTEXT) &&
|
|
|
|
child->TextLength() > 0) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2007-01-30 05:48:22 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
PRBool
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
|
|
|
|
const nsIContent* aContent)
|
2007-01-30 05:48:22 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aNode,
|
|
|
|
"Must have a node to work with");
|
|
|
|
NS_PRECONDITION(aContent,
|
|
|
|
"Must have a content to work with");
|
|
|
|
|
|
|
|
if (!aNode->IsNodeOfType(nsINode::eCONTENT)) {
|
|
|
|
/**
|
|
|
|
* The root isn't an nsIContent, so it's a document or attribute. The only
|
|
|
|
* nodes in the same anonymous subtree as it will have a null
|
|
|
|
* bindingParent.
|
|
|
|
*
|
|
|
|
* XXXbz strictly speaking, that's not true for attribute nodes.
|
|
|
|
*/
|
|
|
|
return aContent->GetBindingParent() == nsnull;
|
|
|
|
}
|
|
|
|
|
2010-10-07 19:19:32 +00:00
|
|
|
return static_cast<const nsIContent*>(aNode)->GetBindingParent() ==
|
2007-01-30 06:25:07 +00:00
|
|
|
aContent->GetBindingParent();
|
2007-01-30 05:48:22 +00:00
|
|
|
|
|
|
|
}
|
2007-02-18 17:34:09 +00:00
|
|
|
|
2009-05-17 22:08:08 +00:00
|
|
|
class AnonymousContentDestroyer : public nsRunnable {
|
|
|
|
public:
|
|
|
|
AnonymousContentDestroyer(nsCOMPtr<nsIContent>* aContent) {
|
|
|
|
mContent.swap(*aContent);
|
|
|
|
mParent = mContent->GetParent();
|
|
|
|
mDoc = mContent->GetOwnerDoc();
|
|
|
|
}
|
|
|
|
NS_IMETHOD Run() {
|
|
|
|
mContent->UnbindFromTree();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
nsCOMPtr<nsIContent> mContent;
|
|
|
|
// Hold strong refs to the parent content and document so that they
|
|
|
|
// don't die unexpectedly
|
|
|
|
nsCOMPtr<nsIDocument> mDoc;
|
|
|
|
nsCOMPtr<nsIContent> mParent;
|
|
|
|
};
|
|
|
|
|
2007-02-18 17:34:09 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent)
|
|
|
|
{
|
|
|
|
if (*aContent) {
|
2009-05-17 22:08:08 +00:00
|
|
|
AddScriptRunner(new AnonymousContentDestroyer(aContent));
|
2007-02-18 17:34:09 +00:00
|
|
|
}
|
|
|
|
}
|
2007-03-02 13:34:14 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsIDOMScriptObjectFactory*
|
|
|
|
nsContentUtils::GetDOMScriptObjectFactory()
|
|
|
|
{
|
|
|
|
if (!sDOMScriptObjectFactory) {
|
|
|
|
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
|
|
|
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
|
|
|
|
|
|
|
CallGetService(kDOMScriptObjectFactoryCID, &sDOMScriptObjectFactory);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sDOMScriptObjectFactory;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
|
|
|
|
{
|
2007-06-30 03:06:04 +00:00
|
|
|
NS_ASSERTION(aObject, "unexpected null object");
|
2007-10-29 13:45:07 +00:00
|
|
|
NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
|
|
|
|
"Should use HoldJSObjects.");
|
2007-03-02 13:34:14 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
|
|
|
nsIScriptRuntime *runtime = sScriptRuntimes[langIndex];
|
|
|
|
if (!runtime) {
|
|
|
|
nsIDOMScriptObjectFactory *factory = GetDOMScriptObjectFactory();
|
|
|
|
NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
rv = factory->GetScriptRuntimeByID(aLangID, &runtime);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// This makes sScriptRuntimes hold a strong ref.
|
|
|
|
sScriptRuntimes[langIndex] = runtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = runtime->HoldScriptObject(aObject);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
++sScriptRootCount[langIndex];
|
2007-06-30 03:06:04 +00:00
|
|
|
NS_LOG_ADDREF(sScriptRuntimes[langIndex], sScriptRootCount[langIndex],
|
|
|
|
"HoldScriptObject", sizeof(void*));
|
2007-03-02 13:34:14 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
2007-10-29 13:45:07 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject,
|
|
|
|
void *aClosure)
|
2007-03-02 13:34:14 +00:00
|
|
|
{
|
2007-06-30 03:06:04 +00:00
|
|
|
NS_ASSERTION(aObject, "unexpected null object");
|
2007-10-29 13:45:07 +00:00
|
|
|
NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
|
|
|
|
"Should use DropJSObjects.");
|
2007-03-02 13:34:14 +00:00
|
|
|
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
2007-06-30 03:06:04 +00:00
|
|
|
NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
|
|
|
|
"HoldScriptObject");
|
2007-10-29 13:45:07 +00:00
|
|
|
sScriptRuntimes[langIndex]->DropScriptObject(aObject);
|
2007-03-02 13:34:14 +00:00
|
|
|
if (--sScriptRootCount[langIndex] == 0) {
|
|
|
|
NS_RELEASE(sScriptRuntimes[langIndex]);
|
|
|
|
}
|
2007-10-29 13:45:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
|
|
|
|
nsScriptObjectTracer* aTracer)
|
|
|
|
{
|
2010-04-11 13:55:24 +00:00
|
|
|
NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
|
|
|
|
|
2007-10-29 13:45:07 +00:00
|
|
|
nsresult rv = sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-04-11 13:55:24 +00:00
|
|
|
if (sJSGCThingRootCount++ == 0) {
|
|
|
|
nsLayoutStatics::AddRef();
|
|
|
|
}
|
2007-10-29 13:45:07 +00:00
|
|
|
NS_LOG_ADDREF(sXPConnect, sJSGCThingRootCount, "HoldJSObjects",
|
|
|
|
sizeof(void*));
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
|
|
|
|
{
|
|
|
|
NS_LOG_RELEASE(sXPConnect, sJSGCThingRootCount - 1, "HoldJSObjects");
|
|
|
|
nsresult rv = sXPConnect->RemoveJSHolder(aScriptObjectHolder);
|
2010-04-11 13:55:24 +00:00
|
|
|
if (--sJSGCThingRootCount == 0) {
|
|
|
|
nsLayoutStatics::Release();
|
2007-10-29 13:45:07 +00:00
|
|
|
}
|
2007-03-02 13:34:14 +00:00
|
|
|
return rv;
|
|
|
|
}
|
2007-04-15 13:43:55 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
PRUint32
|
2008-07-14 02:56:18 +00:00
|
|
|
nsContentUtils::GetWidgetStatusFromIMEStatus(PRUint32 aState)
|
2007-04-15 13:43:55 +00:00
|
|
|
{
|
|
|
|
switch (aState & nsIContent::IME_STATUS_MASK_ENABLED) {
|
|
|
|
case nsIContent::IME_STATUS_DISABLE:
|
2008-07-14 02:56:18 +00:00
|
|
|
return nsIWidget::IME_STATUS_DISABLED;
|
2007-04-15 13:43:55 +00:00
|
|
|
case nsIContent::IME_STATUS_ENABLE:
|
2008-07-14 02:56:18 +00:00
|
|
|
return nsIWidget::IME_STATUS_ENABLED;
|
2007-04-15 13:43:55 +00:00
|
|
|
case nsIContent::IME_STATUS_PASSWORD:
|
2008-07-14 02:56:18 +00:00
|
|
|
return nsIWidget::IME_STATUS_PASSWORD;
|
2008-12-15 03:54:54 +00:00
|
|
|
case nsIContent::IME_STATUS_PLUGIN:
|
|
|
|
return nsIWidget::IME_STATUS_PLUGIN;
|
2007-04-15 13:43:55 +00:00
|
|
|
default:
|
|
|
|
NS_ERROR("The given state doesn't have valid enable state");
|
2008-07-14 02:56:18 +00:00
|
|
|
return nsIWidget::IME_STATUS_ENABLED;
|
2007-04-15 13:43:55 +00:00
|
|
|
}
|
|
|
|
}
|
2007-05-02 15:34:35 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::NotifyInstalledMenuKeyboardListener(PRBool aInstalling)
|
|
|
|
{
|
|
|
|
nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
|
|
|
|
}
|
2007-06-12 21:56:06 +00:00
|
|
|
|
|
|
|
static PRBool SchemeIs(nsIURI* aURI, const char* aScheme)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
|
|
|
|
NS_ENSURE_TRUE(baseURI, PR_FALSE);
|
|
|
|
|
|
|
|
PRBool isScheme = PR_FALSE;
|
|
|
|
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
|
|
|
nsIPrincipal* aLoadingPrincipal,
|
|
|
|
PRUint32 aCheckLoadFlags,
|
|
|
|
PRBool aAllowData,
|
|
|
|
PRUint32 aContentPolicyType,
|
|
|
|
nsISupports* aContext,
|
|
|
|
const nsACString& aMimeGuess,
|
|
|
|
nsISupports* aExtra)
|
|
|
|
{
|
2007-08-08 01:16:09 +00:00
|
|
|
NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal here");
|
2008-04-28 23:56:07 +00:00
|
|
|
|
|
|
|
PRBool isSystemPrin = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(aLoadingPrincipal,
|
|
|
|
&isSystemPrin)) &&
|
|
|
|
isSystemPrin) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-08-08 01:16:09 +00:00
|
|
|
|
2007-07-18 21:56:57 +00:00
|
|
|
// XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
|
2007-06-12 21:56:06 +00:00
|
|
|
// CheckLoadURIWithPrincipal
|
2007-08-08 01:16:09 +00:00
|
|
|
nsresult rv = sSecurityManager->
|
2007-06-12 21:56:06 +00:00
|
|
|
CheckLoadURIWithPrincipal(aLoadingPrincipal, aURIToLoad, aCheckLoadFlags);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Content Policy
|
|
|
|
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
|
|
|
rv = NS_CheckContentLoadPolicy(aContentPolicyType,
|
|
|
|
aURIToLoad,
|
2007-08-08 01:16:09 +00:00
|
|
|
aLoadingPrincipal,
|
2007-06-12 21:56:06 +00:00
|
|
|
aContext,
|
|
|
|
aMimeGuess,
|
|
|
|
aExtra,
|
|
|
|
&shouldLoad,
|
2007-08-08 01:16:09 +00:00
|
|
|
GetContentPolicy(),
|
|
|
|
sSecurityManager);
|
2007-06-12 21:56:06 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (NS_CP_REJECTED(shouldLoad)) {
|
|
|
|
return NS_ERROR_CONTENT_BLOCKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Same Origin
|
|
|
|
if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
|
|
|
|
((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
|
|
|
|
SchemeIs(aURIToLoad, "chrome"))) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-08-08 01:16:09 +00:00
|
|
|
|
2008-02-27 03:45:29 +00:00
|
|
|
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, PR_TRUE);
|
2007-06-12 21:56:06 +00:00
|
|
|
}
|
2007-07-11 13:05:05 +00:00
|
|
|
|
2010-03-02 19:40:14 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
|
|
|
|
{
|
|
|
|
PRBool isSystem;
|
|
|
|
nsresult rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
|
|
|
|
return NS_SUCCEEDED(rv) && isSystem;
|
|
|
|
}
|
|
|
|
|
2007-07-11 13:05:05 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
|
|
|
|
nsIURI *aLinkURI, const nsString &aTargetSpec,
|
|
|
|
PRBool aClick, PRBool aIsUserTriggered)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aPresContext, "Need a nsPresContext");
|
|
|
|
NS_PRECONDITION(aLinkURI, "No link URI");
|
|
|
|
|
|
|
|
if (aContent->IsEditable()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsILinkHandler *handler = aPresContext->GetLinkHandler();
|
|
|
|
if (!handler) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!aClick) {
|
|
|
|
handler->OnOverLink(aContent, aLinkURI, aTargetSpec.get());
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that this page is allowed to load this URI.
|
|
|
|
nsresult proceed = NS_OK;
|
|
|
|
|
|
|
|
if (sSecurityManager) {
|
|
|
|
PRUint32 flag =
|
|
|
|
aIsUserTriggered ?
|
|
|
|
(PRUint32)nsIScriptSecurityManager::STANDARD :
|
|
|
|
(PRUint32)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT;
|
|
|
|
proceed =
|
|
|
|
sSecurityManager->CheckLoadURIWithPrincipal(aContent->NodePrincipal(),
|
|
|
|
aLinkURI, flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only pass off the click event if the script security manager says it's ok.
|
|
|
|
if (NS_SUCCEEDED(proceed)) {
|
|
|
|
handler->OnLinkClick(aContent, aLinkURI, aTargetSpec.get());
|
|
|
|
}
|
|
|
|
}
|
2007-10-12 18:37:51 +00:00
|
|
|
|
2007-11-16 08:21:44 +00:00
|
|
|
/* static */
|
|
|
|
nsIWidget*
|
|
|
|
nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget)
|
|
|
|
{
|
2008-09-16 08:21:06 +00:00
|
|
|
if (!aWidget)
|
2007-11-16 08:21:44 +00:00
|
|
|
return nsnull;
|
|
|
|
|
2008-09-16 08:21:06 +00:00
|
|
|
return aWidget->GetTopLevelWidget();
|
2007-11-16 08:21:44 +00:00
|
|
|
}
|
|
|
|
|
2007-11-19 10:17:17 +00:00
|
|
|
/* static */
|
|
|
|
const nsDependentString
|
|
|
|
nsContentUtils::GetLocalizedEllipsis()
|
|
|
|
{
|
|
|
|
static PRUnichar sBuf[4] = { 0, 0, 0, 0 };
|
|
|
|
if (!sBuf[0]) {
|
2011-05-27 04:53:03 +00:00
|
|
|
nsAdoptingString tmp = Preferences::GetLocalizedString("intl.ellipsis");
|
2010-02-22 20:13:19 +00:00
|
|
|
PRUint32 len = NS_MIN(PRUint32(tmp.Length()),
|
|
|
|
PRUint32(NS_ARRAY_LENGTH(sBuf) - 1));
|
2007-11-19 10:17:17 +00:00
|
|
|
CopyUnicodeTo(tmp, 0, sBuf, len);
|
|
|
|
if (!sBuf[0])
|
|
|
|
sBuf[0] = PRUnichar(0x2026);
|
|
|
|
}
|
|
|
|
return nsDependentString(sBuf);
|
|
|
|
}
|
|
|
|
|
2007-12-18 05:41:56 +00:00
|
|
|
//static
|
|
|
|
nsEvent*
|
|
|
|
nsContentUtils::GetNativeEvent(nsIDOMEvent* aDOMEvent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aDOMEvent));
|
|
|
|
if (!privateEvent)
|
|
|
|
return nsnull;
|
2008-10-09 23:23:07 +00:00
|
|
|
return privateEvent->GetInternalNSEvent();
|
2007-12-18 05:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//static
|
|
|
|
PRBool
|
2008-10-15 10:50:42 +00:00
|
|
|
nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMKeyEvent* aKeyEvent,
|
2007-12-18 05:41:56 +00:00
|
|
|
nsNativeKeyEvent* aNativeEvent,
|
|
|
|
PRBool aGetCharCode)
|
|
|
|
{
|
2008-10-15 10:50:42 +00:00
|
|
|
nsCOMPtr<nsIDOMNSUIEvent> uievent = do_QueryInterface(aKeyEvent);
|
2007-12-18 05:41:56 +00:00
|
|
|
PRBool defaultPrevented;
|
|
|
|
uievent->GetPreventDefault(&defaultPrevented);
|
|
|
|
if (defaultPrevented)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
2008-10-15 10:50:42 +00:00
|
|
|
nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(aKeyEvent);
|
2007-12-18 05:41:56 +00:00
|
|
|
PRBool trusted = PR_FALSE;
|
|
|
|
nsevent->GetIsTrusted(&trusted);
|
|
|
|
if (!trusted)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
if (aGetCharCode) {
|
2008-10-15 10:50:42 +00:00
|
|
|
aKeyEvent->GetCharCode(&aNativeEvent->charCode);
|
2007-12-18 05:41:56 +00:00
|
|
|
} else {
|
|
|
|
aNativeEvent->charCode = 0;
|
|
|
|
}
|
2008-10-15 10:50:42 +00:00
|
|
|
aKeyEvent->GetKeyCode(&aNativeEvent->keyCode);
|
|
|
|
aKeyEvent->GetAltKey(&aNativeEvent->altKey);
|
|
|
|
aKeyEvent->GetCtrlKey(&aNativeEvent->ctrlKey);
|
|
|
|
aKeyEvent->GetShiftKey(&aNativeEvent->shiftKey);
|
|
|
|
aKeyEvent->GetMetaKey(&aNativeEvent->metaKey);
|
2007-12-18 05:41:56 +00:00
|
|
|
|
2008-10-15 10:50:42 +00:00
|
|
|
aNativeEvent->nativeEvent = GetNativeEvent(aKeyEvent);
|
2007-12-18 05:41:56 +00:00
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-05-02 14:50:42 +00:00
|
|
|
static PRBool
|
|
|
|
HasASCIIDigit(const nsTArray<nsShortcutCandidate>& aCandidates)
|
|
|
|
{
|
|
|
|
for (PRUint32 i = 0; i < aCandidates.Length(); ++i) {
|
|
|
|
PRUint32 ch = aCandidates[i].mCharCode;
|
|
|
|
if (ch >= '0' && ch <= '9')
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-05-12 00:39:29 +00:00
|
|
|
static PRBool
|
|
|
|
CharsCaseInsensitiveEqual(PRUint32 aChar1, PRUint32 aChar2)
|
|
|
|
{
|
|
|
|
return aChar1 == aChar2 ||
|
|
|
|
(IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
|
|
|
|
ToLowerCase(PRUnichar(aChar1)) == ToLowerCase(PRUnichar(aChar2)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PRBool
|
|
|
|
IsCaseChangeableChar(PRUint32 aChar)
|
|
|
|
{
|
|
|
|
return IS_IN_BMP(aChar) &&
|
|
|
|
ToLowerCase(PRUnichar(aChar)) != ToUpperCase(PRUnichar(aChar));
|
|
|
|
}
|
|
|
|
|
2008-04-15 04:16:24 +00:00
|
|
|
/* static */
|
|
|
|
void
|
2008-09-16 01:37:13 +00:00
|
|
|
nsContentUtils::GetAccelKeyCandidates(nsIDOMKeyEvent* aDOMKeyEvent,
|
2008-04-15 04:16:24 +00:00
|
|
|
nsTArray<nsShortcutCandidate>& aCandidates)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
|
|
|
|
|
|
|
|
nsAutoString eventType;
|
2008-09-16 01:37:13 +00:00
|
|
|
aDOMKeyEvent->GetType(eventType);
|
|
|
|
// Don't process if aDOMKeyEvent is not a keypress event.
|
2008-04-15 04:16:24 +00:00
|
|
|
if (!eventType.EqualsLiteral("keypress"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsKeyEvent* nativeKeyEvent =
|
2008-09-16 01:37:13 +00:00
|
|
|
static_cast<nsKeyEvent*>(GetNativeEvent(aDOMKeyEvent));
|
2008-04-15 04:16:24 +00:00
|
|
|
if (nativeKeyEvent) {
|
2008-09-16 01:37:13 +00:00
|
|
|
NS_ASSERTION(nativeKeyEvent->eventStructType == NS_KEY_EVENT,
|
|
|
|
"wrong type of native event");
|
2008-04-15 04:16:24 +00:00
|
|
|
// nsShortcutCandidate::mCharCode is a candidate charCode.
|
|
|
|
// nsShoftcutCandidate::mIgnoreShift means the mCharCode should be tried to
|
|
|
|
// execute a command with/without shift key state. If this is TRUE, the
|
|
|
|
// shifted key state should be ignored. Otherwise, don't ignore the state.
|
|
|
|
// the priority of the charCodes are (shift key is not pressed):
|
|
|
|
// 0: charCode/PR_FALSE,
|
|
|
|
// 1: unshiftedCharCodes[0]/PR_FALSE, 2: unshiftedCharCodes[1]/PR_FALSE...
|
|
|
|
// the priority of the charCodes are (shift key is pressed):
|
|
|
|
// 0: charCode/PR_FALSE,
|
|
|
|
// 1: shiftedCharCodes[0]/PR_FALSE, 2: shiftedCharCodes[0]/PR_TRUE,
|
|
|
|
// 3: shiftedCharCodes[1]/PR_FALSE, 4: shiftedCharCodes[1]/PR_TRUE...
|
|
|
|
if (nativeKeyEvent->charCode) {
|
|
|
|
nsShortcutCandidate key(nativeKeyEvent->charCode, PR_FALSE);
|
|
|
|
aCandidates.AppendElement(key);
|
|
|
|
}
|
|
|
|
|
2008-05-02 14:50:42 +00:00
|
|
|
PRUint32 len = nativeKeyEvent->alternativeCharCodes.Length();
|
2008-04-15 04:16:24 +00:00
|
|
|
if (!nativeKeyEvent->isShift) {
|
2008-05-02 14:50:42 +00:00
|
|
|
for (PRUint32 i = 0; i < len; ++i) {
|
2008-04-15 04:16:24 +00:00
|
|
|
PRUint32 ch =
|
2008-04-17 14:40:06 +00:00
|
|
|
nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
|
2008-04-15 04:16:24 +00:00
|
|
|
if (!ch || ch == nativeKeyEvent->charCode)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
nsShortcutCandidate key(ch, PR_FALSE);
|
|
|
|
aCandidates.AppendElement(key);
|
|
|
|
}
|
2008-05-02 14:50:42 +00:00
|
|
|
// If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
|
|
|
|
// this keyboard layout is AZERTY or similar layout, probably.
|
|
|
|
// In this case, Accel+[0-9] should be accessible without shift key.
|
|
|
|
// However, the priority should be lowest.
|
|
|
|
if (!HasASCIIDigit(aCandidates)) {
|
|
|
|
for (PRUint32 i = 0; i < len; ++i) {
|
|
|
|
PRUint32 ch =
|
|
|
|
nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
|
|
|
|
if (ch >= '0' && ch <= '9') {
|
|
|
|
nsShortcutCandidate key(ch, PR_FALSE);
|
|
|
|
aCandidates.AppendElement(key);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-04-15 04:16:24 +00:00
|
|
|
} else {
|
2008-05-02 14:50:42 +00:00
|
|
|
for (PRUint32 i = 0; i < len; ++i) {
|
2008-04-15 04:16:24 +00:00
|
|
|
PRUint32 ch = nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
|
|
|
|
if (!ch)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ch != nativeKeyEvent->charCode) {
|
|
|
|
nsShortcutCandidate key(ch, PR_FALSE);
|
|
|
|
aCandidates.AppendElement(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the char is an alphabet, the shift key state should not be
|
|
|
|
// ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
|
2008-05-12 00:39:29 +00:00
|
|
|
|
2008-04-15 04:16:24 +00:00
|
|
|
// And checking the charCode is same as unshiftedCharCode too.
|
|
|
|
// E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
|
|
|
|
PRUint32 unshiftCh =
|
|
|
|
nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
|
2008-05-12 00:39:29 +00:00
|
|
|
if (CharsCaseInsensitiveEqual(ch, unshiftCh))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// On the Hebrew keyboard layout on Windows, the unshifted char is a
|
|
|
|
// localized character but the shifted char is a Latin alphabet,
|
|
|
|
// then, we should not execute without the shift state. See bug 433192.
|
|
|
|
if (IsCaseChangeableChar(ch))
|
2008-04-15 04:16:24 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Setting the alternative charCode candidates for retry without shift
|
|
|
|
// key state only when the shift key is pressed.
|
|
|
|
nsShortcutCandidate key(ch, PR_TRUE);
|
|
|
|
aCandidates.AppendElement(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PRUint32 charCode;
|
2008-09-16 01:37:13 +00:00
|
|
|
aDOMKeyEvent->GetCharCode(&charCode);
|
2008-04-15 04:16:24 +00:00
|
|
|
if (charCode) {
|
|
|
|
nsShortcutCandidate key(charCode, PR_FALSE);
|
|
|
|
aCandidates.AppendElement(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::GetAccessKeyCandidates(nsKeyEvent* aNativeKeyEvent,
|
|
|
|
nsTArray<PRUint32>& aCandidates)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
|
|
|
|
|
|
|
|
// return the lower cased charCode candidates for access keys.
|
|
|
|
// the priority of the charCodes are:
|
|
|
|
// 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
|
|
|
|
// 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
|
|
|
|
if (aNativeKeyEvent->charCode) {
|
|
|
|
PRUint32 ch = aNativeKeyEvent->charCode;
|
|
|
|
if (IS_IN_BMP(ch))
|
|
|
|
ch = ToLowerCase(PRUnichar(ch));
|
|
|
|
aCandidates.AppendElement(ch);
|
|
|
|
}
|
|
|
|
for (PRUint32 i = 0;
|
|
|
|
i < aNativeKeyEvent->alternativeCharCodes.Length(); ++i) {
|
|
|
|
PRUint32 ch[2] =
|
|
|
|
{ aNativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode,
|
|
|
|
aNativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode };
|
|
|
|
for (PRUint32 j = 0; j < 2; ++j) {
|
|
|
|
if (!ch[j])
|
|
|
|
continue;
|
|
|
|
if (IS_IN_BMP(ch[j]))
|
|
|
|
ch[j] = ToLowerCase(PRUnichar(ch[j]));
|
|
|
|
// Don't append the charCode that was already appended.
|
|
|
|
if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex)
|
|
|
|
aCandidates.AppendElement(ch[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-14 23:08:57 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::AddScriptBlocker()
|
|
|
|
{
|
|
|
|
if (!sScriptBlockerCount) {
|
|
|
|
NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
|
|
|
|
"Should not already have a count");
|
|
|
|
sRunnersCountAtFirstBlocker = sBlockedScriptRunners->Count();
|
|
|
|
}
|
|
|
|
++sScriptBlockerCount;
|
|
|
|
}
|
|
|
|
|
2010-01-11 21:45:20 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::AddScriptBlockerAndPreventAddingRunners()
|
|
|
|
{
|
|
|
|
AddScriptBlocker();
|
|
|
|
if (sScriptBlockerCountWhereRunnersPrevented == 0) {
|
|
|
|
sScriptBlockerCountWhereRunnersPrevented = sScriptBlockerCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-14 23:08:57 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::RemoveScriptBlocker()
|
|
|
|
{
|
2008-04-14 23:59:21 +00:00
|
|
|
NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers");
|
2008-03-14 23:08:57 +00:00
|
|
|
--sScriptBlockerCount;
|
2010-01-11 21:45:20 +00:00
|
|
|
if (sScriptBlockerCount < sScriptBlockerCountWhereRunnersPrevented) {
|
|
|
|
sScriptBlockerCountWhereRunnersPrevented = 0;
|
|
|
|
}
|
2008-03-14 23:08:57 +00:00
|
|
|
if (sScriptBlockerCount) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32 firstBlocker = sRunnersCountAtFirstBlocker;
|
2010-03-12 06:50:12 +00:00
|
|
|
PRUint32 lastBlocker = (PRUint32)sBlockedScriptRunners->Count();
|
2011-04-14 14:18:28 +00:00
|
|
|
PRUint32 originalFirstBlocker = firstBlocker;
|
|
|
|
PRUint32 blockersCount = lastBlocker - firstBlocker;
|
2008-03-14 23:08:57 +00:00
|
|
|
sRunnersCountAtFirstBlocker = 0;
|
|
|
|
NS_ASSERTION(firstBlocker <= lastBlocker,
|
|
|
|
"bad sRunnersCountAtFirstBlocker");
|
|
|
|
|
|
|
|
while (firstBlocker < lastBlocker) {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable = (*sBlockedScriptRunners)[firstBlocker];
|
2011-04-14 14:18:28 +00:00
|
|
|
++firstBlocker;
|
2008-03-14 23:08:57 +00:00
|
|
|
|
|
|
|
runnable->Run();
|
2011-04-14 14:18:28 +00:00
|
|
|
NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
|
2008-03-14 23:08:57 +00:00
|
|
|
"Bad count");
|
|
|
|
NS_ASSERTION(!sScriptBlockerCount, "This is really bad");
|
|
|
|
}
|
2011-04-14 14:18:28 +00:00
|
|
|
sBlockedScriptRunners->RemoveObjectsAt(originalFirstBlocker, blockersCount);
|
2008-03-14 23:08:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable)
|
|
|
|
{
|
|
|
|
if (!aRunnable) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sScriptBlockerCount) {
|
2010-01-11 21:45:20 +00:00
|
|
|
if (sScriptBlockerCountWhereRunnersPrevented > 0) {
|
|
|
|
NS_ERROR("Adding a script runner when that is prevented!");
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2008-03-14 23:08:57 +00:00
|
|
|
return sBlockedScriptRunners->AppendObject(aRunnable);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRunnable> run = aRunnable;
|
|
|
|
run->Run();
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-07-17 03:16:23 +00:00
|
|
|
/*
|
|
|
|
* Helper function for nsContentUtils::ProcessViewportInfo.
|
|
|
|
*
|
|
|
|
* Handles a single key=value pair. If it corresponds to a valid viewport
|
|
|
|
* attribute, add it to the document header data. No validation is done on the
|
|
|
|
* value itself (this is done at display time).
|
|
|
|
*/
|
|
|
|
static void ProcessViewportToken(nsIDocument *aDocument,
|
|
|
|
const nsAString &token) {
|
|
|
|
|
|
|
|
/* Iterators. */
|
|
|
|
nsAString::const_iterator tip, tail, end;
|
|
|
|
token.BeginReading(tip);
|
|
|
|
tail = tip;
|
|
|
|
token.EndReading(end);
|
|
|
|
|
|
|
|
/* Move tip to the '='. */
|
|
|
|
while ((tip != end) && (*tip != '='))
|
|
|
|
++tip;
|
|
|
|
|
|
|
|
/* If we didn't find an '=', punt. */
|
|
|
|
if (tip == end)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Extract the key and value. */
|
2010-11-05 17:27:24 +00:00
|
|
|
const nsAString &key =
|
|
|
|
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(tail, tip),
|
|
|
|
PR_TRUE);
|
|
|
|
const nsAString &value =
|
|
|
|
nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(++tip, end),
|
|
|
|
PR_TRUE);
|
2008-07-17 03:16:23 +00:00
|
|
|
|
|
|
|
/* Check for known keys. If we find a match, insert the appropriate
|
|
|
|
* information into the document header. */
|
|
|
|
nsCOMPtr<nsIAtom> key_atom = do_GetAtom(key);
|
|
|
|
if (key_atom == nsGkAtoms::height)
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport_height, value);
|
|
|
|
else if (key_atom == nsGkAtoms::width)
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport_width, value);
|
|
|
|
else if (key_atom == nsGkAtoms::initial_scale)
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport_initial_scale, value);
|
|
|
|
else if (key_atom == nsGkAtoms::minimum_scale)
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport_minimum_scale, value);
|
|
|
|
else if (key_atom == nsGkAtoms::maximum_scale)
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport_maximum_scale, value);
|
|
|
|
else if (key_atom == nsGkAtoms::user_scalable)
|
|
|
|
aDocument->SetHeaderData(nsGkAtoms::viewport_user_scalable, value);
|
|
|
|
}
|
|
|
|
|
2010-11-05 17:27:24 +00:00
|
|
|
#define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
|
|
|
|
(c == '\t') || (c == '\n') || (c == '\r'))
|
|
|
|
|
2008-07-17 03:16:23 +00:00
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
|
|
|
|
const nsAString &viewportInfo) {
|
|
|
|
|
|
|
|
/* We never fail. */
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
/* Iterators. */
|
|
|
|
nsAString::const_iterator tip, tail, end;
|
|
|
|
viewportInfo.BeginReading(tip);
|
|
|
|
tail = tip;
|
|
|
|
viewportInfo.EndReading(end);
|
|
|
|
|
|
|
|
/* Read the tip to the first non-separator character. */
|
2010-11-05 17:27:24 +00:00
|
|
|
while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
|
2008-07-17 03:16:23 +00:00
|
|
|
++tip;
|
|
|
|
|
2010-05-13 12:19:50 +00:00
|
|
|
/* Read through and find tokens separated by separators. */
|
2008-07-17 03:16:23 +00:00
|
|
|
while (tip != end) {
|
2010-11-05 17:27:24 +00:00
|
|
|
|
2008-07-17 03:16:23 +00:00
|
|
|
/* Synchronize tip and tail. */
|
|
|
|
tail = tip;
|
|
|
|
|
|
|
|
/* Advance tip past non-separator characters. */
|
|
|
|
while ((tip != end) && !IS_SEPARATOR(*tip))
|
|
|
|
++tip;
|
|
|
|
|
2010-11-05 17:27:24 +00:00
|
|
|
/* Allow white spaces that surround the '=' character */
|
|
|
|
if ((tip != end) && (*tip == '=')) {
|
|
|
|
++tip;
|
|
|
|
|
|
|
|
while ((tip != end) && nsCRT::IsAsciiSpace(*tip))
|
|
|
|
++tip;
|
|
|
|
|
|
|
|
while ((tip != end) && !(IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
|
|
|
|
++tip;
|
|
|
|
}
|
|
|
|
|
2008-07-17 03:16:23 +00:00
|
|
|
/* Our token consists of the characters between tail and tip. */
|
|
|
|
ProcessViewportToken(aDocument, Substring(tail, tip));
|
|
|
|
|
|
|
|
/* Skip separators. */
|
2010-11-05 17:27:24 +00:00
|
|
|
while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
|
2008-07-17 03:16:23 +00:00
|
|
|
++tip;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef IS_SEPARATOR
|
|
|
|
|
2008-02-08 20:23:05 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument)
|
|
|
|
{
|
2008-02-24 07:40:39 +00:00
|
|
|
#ifdef MOZ_XUL
|
2008-02-08 20:23:05 +00:00
|
|
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
2009-10-23 20:24:47 +00:00
|
|
|
if (pm && aDocument) {
|
2008-02-08 20:23:05 +00:00
|
|
|
nsCOMPtr<nsISupports> container = aDocument->GetContainer();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellToHide = do_QueryInterface(container);
|
|
|
|
if (docShellToHide)
|
|
|
|
pm->HidePopupsInDocShell(docShellToHide);
|
|
|
|
}
|
2008-02-24 07:40:39 +00:00
|
|
|
#endif
|
2008-02-08 20:23:05 +00:00
|
|
|
}
|
|
|
|
|
2008-08-27 12:07:27 +00:00
|
|
|
/* static */
|
|
|
|
already_AddRefed<nsIDragSession>
|
|
|
|
nsContentUtils::GetDragSession()
|
|
|
|
{
|
|
|
|
nsIDragSession* dragSession = nsnull;
|
|
|
|
nsCOMPtr<nsIDragService> dragService =
|
|
|
|
do_GetService("@mozilla.org/widget/dragservice;1");
|
|
|
|
if (dragService)
|
|
|
|
dragService->GetCurrentSession(&dragSession);
|
|
|
|
return dragSession;
|
|
|
|
}
|
|
|
|
|
2008-03-22 16:50:47 +00:00
|
|
|
/* static */
|
2009-06-24 17:12:33 +00:00
|
|
|
nsresult
|
|
|
|
nsContentUtils::SetDataTransferInEvent(nsDragEvent* aDragEvent)
|
|
|
|
{
|
|
|
|
if (aDragEvent->dataTransfer || !NS_IS_TRUSTED_EVENT(aDragEvent))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// For draggesture and dragstart events, the data transfer object is
|
|
|
|
// created before the event fires, so it should already be set. For other
|
|
|
|
// drag events, get the object from the drag session.
|
|
|
|
NS_ASSERTION(aDragEvent->message != NS_DRAGDROP_GESTURE &&
|
|
|
|
aDragEvent->message != NS_DRAGDROP_START,
|
|
|
|
"draggesture event created without a dataTransfer");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
|
|
|
|
NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
|
|
|
|
dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
|
|
|
|
if (!initialDataTransfer) {
|
|
|
|
// A dataTransfer won't exist when a drag was started by some other
|
|
|
|
// means, for instance calling the drag service directly, or a drag
|
|
|
|
// from another application. In either case, a new dataTransfer should
|
2010-11-24 18:31:24 +00:00
|
|
|
// be created that reflects the data.
|
2009-06-24 17:12:33 +00:00
|
|
|
initialDataTransfer =
|
2010-11-24 18:31:24 +00:00
|
|
|
new nsDOMDataTransfer(aDragEvent->message);
|
2009-06-24 17:12:33 +00:00
|
|
|
NS_ENSURE_TRUE(initialDataTransfer, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
// now set it in the drag session so we don't need to create it again
|
|
|
|
dragSession->SetDataTransfer(initialDataTransfer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// each event should use a clone of the original dataTransfer.
|
|
|
|
nsCOMPtr<nsIDOMNSDataTransfer> initialDataTransferNS =
|
|
|
|
do_QueryInterface(initialDataTransfer);
|
|
|
|
NS_ENSURE_TRUE(initialDataTransferNS, NS_ERROR_FAILURE);
|
|
|
|
initialDataTransferNS->Clone(aDragEvent->message, aDragEvent->userCancelled,
|
|
|
|
getter_AddRefs(aDragEvent->dataTransfer));
|
|
|
|
NS_ENSURE_TRUE(aDragEvent->dataTransfer, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
// for the dragenter and dragover events, initialize the drop effect
|
|
|
|
// from the drop action, which platform specific widget code sets before
|
|
|
|
// the event is fired based on the keyboard state.
|
|
|
|
if (aDragEvent->message == NS_DRAGDROP_ENTER ||
|
|
|
|
aDragEvent->message == NS_DRAGDROP_OVER) {
|
|
|
|
nsCOMPtr<nsIDOMNSDataTransfer> newDataTransfer =
|
|
|
|
do_QueryInterface(aDragEvent->dataTransfer);
|
|
|
|
NS_ENSURE_TRUE(newDataTransfer, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
PRUint32 action, effectAllowed;
|
|
|
|
dragSession->GetDragAction(&action);
|
|
|
|
newDataTransfer->GetEffectAllowedInt(&effectAllowed);
|
|
|
|
newDataTransfer->SetDropEffectInt(FilterDropEffect(action, effectAllowed));
|
|
|
|
}
|
|
|
|
else if (aDragEvent->message == NS_DRAGDROP_DROP ||
|
|
|
|
aDragEvent->message == NS_DRAGDROP_DRAGDROP ||
|
|
|
|
aDragEvent->message == NS_DRAGDROP_END) {
|
|
|
|
// For the drop and dragend events, set the drop effect based on the
|
|
|
|
// last value that the dropEffect had. This will have been set in
|
|
|
|
// nsEventStateManager::PostHandleEvent for the last dragenter or
|
|
|
|
// dragover event.
|
|
|
|
nsCOMPtr<nsIDOMNSDataTransfer> newDataTransfer =
|
|
|
|
do_QueryInterface(aDragEvent->dataTransfer);
|
|
|
|
NS_ENSURE_TRUE(newDataTransfer, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
PRUint32 dropEffect;
|
|
|
|
initialDataTransferNS->GetDropEffectInt(&dropEffect);
|
|
|
|
newDataTransfer->SetDropEffectInt(dropEffect);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
PRUint32
|
|
|
|
nsContentUtils::FilterDropEffect(PRUint32 aAction, PRUint32 aEffectAllowed)
|
|
|
|
{
|
|
|
|
// It is possible for the drag action to include more than one action, but
|
|
|
|
// the widget code which sets the action from the keyboard state should only
|
|
|
|
// be including one. If multiple actions were set, we just consider them in
|
|
|
|
// the following order:
|
|
|
|
// copy, link, move
|
|
|
|
if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
|
|
|
|
aAction = nsIDragService::DRAGDROP_ACTION_COPY;
|
|
|
|
else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
|
|
|
|
aAction = nsIDragService::DRAGDROP_ACTION_LINK;
|
|
|
|
else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
|
|
|
|
aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
|
|
|
|
|
|
|
|
// Filter the action based on the effectAllowed. If the effectAllowed
|
|
|
|
// doesn't include the action, then that action cannot be done, so adjust
|
|
|
|
// the action to something that is allowed. For a copy, adjust to move or
|
|
|
|
// link. For a move, adjust to copy or link. For a link, adjust to move or
|
|
|
|
// link. Otherwise, use none.
|
|
|
|
if (aAction & aEffectAllowed ||
|
|
|
|
aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
|
|
|
|
return aAction;
|
|
|
|
if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
|
|
|
|
return nsIDragService::DRAGDROP_ACTION_MOVE;
|
|
|
|
if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
|
|
|
|
return nsIDragService::DRAGDROP_ACTION_COPY;
|
|
|
|
if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
|
|
|
|
return nsIDragService::DRAGDROP_ACTION_LINK;
|
|
|
|
return nsIDragService::DRAGDROP_ACTION_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
2008-03-22 16:50:47 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::URIIsLocalFile(nsIURI *aURI)
|
|
|
|
{
|
|
|
|
PRBool isFile;
|
|
|
|
nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
|
|
|
|
|
|
|
|
return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
|
|
|
|
nsIProtocolHandler::URI_IS_LOCAL_FILE,
|
|
|
|
&isFile)) &&
|
|
|
|
isFile;
|
|
|
|
}
|
|
|
|
|
2011-03-31 16:35:04 +00:00
|
|
|
nsresult
|
|
|
|
nsContentUtils::SplitURIAtHash(nsIURI *aURI,
|
|
|
|
nsACString &aBeforeHash,
|
|
|
|
nsACString &aAfterHash)
|
|
|
|
{
|
|
|
|
// See bug 225910 for why we can't do this using nsIURL.
|
|
|
|
|
|
|
|
aBeforeHash.Truncate();
|
|
|
|
aAfterHash.Truncate();
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
|
|
|
|
|
|
|
nsCAutoString spec;
|
|
|
|
nsresult rv = aURI->GetSpec(spec);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
PRInt32 index = spec.FindChar('#');
|
|
|
|
if (index == -1) {
|
|
|
|
index = spec.Length();
|
|
|
|
}
|
|
|
|
|
|
|
|
aBeforeHash.Assign(Substring(spec, 0, index));
|
|
|
|
aAfterHash.Assign(Substring(spec, index));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-07-19 15:11:37 +00:00
|
|
|
/* static */
|
2009-04-24 09:18:37 +00:00
|
|
|
nsIScriptContext*
|
2008-07-19 15:11:37 +00:00
|
|
|
nsContentUtils::GetContextForEventHandlers(nsINode* aNode,
|
2009-04-24 09:18:37 +00:00
|
|
|
nsresult* aRv)
|
2008-07-19 15:11:37 +00:00
|
|
|
{
|
2009-04-24 09:18:37 +00:00
|
|
|
*aRv = NS_OK;
|
2008-07-19 15:11:37 +00:00
|
|
|
nsIDocument* ownerDoc = aNode->GetOwnerDoc();
|
2009-04-24 09:18:37 +00:00
|
|
|
if (!ownerDoc) {
|
|
|
|
*aRv = NS_ERROR_UNEXPECTED;
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2008-07-19 15:11:37 +00:00
|
|
|
PRBool hasHadScriptObject = PR_TRUE;
|
2009-04-24 09:18:37 +00:00
|
|
|
nsIScriptGlobalObject* sgo =
|
|
|
|
ownerDoc->GetScriptHandlingObject(hasHadScriptObject);
|
2008-07-19 15:11:37 +00:00
|
|
|
// It is bad if the document doesn't have event handling context,
|
|
|
|
// but it used to have one.
|
2009-04-24 09:18:37 +00:00
|
|
|
if (!sgo && hasHadScriptObject) {
|
|
|
|
*aRv = NS_ERROR_UNEXPECTED;
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2008-07-19 15:11:37 +00:00
|
|
|
if (sgo) {
|
2009-04-24 09:18:37 +00:00
|
|
|
nsIScriptContext* scx = sgo->GetContext();
|
2008-07-19 15:11:37 +00:00
|
|
|
// Bad, no context from script global object!
|
2009-04-24 09:18:37 +00:00
|
|
|
if (!scx) {
|
|
|
|
*aRv = NS_ERROR_UNEXPECTED;
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
return scx;
|
2008-07-19 15:11:37 +00:00
|
|
|
}
|
|
|
|
|
2009-04-24 09:18:37 +00:00
|
|
|
return nsnull;
|
2008-07-19 15:11:37 +00:00
|
|
|
}
|
|
|
|
|
2008-09-05 21:51:24 +00:00
|
|
|
/* static */
|
|
|
|
JSContext *
|
|
|
|
nsContentUtils::GetCurrentJSContext()
|
|
|
|
{
|
|
|
|
JSContext *cx = nsnull;
|
|
|
|
|
|
|
|
sThreadJSContextStack->Peek(&cx);
|
|
|
|
|
|
|
|
return cx;
|
|
|
|
}
|
|
|
|
|
2010-08-02 22:19:04 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::ASCIIToLower(nsAString& aStr)
|
|
|
|
{
|
|
|
|
PRUnichar* iter = aStr.BeginWriting();
|
|
|
|
PRUnichar* end = aStr.EndWriting();
|
|
|
|
while (iter != end) {
|
|
|
|
PRUnichar c = *iter;
|
|
|
|
if (c >= 'A' && c <= 'Z') {
|
|
|
|
*iter = c + ('a' - 'A');
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:38:10 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest)
|
|
|
|
{
|
|
|
|
PRUint32 len = aSource.Length();
|
|
|
|
aDest.SetLength(len);
|
|
|
|
if (aDest.Length() == len) {
|
|
|
|
PRUnichar* dest = aDest.BeginWriting();
|
|
|
|
const PRUnichar* iter = aSource.BeginReading();
|
|
|
|
const PRUnichar* end = aSource.EndReading();
|
|
|
|
while (iter != end) {
|
|
|
|
PRUnichar c = *iter;
|
|
|
|
*dest = (c >= 'A' && c <= 'Z') ?
|
|
|
|
c + ('a' - 'A') : c;
|
|
|
|
++iter;
|
|
|
|
++dest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::ASCIIToUpper(nsAString& aStr)
|
|
|
|
{
|
|
|
|
PRUnichar* iter = aStr.BeginWriting();
|
|
|
|
PRUnichar* end = aStr.EndWriting();
|
|
|
|
while (iter != end) {
|
|
|
|
PRUnichar c = *iter;
|
|
|
|
if (c >= 'a' && c <= 'z') {
|
|
|
|
*iter = c + ('A' - 'a');
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-02 22:19:04 +00:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest)
|
|
|
|
{
|
|
|
|
PRUint32 len = aSource.Length();
|
|
|
|
aDest.SetLength(len);
|
|
|
|
if (aDest.Length() == len) {
|
|
|
|
PRUnichar* dest = aDest.BeginWriting();
|
|
|
|
const PRUnichar* iter = aSource.BeginReading();
|
|
|
|
const PRUnichar* end = aSource.EndReading();
|
|
|
|
while (iter != end) {
|
|
|
|
PRUnichar c = *iter;
|
|
|
|
*dest = (c >= 'a' && c <= 'z') ?
|
|
|
|
c + ('A' - 'a') : c;
|
|
|
|
++iter;
|
|
|
|
++dest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-08 15:45:00 +00:00
|
|
|
PRBool
|
|
|
|
nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
|
|
|
|
const nsAString& aStr2)
|
|
|
|
{
|
|
|
|
PRUint32 len = aStr1.Length();
|
|
|
|
if (len != aStr2.Length()) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PRUnichar* str1 = aStr1.BeginReading();
|
|
|
|
const PRUnichar* str2 = aStr2.BeginReading();
|
|
|
|
const PRUnichar* end = str1 + len;
|
|
|
|
|
|
|
|
while (str1 < end) {
|
|
|
|
PRUnichar c1 = *str1++;
|
|
|
|
PRUnichar c2 = *str2++;
|
|
|
|
|
|
|
|
// First check if any bits other than the 0x0020 differs
|
|
|
|
if ((c1 ^ c2) & 0xffdf) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We know they only differ in the 0x0020 bit.
|
|
|
|
// Likely the two chars are the same, so check that first
|
|
|
|
if (c1 != c2) {
|
|
|
|
// They do differ, but since it's only in the 0x0020 bit, check if it's
|
|
|
|
// the same ascii char, but just differing in case
|
|
|
|
PRUnichar c1Upper = c1 & 0xffdf;
|
|
|
|
if (!('A' <= c1Upper && c1Upper <= 'Z')) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-09-08 01:13:02 +00:00
|
|
|
/* static */
|
|
|
|
nsIInterfaceRequestor*
|
|
|
|
nsContentUtils::GetSameOriginChecker()
|
|
|
|
{
|
|
|
|
if (!sSameOriginChecker) {
|
|
|
|
sSameOriginChecker = new nsSameOriginChecker();
|
|
|
|
NS_IF_ADDREF(sSameOriginChecker);
|
|
|
|
}
|
|
|
|
return sSameOriginChecker;
|
|
|
|
}
|
|
|
|
|
2010-12-03 15:46:10 +00:00
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel)
|
2008-09-08 01:13:02 +00:00
|
|
|
{
|
2010-08-05 02:15:55 +00:00
|
|
|
if (!nsContentUtils::GetSecurityManager())
|
2008-11-26 01:50:04 +00:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2008-09-08 01:13:02 +00:00
|
|
|
|
2008-11-26 01:50:04 +00:00
|
|
|
nsCOMPtr<nsIPrincipal> oldPrincipal;
|
|
|
|
nsContentUtils::GetSecurityManager()->
|
|
|
|
GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
|
2008-09-08 01:13:02 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> newURI;
|
2008-11-26 01:50:04 +00:00
|
|
|
aNewChannel->GetURI(getter_AddRefs(newURI));
|
|
|
|
nsCOMPtr<nsIURI> newOriginalURI;
|
|
|
|
aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
|
2008-09-08 01:13:02 +00:00
|
|
|
|
2008-11-26 01:50:04 +00:00
|
|
|
NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
|
|
|
|
|
|
|
|
nsresult rv = oldPrincipal->CheckMayLoad(newURI, PR_FALSE);
|
|
|
|
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
|
|
|
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
|
|
|
|
}
|
2010-08-05 02:15:55 +00:00
|
|
|
|
2010-12-03 15:46:10 +00:00
|
|
|
return rv;
|
|
|
|
}
|
2010-08-05 02:15:55 +00:00
|
|
|
|
2010-12-03 15:46:10 +00:00
|
|
|
NS_IMPL_ISUPPORTS2(nsSameOriginChecker,
|
|
|
|
nsIChannelEventSink,
|
|
|
|
nsIInterfaceRequestor)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSameOriginChecker::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|
|
|
nsIChannel *aNewChannel,
|
|
|
|
PRUint32 aFlags,
|
|
|
|
nsIAsyncVerifyRedirectCallback *cb)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
|
|
|
|
|
|
|
|
nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
cb->OnRedirectVerifyCallback(NS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
2008-09-08 01:13:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsSameOriginChecker::GetInterface(const nsIID & aIID, void **aResult)
|
|
|
|
{
|
|
|
|
return QueryInterface(aIID, aResult);
|
|
|
|
}
|
|
|
|
|
2009-01-21 22:50:28 +00:00
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal, nsCString& aOrigin)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPrincipal, "missing principal");
|
|
|
|
|
|
|
|
aOrigin.Truncate();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (uri) {
|
|
|
|
return GetASCIIOrigin(uri, aOrigin);
|
|
|
|
}
|
|
|
|
|
|
|
|
aOrigin.AssignLiteral("null");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsCString& aOrigin)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aURI, "missing uri");
|
|
|
|
|
|
|
|
aOrigin.Truncate();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
|
|
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
|
|
|
|
|
|
|
nsCString host;
|
|
|
|
nsresult rv = uri->GetAsciiHost(host);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
|
|
|
|
nsCString scheme;
|
|
|
|
rv = uri->GetScheme(scheme);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
aOrigin = scheme + NS_LITERAL_CSTRING("://") + host;
|
|
|
|
|
|
|
|
// If needed, append the port
|
|
|
|
PRInt32 port;
|
|
|
|
uri->GetPort(&port);
|
|
|
|
if (port != -1) {
|
|
|
|
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
|
|
|
if (port != defaultPort) {
|
|
|
|
aOrigin.Append(':');
|
|
|
|
aOrigin.AppendInt(port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aOrigin.AssignLiteral("null");
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aPrincipal, "missing principal");
|
|
|
|
|
|
|
|
aOrigin.Truncate();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (uri) {
|
|
|
|
return GetUTFOrigin(uri, aOrigin);
|
|
|
|
}
|
|
|
|
|
|
|
|
aOrigin.AssignLiteral("null");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsString& aOrigin)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aURI, "missing uri");
|
|
|
|
|
|
|
|
aOrigin.Truncate();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
|
|
|
|
NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
|
|
|
|
|
|
|
|
nsCString host;
|
|
|
|
nsresult rv = uri->GetHost(host);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
|
|
|
|
nsCString scheme;
|
|
|
|
rv = uri->GetScheme(scheme);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
aOrigin = NS_ConvertUTF8toUTF16(scheme + NS_LITERAL_CSTRING("://") + host);
|
|
|
|
|
|
|
|
// If needed, append the port
|
|
|
|
PRInt32 port;
|
|
|
|
uri->GetPort(&port);
|
|
|
|
if (port != -1) {
|
|
|
|
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
|
|
|
if (port != defaultPort) {
|
|
|
|
aOrigin.Append(':');
|
|
|
|
aOrigin.AppendInt(port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aOrigin.AssignLiteral("null");
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-06-15 08:27:29 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
already_AddRefed<nsIDocument>
|
|
|
|
nsContentUtils::GetDocumentFromScriptContext(nsIScriptContext *aScriptContext)
|
|
|
|
{
|
|
|
|
if (!aScriptContext)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMWindow> window =
|
|
|
|
do_QueryInterface(aScriptContext->GetGlobalObject());
|
|
|
|
nsIDocument *doc = nsnull;
|
|
|
|
if (window) {
|
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc;
|
|
|
|
window->GetDocument(getter_AddRefs(domdoc));
|
|
|
|
if (domdoc) {
|
|
|
|
CallQueryInterface(domdoc, &doc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
|
2010-06-17 11:27:52 +00:00
|
|
|
/* static */
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIURI> channelURI;
|
|
|
|
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
|
|
|
|
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
|
|
|
|
|
|
|
return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, PR_FALSE));
|
|
|
|
}
|
|
|
|
|
2008-12-17 02:11:07 +00:00
|
|
|
nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
|
|
|
|
: mString(aString), mService(nsnull)
|
|
|
|
{
|
|
|
|
CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsContentTypeParser::~nsContentTypeParser()
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(mService);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsContentTypeParser::GetParameter(const char* aParameterName, nsAString& aResult)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(mService, NS_ERROR_FAILURE);
|
|
|
|
return mService->GetParameter(mString, aParameterName,
|
|
|
|
EmptyCString(), PR_FALSE, nsnull,
|
|
|
|
aResult);
|
|
|
|
}
|
2009-06-28 19:46:52 +00:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
|
|
|
|
// If you change this code, change also AllowedToAct() in
|
|
|
|
// XPCSystemOnlyWrapper.cpp!
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::CanAccessNativeAnon()
|
|
|
|
{
|
|
|
|
JSContext* cx = nsnull;
|
|
|
|
sThreadJSContextStack->Peek(&cx);
|
|
|
|
if (!cx) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
JSStackFrame* fp;
|
|
|
|
nsIPrincipal* principal =
|
|
|
|
sSecurityManager->GetCxSubjectPrincipalAndFrame(cx, &fp);
|
|
|
|
NS_ENSURE_TRUE(principal, PR_FALSE);
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
if (!JS_FrameIterator(cx, &fp)) {
|
|
|
|
// No code at all is running. So we must be arriving here as the result
|
|
|
|
// of C++ code asking us to do something. Allow access.
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some code is running, we can't make the assumption, as above, but we
|
|
|
|
// can't use a native frame, so clear fp.
|
|
|
|
fp = nsnull;
|
2010-08-10 05:43:33 +00:00
|
|
|
} else if (!JS_IsScriptFrame(cx, fp)) {
|
2009-08-11 01:07:47 +00:00
|
|
|
fp = nsnull;
|
2009-06-28 19:46:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool privileged;
|
2009-08-07 03:25:13 +00:00
|
|
|
if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(principal, &privileged)) &&
|
2009-06-28 19:46:52 +00:00
|
|
|
privileged) {
|
2009-08-07 03:25:13 +00:00
|
|
|
// Chrome things are allowed to touch us.
|
2009-06-28 19:46:52 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX HACK EWW! Allow chrome://global/ access to these things, even
|
|
|
|
// if they've been cloned into less privileged contexts.
|
|
|
|
static const char prefix[] = "chrome://global/";
|
|
|
|
const char *filename;
|
2010-08-10 05:43:33 +00:00
|
|
|
if (fp && JS_IsScriptFrame(cx, fp) &&
|
|
|
|
(filename = JS_GetFrameScript(cx, fp)->filename) &&
|
2009-06-28 19:46:52 +00:00
|
|
|
!strncmp(filename, prefix, NS_ARRAY_LENGTH(prefix) - 1)) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-08-07 03:25:13 +00:00
|
|
|
// Before we throw, check for UniversalXPConnect.
|
|
|
|
nsresult rv = sSecurityManager->IsCapabilityEnabled("UniversalXPConnect", &privileged);
|
|
|
|
if (NS_SUCCEEDED(rv) && privileged) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-06-28 19:46:52 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2009-06-30 07:56:40 +00:00
|
|
|
|
|
|
|
/* static */ nsresult
|
|
|
|
nsContentUtils::DispatchXULCommand(nsIContent* aTarget,
|
|
|
|
PRBool aTrusted,
|
|
|
|
nsIDOMEvent* aSourceEvent,
|
|
|
|
nsIPresShell* aShell,
|
|
|
|
PRBool aCtrl,
|
|
|
|
PRBool aAlt,
|
|
|
|
PRBool aShift,
|
|
|
|
PRBool aMeta)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(aTarget);
|
|
|
|
nsIDocument* doc = aTarget->GetOwnerDoc();
|
2011-05-23 16:46:36 +00:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
|
|
|
|
NS_ENSURE_STATE(domDoc);
|
2009-06-30 07:56:40 +00:00
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
2011-05-23 16:46:36 +00:00
|
|
|
domDoc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"),
|
|
|
|
getter_AddRefs(event));
|
2009-06-30 07:56:40 +00:00
|
|
|
nsCOMPtr<nsIDOMXULCommandEvent> xulCommand = do_QueryInterface(event);
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> pEvent = do_QueryInterface(xulCommand);
|
|
|
|
NS_ENSURE_STATE(pEvent);
|
|
|
|
nsresult rv = xulCommand->InitCommandEvent(NS_LITERAL_STRING("command"),
|
2011-04-24 06:54:25 +00:00
|
|
|
PR_TRUE, PR_TRUE, doc->GetWindow(),
|
2009-06-30 07:56:40 +00:00
|
|
|
0, aCtrl, aAlt, aShift, aMeta,
|
|
|
|
aSourceEvent);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (aShell) {
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsCOMPtr<nsIPresShell> kungFuDeathGrip = aShell;
|
|
|
|
return aShell->HandleDOMEventWithTarget(aTarget, event, &status);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aTarget);
|
|
|
|
NS_ENSURE_STATE(target);
|
|
|
|
PRBool dummy;
|
|
|
|
return target->DispatchEvent(event, &dummy);
|
|
|
|
}
|
2009-08-14 19:00:24 +00:00
|
|
|
|
|
|
|
// static
|
|
|
|
nsresult
|
2010-09-15 05:27:02 +00:00
|
|
|
nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
|
|
|
|
nsWrapperCache *cache, const nsIID* aIID, jsval *vp,
|
|
|
|
nsIXPConnectJSObjectHolder **aHolder,
|
|
|
|
PRBool aAllowWrapping)
|
2009-08-14 19:00:24 +00:00
|
|
|
{
|
2010-09-15 05:27:02 +00:00
|
|
|
if (!native) {
|
|
|
|
NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
|
|
|
|
|
|
|
|
*vp = JSVAL_NULL;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-03-23 14:45:21 +00:00
|
|
|
JSObject *wrapper = xpc_FastGetCachedWrapper(cache, scope, vp);
|
2010-08-28 08:04:25 +00:00
|
|
|
if (wrapper) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-08-14 19:00:24 +00:00
|
|
|
NS_ENSURE_TRUE(sXPConnect && sThreadJSContextStack, NS_ERROR_UNEXPECTED);
|
|
|
|
|
2010-02-24 01:44:52 +00:00
|
|
|
// Keep sXPConnect and sThreadJSContextStack alive. If we're on the main
|
|
|
|
// thread then this can be done simply and cheaply by adding a reference to
|
|
|
|
// nsLayoutStatics. If we're not on the main thread then we need to add a
|
|
|
|
// more expensive reference sXPConnect directly. We have to use manual
|
|
|
|
// AddRef and Release calls so don't early-exit from this function after we've
|
|
|
|
// added the reference!
|
|
|
|
PRBool isMainThread = NS_IsMainThread();
|
|
|
|
|
|
|
|
if (isMainThread) {
|
|
|
|
nsLayoutStatics::AddRef();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sXPConnect->AddRef();
|
|
|
|
}
|
2009-08-14 19:00:24 +00:00
|
|
|
|
|
|
|
JSContext *topJSContext;
|
|
|
|
nsresult rv = sThreadJSContextStack->Peek(&topJSContext);
|
2010-02-24 01:44:52 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
PRBool push = topJSContext != cx;
|
|
|
|
if (push) {
|
|
|
|
rv = sThreadJSContextStack->Push(cx);
|
|
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2010-05-10 18:53:05 +00:00
|
|
|
rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
|
2010-02-24 01:44:52 +00:00
|
|
|
aAllowWrapping, vp, aHolder);
|
|
|
|
if (push) {
|
|
|
|
sThreadJSContextStack->Pop(nsnull);
|
|
|
|
}
|
|
|
|
}
|
2009-08-14 19:00:24 +00:00
|
|
|
}
|
|
|
|
|
2010-02-24 01:44:52 +00:00
|
|
|
if (isMainThread) {
|
|
|
|
nsLayoutStatics::Release();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sXPConnect->Release();
|
2009-08-14 19:00:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
2009-10-30 01:48:38 +00:00
|
|
|
|
2010-03-03 12:41:57 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
|
|
|
|
{
|
|
|
|
// In common cases where we don't have nulls in the
|
|
|
|
// string we can simple simply bypass the checking code.
|
|
|
|
PRInt32 firstNullPos = aInStr.FindChar('\0');
|
|
|
|
if (firstNullPos == kNotFound) {
|
|
|
|
aOutStr.Assign(aInStr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aOutStr.SetCapacity(aInStr.Length() - 1);
|
|
|
|
nsAString::const_iterator start, end;
|
|
|
|
aInStr.BeginReading(start);
|
|
|
|
aInStr.EndReading(end);
|
|
|
|
while (start != end) {
|
|
|
|
if (*start != '\0')
|
|
|
|
aOutStr.Append(*start);
|
|
|
|
++start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-19 15:40:15 +00:00
|
|
|
struct ClassMatchingInfo {
|
2010-08-11 21:05:28 +00:00
|
|
|
nsAttrValue::AtomArray mClasses;
|
2010-04-19 15:40:15 +00:00
|
|
|
nsCaseTreatment mCaseTreatment;
|
|
|
|
};
|
|
|
|
|
2010-04-19 15:41:37 +00:00
|
|
|
static PRBool
|
|
|
|
MatchClassNames(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom,
|
|
|
|
void* aData)
|
2010-04-19 15:40:15 +00:00
|
|
|
{
|
|
|
|
// We can't match if there are no class names
|
|
|
|
const nsAttrValue* classAttr = aContent->GetClasses();
|
|
|
|
if (!classAttr) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// need to match *all* of the classes
|
|
|
|
ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
|
2010-08-11 21:05:28 +00:00
|
|
|
PRUint32 length = info->mClasses.Length();
|
2010-06-08 19:58:26 +00:00
|
|
|
if (!length) {
|
|
|
|
// If we actually had no classes, don't match.
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2010-08-11 21:05:28 +00:00
|
|
|
PRUint32 i;
|
2010-04-19 15:40:15 +00:00
|
|
|
for (i = 0; i < length; ++i) {
|
2010-08-11 21:05:28 +00:00
|
|
|
if (!classAttr->Contains(info->mClasses[i],
|
2010-04-19 15:40:15 +00:00
|
|
|
info->mCaseTreatment)) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-04-19 15:41:37 +00:00
|
|
|
static void
|
|
|
|
DestroyClassNameArray(void* aData)
|
2010-04-19 15:40:15 +00:00
|
|
|
{
|
|
|
|
ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
|
|
|
|
delete info;
|
|
|
|
}
|
|
|
|
|
2010-06-08 19:58:26 +00:00
|
|
|
static void*
|
|
|
|
AllocClassMatchingInfo(nsINode* aRootNode,
|
|
|
|
const nsString* aClasses)
|
2010-04-19 15:40:15 +00:00
|
|
|
{
|
|
|
|
nsAttrValue attrValue;
|
2010-06-08 19:58:26 +00:00
|
|
|
attrValue.ParseAtomArray(*aClasses);
|
2010-04-19 15:40:15 +00:00
|
|
|
// nsAttrValue::Equals is sensitive to order, so we'll send an array
|
|
|
|
ClassMatchingInfo* info = new ClassMatchingInfo;
|
2010-06-08 19:58:26 +00:00
|
|
|
NS_ENSURE_TRUE(info, nsnull);
|
2010-04-19 15:40:15 +00:00
|
|
|
|
|
|
|
if (attrValue.Type() == nsAttrValue::eAtomArray) {
|
2010-08-11 21:05:28 +00:00
|
|
|
info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
|
2010-04-19 15:40:15 +00:00
|
|
|
} else if (attrValue.Type() == nsAttrValue::eAtom) {
|
2010-08-11 21:05:28 +00:00
|
|
|
info->mClasses.AppendElement(attrValue.GetAtomValue());
|
2010-04-19 15:40:15 +00:00
|
|
|
}
|
|
|
|
|
2010-06-08 19:58:26 +00:00
|
|
|
info->mCaseTreatment =
|
2010-07-22 21:33:37 +00:00
|
|
|
aRootNode->GetOwnerDoc() &&
|
2010-06-08 19:58:26 +00:00
|
|
|
aRootNode->GetOwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
|
|
|
|
eIgnoreCase : eCaseMatters;
|
|
|
|
return info;
|
|
|
|
}
|
2010-04-19 15:40:15 +00:00
|
|
|
|
2010-06-08 19:58:26 +00:00
|
|
|
// static
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsContentUtils::GetElementsByClassName(nsINode* aRootNode,
|
|
|
|
const nsAString& aClasses,
|
|
|
|
nsIDOMNodeList** aReturn)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aRootNode, "Must have root node");
|
|
|
|
|
|
|
|
nsContentList* elements =
|
|
|
|
NS_GetFuncStringContentList(aRootNode, MatchClassNames,
|
|
|
|
DestroyClassNameArray,
|
|
|
|
AllocClassMatchingInfo,
|
|
|
|
aClasses).get();
|
|
|
|
NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY);
|
2010-04-19 15:40:15 +00:00
|
|
|
|
|
|
|
// Transfer ownership
|
|
|
|
*aReturn = elements;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-29 08:32:39 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DebugWrapperTraversalCallback(void* aWrapper) : mFound(PR_FALSE),
|
|
|
|
mWrapper(aWrapper)
|
|
|
|
{
|
|
|
|
mFlags = WANT_ALL_TRACES;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD_(void) DescribeNode(CCNodeType type,
|
|
|
|
nsrefcnt refcount,
|
|
|
|
size_t objsz,
|
|
|
|
const char* objname)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHOD_(void) NoteRoot(PRUint32 langID, void* root,
|
|
|
|
nsCycleCollectionParticipant* helper)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void* child)
|
|
|
|
{
|
|
|
|
if (langID == nsIProgrammingLanguage::JAVASCRIPT) {
|
|
|
|
mFound = child == mWrapper;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
NS_IMETHOD_(void) NoteNativeChild(void* child,
|
|
|
|
nsCycleCollectionParticipant* helper)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD_(void) NoteNextEdgeName(const char* name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool mFound;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void* mWrapper;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2011-02-02 15:30:03 +00:00
|
|
|
DebugWrapperTraceCallback(PRUint32 langID, void *p, const char *name,
|
|
|
|
void *closure)
|
2009-11-29 08:32:39 +00:00
|
|
|
{
|
|
|
|
DebugWrapperTraversalCallback* callback =
|
|
|
|
static_cast<DebugWrapperTraversalCallback*>(closure);
|
|
|
|
callback->NoteScriptChild(langID, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
|
|
|
nsContentUtils::CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
|
|
|
|
nsWrapperCache* aCache)
|
|
|
|
{
|
|
|
|
nsXPCOMCycleCollectionParticipant* participant;
|
|
|
|
CallQueryInterface(aScriptObjectHolder, &participant);
|
|
|
|
|
|
|
|
DebugWrapperTraversalCallback callback(aCache->GetWrapper());
|
|
|
|
|
|
|
|
participant->Traverse(aScriptObjectHolder, callback);
|
|
|
|
NS_ASSERTION(callback.mFound,
|
|
|
|
"Cycle collection participant didn't traverse to preserved "
|
|
|
|
"wrapper! This will probably crash.");
|
|
|
|
|
|
|
|
callback.mFound = PR_FALSE;
|
|
|
|
participant->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback);
|
|
|
|
NS_ASSERTION(callback.mFound,
|
|
|
|
"Cycle collection participant didn't trace preserved wrapper! "
|
|
|
|
"This will probably crash.");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-04-21 20:17:41 +00:00
|
|
|
// static
|
|
|
|
PRBool
|
2010-10-07 19:19:32 +00:00
|
|
|
nsContentUtils::IsFocusedContent(const nsIContent* aContent)
|
2010-04-21 20:17:41 +00:00
|
|
|
{
|
|
|
|
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
|
|
|
|
return fm && fm->GetFocusedContent() == aContent;
|
|
|
|
}
|
|
|
|
|
2010-10-08 10:20:20 +00:00
|
|
|
bool
|
|
|
|
nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
nsIDocument* doc = aContent->GetCurrentDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXXbz should this use GetOwnerDoc() for GetSubDocumentFor?
|
|
|
|
// sXBL/XBL2 issue!
|
|
|
|
nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
|
|
|
|
if (!subDoc) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> container = subDoc->GetContainer();
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
|
|
|
|
if (!docShell) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContentViewer> contentViewer;
|
|
|
|
docShell->GetContentViewer(getter_AddRefs(contentViewer));
|
|
|
|
if (!contentViewer) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContentViewer> zombieViewer;
|
|
|
|
contentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
|
|
|
|
|
|
|
|
// If there are 2 viewers for the current docshell, that
|
|
|
|
// means the current document is a zombie document.
|
|
|
|
// Only navigate into the subdocument if it's not a zombie.
|
|
|
|
return !zombieViewer;
|
|
|
|
}
|
|
|
|
|
2010-11-03 12:57:15 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::FlushLayoutForTree(nsIDOMWindow* aWindow)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
|
|
|
|
if (!piWin)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Note that because FlushPendingNotifications flushes parents, this
|
|
|
|
// is O(N^2) in docshell tree depth. However, the docshell tree is
|
|
|
|
// usually pretty shallow.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
|
|
aWindow->GetDocument(getter_AddRefs(domDoc));
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
|
|
|
if (doc) {
|
|
|
|
doc->FlushPendingNotifications(Flush_Layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeNode> node =
|
|
|
|
do_QueryInterface(piWin->GetDocShell());
|
|
|
|
if (node) {
|
|
|
|
PRInt32 i = 0, i_end;
|
|
|
|
node->GetChildCount(&i_end);
|
|
|
|
for (; i < i_end; ++i) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> item;
|
|
|
|
node->GetChildAt(i, getter_AddRefs(item));
|
|
|
|
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
|
|
|
|
if (win) {
|
|
|
|
FlushLayoutForTree(win);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-23 00:15:56 +00:00
|
|
|
void nsContentUtils::RemoveNewlines(nsString &aString)
|
|
|
|
{
|
|
|
|
// strip CR/LF and null
|
|
|
|
static const char badChars[] = {'\r', '\n', 0};
|
|
|
|
aString.StripChars(badChars);
|
|
|
|
}
|
|
|
|
|
2010-05-18 04:04:22 +00:00
|
|
|
void
|
|
|
|
nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
|
2010-02-23 00:15:56 +00:00
|
|
|
{
|
|
|
|
if (aString.FindChar(PRUnichar('\r')) != -1) {
|
|
|
|
// Windows linebreaks: Map CRLF to LF:
|
|
|
|
aString.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
|
|
|
|
NS_LITERAL_STRING("\n").get());
|
|
|
|
|
|
|
|
// Mac linebreaks: Map any remaining CR to LF:
|
|
|
|
aString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
|
|
|
|
NS_LITERAL_STRING("\n").get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-07 02:05:52 +00:00
|
|
|
static already_AddRefed<LayerManager>
|
2011-03-02 08:53:27 +00:00
|
|
|
LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
|
|
|
|
bool* aAllowRetaining)
|
2010-05-18 04:04:22 +00:00
|
|
|
{
|
|
|
|
nsIDocument* doc = aDoc;
|
|
|
|
nsIDocument* displayDoc = doc->GetDisplayDocument();
|
|
|
|
if (displayDoc) {
|
|
|
|
doc = displayDoc;
|
|
|
|
}
|
|
|
|
|
2010-06-25 13:59:57 +00:00
|
|
|
nsIPresShell* shell = doc->GetShell();
|
2010-05-18 04:04:22 +00:00
|
|
|
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
|
|
|
|
while (!shell && docShellTreeItem) {
|
|
|
|
// We may be in a display:none subdocument, or we may not have a presshell
|
|
|
|
// created yet.
|
|
|
|
// Walk the docshell tree to find the nearest container that has a presshell,
|
|
|
|
// and find the root widget from that.
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
docShell->GetPresShell(getter_AddRefs(presShell));
|
|
|
|
if (presShell) {
|
|
|
|
shell = presShell;
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parent;
|
|
|
|
docShellTreeItem->GetParent(getter_AddRefs(parent));
|
|
|
|
docShellTreeItem = parent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shell) {
|
2011-03-01 16:15:23 +00:00
|
|
|
nsIViewManager* VM = shell->GetViewManager();
|
|
|
|
if (VM) {
|
2011-03-30 02:24:54 +00:00
|
|
|
nsIView* rootView = VM->GetRootView();
|
|
|
|
if (rootView) {
|
2011-05-30 03:15:00 +00:00
|
|
|
nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
|
2011-03-01 16:15:23 +00:00
|
|
|
if (displayRoot) {
|
|
|
|
nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
|
|
|
|
if (widget) {
|
|
|
|
nsRefPtr<LayerManager> manager =
|
2011-03-25 15:03:35 +00:00
|
|
|
widget->
|
|
|
|
GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
|
|
|
|
nsIWidget::LAYER_MANAGER_CURRENT,
|
2011-03-02 08:53:27 +00:00
|
|
|
aAllowRetaining);
|
2011-03-01 16:15:23 +00:00
|
|
|
return manager.forget();
|
|
|
|
}
|
|
|
|
}
|
2010-05-18 04:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-01 16:15:23 +00:00
|
|
|
return nsnull;
|
2010-05-18 04:04:22 +00:00
|
|
|
}
|
|
|
|
|
2010-12-07 02:05:52 +00:00
|
|
|
already_AddRefed<LayerManager>
|
2011-03-02 08:53:27 +00:00
|
|
|
nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
|
2010-12-07 02:05:52 +00:00
|
|
|
{
|
2011-03-02 08:53:27 +00:00
|
|
|
return LayerManagerForDocumentInternal(aDoc, false, aAllowRetaining);
|
2010-12-07 02:05:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<LayerManager>
|
2011-03-02 08:53:27 +00:00
|
|
|
nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
|
2010-12-07 02:05:52 +00:00
|
|
|
{
|
2011-03-02 08:53:27 +00:00
|
|
|
return LayerManagerForDocumentInternal(aDoc, true, aAllowRetaining);
|
2010-12-07 02:05:52 +00:00
|
|
|
}
|
|
|
|
|
2010-11-23 08:50:55 +00:00
|
|
|
bool
|
|
|
|
nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
|
|
|
|
{
|
|
|
|
if (IsSystemPrincipal(aPrincipal)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> princURI;
|
|
|
|
aPrincipal->GetURI(getter_AddRefs(princURI));
|
|
|
|
|
|
|
|
return princURI &&
|
|
|
|
((sAllowXULXBL_for_file && SchemeIs(princURI, "file")) ||
|
|
|
|
IsSitePermAllow(princURI, "allowXULXBL"));
|
|
|
|
}
|
2010-05-18 04:04:22 +00:00
|
|
|
|
2010-06-10 16:42:16 +00:00
|
|
|
already_AddRefed<nsIDocumentLoaderFactory>
|
2011-04-14 20:58:36 +00:00
|
|
|
nsContentUtils::FindInternalContentViewer(const char* aType,
|
|
|
|
ContentViewerType* aLoaderType)
|
2010-06-10 16:42:16 +00:00
|
|
|
{
|
|
|
|
if (aLoaderType) {
|
|
|
|
*aLoaderType = TYPE_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// one helper factory, please
|
|
|
|
nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
|
|
|
|
if (!catMan)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
|
|
|
|
|
|
|
|
nsXPIDLCString contractID;
|
|
|
|
nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, getter_Copies(contractID));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
docFactory = do_GetService(contractID);
|
|
|
|
if (docFactory && aLoaderType) {
|
2010-06-29 20:56:13 +00:00
|
|
|
if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID))
|
|
|
|
*aLoaderType = TYPE_CONTENT;
|
|
|
|
else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID))
|
|
|
|
*aLoaderType = TYPE_PLUGIN;
|
|
|
|
else
|
|
|
|
*aLoaderType = TYPE_UNKNOWN;
|
2011-04-14 20:58:36 +00:00
|
|
|
}
|
2010-06-10 16:42:16 +00:00
|
|
|
return docFactory.forget();
|
|
|
|
}
|
|
|
|
|
2010-06-21 16:46:26 +00:00
|
|
|
#ifdef MOZ_MEDIA
|
|
|
|
#ifdef MOZ_OGG
|
2010-06-10 18:11:11 +00:00
|
|
|
if (nsHTMLMediaElement::IsOggEnabled()) {
|
2010-08-06 11:04:32 +00:00
|
|
|
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(nsHTMLMediaElement::gOggTypes); ++i) {
|
2010-06-10 18:11:11 +00:00
|
|
|
const char* type = nsHTMLMediaElement::gOggTypes[i];
|
|
|
|
if (!strcmp(aType, type)) {
|
|
|
|
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
|
|
|
if (docFactory && aLoaderType) {
|
|
|
|
*aLoaderType = TYPE_CONTENT;
|
|
|
|
}
|
|
|
|
return docFactory.forget();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-21 16:46:26 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MOZ_WEBM
|
|
|
|
if (nsHTMLMediaElement::IsWebMEnabled()) {
|
2010-08-06 11:04:32 +00:00
|
|
|
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(nsHTMLMediaElement::gWebMTypes); ++i) {
|
2010-06-21 16:46:26 +00:00
|
|
|
const char* type = nsHTMLMediaElement::gWebMTypes[i];
|
|
|
|
if (!strcmp(aType, type)) {
|
|
|
|
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
|
|
|
|
if (docFactory && aLoaderType) {
|
|
|
|
*aLoaderType = TYPE_CONTENT;
|
|
|
|
}
|
|
|
|
return docFactory.forget();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // MOZ_MEDIA
|
2010-06-10 18:11:11 +00:00
|
|
|
|
2010-06-10 16:42:16 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2011-04-28 17:21:37 +00:00
|
|
|
|
|
|
|
// static
|
|
|
|
PRBool
|
|
|
|
nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
|
|
|
nsIDocument* aDocument)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
|
|
|
|
NS_ENSURE_TRUE(aDocument->GetScriptGlobalObject(), PR_TRUE);
|
|
|
|
|
|
|
|
JSContext* ctx = (JSContext*) aDocument->GetScriptGlobalObject()->
|
|
|
|
GetContext()->GetNativeContext();
|
|
|
|
NS_ENSURE_TRUE(ctx, PR_TRUE);
|
|
|
|
|
|
|
|
JSAutoRequest ar(ctx);
|
|
|
|
|
|
|
|
// The pattern has to match the entire value.
|
|
|
|
aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0);
|
|
|
|
aPattern.Append(NS_LITERAL_STRING(")$"));
|
|
|
|
|
|
|
|
JSObject* re = JS_NewUCRegExpObjectNoStatics(ctx, reinterpret_cast<jschar*>
|
|
|
|
(aPattern.BeginWriting()),
|
|
|
|
aPattern.Length(), 0);
|
|
|
|
NS_ENSURE_TRUE(re, PR_TRUE);
|
|
|
|
|
|
|
|
jsval rval = JSVAL_NULL;
|
|
|
|
size_t idx = 0;
|
|
|
|
JSBool res;
|
|
|
|
|
|
|
|
res = JS_ExecuteRegExpNoStatics(ctx, re, reinterpret_cast<jschar*>
|
|
|
|
(aValue.BeginWriting()),
|
|
|
|
aValue.Length(), &idx, JS_TRUE, &rval);
|
|
|
|
|
|
|
|
return res == JS_FALSE || rval != JSVAL_NULL;
|
|
|
|
}
|