Commit 30f3ee0f authored by haftandilian@mozilla.com's avatar haftandilian@mozilla.com
Browse files

Bug 1397257 - [Windows] Awesome Screenshot removing error for a second uninstallation. r=jimm

Fix circular dependency created when encountering a path to a nonexistent JAR
inner file.

Change cache JAR loads to not use ExtensionStreamGetter, instead call the JAR
channel's AsyncOpen2 method directly in the SimpleChannel callback.
Remove the code to handle cached JAR loads from ExtensionStreamGetter.

MozReview-Commit-ID: Kmry02eLYU1

--HG--
extra : rebase_source : 2d750b393b77e23f6ec4e20c322214611f5daea7
parent a75dea4e
Loading
Loading
Loading
Loading
+62 −62
Original line number Diff line number Diff line
@@ -77,7 +77,6 @@ class ExtensionStreamGetter : public RefCounted<ExtensionStreamGetter>
      : mURI(aURI)
      , mLoadInfo(aLoadInfo)
      , mIsJarChannel(false)
      , mIsCachedJar(false)
    {
      MOZ_ASSERT(aURI);
      MOZ_ASSERT(aLoadInfo);
@@ -95,7 +94,6 @@ class ExtensionStreamGetter : public RefCounted<ExtensionStreamGetter>
      , mJarChannel(Move(aJarChannel))
      , mJarFile(aJarFile)
      , mIsJarChannel(true)
      , mIsCachedJar(false)
    {
      MOZ_ASSERT(aURI);
      MOZ_ASSERT(aLoadInfo);
@@ -105,23 +103,6 @@ class ExtensionStreamGetter : public RefCounted<ExtensionStreamGetter>
      SetupEventTarget();
    }

    // To use when the request resolves to a JAR file that is already cached.
    // Using a SimpleChannel with an ExtensionStreamGetter here (like the
    // non-cached JAR case) isn't needed to load the extension resource
    // because we don't need to ask the parent for an FD for the JAR, but
    // wrapping the JARChannel in a SimpleChannel allows HTTP forwarding to
    // moz-extension URI's to work because HTTP forwarding requires the
    // target channel implement nsIChildChannel. mMainThreadEventTarget is
    // not used for this case, so don't set it up.
    explicit
      ExtensionStreamGetter(already_AddRefed<nsIJARChannel>&& aJarChannel)
      : mJarChannel(Move(aJarChannel))
      , mIsJarChannel(true)
      , mIsCachedJar(true)
    {
      MOZ_ASSERT(mJarChannel);
    }

    ~ExtensionStreamGetter() {}

    void SetupEventTarget()
@@ -154,10 +135,6 @@ class ExtensionStreamGetter : public RefCounted<ExtensionStreamGetter>
    nsCOMPtr<nsIChannel> mChannel;
    nsCOMPtr<nsISerialEventTarget> mMainThreadEventTarget;
    bool mIsJarChannel;

    // Indicates the JAR for this channel is cached
    // and implies mIsJarChannel==true
    bool mIsCachedJar;
};

class ExtensionJARFileOpener : public nsISupports
@@ -233,23 +210,11 @@ ExtensionStreamGetter::GetAsync(nsIStreamListener* aListener,
                                nsIChannel* aChannel)
{
  MOZ_ASSERT(IsNeckoChild());
  MOZ_ASSERT(mMainThreadEventTarget || mIsCachedJar);
  MOZ_ASSERT(mMainThreadEventTarget);

  mListener = aListener;
  mChannel = aChannel;

  // We don't have to request an FD from the
  // parent if the JAR is cached
  if (mIsCachedJar) {
    MOZ_ASSERT(mIsJarChannel);
    nsresult rv = mJarChannel->AsyncOpen2(mListener);
    if (NS_FAILED(rv)) {
      mChannel->Cancel(NS_BINDING_ABORTED);
      return Result<Ok, nsresult>(rv);
    }
    return Ok();
  }

  // Serialize the URI to send to parent
  mozilla::ipc::URIParams uri;
  SerializeURI(mURI, uri);
@@ -827,6 +792,22 @@ ExtensionProtocolHandler::NewFD(nsIURI* aChildURI,
  return Ok();
}

// Set the channel's content type using the provided URI's type
void
SetContentType(nsIURI* aURI, nsIChannel* aChannel)
{
  nsresult rv;
  nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv);
  if (NS_SUCCEEDED(rv)) {
    nsAutoCString contentType;
    rv = mime->GetTypeFromURI(aURI, contentType);
    if (NS_SUCCEEDED(rv)) {
      Unused << aChannel->SetContentType(contentType);
    }
  }
}

// Gets a SimpleChannel that wraps the provided ExtensionStreamGetter
static void
NewSimpleChannel(nsIURI* aURI,
                 nsILoadInfo* aLoadinfo,
@@ -835,22 +816,35 @@ NewSimpleChannel(nsIURI* aURI,
{
  nsCOMPtr<nsIChannel> channel = NS_NewSimpleChannel(
    aURI, aLoadinfo, aStreamGetter,
    [] (nsIStreamListener* listener, nsIChannel* channel,
    [] (nsIStreamListener* listener, nsIChannel* simpleChannel,
        ExtensionStreamGetter* getter) -> RequestOrReason {
      MOZ_TRY(getter->GetAsync(listener, channel));
      MOZ_TRY(getter->GetAsync(listener, simpleChannel));
      return RequestOrReason(nullptr);
    });

  nsresult rv;
  nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv);
  if (NS_SUCCEEDED(rv)) {
    nsAutoCString contentType;
    rv = mime->GetTypeFromURI(aURI, contentType);
    if (NS_SUCCEEDED(rv)) {
      Unused << channel->SetContentType(contentType);
  SetContentType(aURI, channel);
  channel.swap(*aRetVal);
}

// Gets a SimpleChannel that wraps the provided channel
static void
NewSimpleChannel(nsIURI* aURI,
                 nsILoadInfo* aLoadinfo,
                 nsIChannel* aChannel,
                 nsIChannel** aRetVal)
{
  nsCOMPtr<nsIChannel> channel = NS_NewSimpleChannel(aURI, aLoadinfo, aChannel,
    [] (nsIStreamListener* listener, nsIChannel* simpleChannel,
        nsIChannel* origChannel) -> RequestOrReason {
      nsresult rv = origChannel->AsyncOpen2(listener);
      if (NS_FAILED(rv)) {
        simpleChannel->Cancel(NS_BINDING_ABORTED);
        return RequestOrReason(rv);
      }
      return RequestOrReason(origChannel);
    });

  SetContentType(aURI, channel);
  channel.swap(*aRetVal);
}

@@ -919,11 +913,17 @@ ExtensionProtocolHandler::SubstituteRemoteJarChannel(nsIURI* aURI,
    Unused << LogCacheCheck(jarChannel, jarURI, isCached);
  }

  RefPtr<ExtensionStreamGetter> streamGetter;

  if (isCached) {
    streamGetter = new ExtensionStreamGetter(jarChannel.forget());
  } else {
    // Using a SimpleChannel with an ExtensionStreamGetter here (like the
    // non-cached JAR case) isn't needed to load the extension resource
    // because we don't need to ask the parent for an FD for the JAR, but
    // wrapping the JARChannel in a SimpleChannel allows HTTP forwarding to
    // moz-extension URI's to work because HTTP forwarding requires the
    // target channel implement nsIChildChannel.
    NewSimpleChannel(aURI, aLoadinfo, jarChannel.get(), aRetVal);
    return Ok();
  }

  nsCOMPtr<nsIURI> innerFileURI;
  MOZ_TRY(jarURI->GetJARFile(getter_AddRefs(innerFileURI)));

@@ -933,11 +933,11 @@ ExtensionProtocolHandler::SubstituteRemoteJarChannel(nsIURI* aURI,
  nsCOMPtr<nsIFile> jarFile;
  MOZ_TRY(innerFileURL->GetFile(getter_AddRefs(jarFile)));

    streamGetter = new ExtensionStreamGetter(aURI,
  RefPtr<ExtensionStreamGetter> streamGetter =
    new ExtensionStreamGetter(aURI,
                              aLoadinfo,
                              jarChannel.forget(),
                              jarFile);
  }

  NewSimpleChannel(aURI, aLoadinfo, streamGetter, aRetVal);
  return Ok();