Exemplo n.º 1
0
nsresult
EventSource::SetupHttpChannel()
{
  mHttpChannel->SetRequestMethod(NS_LITERAL_CSTRING("GET"));

  /* set the http request headers */

  mHttpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
    NS_LITERAL_CSTRING(TEXT_EVENT_STREAM), false);

  // LOAD_BYPASS_CACHE already adds the Cache-Control: no-cache header

  if (!mLastEventID.IsEmpty()) {
    mHttpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Last-Event-ID"),
      NS_ConvertUTF16toUTF8(mLastEventID), false);
  }

  nsCOMPtr<nsIURI> codebase;
  nsresult rv = GetBaseURI(getter_AddRefs(codebase));
  if (NS_SUCCEEDED(rv)) {
    rv = mHttpChannel->SetReferrerWithPolicy(codebase, this->GetReferrerPolicy());
    NS_ENSURE_SUCCESS(rv, rv);
  }

  return NS_OK;
}
Exemplo n.º 2
0
/*
 * This is a utility function.  It will only fail if it can't get a
 * parser.  This means it can return NS_OK without aURI or aCSSLoader
 * being initialized.
 */
nsresult
nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIURI** aSheetURI,
                                                       nsIURI** aBaseURI,
                                                       nsIPrincipal** aSheetPrincipal,
                                                       mozilla::css::Loader** aCSSLoader)
{
  NS_ASSERTION(mElement, "Something is severely broken -- there should be an Element here!");
  // null out the out params since some of them may not get initialized below
  *aSheetURI = nsnull;
  *aBaseURI = nsnull;
  *aSheetPrincipal = nsnull;
  *aCSSLoader = nsnull;

  nsIDocument* doc = mElement->GetOwnerDoc();
  if (!doc) {
    // document has been destroyed
    return NS_ERROR_NOT_AVAILABLE;
  }

  nsCOMPtr<nsIURI> baseURI = mElement->GetBaseURI();
  nsCOMPtr<nsIURI> sheetURI = doc->GetDocumentURI();

  NS_ADDREF(*aCSSLoader = doc->CSSLoader());

  baseURI.swap(*aBaseURI);
  sheetURI.swap(*aSheetURI);
  NS_ADDREF(*aSheetPrincipal = mElement->NodePrincipal());

  return NS_OK;
}
void
SVGMPathElement::UpdateHrefTarget(nsIContent* aParent,
                                  const nsAString& aHrefStr)
{
  nsCOMPtr<nsIURI> targetURI;
  nsCOMPtr<nsIURI> baseURI = GetBaseURI();
  nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI),
                                            aHrefStr, OwnerDoc(), baseURI);

  // Stop observing old target (if any)
  if (mHrefTarget.get()) {
    mHrefTarget.get()->RemoveMutationObserver(this);
  }

  if (aParent) {
    // Pass in |aParent| instead of |this| -- first argument is only used
    // for a call to GetCurrentDoc(), and |this| might not have a current
    // document yet (if our caller is BindToTree).
    mHrefTarget.Reset(aParent, targetURI);
  } else {
    // if we don't have a parent, then there's no animateMotion element
    // depending on our target, so there's no point tracking it right now.
    mHrefTarget.Unlink();
  }

  // Start observing new target (if any)
  if (mHrefTarget.get()) {
    mHrefTarget.get()->AddMutationObserver(this);
  }

  NotifyParentOfMpathChange(aParent);
}
NS_IMETHODIMP
WebBrowserPersistLocalDocument::GetBaseURI(nsACString& aURISpec) {
  nsCOMPtr<nsIURI> uri = GetBaseURI();
  if (!uri) {
    return NS_ERROR_UNEXPECTED;
  }
  return uri->GetSpec(aURISpec);
}
void
SVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext,
                                      const nsAString& aHrefStr)
{
  nsCOMPtr<nsIURI> targetURI;
  nsCOMPtr<nsIURI> baseURI = GetBaseURI();
  nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI),
                                            aHrefStr, OwnerDoc(), baseURI);
  mHrefTarget.Reset(aNodeForContext, targetURI);
  AnimationTargetChanged();
}
void
nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
{
  NS_ASSERTION(mElement, "Something is severely broken -- there should be an Element here!");

  nsIDocument* doc = mElement->OwnerDoc();
  aCSSParseEnv.mSheetURI = doc->GetDocumentURI();
  aCSSParseEnv.mBaseURI = mElement->GetBaseURI();
  aCSSParseEnv.mPrincipal = mElement->NodePrincipal();
  aCSSParseEnv.mCSSLoader = doc->CSSLoader();
}
Exemplo n.º 7
0
bool
SVGAElement::IsLink(nsIURI** aURI) const
{
  // To be a clickable XLink for styling and interaction purposes, we require:
  //
  //   xlink:href    - must be set
  //   xlink:type    - must be unset or set to "" or set to "simple"
  //   xlink:show    - must be unset or set to "", "new" or "replace"
  //   xlink:actuate - must be unset or set to "" or "onRequest"
  //
  // For any other values, we're either not a *clickable* XLink, or the end
  // result is poorly specified. Either way, we return false.

  static nsIContent::AttrValuesArray sTypeVals[] =
    { &nsGkAtoms::_empty, &nsGkAtoms::simple, nullptr };

  static nsIContent::AttrValuesArray sShowVals[] =
    { &nsGkAtoms::_empty, &nsGkAtoms::_new, &nsGkAtoms::replace, nullptr };

  static nsIContent::AttrValuesArray sActuateVals[] =
    { &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nullptr };

  // Optimization: check for href first for early return
  bool useXLink = !HasAttr(kNameSpaceID_None, nsGkAtoms::href);
  const nsAttrValue* href =
    useXLink
    ? mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_XLink)
    : mAttrsAndChildren.GetAttr(nsGkAtoms::href, kNameSpaceID_None);

  if (href &&
      FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::type,
                      sTypeVals, eCaseMatters) !=
                      nsIContent::ATTR_VALUE_NO_MATCH &&
      FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
                      sShowVals, eCaseMatters) !=
                      nsIContent::ATTR_VALUE_NO_MATCH &&
      FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::actuate,
                      sActuateVals, eCaseMatters) !=
                      nsIContent::ATTR_VALUE_NO_MATCH) {
    nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    // Get absolute URI
    nsAutoString str;
    const uint8_t idx = useXLink ? XLINK_HREF : HREF;
    mStringAttributes[idx].GetAnimValue(str, this);
    nsContentUtils::NewURIWithDocumentCharset(aURI, str, OwnerDoc(), baseURI);
    // must promise out param is non-null if we return true
    return !!*aURI;
  }

  *aURI = nullptr;
  return false;
}
Exemplo n.º 8
0
nsresult CViewSourceHTML::CreateViewSourceURL(const nsAString& linkUrl,
                                              nsString& viewSourceUrl) {
  nsCOMPtr<nsIURI> baseURI;
  nsCOMPtr<nsIURI> hrefURI;
  nsresult rv;

  // Default the view source URL to the empty string in case we fail.
  viewSourceUrl.Truncate();

  // Get the BaseURI.
  rv = GetBaseURI(getter_AddRefs(baseURI));
  NS_ENSURE_SUCCESS(rv, rv);

  // Use the link URL and the base URI to build a URI for the link.  Note that
  // the link URL may have untranslated entities in it.
  nsAutoString expandedLinkUrl;
  ExpandEntities(linkUrl, expandedLinkUrl);
  rv = NS_NewURI(getter_AddRefs(hrefURI), expandedLinkUrl, mCharset.get(), baseURI);
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the absolute URL from the link URI.
  nsCString absoluteLinkUrl;
  hrefURI->GetSpec(absoluteLinkUrl);

  // URLs that execute script (e.g. "javascript:" URLs) should just be
  // ignored.  There's nothing reasonable we can do with them, and allowing
  // them to execute in the context of the view-source window presents a
  // security risk.  Just return the empty string in this case.
  PRBool openingExecutesScript = PR_FALSE;
  rv = NS_URIChainHasFlags(hrefURI, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT,
                           &openingExecutesScript);
  NS_ENSURE_SUCCESS(rv, NS_OK); // if there's an error, return the empty string
  if (openingExecutesScript) {
    return NS_OK;
  }

  // URLs that return data (e.g. "http:" URLs) should be prefixed with
  // "view-source:".  URLs that don't return data should just be returned
  // undecorated.
  PRBool doesNotReturnData = PR_FALSE;
  rv = NS_URIChainHasFlags(hrefURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
                           &doesNotReturnData);
  NS_ENSURE_SUCCESS(rv, NS_OK);  // if there's an error, return the empty string
  if (!doesNotReturnData) {
    viewSourceUrl.AssignLiteral("view-source:");    
  }

  viewSourceUrl.AppendWithConversion(absoluteLinkUrl);

  return NS_OK;
}
Exemplo n.º 9
0
void
SVGScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
{
  if (mFrozen) {
    return;
  }

  if (mStringAttributes[HREF].IsExplicitlySet() ||
      mStringAttributes[XLINK_HREF].IsExplicitlySet()) {
    // variation of this code in nsHTMLScriptElement - check if changes
    // need to be transferred when modifying
    bool isHref = false;
    nsAutoString src;
    if (mStringAttributes[HREF].IsExplicitlySet()) {
      mStringAttributes[HREF].GetAnimValue(src, this);
      isHref = true;
    } else {
      mStringAttributes[XLINK_HREF].GetAnimValue(src, this);
    }

    // Empty src should be treated as invalid URL.
    if (!src.IsEmpty()) {
      nsCOMPtr<nsIURI> baseURI = GetBaseURI();
      NS_NewURI(getter_AddRefs(mUri), src, nullptr, baseURI);

      if (!mUri) {
        const char16_t* params[] = { isHref ? u"href" : u"xlink:href", src.get() };

        nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
          NS_LITERAL_CSTRING("SVG"), OwnerDoc(),
          nsContentUtils::eDOM_PROPERTIES, "ScriptSourceInvalidUri",
          params, ArrayLength(params), nullptr,
          EmptyString(), GetScriptLineNumber(), GetScriptColumnNumber());
      }
    } else {
      const char16_t* params[] = { isHref ? u"href" : u"xlink:href" };

      nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
        NS_LITERAL_CSTRING("SVG"), OwnerDoc(),
        nsContentUtils::eDOM_PROPERTIES, "ScriptSourceEmpty",
        params, ArrayLength(params), nullptr,
        EmptyString(), GetScriptLineNumber(), GetScriptColumnNumber());
    }

    // At this point mUri will be null for invalid URLs.
    mExternal = true;
  }

  mFrozen = true;
}
Exemplo n.º 10
0
void
SVGUseElement::LookupHref()
{
  nsAutoString href;
  mStringAttributes[HREF].GetAnimValue(href, this);
  if (href.IsEmpty())
    return;

  nsCOMPtr<nsIURI> targetURI;
  nsCOMPtr<nsIURI> baseURI = mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
  nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
                                            GetComposedDoc(), baseURI);

  mSource.Reset(this, targetURI);
}
Exemplo n.º 11
0
nsresult
nsSVGImageElement::LoadSVGImage(PRBool aForce, PRBool aNotify)
{
  // resolve href attribute
  nsCOMPtr<nsIURI> baseURI = GetBaseURI();

  nsAutoString href;
  mStringAttributes[HREF].GetAnimValue(href, this);
  href.Trim(" \t\n\r");

  if (baseURI && !href.IsEmpty())
    NS_MakeAbsoluteURI(href, href, baseURI);

  return LoadImage(href, aForce, aNotify);
}
Exemplo n.º 12
0
PRBool
nsXMLElement::IsLink(nsIURI** aURI) const
{
  NS_PRECONDITION(aURI, "Must provide aURI out param");

  // To be an XLink for styling and interaction purposes, we require:
  //
  //   xlink:href          - must be set
  //   xlink:type          - must be set to "simple"
  //     xlink:_moz_target - must be set, OR
  //     xlink:show        - must be unset or set to "", "new" or "replace"
  //   xlink:actuate       - must be unset or set to "" or "onRequest"
  //
  // For any other values, we're either not a *clickable* XLink, or the end
  // result is poorly specified. Either way, we return PR_FALSE.

  static nsIContent::AttrValuesArray sShowVals[] =
    { &nsGkAtoms::_empty, &nsGkAtoms::_new, &nsGkAtoms::replace, nsnull };

  static nsIContent::AttrValuesArray sActuateVals[] =
    { &nsGkAtoms::_empty, &nsGkAtoms::onRequest, nsnull };

  // Optimization: check for href first for early return
  const nsAttrValue* href = mAttrsAndChildren.GetAttr(nsGkAtoms::href,
                                                      kNameSpaceID_XLink);
  if (href &&
      AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
                  nsGkAtoms::simple, eCaseMatters) &&
      (HasAttr(kNameSpaceID_XLink, nsGkAtoms::_moz_target) ||
       FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::show,
                       sShowVals, eCaseMatters) !=
                       nsIContent::ATTR_VALUE_NO_MATCH) &&
      FindAttrValueIn(kNameSpaceID_XLink, nsGkAtoms::actuate,
                      sActuateVals, eCaseMatters) !=
                      nsIContent::ATTR_VALUE_NO_MATCH) {
    // Get absolute URI
    nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    nsContentUtils::NewURIWithDocumentCharset(aURI, href->GetStringValue(),
                                              GetOwnerDoc(), baseURI);
    return !!*aURI; // must promise out param is non-null if we return true
  }

  *aURI = nsnull;
  return PR_FALSE;
}
void
nsStyledElementNotElementCSSInlineStyle::ParseStyleAttribute(const nsAString& aValue,
                                                             nsAttrValue& aResult,
                                                             bool aForceInDataDoc)
{
  nsIDocument* doc = OwnerDoc();

  if (aForceInDataDoc ||
      !doc->IsLoadedAsData() ||
      doc->IsStaticDocument()) {
    bool isCSS = true; // assume CSS until proven otherwise

    if (!IsInNativeAnonymousSubtree()) {  // native anonymous content
                                          // always assumes CSS
      nsAutoString styleType;
      doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
      if (!styleType.IsEmpty()) {
        static const char textCssStr[] = "text/css";
        isCSS = (styleType.EqualsIgnoreCase(textCssStr, sizeof(textCssStr) - 1));
      }
    }

    if (isCSS) {
      css::Loader* cssLoader = doc->CSSLoader();
      nsCSSParser cssParser(cssLoader);

      nsCOMPtr<nsIURI> baseURI = GetBaseURI();

      nsRefPtr<css::StyleRule> rule;
      cssParser.ParseStyleAttribute(aValue, doc->GetDocumentURI(),
                                    baseURI,
                                    NodePrincipal(),
                                    getter_AddRefs(rule));
      if (rule) {
        aResult.SetTo(rule, &aValue);
        return;
      }
    }
  }

  aResult.SetTo(aValue);
}
void
SVGScriptElement::FreezeUriAsyncDefer()
{
  if (mFrozen) {
    return;
  }

  if (mStringAttributes[HREF].IsExplicitlySet()) {
    // variation of this code in nsHTMLScriptElement - check if changes
    // need to be transfered when modifying
    nsAutoString src;
    mStringAttributes[HREF].GetAnimValue(src, this);

    nsCOMPtr<nsIURI> baseURI = GetBaseURI();
    NS_NewURI(getter_AddRefs(mUri), src, nullptr, baseURI);
    // At this point mUri will be null for invalid URLs.
    mExternal = true;
  }
  
  mFrozen = true;
}
already_AddRefed<nsIURI> WebBrowserPersistLocalDocument::GetBaseURI() const {
  return mDocument->GetBaseURI();
}
Exemplo n.º 16
0
void
nsSVGElement::UpdateContentStyleRule()
{
  NS_ASSERTION(!mContentStyleRule, "we already have a content style rule");
  
  nsIDocument* doc = GetOwnerDoc();
  if (!doc) {
    NS_ERROR("SVG element without owner document");
    return;
  }
  
  nsCOMPtr<nsIURI> baseURI = GetBaseURI();
  nsIURI *docURI = doc->GetDocumentURI();
  nsICSSLoader* cssLoader = doc->CSSLoader();

  nsCSSDeclaration* declaration = nsnull;
  nsCOMPtr<nsICSSParser> parser;

  nsresult rv = NS_OK; 

  PRUint32 attrCount = mAttrsAndChildren.AttrCount();
  for (PRUint32 i = 0; i < attrCount; ++i) {
    const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
    if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
      continue;

    if (!declaration) {
      // Create the nsCSSDeclaration.
      declaration = new nsCSSDeclaration();
      if (!declaration) {
        NS_WARNING("Failed to allocate nsCSSDeclaration");
        return;
      }
      if (!declaration->InitializeEmpty()) {
        NS_WARNING("could not initialize nsCSSDeclaration");
        declaration->RuleAbort();  // deletes declaration
        return;
      }

      // Try to fetch the CSS Parser from the document.
      rv = cssLoader->GetParserFor(nsnull, getter_AddRefs(parser));
      if (NS_FAILED(rv)) {
        NS_WARNING("failed to get a css parser");
        declaration->RuleAbort();  // deletes declaration
        return;
      }

      // SVG and CSS differ slightly in their interpretation of some of
      // the attributes.  SVG allows attributes of the form: font-size="5" 
      // (style="font-size: 5" if using a style attribute)
      // where CSS requires units: font-size="5pt" (style="font-size: 5pt")
      // Set a flag to pass information to the parser so that we can use
      // the CSS parser to parse the font-size attribute.  Note that this
      // does *not* affect the use of CSS stylesheets, which will still
      // require units.
      parser->SetSVGMode(PR_TRUE);
    }

    nsAutoString name;
    attrName->Atom()->ToString(name);

    nsAutoString value;
    mAttrsAndChildren.AttrAt(i)->ToString(value);

    PRBool changed;
    parser->ParseProperty(nsCSSProps::LookupProperty(name), value,
                          docURI, baseURI, NodePrincipal(),
                          declaration, &changed);
  }

  if (declaration) {
    rv = NS_NewCSSStyleRule(getter_AddRefs(mContentStyleRule), nsnull, declaration);
    if (NS_FAILED(rv)) {
      NS_WARNING("could not create contentstylerule");
      declaration->RuleAbort();  // deletes declaration
    }

    // Recycle the parser
    parser->SetSVGMode(PR_FALSE);
    cssLoader->RecycleParser(parser);
  }
}
Exemplo n.º 17
0
NS_IMETHODIMP
ImportLoader::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
{
  AutoError ae(this);
  nsIPrincipal* principal = Principal();

  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
  if (!channel) {
    return NS_ERROR_DOM_ABORT_ERR;
  }

  if (nsContentUtils::IsSystemPrincipal(principal)) {
    // We should never import non-system documents and run their scripts with system principal!
    nsCOMPtr<nsIPrincipal> channelPrincipal;
    nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(channel,
                                                                    getter_AddRefs(channelPrincipal));
    if (!nsContentUtils::IsSystemPrincipal(channelPrincipal)) {
      return NS_ERROR_FAILURE;
    }
  }
  channel->SetOwner(principal);

  nsAutoCString type;
  channel->GetContentType(type);
  if (!type.EqualsLiteral("text/html")) {
    NS_WARNING("ImportLoader wrong content type");
    return NS_ERROR_DOM_ABORT_ERR;
  }

  // The scope object is same for all the imports in an import tree,
  // let's get it form the import parent.
  nsCOMPtr<nsIGlobalObject> global = mImportParent->GetScopeObject();
  nsCOMPtr<nsIDOMDocument> importDoc;
  nsCOMPtr<nsIURI> baseURI = mImportParent->GetBaseURI();
  const nsAString& emptyStr = EmptyString();
  nsresult rv = NS_NewDOMDocument(getter_AddRefs(importDoc),
                                  emptyStr, emptyStr, nullptr, mURI,
                                  baseURI, principal, false, global,
                                  DocumentFlavorHTML);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR);

  // The imported document must know which master document it belongs to.
  mDocument = do_QueryInterface(importDoc);
  nsCOMPtr<nsIDocument> master = mImportParent->MasterDocument();
  mDocument->SetMasterDocument(master);

  // We want to inherit the sandbox flags and fullscreen enabled flag
  // from the master document.
  mDocument->SetSandboxFlags(master->GetSandboxFlags());

  // We have to connect the blank document we created with the channel we opened,
  // and create its own LoadGroup for it.
  nsCOMPtr<nsIStreamListener> listener;
  nsCOMPtr<nsILoadGroup> loadGroup;
  channel->GetLoadGroup(getter_AddRefs(loadGroup));
  nsCOMPtr<nsILoadGroup> newLoadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
  NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY);
  newLoadGroup->SetLoadGroup(loadGroup);
  rv = mDocument->StartDocumentLoad("import", channel, newLoadGroup,
                                    nullptr, getter_AddRefs(listener),
                                    true);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR);

  nsCOMPtr<nsIURI> originalURI;
  rv = channel->GetOriginalURI(getter_AddRefs(originalURI));
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR);

  nsCOMPtr<nsIURI> URI;
  rv = channel->GetURI(getter_AddRefs(URI));
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR);
  MOZ_ASSERT(URI, "URI of a channel should never be null");

  bool equals;
  rv = URI->Equals(originalURI, &equals);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR);

  if (!equals) {
    // In case of a redirection we must add the new URI to the import map.
    Manager()->AddLoaderWithNewURI(this, URI);
  }

  // Let's start the parser.
  mParserStreamListener = listener;
  rv = listener->OnStartRequest(aRequest, aContext);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_ABORT_ERR);

  ae.Pass();
  return NS_OK;
}
Exemplo n.º 18
0
nsresult
nsXMLElement::MaybeTriggerAutoLink(nsIDocShell *aShell)
{
  NS_ENSURE_ARG_POINTER(aShell);

  // We require an xlink:href, xlink:type="simple" and xlink:actuate="onLoad"
  // XXX: as of XLink 1.1, elements will be links even without xlink:type set
  if (!HasAttr(kNameSpaceID_XLink, nsGkAtoms::href) ||
      !AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
                   nsGkAtoms::simple, eCaseMatters) ||
      !AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::actuate,
                   nsGkAtoms::onLoad, eCaseMatters)) {
    return NS_OK;
  }

  // Disable in Mail/News for now. We may want a pref to control
  // this at some point.
  nsCOMPtr<nsIDocShellTreeItem> docShellItem = do_QueryInterface(aShell);
  if (docShellItem) {
    nsCOMPtr<nsIDocShellTreeItem> rootItem;
    docShellItem->GetRootTreeItem(getter_AddRefs(rootItem));
    nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(rootItem);
    if (docshell) {
      PRUint32 appType;
      if (NS_SUCCEEDED(docshell->GetAppType(&appType)) &&
          appType == nsIDocShell::APP_TYPE_MAIL) {
        return NS_OK;
      }
    }
  }

  // Get absolute URI
  nsCOMPtr<nsIURI> absURI;
  nsAutoString href;
  GetAttr(kNameSpaceID_XLink, nsGkAtoms::href, href);
  nsCOMPtr<nsIURI> baseURI = GetBaseURI();
  nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(absURI), href,
                                            GetOwnerDoc(), baseURI);
  if (!absURI) {
    return NS_OK;
  }

  // Check that the link's URI isn't the same as its document's URI, or else
  // we'll recursively load the document forever (possibly in new windows!)
  PRBool isDocURI;
  absURI->Equals(GetOwnerDoc()->GetDocumentURI(), &isDocURI);
  if (isDocURI) {
    return NS_OK;
  }

  // Get target
  nsAutoString target;
  nsresult special_rv = GetLinkTargetAndAutoType(target);
  // Ignore this link if xlink:show has a value we don't implement
  if (NS_FAILED(special_rv)) return NS_OK;

  // Attempt to load the URI
  nsCOMPtr<nsPresContext> pc;
  nsresult rv = DocShellToPresContext(aShell, getter_AddRefs(pc));
  NS_ENSURE_SUCCESS(rv, rv);

  if (pc) {
    nsContentUtils::TriggerLink(this, pc, absURI, target, PR_TRUE, PR_FALSE);
  }

  return special_rv; // return GetLinkTargetAndAutoType's special rv!
}