HTML WebView control sample

This sample demonstrates how to use WebView.

 
 
 
 
 
3.7 Star
(3)
5,227 times
Add to favorites
11/26/2013
E-mail Twitter del.icio.us Digg Facebook
// Copyright (c) Microsoft Corporation.  All rights reserved.

#include "StreamUriResolver.h"
#include <ppltasks.h>
#include <strsafe.h>
#include <assert.h>

using namespace SDK::WebViewSampleCpp;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
using namespace Windows::Security::Cryptography;
using namespace concurrency;

namespace SDK
{
namespace WebViewSampleCpp
{

IAsyncOperation<IInputStream^>^ StreamUriResolver::UriToStreamAsync(Uri^ uri)
{
    // The WebView's buildLocalStreamUri method takes contentIdentifier and relativePath
    // parameters to generate a URI of the form:
    //     ms-local-stream://<package name>_<encoded contentIdentifier>/<relativePath>
    // The resolver can decode the contentIdentifier to determine what content should be
    // returned in the output stream.
    PCWSTR encodedContentIdentifier = wcschr(uri->Host->Data(), L'_');
    if (encodedContentIdentifier == nullptr)
    {
        throw ref new InvalidArgumentException();
    }
    else
    {
        encodedContentIdentifier++;
    }

    IBuffer^ buffer = CryptographicBuffer::DecodeFromHexString(ref new String(encodedContentIdentifier));
    String^ contentIdentifier = CryptographicBuffer::ConvertBinaryToString(BinaryStringEncoding::Utf8, buffer);
    String^ relativePath = ref new String(uri->Path->Data());

    // For this sample, we will return a stream for a file under the local app data
    // folder, under the subfolder named after the contentIdentifier and having the
    // given relativePath.  Real apps can have more complex behavior, such as handling
    // contentIdentifiers in a custom manner (not necessarily as paths), and generating
    // arbitrary streams that are not read directly from a file.
    Uri^ appDataUri = ref new Uri(L"ms-appdata:///local/" + contentIdentifier + relativePath);

    StreamRetrievalOperation^ asyncOp = ref new StreamRetrievalOperation();
    asyncOp->Start(appDataUri);
    return asyncOp;
}

StreamRetrievalOperation::StreamRetrievalOperation()
{
    _result = nullptr;
    _completedHandler = nullptr;
    _asyncStatus = AsyncStatus::Started;
    _errorCode.Value = S_OK;
    _firedCompletion = false;
    _isClosed = false;
}

void StreamRetrievalOperation::Start(Uri^ uri)
{
    create_task(StorageFile::GetFileFromApplicationUriAsync(uri), task_continuation_context::use_arbitrary()).then([this](StorageFile^ storageFile)
    {
        return create_task(storageFile->OpenAsync(FileAccessMode::Read), task_continuation_context::use_arbitrary());
    }, task_continuation_context::use_arbitrary()).then([this](task<IRandomAccessStream^> task)
    {
        // The final lamdba takes the task instead of the IRandomAccessStream as the parameter so
        // get can be called explicitly on the task. Get will throw an exception if the task
        // failed. The completed handler needs to be invoked whether the task succeeds or fails.
        try
        {
            IRandomAccessStream^ stream = task.get();
            // The IRandomAccessStream can be cast to an IInputStream because IRandomAccessStream
            // requires IInputStream.
            IInputStream^ inputStream = static_cast<IInputStream^>(stream);
            TransitionToCompleted(inputStream);
        }
        catch (Platform::COMException^ e)
        {
            TransitionToError(e);
        }
    }, task_continuation_context::use_arbitrary());
}

void StreamRetrievalOperation::Cancel()
{
    _asyncStatus = AsyncStatus::Canceled;
    FireCompletion();
}

void StreamRetrievalOperation::Close()
{
    _isClosed = true;
    _result = nullptr;
    _completedHandler = nullptr;
}

IInputStream^ StreamRetrievalOperation::GetResults()
{
    if (_isClosed)
    {
        throw ref new Exception(E_ILLEGAL_METHOD_CALL);
    }

    return _result;
}

void StreamRetrievalOperation::Completed::set(AsyncOperationCompletedHandler<IInputStream^>^ value)
{
    _completedHandler = value;
    FireCompletion();
}

AsyncOperationCompletedHandler<IInputStream^>^ StreamRetrievalOperation::Completed::get()
{
    if (_isClosed)
    {
        throw ref new Exception(E_ILLEGAL_METHOD_CALL);
    }

    return _completedHandler;
}

void StreamRetrievalOperation::TransitionToCompleted(IInputStream^ inputStream)
{
    if (_asyncStatus == AsyncStatus::Started)
    {
        _result = inputStream;
        _asyncStatus = AsyncStatus::Completed;
        FireCompletion();
    }
}

void StreamRetrievalOperation::TransitionToError(COMException^ exception)
{
    if (_asyncStatus == AsyncStatus::Started)
    {
        _result = nullptr;
        _asyncStatus = AsyncStatus::Error;
        _errorCode.Value = exception->HResult;
        FireCompletion();
    }
}

void StreamRetrievalOperation::FireCompletion()
{
    // Fire the completed handler once, and only after
    // a completed handler has been set and the operation
    // has finished.
    if (_asyncStatus != AsyncStatus::Started &&
        _completedHandler != nullptr &&
        !_firedCompletion)
    {
        _firedCompletion = true;
        _completedHandler(this, _asyncStatus);
    }
}

} // namespace WebViewSampleCpp
} // namespace SDK