blob: dbd0919a44ec72f30f1d20b6e886a00e82e7e178 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modules/notifications/NotificationImageLoader.h"
#include "core/dom/ExecutionContext.h"
#include "core/fetch/ResourceLoaderOptions.h"
#include "platform/image-decoders/ImageDecoder.h"
#include "platform/image-decoders/ImageFrame.h"
#include "platform/network/ResourceError.h"
#include "platform/network/ResourceLoadPriority.h"
#include "platform/network/ResourceRequest.h"
#include "platform/weborigin/KURL.h"
#include "public/platform/WebURLRequest.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace blink {
NotificationImageLoader::NotificationImageLoader()
: m_stopped(false)
{
}
NotificationImageLoader::~NotificationImageLoader()
{
}
void NotificationImageLoader::start(ExecutionContext* executionContext, const KURL& url, PassOwnPtr<ImageCallback> imageCallback)
{
DCHECK(!m_stopped);
m_imageCallback = imageCallback;
// TODO(mvanouwerkerk): Add a timeout mechanism: crbug.com/579137.
ThreadableLoaderOptions threadableLoaderOptions;
threadableLoaderOptions.preflightPolicy = PreventPreflight;
threadableLoaderOptions.crossOriginRequestPolicy = AllowCrossOriginRequests;
// TODO(mvanouwerkerk): Add an entry for notifications to FetchInitiatorTypeNames and use it.
ResourceLoaderOptions resourceLoaderOptions;
resourceLoaderOptions.allowCredentials = AllowStoredCredentials;
if (executionContext->isWorkerGlobalScope())
resourceLoaderOptions.requestInitiatorContext = WorkerContext;
ResourceRequest resourceRequest(url);
resourceRequest.setRequestContext(WebURLRequest::RequestContextImage);
resourceRequest.setPriority(ResourceLoadPriorityMedium);
resourceRequest.setRequestorOrigin(executionContext->getSecurityOrigin());
m_threadableLoader = ThreadableLoader::create(*executionContext, this, threadableLoaderOptions, resourceLoaderOptions);
m_threadableLoader->start(resourceRequest);
}
void NotificationImageLoader::stop()
{
if (m_stopped)
return;
m_stopped = true;
if (m_threadableLoader) {
m_threadableLoader->cancel();
// WorkerThreadableLoader keeps a Persistent<WorkerGlobalScope> to the
// ExecutionContext it received in |create|. Kill it to prevent
// reference cycles involving a mix of GC and non-GC types that fail to
// clear in ThreadState::cleanup.
m_threadableLoader.clear();
}
}
void NotificationImageLoader::didReceiveData(const char* data, unsigned length)
{
if (!m_data)
m_data = SharedBuffer::create();
m_data->append(data, length);
}
void NotificationImageLoader::didFinishLoading(unsigned long resourceIdentifier, double finishTime)
{
// If this has been stopped it is not desirable to trigger further work,
// there is a shutdown of some sort in progress.
if (m_stopped)
return;
if (m_data) {
OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*m_data.get(), ImageDecoder::AlphaPremultiplied, ImageDecoder::GammaAndColorProfileApplied);
if (decoder) {
decoder->setData(m_data.get(), true /* allDataReceived */);
// The |ImageFrame*| is owned by the decoder.
ImageFrame* imageFrame = decoder->frameBufferAtIndex(0);
if (imageFrame) {
(*m_imageCallback)(imageFrame->bitmap());
return;
}
}
}
runCallbackWithEmptyBitmap();
}
void NotificationImageLoader::didFail(const ResourceError& error)
{
runCallbackWithEmptyBitmap();
}
void NotificationImageLoader::didFailRedirectCheck()
{
runCallbackWithEmptyBitmap();
}
void NotificationImageLoader::runCallbackWithEmptyBitmap()
{
// If this has been stopped it is not desirable to trigger further work,
// there is a shutdown of some sort in progress.
if (m_stopped)
return;
(*m_imageCallback)(SkBitmap());
}
} // namespace blink