Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / MS / Internal / AppModel / Journaling.cs / 1 / Journaling.cs
//---------------------------------------------------------------------------- // // File: Journaling.cs // // Description: Contains various journaling related internal enums and classes // // History: // 1/20/2005: ChangoV Branched off system/windows/navigation/JournalEntry.cs // // Copyright (C) 2006 by Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Security; using System.Security.Permissions; using System.Runtime.Serialization; using System.Diagnostics; using System.Windows; using System.Windows.Markup; using System.Windows.Navigation; using MS.Internal.Utility; //In order to avoid generating warnings about unknown message numbers and //unknown pragmas when compiling your C# source code with the actual C# compiler, //you need to disable warnings 1634 and 1691. (Presharp Documentation) #pragma warning disable 1634, 1691 namespace MS.Internal.AppModel { [Serializable] internal enum JournalEntryType : byte { Navigable, UiLess, } internal enum JournalReason { NewContentNavigation = 1, FragmentNavigation, AddBackEntry }; ////// Encapsulates the custom journal state of an element implementing IJournalState. /// [Serializable] internal abstract class CustomJournalStateInternal { ////// Called when the entire journal is about to be binary-serialized. Non-serializable objects /// should be removed or replaced with serializable ones. /// internal virtual void PrepareForSerialization() { } }; ////// Currently used in two contexts: /// 1) Allows an element in the logical tree of INavigator.Content to implement "custom" journaling /// of its state, beyond the DP journaling that DataStreams does. /// [The public IProvideCustomContentState applies only to the root element.] /// journalReason is always NewContentNavigation in this use. /// Initially, the only actual use is for Frame to preserve its own journal. /// 2) Root viewer journaling. See NavigationService.MakeJournalEntry()... /// internal interface IJournalState { CustomJournalStateInternal GetJournalState(JournalReason journalReason); void RestoreJournalState(CustomJournalStateInternal state); }; ////// Shared state for all journal entries associated with the same content object ("bind product"). /// Journal entries created for fragment navigations or CustomContentState navigations within the /// current page share one JournalEntryGroupState object. This avoids duplication of state and /// the problems described in bug 1216726. /// [Serializable] internal class JournalEntryGroupState { internal JournalEntryGroupState() { } internal JournalEntryGroupState(Guid navSvcId, uint contentId) { _navigationServiceId = navSvcId; _contentId = contentId; } internal Guid NavigationServiceId { get { return _navigationServiceId; } set { _navigationServiceId = value; } } ////// Unique identifier (within a NavigationService, not across the entire Journal) of the page /// content ("bind product") this journal entry group is associated with. /// One use of this property is to help us distinguish back/fwd navigations /// within the same page from navigations to a different instance of the same page /// (same URI, modulo #frament id). (Bugs 1187603 and 1187613). /// Zero is not a valid id. /// internal uint ContentId { get { return _contentId; } set { Debug.Assert(_contentId == 0 || _contentId == value, "Once set, the ContentId for a JournalEntryGroup should not be changed."); _contentId = value; } } internal DataStreams JournalDataStreams { #if DEBUG [DebuggerStepThrough] #endif get { // Do not make this getter create a new DataStreams object. Keep-alive journal entries // don't need it. return _journalDataStreams; } set { _journalDataStreams = value; } } internal JournalEntry GroupExitEntry { get { return _groupExitEntry; } set { Debug.Assert(value.JEGroupState == this); Debug.Assert(_groupExitEntry == null || _groupExitEntry.ContentId == value.ContentId); _groupExitEntry = value; } } private Guid _navigationServiceId; private uint _contentId; private DataStreams _journalDataStreams; private JournalEntry _groupExitEntry; }; ////// The journal entry when journaling by URI. When navigating away, it will save the form state. /// When navigating back/forwards to this entry, it will navigate back to the URI, and then /// restore the form state. /// [Serializable] internal class JournalEntryUri : JournalEntry, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryUri(JournalEntryGroupState jeGroupState, Uri uri) : base(jeGroupState, uri) { } ////// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// protected JournalEntryUri(SerializationInfo info, StreamingContext context) : base(info, context) { } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override void SaveState(object contentObject) { Invariant.Assert(this.Source != null, "Can't journal by Uri without a Uri."); base.SaveState(contentObject); // Save controls state (JournalDataStreams). } #endregion } ////// This is the journal entry class for use when the entire tree is being kept alive. It will be /// saved when navigated away from, and when restored, it navigates to the saved tree. /// // Not [Serializable], because keep-alive content should not be serialized into the TravelLog. internal class JournalEntryKeepAlive : JournalEntry { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryKeepAlive(JournalEntryGroupState jeGroupState, Uri uri, object keepAliveRoot) : base(jeGroupState, uri) { Invariant.Assert(keepAliveRoot != null); _keepAliveRoot = keepAliveRoot; } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods ////// This is how the JournalEntry holds on to the tree itself. There is no need to keep track of other /// things c.f. AlivePageFunction. /// internal object KeepAliveRoot { get { return _keepAliveRoot; } } internal override bool IsAlive() { return this.KeepAliveRoot != null; } internal override void SaveState(object contentObject) { Debug.Assert(this.KeepAliveRoot == contentObject); // set by ctor; shouldn't change this._keepAliveRoot = contentObject; // No call to base.SaveState() since it saves controls state, and contentObject is KeepAlive. } internal override bool Navigate(INavigator navigator, NavigationMode navMode) { Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward); Debug.Assert(this.KeepAliveRoot != null); return navigator.Navigate(this.KeepAliveRoot, new NavigateInfo(Source, navMode, this)); } #endregion #region Private fields private object _keepAliveRoot; // the root of a tree being kept alive #endregion } ////// The journal entry for page functions. Ideally, these would use the same journal method /// that the other entries use, and derive from the other JournalEntry* classes to add the /// small bit of functionality that the page functions require (the Finish handler, for one.) /// [Serializable] internal abstract class JournalEntryPageFunction : JournalEntry, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryPageFunction(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, null) { PageFunctionId = pageFunction.PageFunctionId; ParentPageFunctionId = pageFunction.ParentPageFunctionId; } ////// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// The base implementation needs to be called if this class is overridden /// protected JournalEntryPageFunction(SerializationInfo info, StreamingContext context) : base(info, context) { _pageFunctionId = (Guid)info.GetValue("_pageFunctionId", typeof(Guid)); _parentPageFunctionId = (Guid)info.GetValue("_parentPageFunctionId", typeof(Guid)); ; } // // ISerializable implementation // ////// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_pageFunctionId", _pageFunctionId); info.AddValue("_parentPageFunctionId", _parentPageFunctionId); } #endregion // Internal Properties ///////////////////////////////////////////////////////////////////// ////// This is the GUID for this PageFunction. It will be used as its childrens' /// ParentPageFunctionId. /// internal Guid PageFunctionId { get { return _pageFunctionId; } set { _pageFunctionId = value; } } ////// If this PageFunction is a child PageFunction, this will be the GUID of its /// parent PageFunction. If this is Guid.Empty, then the parent is NOT a /// PageFunction. /// internal Guid ParentPageFunctionId { get { return _parentPageFunctionId; } set { _parentPageFunctionId = value; } } // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override bool IsPageFunction() { return true; } internal override bool IsAlive() { return false; } ////// Reconstitutes the PageFunction associated with this journal entry so that it can be /// re-navigated to. Happens when returning from a child PF or doing journal navigation. /// internal abstract PageFunctionBase ResumePageFunction(); #endregion #region internal Static method // // This method is to get the journal entry index in the Journal List for the parent page // of this PageFunction. // // The parent page could be a PageFunction or a Non-PageFunction. // For the non PageFunction case, it could have a Uri or could not have a Uri. // // Case 1: The ParentPageFunction has been set, so just go back and look for it. // Case 2: The ParentPageFunction has NOT been set, so the parent must be most recent non-PF entry. // internal static int GetParentPageJournalIndex(NavigationService NavigationService, Journal journal, PageFunctionBase endingPF) { JournalEntryPageFunction pageFunctionEntry; JournalEntry journalEntry; for (int index = journal.CurrentIndex - 1; index >= 0; --index) { journalEntry = journal[index]; // Be sure that the navigation containers match if (journalEntry.NavigationServiceId != NavigationService.GuidId) continue; pageFunctionEntry = journalEntry as JournalEntryPageFunction; if (endingPF.ParentPageFunctionId == Guid.Empty) { // We are looking for a non-PageFunction if (pageFunctionEntry == null) { return index; // found! } } else { // we are looking for a PageFunction if ((pageFunctionEntry != null) && (pageFunctionEntry.PageFunctionId == endingPF.ParentPageFunctionId)) { return index; // found! } } } Debug.Assert(endingPF.ParentPageFunctionId == Guid.Empty, "Should have been able to find the parent if the ParentPageFunctionId was set. Are they in different NavigationServices? They shouldn't be."); return _NoParentPage; } #endregion // Private fields // // If you add any fields here, check if it needs to be serialized. // If yes, then add it to the ISerializable implementation and make // corresponding changes in the Serialization constructor. // ///////////////////////////////////////////////////////////////////// private Guid _pageFunctionId; private Guid _parentPageFunctionId; internal const int _NoParentPage = -1; } ////// This is the class for page functions that are being kept alive. /// // Not [Serializable], because keep-alive content should not be serialized into the TravelLog. internal class JournalEntryPageFunctionKeepAlive : JournalEntryPageFunction { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryPageFunctionKeepAlive(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, pageFunction) { Debug.Assert(pageFunction != null && pageFunction.KeepAlive); this._keepAlivePageFunction = pageFunction; } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override bool IsPageFunction() { return true; } internal override bool IsAlive() { return this.KeepAlivePageFunction != null; } internal PageFunctionBase KeepAlivePageFunction { get { return _keepAlivePageFunction; } } internal override PageFunctionBase ResumePageFunction() { PageFunctionBase pageFunction = this.KeepAlivePageFunction; pageFunction._Resume = true; return pageFunction; } internal override void SaveState(object contentObject) { Invariant.Assert(_keepAlivePageFunction == contentObject); // set by ctor // No call to base.SaveState() since it saves controls state, and this PF is KeepAlive. } ////// This override is used when doing journal navigation to a PF, not when it is resumed after /// a child PF finishes. /// internal override bool Navigate(INavigator navigator, NavigationMode navMode) { Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward); // When doing fragment navigation within the PF, it should not be marked as Resumed; // otherwise, its Start() override may not be called. PageFunctionBase pf = (navigator.Content == _keepAlivePageFunction) ? _keepAlivePageFunction : ResumePageFunction(); Debug.Assert(pf != null); return navigator.Navigate(pf, new NavigateInfo(this.Source, navMode, this)); } #endregion #region Private fields PageFunctionBase _keepAlivePageFunction = null; #endregion } ////// JournalEntryPageFunctionSaver /// This is JournalEntry for PageFunction which is not set as KeepAlive. The PageFunction could be /// navigated from a Uri or the instance created from a PageFunction type. /// [Serializable] internal abstract class JournalEntryPageFunctionSaver : JournalEntryPageFunction, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors // // Ctor of JournalEntryPageFunctionSaver // internal JournalEntryPageFunctionSaver(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, pageFunction) { Debug.Assert(!pageFunction.KeepAlive); } ////// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// The base implementation needs to be called if this class is overridden /// protected JournalEntryPageFunctionSaver(SerializationInfo info, StreamingContext context) : base(info, context) { _returnEventSaver = (ReturnEventSaver)info.GetValue("_returnEventSaver", typeof(ReturnEventSaver)); } // // ISerializable implementation // ////// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_returnEventSaver", _returnEventSaver); } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override void SaveState(object contentObject) { PageFunctionBase pageFunction = (PageFunctionBase)contentObject; _returnEventSaver = pageFunction._Saver; base.SaveState(contentObject); // Save controls state (JournalDataStreams). } // // Take the PageFunction specific setting, then call the RestoreState in base class // to store previous state in a journal navigation. // internal override void RestoreState(object contentObject) { if (contentObject == null) throw new ArgumentNullException("contentObject"); PageFunctionBase pageFunction = (PageFunctionBase)contentObject; if (pageFunction == null) { throw new Exception(SR.Get(SRID.InvalidPageFunctionType, contentObject.GetType( ))); } pageFunction.ParentPageFunctionId = ParentPageFunctionId; pageFunction.PageFunctionId = PageFunctionId; pageFunction._Saver = _returnEventSaver; // saved Return event delegate from the *parent* of this PF pageFunction._Resume = true; base.RestoreState(pageFunction); } ////// This override is used when doing journal navigation to a PF, not when it is resumed after /// a child PF finishes. /// internal override bool Navigate(INavigator navigator, NavigationMode navMode) { Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward); // Resume the PF and navigate to it. // Special case: doing fragment navigation or CustomContentState navigation // within a PF. Then don't create a new PF object! IDownloader idl = navigator as IDownloader; NavigationService ns = idl != null ? idl.Downloader : null; Debug.Assert(ns != null, "Fragment navigation won't work when the INavigator doesn't have a NavigationService."); PageFunctionBase pageFunction = (ns != null && ns.ContentId == this.ContentId) ? (PageFunctionBase)ns.Content : ResumePageFunction(); Debug.Assert(pageFunction != null); return navigator.Navigate(pageFunction, new NavigateInfo(this.Source, navMode, this)); } #endregion // Internal properties ///////////////////////////////////////////////////////////////////// #region Internal properties #endregion // private methods ///////////////////////////////////////////////////////////////////// // Private fields // // If you add any fields here, check if it needs to be serialized. // If yes, then add it to the ISerializable implementation and make // corresponding changes in the Serialization constructor. // ///////////////////////////////////////////////////////////////////// #region Private fields private ReturnEventSaver _returnEventSaver; #endregion } // // When the PageFunction is implemented in a pure code file without Xaml file involved, // and the instance of such PageFunction was passed to Navigiation method, JournalEntryPageFunctionType // would be created to save journal data information. // [Serializable] internal class JournalEntryPageFunctionType : JournalEntryPageFunctionSaver, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors ////// Critical: Sets the crtical _typeName. /// Safe: The type is a subtype of PageFunctionBase, and the application has access to it. /// [SecurityCritical, SecurityTreatAsSafe] internal JournalEntryPageFunctionType(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, pageFunction) { string typeName = pageFunction.GetType().AssemblyQualifiedName; this._typeName = new SecurityCriticalDataForSet(typeName); } /// /// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// The base implementation needs to be called if this class is overridden /// ////// Critical: Sets the critical _typeName. /// [SecurityCritical] protected JournalEntryPageFunctionType(SerializationInfo info, StreamingContext context) : base(info, context) { _typeName = new SecurityCriticalDataForSet(info.GetString("_typeName")); } // // ISerializable implementation // /// /// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_typeName", _typeName.Value); } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override void SaveState(object contentObject) { Debug.Assert(contentObject.GetType().AssemblyQualifiedName == this._typeName.Value, "The type of a PageFunction a journal entry is associated with cannot change."); base.SaveState(contentObject); // Save controls state (JournalDataStreams). } // // Reconstitutes the PageFunction associated with this journal entry so that it can be // re-navigated to. Happens when returning from a child PF or doing journal navigation. // // The PageFunction should be implemented in pure code file without xaml file involved. // ////// Critical: Asserts ReflectionPermission to create an instance of the page function type. /// Safe: The object created is of the same type that the application originally navigated to. /// It is necessarily derived from PageFunctionBase. /// [SecurityCritical, SecurityTreatAsSafe] internal override PageFunctionBase ResumePageFunction() { PageFunctionBase pageFunction; Invariant.Assert(this._typeName.Value != null, "JournalEntry does not contain the Type for the PageFunction to be created"); //First try Type.GetType from the saved typename, then try Activator.CreateInstanceFrom //Type.GetType - Since the typename is fullyqualified //we will end up using the default binding mechanism to locate and bind to the assembly. //If the assembly was not a strongly named one nor is present in the APPBASE, this will //fail. Type pfType = Type.GetType(this._typeName.Value); new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); try { pageFunction = (PageFunctionBase)Activator.CreateInstance(pfType); } catch (Exception ex) { throw new Exception(SR.Get(SRID.FailedResumePageFunction, this._typeName.Value), ex); } finally { ReflectionPermission.RevertAssert(); } InitializeComponent(pageFunction); RestoreState(pageFunction); return pageFunction; } #endregion #region private method private void InitializeComponent(PageFunctionBase pageFunction) { // Need to explicitly add a call to InitializeComponent() for Page IComponentConnector iComponentConnector = pageFunction as IComponentConnector; if (iComponentConnector != null) { iComponentConnector.InitializeComponent(); } } #endregion // private methods ///////////////////////////////////////////////////////////////////// // Private fields // // If you add any fields here, check if it needs to be serialized. // If yes, then add it to the ISerializable implementation and make // corresponding changes in the Serialization constructor. // ///////////////////////////////////////////////////////////////////// #region Private fields /// AssemblyQualifiedName of the PageFunction Type ////// Critical: The type name is used to create an instance under elevation. We have to make /// sure that it is the same page function type that the application originally navigated to. /// private SecurityCriticalDataForSet_typeName; #endregion } // // When the PageFunction is implemented in a xaml file, or it was navigated from a Uri, // JournalEntryPageFunctionUri would be created to save journal data information. // [Serializable] internal class JournalEntryPageFunctionUri : JournalEntryPageFunctionSaver, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryPageFunctionUri(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction, Uri markupUri) : base(jeGroupState, pageFunction) { _markupUri = markupUri; } protected JournalEntryPageFunctionUri(SerializationInfo info, StreamingContext context) : base(info, context) { _markupUri = (Uri)info.GetValue("_markupUri", typeof(Uri)); } // // ISerializable implementation // /// /// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_markupUri", _markupUri); } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods // // Create an instance of PageFunction for Resume purpose. this PageFunction should be created // from a Uri. // internal override PageFunctionBase ResumePageFunction() { PageFunctionBase pageFunction; // // The page function was compiled from a xaml file. // // We should pay more attention on this scenario. The instance of PageFunction is created from // the baml stream, but it should ignore the value setting for all the Journal-able properties // and elements while the tree is created from the original baml stream. // Debug.Assert(_markupUri != null, "_markupUri in JournalEntryPageFunctionUri should be set."); pageFunction = Application.LoadComponent(_markupUri, true) as PageFunctionBase; RestoreState(pageFunction); return pageFunction; } #endregion // Private field #region private fields // // Keep the Uri that is associated with current PageFunction page. // It could be Navigator.Source or the Uri of Baml resource for the PageFunction type. // // Notes: We don't mix this with JournalEntry.Source, since NavigationService has some special usage // for JE.Source, JE.Source could affect the Navigator.Source in some scenario. // private Uri _markupUri; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // File: Journaling.cs // // Description: Contains various journaling related internal enums and classes // // History: // 1/20/2005: ChangoV Branched off system/windows/navigation/JournalEntry.cs // // Copyright (C) 2006 by Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Security; using System.Security.Permissions; using System.Runtime.Serialization; using System.Diagnostics; using System.Windows; using System.Windows.Markup; using System.Windows.Navigation; using MS.Internal.Utility; //In order to avoid generating warnings about unknown message numbers and //unknown pragmas when compiling your C# source code with the actual C# compiler, //you need to disable warnings 1634 and 1691. (Presharp Documentation) #pragma warning disable 1634, 1691 namespace MS.Internal.AppModel { [Serializable] internal enum JournalEntryType : byte { Navigable, UiLess, } internal enum JournalReason { NewContentNavigation = 1, FragmentNavigation, AddBackEntry }; ////// Encapsulates the custom journal state of an element implementing IJournalState. /// [Serializable] internal abstract class CustomJournalStateInternal { ////// Called when the entire journal is about to be binary-serialized. Non-serializable objects /// should be removed or replaced with serializable ones. /// internal virtual void PrepareForSerialization() { } }; ////// Currently used in two contexts: /// 1) Allows an element in the logical tree of INavigator.Content to implement "custom" journaling /// of its state, beyond the DP journaling that DataStreams does. /// [The public IProvideCustomContentState applies only to the root element.] /// journalReason is always NewContentNavigation in this use. /// Initially, the only actual use is for Frame to preserve its own journal. /// 2) Root viewer journaling. See NavigationService.MakeJournalEntry()... /// internal interface IJournalState { CustomJournalStateInternal GetJournalState(JournalReason journalReason); void RestoreJournalState(CustomJournalStateInternal state); }; ////// Shared state for all journal entries associated with the same content object ("bind product"). /// Journal entries created for fragment navigations or CustomContentState navigations within the /// current page share one JournalEntryGroupState object. This avoids duplication of state and /// the problems described in bug 1216726. /// [Serializable] internal class JournalEntryGroupState { internal JournalEntryGroupState() { } internal JournalEntryGroupState(Guid navSvcId, uint contentId) { _navigationServiceId = navSvcId; _contentId = contentId; } internal Guid NavigationServiceId { get { return _navigationServiceId; } set { _navigationServiceId = value; } } ////// Unique identifier (within a NavigationService, not across the entire Journal) of the page /// content ("bind product") this journal entry group is associated with. /// One use of this property is to help us distinguish back/fwd navigations /// within the same page from navigations to a different instance of the same page /// (same URI, modulo #frament id). (Bugs 1187603 and 1187613). /// Zero is not a valid id. /// internal uint ContentId { get { return _contentId; } set { Debug.Assert(_contentId == 0 || _contentId == value, "Once set, the ContentId for a JournalEntryGroup should not be changed."); _contentId = value; } } internal DataStreams JournalDataStreams { #if DEBUG [DebuggerStepThrough] #endif get { // Do not make this getter create a new DataStreams object. Keep-alive journal entries // don't need it. return _journalDataStreams; } set { _journalDataStreams = value; } } internal JournalEntry GroupExitEntry { get { return _groupExitEntry; } set { Debug.Assert(value.JEGroupState == this); Debug.Assert(_groupExitEntry == null || _groupExitEntry.ContentId == value.ContentId); _groupExitEntry = value; } } private Guid _navigationServiceId; private uint _contentId; private DataStreams _journalDataStreams; private JournalEntry _groupExitEntry; }; ////// The journal entry when journaling by URI. When navigating away, it will save the form state. /// When navigating back/forwards to this entry, it will navigate back to the URI, and then /// restore the form state. /// [Serializable] internal class JournalEntryUri : JournalEntry, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryUri(JournalEntryGroupState jeGroupState, Uri uri) : base(jeGroupState, uri) { } ////// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// protected JournalEntryUri(SerializationInfo info, StreamingContext context) : base(info, context) { } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override void SaveState(object contentObject) { Invariant.Assert(this.Source != null, "Can't journal by Uri without a Uri."); base.SaveState(contentObject); // Save controls state (JournalDataStreams). } #endregion } ////// This is the journal entry class for use when the entire tree is being kept alive. It will be /// saved when navigated away from, and when restored, it navigates to the saved tree. /// // Not [Serializable], because keep-alive content should not be serialized into the TravelLog. internal class JournalEntryKeepAlive : JournalEntry { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryKeepAlive(JournalEntryGroupState jeGroupState, Uri uri, object keepAliveRoot) : base(jeGroupState, uri) { Invariant.Assert(keepAliveRoot != null); _keepAliveRoot = keepAliveRoot; } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods ////// This is how the JournalEntry holds on to the tree itself. There is no need to keep track of other /// things c.f. AlivePageFunction. /// internal object KeepAliveRoot { get { return _keepAliveRoot; } } internal override bool IsAlive() { return this.KeepAliveRoot != null; } internal override void SaveState(object contentObject) { Debug.Assert(this.KeepAliveRoot == contentObject); // set by ctor; shouldn't change this._keepAliveRoot = contentObject; // No call to base.SaveState() since it saves controls state, and contentObject is KeepAlive. } internal override bool Navigate(INavigator navigator, NavigationMode navMode) { Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward); Debug.Assert(this.KeepAliveRoot != null); return navigator.Navigate(this.KeepAliveRoot, new NavigateInfo(Source, navMode, this)); } #endregion #region Private fields private object _keepAliveRoot; // the root of a tree being kept alive #endregion } ////// The journal entry for page functions. Ideally, these would use the same journal method /// that the other entries use, and derive from the other JournalEntry* classes to add the /// small bit of functionality that the page functions require (the Finish handler, for one.) /// [Serializable] internal abstract class JournalEntryPageFunction : JournalEntry, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryPageFunction(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, null) { PageFunctionId = pageFunction.PageFunctionId; ParentPageFunctionId = pageFunction.ParentPageFunctionId; } ////// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// The base implementation needs to be called if this class is overridden /// protected JournalEntryPageFunction(SerializationInfo info, StreamingContext context) : base(info, context) { _pageFunctionId = (Guid)info.GetValue("_pageFunctionId", typeof(Guid)); _parentPageFunctionId = (Guid)info.GetValue("_parentPageFunctionId", typeof(Guid)); ; } // // ISerializable implementation // ////// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_pageFunctionId", _pageFunctionId); info.AddValue("_parentPageFunctionId", _parentPageFunctionId); } #endregion // Internal Properties ///////////////////////////////////////////////////////////////////// ////// This is the GUID for this PageFunction. It will be used as its childrens' /// ParentPageFunctionId. /// internal Guid PageFunctionId { get { return _pageFunctionId; } set { _pageFunctionId = value; } } ////// If this PageFunction is a child PageFunction, this will be the GUID of its /// parent PageFunction. If this is Guid.Empty, then the parent is NOT a /// PageFunction. /// internal Guid ParentPageFunctionId { get { return _parentPageFunctionId; } set { _parentPageFunctionId = value; } } // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override bool IsPageFunction() { return true; } internal override bool IsAlive() { return false; } ////// Reconstitutes the PageFunction associated with this journal entry so that it can be /// re-navigated to. Happens when returning from a child PF or doing journal navigation. /// internal abstract PageFunctionBase ResumePageFunction(); #endregion #region internal Static method // // This method is to get the journal entry index in the Journal List for the parent page // of this PageFunction. // // The parent page could be a PageFunction or a Non-PageFunction. // For the non PageFunction case, it could have a Uri or could not have a Uri. // // Case 1: The ParentPageFunction has been set, so just go back and look for it. // Case 2: The ParentPageFunction has NOT been set, so the parent must be most recent non-PF entry. // internal static int GetParentPageJournalIndex(NavigationService NavigationService, Journal journal, PageFunctionBase endingPF) { JournalEntryPageFunction pageFunctionEntry; JournalEntry journalEntry; for (int index = journal.CurrentIndex - 1; index >= 0; --index) { journalEntry = journal[index]; // Be sure that the navigation containers match if (journalEntry.NavigationServiceId != NavigationService.GuidId) continue; pageFunctionEntry = journalEntry as JournalEntryPageFunction; if (endingPF.ParentPageFunctionId == Guid.Empty) { // We are looking for a non-PageFunction if (pageFunctionEntry == null) { return index; // found! } } else { // we are looking for a PageFunction if ((pageFunctionEntry != null) && (pageFunctionEntry.PageFunctionId == endingPF.ParentPageFunctionId)) { return index; // found! } } } Debug.Assert(endingPF.ParentPageFunctionId == Guid.Empty, "Should have been able to find the parent if the ParentPageFunctionId was set. Are they in different NavigationServices? They shouldn't be."); return _NoParentPage; } #endregion // Private fields // // If you add any fields here, check if it needs to be serialized. // If yes, then add it to the ISerializable implementation and make // corresponding changes in the Serialization constructor. // ///////////////////////////////////////////////////////////////////// private Guid _pageFunctionId; private Guid _parentPageFunctionId; internal const int _NoParentPage = -1; } ////// This is the class for page functions that are being kept alive. /// // Not [Serializable], because keep-alive content should not be serialized into the TravelLog. internal class JournalEntryPageFunctionKeepAlive : JournalEntryPageFunction { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryPageFunctionKeepAlive(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, pageFunction) { Debug.Assert(pageFunction != null && pageFunction.KeepAlive); this._keepAlivePageFunction = pageFunction; } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override bool IsPageFunction() { return true; } internal override bool IsAlive() { return this.KeepAlivePageFunction != null; } internal PageFunctionBase KeepAlivePageFunction { get { return _keepAlivePageFunction; } } internal override PageFunctionBase ResumePageFunction() { PageFunctionBase pageFunction = this.KeepAlivePageFunction; pageFunction._Resume = true; return pageFunction; } internal override void SaveState(object contentObject) { Invariant.Assert(_keepAlivePageFunction == contentObject); // set by ctor // No call to base.SaveState() since it saves controls state, and this PF is KeepAlive. } ////// This override is used when doing journal navigation to a PF, not when it is resumed after /// a child PF finishes. /// internal override bool Navigate(INavigator navigator, NavigationMode navMode) { Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward); // When doing fragment navigation within the PF, it should not be marked as Resumed; // otherwise, its Start() override may not be called. PageFunctionBase pf = (navigator.Content == _keepAlivePageFunction) ? _keepAlivePageFunction : ResumePageFunction(); Debug.Assert(pf != null); return navigator.Navigate(pf, new NavigateInfo(this.Source, navMode, this)); } #endregion #region Private fields PageFunctionBase _keepAlivePageFunction = null; #endregion } ////// JournalEntryPageFunctionSaver /// This is JournalEntry for PageFunction which is not set as KeepAlive. The PageFunction could be /// navigated from a Uri or the instance created from a PageFunction type. /// [Serializable] internal abstract class JournalEntryPageFunctionSaver : JournalEntryPageFunction, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors // // Ctor of JournalEntryPageFunctionSaver // internal JournalEntryPageFunctionSaver(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, pageFunction) { Debug.Assert(!pageFunction.KeepAlive); } ////// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// The base implementation needs to be called if this class is overridden /// protected JournalEntryPageFunctionSaver(SerializationInfo info, StreamingContext context) : base(info, context) { _returnEventSaver = (ReturnEventSaver)info.GetValue("_returnEventSaver", typeof(ReturnEventSaver)); } // // ISerializable implementation // ////// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_returnEventSaver", _returnEventSaver); } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override void SaveState(object contentObject) { PageFunctionBase pageFunction = (PageFunctionBase)contentObject; _returnEventSaver = pageFunction._Saver; base.SaveState(contentObject); // Save controls state (JournalDataStreams). } // // Take the PageFunction specific setting, then call the RestoreState in base class // to store previous state in a journal navigation. // internal override void RestoreState(object contentObject) { if (contentObject == null) throw new ArgumentNullException("contentObject"); PageFunctionBase pageFunction = (PageFunctionBase)contentObject; if (pageFunction == null) { throw new Exception(SR.Get(SRID.InvalidPageFunctionType, contentObject.GetType( ))); } pageFunction.ParentPageFunctionId = ParentPageFunctionId; pageFunction.PageFunctionId = PageFunctionId; pageFunction._Saver = _returnEventSaver; // saved Return event delegate from the *parent* of this PF pageFunction._Resume = true; base.RestoreState(pageFunction); } ////// This override is used when doing journal navigation to a PF, not when it is resumed after /// a child PF finishes. /// internal override bool Navigate(INavigator navigator, NavigationMode navMode) { Debug.Assert(navMode == NavigationMode.Back || navMode == NavigationMode.Forward); // Resume the PF and navigate to it. // Special case: doing fragment navigation or CustomContentState navigation // within a PF. Then don't create a new PF object! IDownloader idl = navigator as IDownloader; NavigationService ns = idl != null ? idl.Downloader : null; Debug.Assert(ns != null, "Fragment navigation won't work when the INavigator doesn't have a NavigationService."); PageFunctionBase pageFunction = (ns != null && ns.ContentId == this.ContentId) ? (PageFunctionBase)ns.Content : ResumePageFunction(); Debug.Assert(pageFunction != null); return navigator.Navigate(pageFunction, new NavigateInfo(this.Source, navMode, this)); } #endregion // Internal properties ///////////////////////////////////////////////////////////////////// #region Internal properties #endregion // private methods ///////////////////////////////////////////////////////////////////// // Private fields // // If you add any fields here, check if it needs to be serialized. // If yes, then add it to the ISerializable implementation and make // corresponding changes in the Serialization constructor. // ///////////////////////////////////////////////////////////////////// #region Private fields private ReturnEventSaver _returnEventSaver; #endregion } // // When the PageFunction is implemented in a pure code file without Xaml file involved, // and the instance of such PageFunction was passed to Navigiation method, JournalEntryPageFunctionType // would be created to save journal data information. // [Serializable] internal class JournalEntryPageFunctionType : JournalEntryPageFunctionSaver, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors ////// Critical: Sets the crtical _typeName. /// Safe: The type is a subtype of PageFunctionBase, and the application has access to it. /// [SecurityCritical, SecurityTreatAsSafe] internal JournalEntryPageFunctionType(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction) : base(jeGroupState, pageFunction) { string typeName = pageFunction.GetType().AssemblyQualifiedName; this._typeName = new SecurityCriticalDataForSet(typeName); } /// /// Serialization constructor. Marked Protected so derived classes can be deserialized correctly /// The base implementation needs to be called if this class is overridden /// ////// Critical: Sets the critical _typeName. /// [SecurityCritical] protected JournalEntryPageFunctionType(SerializationInfo info, StreamingContext context) : base(info, context) { _typeName = new SecurityCriticalDataForSet(info.GetString("_typeName")); } // // ISerializable implementation // /// /// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_typeName", _typeName.Value); } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods internal override void SaveState(object contentObject) { Debug.Assert(contentObject.GetType().AssemblyQualifiedName == this._typeName.Value, "The type of a PageFunction a journal entry is associated with cannot change."); base.SaveState(contentObject); // Save controls state (JournalDataStreams). } // // Reconstitutes the PageFunction associated with this journal entry so that it can be // re-navigated to. Happens when returning from a child PF or doing journal navigation. // // The PageFunction should be implemented in pure code file without xaml file involved. // ////// Critical: Asserts ReflectionPermission to create an instance of the page function type. /// Safe: The object created is of the same type that the application originally navigated to. /// It is necessarily derived from PageFunctionBase. /// [SecurityCritical, SecurityTreatAsSafe] internal override PageFunctionBase ResumePageFunction() { PageFunctionBase pageFunction; Invariant.Assert(this._typeName.Value != null, "JournalEntry does not contain the Type for the PageFunction to be created"); //First try Type.GetType from the saved typename, then try Activator.CreateInstanceFrom //Type.GetType - Since the typename is fullyqualified //we will end up using the default binding mechanism to locate and bind to the assembly. //If the assembly was not a strongly named one nor is present in the APPBASE, this will //fail. Type pfType = Type.GetType(this._typeName.Value); new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); try { pageFunction = (PageFunctionBase)Activator.CreateInstance(pfType); } catch (Exception ex) { throw new Exception(SR.Get(SRID.FailedResumePageFunction, this._typeName.Value), ex); } finally { ReflectionPermission.RevertAssert(); } InitializeComponent(pageFunction); RestoreState(pageFunction); return pageFunction; } #endregion #region private method private void InitializeComponent(PageFunctionBase pageFunction) { // Need to explicitly add a call to InitializeComponent() for Page IComponentConnector iComponentConnector = pageFunction as IComponentConnector; if (iComponentConnector != null) { iComponentConnector.InitializeComponent(); } } #endregion // private methods ///////////////////////////////////////////////////////////////////// // Private fields // // If you add any fields here, check if it needs to be serialized. // If yes, then add it to the ISerializable implementation and make // corresponding changes in the Serialization constructor. // ///////////////////////////////////////////////////////////////////// #region Private fields /// AssemblyQualifiedName of the PageFunction Type ////// Critical: The type name is used to create an instance under elevation. We have to make /// sure that it is the same page function type that the application originally navigated to. /// private SecurityCriticalDataForSet_typeName; #endregion } // // When the PageFunction is implemented in a xaml file, or it was navigated from a Uri, // JournalEntryPageFunctionUri would be created to save journal data information. // [Serializable] internal class JournalEntryPageFunctionUri : JournalEntryPageFunctionSaver, ISerializable { // Ctors ///////////////////////////////////////////////////////////////////// #region Ctors internal JournalEntryPageFunctionUri(JournalEntryGroupState jeGroupState, PageFunctionBase pageFunction, Uri markupUri) : base(jeGroupState, pageFunction) { _markupUri = markupUri; } protected JournalEntryPageFunctionUri(SerializationInfo info, StreamingContext context) : base(info, context) { _markupUri = (Uri)info.GetValue("_markupUri", typeof(Uri)); } // // ISerializable implementation // /// /// Critical: does object serialization /// Public OK: has a LinkDemand /// [SecurityCritical] [SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("_markupUri", _markupUri); } #endregion // Internal methods ///////////////////////////////////////////////////////////////////// #region Internal methods // // Create an instance of PageFunction for Resume purpose. this PageFunction should be created // from a Uri. // internal override PageFunctionBase ResumePageFunction() { PageFunctionBase pageFunction; // // The page function was compiled from a xaml file. // // We should pay more attention on this scenario. The instance of PageFunction is created from // the baml stream, but it should ignore the value setting for all the Journal-able properties // and elements while the tree is created from the original baml stream. // Debug.Assert(_markupUri != null, "_markupUri in JournalEntryPageFunctionUri should be set."); pageFunction = Application.LoadComponent(_markupUri, true) as PageFunctionBase; RestoreState(pageFunction); return pageFunction; } #endregion // Private field #region private fields // // Keep the Uri that is associated with current PageFunction page. // It could be Navigator.Source or the Uri of Baml resource for the PageFunction type. // // Notes: We don't mix this with JournalEntry.Source, since NavigationService has some special usage // for JE.Source, JE.Source could affect the Navigator.Source in some scenario. // private Uri _markupUri; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SchemaCollectionCompiler.cs
- sqlcontext.cs
- PolicyAssertionCollection.cs
- XmlAttributeOverrides.cs
- BaseTemplateParser.cs
- SchemaImporter.cs
- SqlUtils.cs
- NavigationEventArgs.cs
- PlatformCulture.cs
- HostedTransportConfigurationBase.cs
- CircleHotSpot.cs
- ControlBuilder.cs
- ISCIIEncoding.cs
- JoinQueryOperator.cs
- Grid.cs
- RoleManagerModule.cs
- MessageSmuggler.cs
- SqlMetaData.cs
- SSmlParser.cs
- SqlDependencyUtils.cs
- StreamedWorkflowDefinitionContext.cs
- BitmapEffectInputData.cs
- PeerNearMe.cs
- NamedObject.cs
- QueryCacheManager.cs
- WithParamAction.cs
- Trustee.cs
- HtmlTitle.cs
- DrawListViewSubItemEventArgs.cs
- URLMembershipCondition.cs
- Setter.cs
- DesignerDataParameter.cs
- ProcessModelSection.cs
- HwndSourceKeyboardInputSite.cs
- EventLog.cs
- DataFormat.cs
- BaseCodePageEncoding.cs
- Adorner.cs
- cryptoapiTransform.cs
- GC.cs
- ListManagerBindingsCollection.cs
- BlobPersonalizationState.cs
- InheritablePropertyChangeInfo.cs
- _Rfc2616CacheValidators.cs
- ConnectionsZone.cs
- SafeMILHandleMemoryPressure.cs
- SessionStateSection.cs
- FloatSumAggregationOperator.cs
- PerformanceCounterNameAttribute.cs
- XmlNotation.cs
- AxisAngleRotation3D.cs
- ContextBase.cs
- RequestCachingSection.cs
- SoapEnumAttribute.cs
- MediaScriptCommandRoutedEventArgs.cs
- SqlDataRecord.cs
- EntityDataSourceDesignerHelper.cs
- ScriptRef.cs
- Win32Native.cs
- CompositeFontFamily.cs
- ItemList.cs
- TriggerAction.cs
- GroupItem.cs
- basecomparevalidator.cs
- IisTraceWebEventProvider.cs
- securitycriticaldata.cs
- PathFigureCollection.cs
- Invariant.cs
- PageRanges.cs
- Tablet.cs
- Int64.cs
- BufferedResponseStream.cs
- GenericsInstances.cs
- EventBuilder.cs
- Translator.cs
- AndCondition.cs
- QualificationDataAttribute.cs
- Brush.cs
- DispatcherOperation.cs
- DataControlCommands.cs
- CursorInteropHelper.cs
- DebuggerService.cs
- Helper.cs
- DataBoundControlAdapter.cs
- SqlDataSourceEnumerator.cs
- TrackingWorkflowEventArgs.cs
- ProcessHostFactoryHelper.cs
- ThicknessAnimationUsingKeyFrames.cs
- SystemPens.cs
- ProtocolsConfigurationHandler.cs
- HttpPostedFile.cs
- GetWinFXPath.cs
- HttpResponse.cs
- Point.cs
- TimeSpanMinutesConverter.cs
- CommittableTransaction.cs
- ListItemCollection.cs
- PropertyTab.cs
- RowTypeElement.cs
- precedingquery.cs