/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation. All
 * Rights Reserved.
 *
 * Contributor(s): 
 */

#include "nsrootidl.idl"
#include "nsISupports.idl"

interface nsIFileSpec;
interface nsIURI;
interface nsIObserver;
interface nsIChannel;
interface nsINetDataCache;
interface nsINetDataCacheRecord;
interface nsILoadGroup;
interface nsIStreamListener;

/**
 * The nsICachedNetData interface represents a single entry in a database that
 * caches data retrieved from the network. This interface is implemented by the
 * cache manager on top of the low-level nsINetDataCacheRecord and
 * nsINetDataCache interfaces that are implemented by the database.
 *
 * Each cache record may contain both content and metadata.  The content may
 * be, for example, GIF image data or HTML, and it is accessed through
 * nsIChannel's streaming API.  The opaque metadata, which may contain HTTP
 * headers among other things, is stored as a byte array.  Each entry in the
 * cache is indexed by two different keys: a record id number and a key created
 * by combining the URI with a "secondary key", e.g. HTTP post data.
 *
 * @See nsINetDataCacheRecord
 * @See nsINetDataCache
 * @See nsINetDataDiskCache
 * @See nsINetDataCacheManager
 */
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
interface nsICachedNetData : nsISupports
{
    /**
     * String form of the URI provided as an argument to the call to
     * nsINetDataCacheManager::GetCachedNetData() that created this record.
     */
    readonly attribute string uriSpec;
    
    /**
     * Getter for the opaque secondary database key provided as an argument to
     * the call to nsINetDataCacheManager::GetCachedNetData() that created this
     * record.
     */
    void getSecondaryKey(out unsigned long length,
                         [retval, size_is(length)] out string secondaryKey);

    /**
     * This flag may be set by a protocol handler to indicate that it supports
     * partial fetching of data.  In that case, the cache manager is permitted
     * to truncate the entry's content to accommodate incoming data for other
     * cache entries rather than deleting it wholesale.
     */
    attribute boolean allowPartial;
    
    /**
     * This flag indicates that the write stream supplying content data for the
     * cache did not complete normally and, therefore, the content may be
     * truncated.
     */
    readonly attribute boolean partialFlag;

    /**
     * This flag can be set and cleared by a protocol handler as a form of
     * self-notification, so as to avoid race conditions in which a protocol
     * handler issues two identical network requests to fill the same cache
     * entry.  The cache manager itself largely ignores this flag.
     */
    attribute boolean updateInProgress;

    /**
     * inUse is set if any existing channels are associated with this cache
     * entry or if the updateInProgess flag is set.  This can be used to
     * prevent writing to a cache entry by a protocol handler if it's being
     * read or written elsewhere.
     */
    readonly attribute boolean inUse;

    /**
     * Date/time that the document was last stored on the origin server, as
     * supplied by the protocol handler.  This value is used as input to the
     * cache replacement policy, i.e. it is not used for validation.  If the
     * protocol can't supply a last-modified time, this attribute should remain
     * unset.  When unset, the value of this attribute is zero.
     *
     * FIXME: Should use nsIDateTime interface, once it's created
     * instead of PRTime, for improved scriptability ? 
     */
    attribute PRTime lastModifiedTime;

    /**
     * Supplied by the protocol handler, the expirationTime attribute specifies
     * the time until which the document is guaranteed fresh, i.e. the document
     * does not have to be validated with the server and, therefore, any data
     * in cache is definitely usable.  The value of this attribute serves as a
     * hint to the cache replacement policy.  Only one of either staleTime or
     * expirationTime may be set for a single cache record.  When unset, the
     * value of this attribute is zero. 
     */
    attribute PRTime expirationTime;

    /**
     * Date/time supplied by the protocol handler, at which point the content
     * is *likely* to be stale, i.e. the data in the cache may be out-of-date
     * with respect to the data on the server.  This heuristic date does not
     * necessarily correspond to the HTTP Expires header, as it does not
     * determine when cached network data must be validated with the origin
     * server, but only serves as a hint to the cache replacement policy.  Only
     * one of either staleTime or expirationTime may be set for a single cache
     * record.  When unset, the value of this attribute is zero.
     */
    attribute PRTime staleTime;

    /**
     * Date/time of last access of the data in this cache record, as determined
     * by the cache manager.
     */
    readonly attribute PRTime lastAccessTime;

    /**
     * Number of times this record has been accessed since it was first stored.
     */
    readonly attribute PRUint16 numberAccesses;

    /**
     * Accessor methods for opaque meta-data which can be read and updated
     * independently of the content data.
     *
     * The aTag argument can be used to accommodate multiple clients of the
     * cache API, each of which wants to store its own private meta-data into
     * the cache.  For example, there could be a "headers" tag that the HTTP
     * protocol handler uses to store http response headers and a "image size"
     * tag used to store the image dimensions of a GIF file.  The aData
     * argument refers to an opaque blob of arbitrary bytes.
     *
     * IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
     *            string, the contents of aData must be byte-swapped by the,
     *            caller, so as to make the cache files endian-independent.
     */
    void getAnnotation(in string aTag, 
                       out PRUint32 aLength, [size_is(aLength), retval] out string aData);
    void setAnnotation(in string aTag,
                       in  PRUint32 aLength, [size_is(aLength)] in string aData);

    /**
     * As a getter, return the number of content bytes stored in the cache,
     * i.e. via the nsIChannel streaming APIs.  This may be less than the
     * complete content length if a partial cache fill occurred.  The cached
     * content can be truncated by setting the value of this attribute.  The
     * value of the attribute represents a logical, not a physical, length.  If
     * compression has been used, the content may consume less storage than
     * indicated by this attribute.
     *
     * When this attribute is set to zero the associated cache disk file, if
     * any, should be deleted.
     */
    attribute PRUint32 storedContentLength;

    /** 
     * Notify any observers associated with this cache entry of the deletion
     * request.  If all observers drop their reference to the cache entry,
     * proceed to delete the underlying cache database record and associated
     * content storage.
     */
    void delete();

    /**
     * Flush any changes in this entry's data to the cache database.  This
     * method will automatically be called when the last reference to the cache
     * is dropped, but it can also be called explicitly for a synchronous
     * effect.
     */
    void commit();

    /**
     * Parent container cache for this entry.
     */
    readonly attribute nsINetDataCache cache;

    /**
     * Create a channel for reading or writing a stream of content into the
     * entry.  It is expected that many of the nsIChannel methods return
     * NS_NOT_IMPLEMENTED, including:
     *
     *    + GetURI()
     *    + GetContentType()
     *    + GetContentLength()
     *
     * Though nsIChannel provides for both async and synchronous I/O APIs, both
     * may not be implemented.  Only AsyncRead() and OpenOutputStream() is
     * required.  The aProxyChannel argument allows another channel to be
     * specified as the proffered argument to nsIStreamListener methods rather
     * than the cache's own channel.
     */
    nsIChannel newChannel(in nsILoadGroup aLoadGroup,
                          in nsIChannel aProxyChannel);

    /**
     * This method can be used by a caching protocol handler to store data in
     * the cache by forking an asynchronous read stream so that it is
     * simultaneously sent to a requester and written into the cache.  This
     * method implicitly sets the updateInProgress flag, if it has not already
     * been set.
     */
    nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
                                         in PRUint32 aStartOffset);
};
