omadrm/drmengine/agentv2/src/Oma2AgentContent.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:52:27 +0200
changeset 0 95b198f216e5
child 18 8a03a285ab14
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: OMA DRM ContentAccess::CContent implementation
*
*/



// INCLUDE FILES
#include <caf/caf.h>
#include <caf/bitset.h>
#include <caf/attribute.h>
#include <e32test.h>
#include <utf.h>


#include <schemehandler.h>


#include "oma2agentcontent.h"
#include "oma2agentattributes.h"
#include "oma1dcf.h"
#include "oma2dcf.h"
#include "symmetric.h"
#include "DrmRights.h"
#include "Oma2DcfPartInfo.h"
#include "DrmProtectedRoParser.h"

using namespace ContentAccess;

// LOCAL FUNCTION PROTOTYPES
LOCAL_C TInt MapContentShareMode(TContentShareMode aMode);
template<class S>
LOCAL_C void PointerArrayResetDestroyAndClose(TAny* aPtr);

// ============================= LOCAL FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// MapContentShareMode
// Maps the CAF specific file share mode to the RFs/RFile sharing mode
// -----------------------------------------------------------------------------
//
TInt MapContentShareMode(TContentShareMode aMode)
    {
    TInt r = EFileRead | EFileShareAny;

    switch (aMode)
        {
        case EContentShareReadOnly:
            r = EFileRead | EFileShareReadersOnly;
            break;
        case EContentShareReadWrite:
            r = EFileRead | EFileShareReadersOrWriters;
            break;
        case EContentShareExclusive:
            r = EFileRead | EFileShareExclusive;
            break;
        }
    return r;
    }

// -----------------------------------------------------------------------------
// PointerArrayResetDestroyAndClose
// Template method used to push RPointerArrays to the cleanup stack. Takes
// care of deleting all pointers in the array.
// -----------------------------------------------------------------------------
//
template<class S>
void PointerArrayResetDestroyAndClose(TAny* aPtr)
    {
    (reinterpret_cast<RPointerArray<S>*>(aPtr))->ResetAndDestroy();
    (reinterpret_cast<RPointerArray<S>*>(aPtr))->Close();
    }

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// COma2AgentContent::COma2AgentContent
// Reset all member variables
// -----------------------------------------------------------------------------
//
COma2AgentContent::COma2AgentContent(void):
    iDcf(NULL),
    iFilePosition(0),
    iDataPosition(0),
    iUri(NULL),
    iCurrentContainer(NULL),
    iNotifier(NULL),
    iWatchedId(NULL)
    {
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::ConstructL
// Initialize the agent from a URI (file name) and file mode, opens the
// the file and takes membership of the handle
// -----------------------------------------------------------------------------
//
void COma2AgentContent::ConstructL(
    const TDesC& aUri,
    TContentShareMode aShareMode)
    {
    iUri = aUri.AllocL();
    User::LeaveIfError(iRdb.Connect());
    User::LeaveIfError(iFs.Connect());
    User::LeaveIfError(iFs.ShareAuto());
    User::LeaveIfError(iFile.Open(iFs, aUri, MapContentShareMode(aShareMode)));
    iDcf = CDcfCommon::NewL(iFile);
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::ConstructL
// Initialize the agent from a file handle, duplicates the handle
// -----------------------------------------------------------------------------
//
void COma2AgentContent::ConstructL(RFile& aFile)
    {
    TFileName name;
    User::LeaveIfError(iRdb.Connect());
    User::LeaveIfError(iFile.Duplicate(aFile));
    User::LeaveIfError(iFs.Connect());
    User::LeaveIfError(iFs.ShareAuto());
    iFile.Name(name);
    iUri = name.AllocL();
    iDcf = CDcfCommon::NewL(iFile);
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::NewL
// Two-phased constructors
// -----------------------------------------------------------------------------
//
COma2AgentContent* COma2AgentContent::NewL(
    const TDesC& aUri,
    TContentShareMode aShareMode)
    {
    COma2AgentContent* self = NewLC(aUri, aShareMode);
    CleanupStack::Pop(self);
    return self;
    }

COma2AgentContent* COma2AgentContent::NewLC(
    const TDesC& aUri,
    TContentShareMode aShareMode)
    {
    COma2AgentContent* self=new(ELeave) COma2AgentContent();
    CleanupStack::PushL(self);
    self->ConstructL(aUri, aShareMode);
    return self;
    }

COma2AgentContent* COma2AgentContent::NewL(RFile& aFile)
    {
    COma2AgentContent* self = NewLC(aFile);
    CleanupStack::Pop(self);
    return self;
    }

COma2AgentContent* COma2AgentContent::NewLC(RFile& aFile)
    {
    COma2AgentContent* self=new(ELeave) COma2AgentContent();
    CleanupStack::PushL(self);
    self->ConstructL(aFile);
    return self;
    }


// Destructor
COma2AgentContent::~COma2AgentContent()
    {
    iRdb.Close();
    iFile.Close();
    iFs.Close();
    delete iDcf;
    delete iUri;
    delete iCurrentContainer;
    if (iNotifier != NULL)
        {
        if( iWatchedId )
            {

            TRAP_IGNORE( iNotifier->UnRegisterEventObserverL(*this, KEventAddRemove, *iWatchedId) );
            TRAP_IGNORE( iNotifier->UnRegisterEventObserverL(*this, KEventModify, *iWatchedId) );

            }

        delete iNotifier;
        }
    delete iWatchedId;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::OpenContainer
// Checks if the part ID is valid and sets the current ID to the part ID
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::OpenContainer(
    const TDesC& aUniqueId)
    {
    TInt r = KErrNotFound;
    TInt err = KErrNone;

    // Only the outermost file can be opened, parts within the file don't have
    // subparts, only attributes.
    if (iCurrentContainer == NULL)
        {
        r = iDcf->CheckUniqueId(aUniqueId);
        if (r == KErrNone)
            {

            TRAP(err, iCurrentContainer = aUniqueId.AllocL() );
            if(err)
                {
                return err;
                }
            }
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::CloseContainer
// Resets the current part ID
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::CloseContainer()
    {
    TInt r = KErrNone;

    if (iCurrentContainer != NULL)
        {
        delete iCurrentContainer;
        iCurrentContainer = NULL;
        }
    else
        {
        r = KErrNotFound;
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::GetEmbeddedObjectsL
// Returns all parts embedded in the current part
// -----------------------------------------------------------------------------
//
void COma2AgentContent::GetEmbeddedObjectsL(
    RStreamablePtrArray<CEmbeddedObject>& aArray)
    {
    TInt i;
    CEmbeddedObject* part = NULL;
    HBufC* id = NULL;
    COma2Dcf* dcf2 = NULL;

    aArray.ResetAndDestroy();
    if (iCurrentContainer == NULL)
        {
        if (iDcf->iVersion == EOma2Dcf)
            {
            dcf2 = static_cast<COma2Dcf*>(iDcf);
            for (i = 0; i < dcf2->iParts.Count(); i++)
                {
                id = CnvUtfConverter::ConvertToUnicodeFromUtf8L(
                    *dcf2->iParts[i]->iContentId);
                CleanupStack::PushL(id);
                part = CEmbeddedObject::NewL(*id, *dcf2->iParts[i]->iMimeType,
                    EContentObject);
                CleanupStack::PopAndDestroy(id);
                aArray.AppendL(part);
                }
            }
        else
            {
            id = CnvUtfConverter::ConvertToUnicodeFromUtf8L(
                *iDcf->iContentID);
            CleanupStack::PushL(id);
            part = CEmbeddedObject::NewL(*id, *iDcf->iMimeType,
                EContentObject);
            CleanupStack::PopAndDestroy(id);
            aArray.AppendL(part);
            }
        }
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::GetEmbeddedObjectsL
// Returns all parts embedded in the current part, filtered by type
// -----------------------------------------------------------------------------
//
void COma2AgentContent::GetEmbeddedObjectsL(
    RStreamablePtrArray<CEmbeddedObject>& aArray,
    TEmbeddedType aType)
    {
    if (aType == EContentObject)
        {
        GetEmbeddedObjectsL(aArray);
        }
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::Search
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::Search(
    RStreamablePtrArray<CEmbeddedObject>& aArray,
    const TDesC8& aMimeType,
    TBool /*aRecursive*/)
    {
    TInt i;
    TInt r = KErrNone;
    RStreamablePtrArray<CEmbeddedObject> parts;
    CEmbeddedObject* item = NULL;

    TRAP(r, GetEmbeddedObjectsL(parts));
    for (i = 0; r == KErrNone && i < parts.Count(); i++)
        {
        if (parts[i]->MimeType().CompareF(aMimeType) == 0)
            {

            TRAP_IGNORE( item = CEmbeddedObject::NewL(
                parts[i]->UniqueId(), parts[i]->Name(),
                parts[i]->MimeType(), parts[i]->Type()) );

            TRAP(r, aArray.AppendL(item));
            }
        }
    parts.ResetAndDestroy();
    parts.Close();
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::GetAttribute
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::GetAttribute(
    TInt aAttribute,
    TInt& aValue,
    const TDesC& aUniqueId)
    {
    TInt r;

    r = iDcf->OpenPart(aUniqueId);
    if (r == KErrNone)
        {
        TRAP(r,aValue = TOma2AgentAttributes::GetAttribute(*iDcf, aAttribute,
            TVirtualPathPtr(*iUri, aUniqueId), &iRdb));
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::GetAttributeSet
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::GetAttributeSet(
    RAttributeSet& aAttributeSet,
    const TDesC& aUniqueId)
    {
    TInt r;
    TInt err = KErrNone;

    r = iDcf->OpenPart(aUniqueId);
    if (r == KErrNone)
        {
        TRAP(err,r = TOma2AgentAttributes::GetAttributeSet(*iDcf, aAttributeSet,
            TVirtualPathPtr(*iUri, aUniqueId), &iRdb));
        if (err != KErrNone)
            {
            return err;
            }
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::GetStringAttribute
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::GetStringAttribute(
    TInt aAttribute,
    TDes& aValue,
    const TDesC& aUniqueId)
    {
    TInt r = KErrNone;
    TInt err = KErrNone;

    r = iDcf->OpenPart(aUniqueId);
    if (r == KErrNone)
        {
        TRAP(err, r = TOma2AgentAttributes::GetStringAttribute(*iDcf, aAttribute,
            aValue, TVirtualPathPtr(*iUri, aUniqueId), &iRdb));
        if(err != KErrNone)
            {
            return err;
            }
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::GetStringAttributeSet
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::GetStringAttributeSet(
    RStringAttributeSet& aStringAttributeSet,
    const TDesC& aUniqueId)
    {
    TInt r;
    TInt err = KErrNone;

    r = iDcf->OpenPart(aUniqueId);
    if (r == KErrNone)
        {
        TRAP(err, r = TOma2AgentAttributes::GetStringAttributeSet(*iDcf,
            aStringAttributeSet, TVirtualPathPtr(*iUri, aUniqueId), &iRdb));
        if(err != KErrNone)
            {
            return err;
            }
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::AgentSpecificCommand
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::AgentSpecificCommand(
    TInt aCommand,
    const TDesC8& /*aInputBuffer*/,
    TDes8& /*aOutputBuffer*/)
    {
    TInt r = KErrCANotSupported;

    if (aCommand == EEmbedDomainRo)
        {
        TRAP(r, EmbedDomainRoL());
        }
    return r;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::AgentSpecificCommand
//
// -----------------------------------------------------------------------------
//
void COma2AgentContent::AgentSpecificCommand(
    TInt aCommand,
    const TDesC8& aInputBuffer,
    TDes8& aOutputBuffer,
    TRequestStatus& aStatus)
    {
    TRequestStatus *ptr = &aStatus;
    User::RequestComplete(ptr, AgentSpecificCommand(aCommand, aInputBuffer,
        aOutputBuffer));
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::NotifyStatusChange
//
// -----------------------------------------------------------------------------
//
void COma2AgentContent::NotifyStatusChangeL(
    TEventMask aEventMask,
    TRequestStatus& aStatus,
    const TDesC& aUniqueId)
    {
    TInt r = KErrNone;
    TInt i;
    TInt part = KErrNotFound;
    COma2Dcf* dcf2 = NULL;
    HBufC8* uniqueId = NULL;

    iStatus = &aStatus;
    iWatchedEvents = aEventMask;
    if (iWatchedId != NULL)
        {
        if( iNotifier )
            {
            iNotifier->UnRegisterEventObserverL(*this, KEventAddRemove, *iWatchedId);
            iNotifier->UnRegisterEventObserverL(*this, KEventModify, *iWatchedId);
            }
        delete iWatchedId;
        iWatchedId = NULL;
        }
    if (iDcf->iVersion == EOma1Dcf || aUniqueId.Compare(KDefaultContentObject) == 0)
        {
        iWatchedId = iDcf->iContentID->AllocL();
        }
    else
        {
        dcf2 = static_cast<COma2Dcf*>(iDcf);
        uniqueId = CnvUtfConverter::ConvertFromUnicodeToUtf8L(aUniqueId);
        CleanupStack::PushL(uniqueId);
        for (i = 0; part == KErrNotFound && i < dcf2->iParts.Count(); i++)
            {
            if (dcf2->iParts[i]->iContentId->CompareF(*uniqueId) == 0)
                {
                iWatchedId = dcf2->iParts[i]->iContentId->AllocL();
                }
            }
        CleanupStack::PopAndDestroy();
        }
    if (iWatchedId != NULL)
        {
        if (iNotifier == NULL)
            {
            iNotifier = CDRMNotifier::NewL();
            }
        if (iNotifier != NULL)
            {
            iNotifier->RegisterEventObserverL(*this, KEventAddRemove, *iWatchedId);
            iNotifier->RegisterEventObserverL(*this, KEventModify, *iWatchedId);
            *iStatus = KRequestPending;
            }
        else
            {
            User::Leave(r);
            }
        }
    else
        {
        User::Leave(KErrNotFound);
        }
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::NotifyStatusChange
//
// -----------------------------------------------------------------------------
// 
void COma2AgentContent::NotifyStatusChange(
    TEventMask aEventMask,
    TRequestStatus& aStatus,
    const TDesC& aUniqueId)
    {
    TInt err = KErrNone;
    TRequestStatus *status = 0;
    TRAP(err, NotifyStatusChangeL(  aEventMask,
                                    aStatus,
                                    aUniqueId ));
    if(err)
        {
        status = &aStatus;
        User::RequestComplete(status, err);
        }
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::CancelNotifyStatusChange
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::CancelNotifyStatusChange(
    TRequestStatus& aStatus,
    const TDesC& /*aUniqueId*/)
    {
    iStatus = &aStatus;
    if(iNotifier == NULL)
         {
         User::RequestComplete(iStatus, KErrNotFound);
         return KErrNotFound;
         }

    TRAP_IGNORE( iNotifier->UnRegisterEventObserverL(*this, KEventAddRemove, *iWatchedId) );
    TRAP_IGNORE( iNotifier->UnRegisterEventObserverL(*this, KEventModify, *iWatchedId) );

    if (iWatchedId != NULL)
        {
        delete iWatchedId;
        iWatchedId = NULL;
        }
    User::RequestComplete(iStatus, KErrCancel);
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::RequestRights
// Opens the browser with the rights issuer URL
// -----------------------------------------------------------------------------
//

void COma2AgentContent::RequestRights(
    TRequestStatus& aStatus,
    const TDesC& aUniqueId)
    {
    TRequestStatus *ptr = &aStatus;
    TInt r;
    HBufC* b = NULL;
    CSchemeHandler* handler = NULL;

    r = iDcf->OpenPart(aUniqueId);
    if (r == KErrNone && iDcf->iRightsIssuerURL != NULL)
        {
        TRAP(r, b = CnvUtfConverter::ConvertToUnicodeFromUtf8L(
            *iDcf->iRightsIssuerURL));
        if (b != NULL)
            {
            TRAP(r, handler = CSchemeHandler::NewL(*b));
            if (handler != NULL)
                {
                TRAP(r, handler->HandleUrlStandaloneL());
                delete handler;
                }
            delete b;
            }
        }
    User::RequestComplete(ptr, r);
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::CancelRequestRights
// Not supported, getting rights is handled outside the scope of the agent and
// cannot be cancelled
// -----------------------------------------------------------------------------
//

TInt COma2AgentContent::CancelRequestRights(
    TRequestStatus& aStatus,
    const TDesC& /*aUniqueId*/)
    {
    TRequestStatus *ptr = &aStatus;
    User::RequestComplete(ptr, KErrNone);
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::DisplayInfoL
//
// -----------------------------------------------------------------------------
//
void COma2AgentContent::DisplayInfoL(
    TDisplayInfo /*aDisplayInfo*/,
    const TDesC& /*aUniqueId*/)
    {
    User::Leave(KErrCANotSupported);
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::SetProperty
//
// -----------------------------------------------------------------------------
//
TInt COma2AgentContent::SetProperty(
    TAgentProperty /*aProperty*/,
    TInt /*aValue*/)
    {
    return KErrCANotSupported;
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::EmbedDomainRoL
//
// -----------------------------------------------------------------------------
//
void COma2AgentContent::EmbedDomainRoL()
    {
    RPointerArray<HBufC8> roList;
    TCleanupItem listCleanup(PointerArrayResetDestroyAndClose<HBufC8>,
        &roList);
    COma2Dcf* dcf;
    CDrmProtectedRoParser* parser = NULL;
    RPointerArray<CDRMRights> rights;

    if (iDcf->iVersion == EOma2Dcf)
        {
        dcf = static_cast<COma2Dcf*>(iDcf);

        __UHEAP_MARK;
        for (TInt i = 0; i < dcf->iRightsObjects.Count(); i++)
            {
            parser = CDrmProtectedRoParser::NewL();
            CleanupStack::PushL(parser);
            TRAP_IGNORE( parser->ParseAndStoreL(*dcf->iRightsObjects[i],
                    rights));
            CleanupStack::PopAndDestroy(); // parser
            rights.ResetAndDestroy();
            rights.Close();
            }
        __UHEAP_MARKEND;

        iRdb.GetDomainRosForCidL(*dcf->iContentID, roList);
        CleanupStack::PushL(listCleanup);
        if(roList.Count())
            {
            // this is not replaceable in UHEAP_MARK delimiters
            dcf->SetRightsObjectsL(roList);
            }
        CleanupStack::PopAndDestroy(); // listCleanup
        }
    else
        {
        User::Leave(KErrArgument);
        }
    }

// -----------------------------------------------------------------------------
// COma2AgentContent::HandleEventL
// Handle notifier events here. Not much logic, consider all events as rights
// changes.
// -----------------------------------------------------------------------------
//
void COma2AgentContent::HandleEventL(
    MDRMEvent* /*aEvent*/)
    {
    TInt r;
    TUint32 reason = 0;

    if ( iWatchedId != NULL)
        {
        r = iRdb.CheckRights(EUnknown, *iWatchedId, reason);
        if (r == KErrNone && (iWatchedEvents & ERightsAvailable) ||
            r != KErrNone && (iWatchedEvents & ERightsExpired))
            {
            iNotifier->UnRegisterEventObserverL(*this, KEventAddRemove, *iWatchedId);
            iNotifier->UnRegisterEventObserverL(*this, KEventModify, *iWatchedId);
            delete iWatchedId;
            iWatchedId = NULL;
            User::RequestComplete(iStatus, KErrNone);
            }
        }
    }

//  End of File