Exemplo n.º 1
0
        private SimulatedPageFile MakeFinalHtmlForPdfMaker()
        {
            if (_currentlyLoadedBook == null)
            {
                _currentlyLoadedBook = BookSelection.CurrentSelection;
            }
            PdfFilePath = GetPdfPath(Path.GetFileName(_currentlyLoadedBook.FolderPath));

            var orientationChanging = BookSelection.CurrentSelection.GetLayout().SizeAndOrientation.IsLandScape !=
                                      PageLayout.SizeAndOrientation.IsLandScape;
            var dom = BookSelection.CurrentSelection.GetDomForPrinting(BookletPortion, _currentBookCollectionSelection.CurrentSelection,
                                                                       _bookServer, orientationChanging, PageLayout);

            AddStylesheetClasses(dom.RawDom);

            PageLayout.UpdatePageSplitMode(dom.RawDom);
            if (_currentlyLoadedBook.FullBleed && !GetPrintingWithFullBleed())
            {
                ClipBookToRemoveFullBleed(dom);
            }

            XmlHtmlConverter.MakeXmlishTagsSafeForInterpretationAsHtml(dom.RawDom);
            dom.UseOriginalImages = true;             // don't want low-res images or transparency in PDF.
            return(BloomServer.MakeSimulatedPageFileInBookFolder(dom, source: BloomServer.SimulatedPageFileSource.Pub));
        }
Exemplo n.º 2
0
        public ProjectContext(string projectSettingsPath, IContainer parentContainer)
        {
            BuildSubContainerForThisProject(projectSettingsPath, parentContainer);

            ProjectWindow = _scope.Resolve <Shell>();

            string collectionDirectory = Path.GetDirectoryName(projectSettingsPath);

            //should we save a link to this in the list of collections?
            var collectionSettings = _scope.Resolve <CollectionSettings>();

            if (collectionSettings.IsSourceCollection)
            {
                AddShortCutInComputersBloomCollections(collectionDirectory);
            }

            if (Path.GetFileNameWithoutExtension(projectSettingsPath).ToLower().Contains("web"))
            {
                BookCollection editableCollection    = _scope.Resolve <BookCollection.Factory>()(collectionDirectory, BookCollection.CollectionType.TheOneEditableCollection);
                var            sourceCollectionsList = _scope.Resolve <SourceCollectionsList>();
                _bloomServer = new BloomServer(_scope.Resolve <CollectionSettings>(), editableCollection, sourceCollectionsList, _scope.Resolve <HtmlThumbNailer>());
                _bloomServer.Start();
            }
            else
            {
                if (Settings.Default.ImageHandler != "off")
                {
                    _imageServer = _scope.Resolve <ImageServer>();

                    _imageServer.StartWithSetupIfNeeded();
                }
            }
        }
        internal static BloomServer GetTestServer()
        {
            var server = new BloomServer(new RuntimeImageProcessor(new BookRenamedEvent()), GetTestBookSelection(), s_collectionSettings, GetTestFileLocator());

            server.StartListening();
            return(server);
        }
Exemplo n.º 4
0
        public void CanRetrieveContentOfFakeTempFile_ButOnlyUntilDisposed()
        {
            using (var server = CreateBloomServer())
            {
                var html = @"<html ><head></head><body>here it is</body></html>";
                var dom  = new HtmlDom(html);
                dom.BaseForRelativePaths = _folder.Path.ToLocalhost();
                string url;
                using (var fakeTempFile = BloomServer.MakeSimulatedPageFileInBookFolder(dom))
                {
                    url = fakeTempFile.Key;
                    var transaction = new PretendRequestInfo(url);

                    // Execute
                    server.MakeReply(transaction);

                    // Verify
                    // Whitespace inserted by CreateHtml5StringFromXml seems to vary across versions and platforms.
                    // I would rather verify the actual output, but don't want this test to be fragile, and the
                    // main point is that we get a file with the DOM content.
                    Assert.That(transaction.ReplyContents,
                                Is.EqualTo(dom.getHtmlStringDisplayOnly()));
                }
                server.DoIdleTasksIfNoActivity();
                var transactionFail = new PretendRequestInfo(url);

                // Execute
                server.MakeReply(transactionFail);

                // Verify
                Assert.That(transactionFail.StatusCode, Is.EqualTo(404));
            }
        }
Exemplo n.º 5
0
 public void Setup()
 {
     // as long as we're only using one, fixed port number, we need to prevent unit test runner
     // from running these tests in parallel.
     Monitor.Enter(_portMonitor);
     _server = new BloomServer(new BookSelection());
 }
Exemplo n.º 6
0
        public static string GetString(BloomServer server, string endPoint, string query = "",
                                       ContentType returnType = ContentType.Text, EndpointHandler handler = null, string endOfUrlForTest = null)
        {
            if (handler != null)
            {
                server.ApiHandler.RegisterEndpointHandler(endPoint, handler, true);
            }
            server.StartListening();
            var client = new WebClientWithTimeout
            {
                Timeout = 3000,
            };

            client.Headers[HttpRequestHeader.ContentType] = returnType == ContentType.Text ? "text/plain" : "application/json";

            if (endOfUrlForTest != null)
            {
                return(client.DownloadString(BloomServer.ServerUrlWithBloomPrefixEndingInSlash + "api/" + endOfUrlForTest));
            }
            else
            {
                if (!string.IsNullOrEmpty(query))
                {
                    query = "?" + query;
                }
                return(client.DownloadString(BloomServer.ServerUrlWithBloomPrefixEndingInSlash + "api/" + endPoint + query));
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Sets up the Bloom server and registers the Problem Report API handler to it
        /// </summary>
        private void SetupApiHandler(BookSelection bookSelection)
        {
            _server = new BloomServer(bookSelection);
            var controller = new ProblemReportApi(bookSelection);

            controller.RegisterWithApiHandler(_server.ApiHandler);
        }
Exemplo n.º 8
0
 public void TearDown()
 {
     if (_server != null)
     {
         _server.Dispose();
         _server = null;
     }
 }
Exemplo n.º 9
0
 private static string AdjustPossibleLocalHostPathToFilePath(string path)
 {
     if (!path.StartsWith("localhost/", StringComparison.InvariantCulture))
     {
         return(path);
     }
     return(BloomServer.LocalHostPathToFilePath(path));
 }
Exemplo n.º 10
0
        public void Setup()
        {
            _bookSelection = new BookSelection();
            _bookSelection.SelectBook(new Bloom.Book.Book());
            _server = new BloomServer(_bookSelection);

            var controller = new ReadersApi(_bookSelection, null);

            controller.RegisterWithApiHandler(_server.ApiHandler);
        }
Exemplo n.º 11
0
        public void InitialSetup()
        {
            var bookSelection = new BookSelection();

            bookSelection.SelectBook(new Bloom.Book.Book());
            _server = new BloomServer(bookSelection);

            var controller = new FileIOApi(bookSelection);

            controller.RegisterWithApiHandler(_server.ApiHandler);
        }
Exemplo n.º 12
0
        public void ServerKnowsDifferenceBetweenRealAndThumbVideos(BloomServer.SimulatedPageFileSource source, bool expectVideo)
        {
            using (var server = CreateBloomServer())
            {
                const string html = @"<html ><head></head><body>
						<div class='bloom-page'>
							<div id='1' class='bloom-videoContainer bloom-noVideoSelected bloom-leadingElement bloom-selected'>
								<video>
									<source src='video/randommp4filename.mp4#t=0.0,4.6'>
									</source>
								</video>
							</div>
							<div class='otherStuff'>
							</div>
							<div id='2' class='bloom-videoContainer'>
								<video>
									<source src='video/otherrandomfilename.mp4'>
									</source>
								</video>
							</div>
							<div id='3' class='bloom-videoContainer bloom-noVideoSelected bloom-leadingElement bloom-selected'>
							</div>
						</div>
						<div class='afterStuff'>
						</div>
					</body></html>"                    ;
                var          dom  = new HtmlDom(html)
                {
                    BaseForRelativePaths = _folder.Path.ToLocalhost()
                };
                using (var fakeTempFile = BloomServer.MakeSimulatedPageFileInBookFolder(dom, true, true, source))
                {
                    var url         = fakeTempFile.Key;
                    var transaction = new PretendRequestInfo(url);

                    // Execute
                    server.MakeReply(transaction);

                    // Verify
                    var contents = transaction.ReplyContents;
                    if (expectVideo)
                    {
                        AssertThatXmlIn.String(contents).HasSpecifiedNumberOfMatchesForXpath("//div[contains(@class,'bloom-videoContainer')]", 3);
                        AssertThatXmlIn.String(contents).HasNoMatchForXpath("//div[contains(@class,'bloom-imageContainer')]");
                    }
                    else
                    {
                        AssertThatXmlIn.String(contents).HasSpecifiedNumberOfMatchesForXpath("//div[contains(@class,'bloom-imageContainer')]", 3);
                        AssertThatXmlIn.String(contents).HasNoMatchForXpath("//div[contains(@class,'bloom-videoContainer')]");
                    }
                }
            }
        }
Exemplo n.º 13
0
        /// ------------------------------------------------------------------------------------
        public void Dispose()
        {
            _scope.Dispose();
            _scope = null;

            if (_bloomServer != null)
            {
                _bloomServer.Dispose();
            }
            _bloomServer = null;
            if (_imageServer != null)
            {
                _imageServer.Dispose();
            }
            _imageServer = null;
        }
Exemplo n.º 14
0
        public static string PostString(BloomServer server, string endPoint, string data, ContentType returnType,
                                        EndpointHandler handler = null)
        {
            if (handler != null)
            {
                server.ApiHandler.RegisterEndpointHandler(endPoint, handler, true);
            }
            server.StartListening();
            var client = new WebClientWithTimeout
            {
                Timeout = 3000
            };

            client.Headers[HttpRequestHeader.ContentType] = returnType == ContentType.Text ? "text/plain" : "application/json";

            return(client.UploadString(BloomServer.ServerUrlWithBloomPrefixEndingInSlash + "api/" + endPoint, "POST", data));
        }
Exemplo n.º 15
0
        private PretendRequestInfo CreateServerMakeSimPageMakeReply(HtmlDom dom, bool simulateCallingFromJavascript = false)
        {
            PretendRequestInfo transaction;

            using (var server = CreateBloomServer())
            {
                using (var fakeTempFile = BloomServer.MakeSimulatedPageFileInBookFolder(dom, simulateCallingFromJavascript))
                {
                    var url = fakeTempFile.Key;
                    transaction = new PretendRequestInfo(url, forPrinting: false, forSrcAttr: simulateCallingFromJavascript);

                    // Execute
                    server.MakeReply(transaction);
                }
            }
            return(transaction);
        }
Exemplo n.º 16
0
        private void ShowBook(bool updatePreview = true)
        {
            if (_bookSelection.CurrentSelection == null || !_visible)
            {
                HidePreview();
            }
            else
            {
                Debug.WriteLine("LibraryBookView.ShowBook() currentselection ok");

                _readmeBrowser.Visible = false;
                _splitContainerForPreviewAndAboutBrowsers.Visible = true;
                if (updatePreview && !TroubleShooterDialog.SuppressBookPreview)
                {
                    var previewDom = _bookSelection.CurrentSelection.GetPreviewHtmlFileForWholeBook();
                    XmlHtmlConverter.MakeXmlishTagsSafeForInterpretationAsHtml(previewDom.RawDom);
                    var fakeTempFile = BloomServer.MakeSimulatedPageFileInBookFolder(previewDom, setAsCurrentPageForDebugging: false, source: BloomServer.SimulatedPageFileSource.Preview);
                    _reactBookPreviewControl.Props = new { initialBookPreviewUrl = fakeTempFile.Key }; // need this for initial selection
                    _webSocketServer.SendString("bookStatus", "changeBook", fakeTempFile.Key);         // need this for changing selection display
                    _webSocketServer.SendEvent("bookStatus", "reload");                                // need this for changing selection's book info display if team collection
                    _reactBookPreviewControl.Visible = true;
                    RecordAndCleanupFakeFiles(fakeTempFile);
                }
                _splitContainerForPreviewAndAboutBrowsers.Panel2Collapsed = true;
                if (_bookSelection.CurrentSelection.HasAboutBookInformationToShow)
                {
                    if (RobustFile.Exists(_bookSelection.CurrentSelection.AboutBookHtmlPath))
                    {
                        _splitContainerForPreviewAndAboutBrowsers.Panel2Collapsed = false;
                        _readmeBrowser.Navigate(_bookSelection.CurrentSelection.AboutBookHtmlPath, false);
                        _readmeBrowser.Visible = true;
                    }
                    else if (RobustFile.Exists(_bookSelection.CurrentSelection.AboutBookMdPath))
                    {
                        _splitContainerForPreviewAndAboutBrowsers.Panel2Collapsed = false;
                        var md       = new Markdown();
                        var contents = RobustFile.ReadAllText(_bookSelection.CurrentSelection.AboutBookMdPath);
                        _readmeBrowser.NavigateRawHtml(string.Format("<html><head><meta charset=\"utf-8\"/></head><body>{0}</body></html>", md.Transform(contents)));
                        _readmeBrowser.Visible = true;
                    }
                }
                _reshowPending = false;
            }
        }
Exemplo n.º 17
0
 public void OneTimeSetUp()
 {
     _server = new BloomServer(new BookSelection());
 }
Exemplo n.º 18
0
 public void Teardown()
 {
     _server.Dispose();
     _server = null;
     Monitor.Exit(_portMonitor);
 }
Exemplo n.º 19
0
        /// <summary>
        /// Returns true if it make some attempt at an image, false if navigation is currently suppressed.
        /// </summary>
        /// <param name="order"></param>
        /// <param name="browser"></param>
        /// <param name="thumbnail"></param>
        /// <returns></returns>
        private bool CreateThumbNail(ThumbnailOrder order, GeckoWebBrowser browser, out Image thumbnail)
        {
            // runs on threadpool thread
            _currentOrder = order;
            thumbnail     = null;
            using (var temp = BloomServer.MakeSimulatedPageFileInBookFolder(order.Document, source: BloomServer.SimulatedPageFileSource.Thumb))
            {
                order.Done  = false;
                browser.Tag = order;
                Color coverColor;
                ImageUtils.TryCssColorFromString(Book.Book.GetCoverColorFromDom(order.Document.RawDom), out coverColor);
                if (!OpenTempFileInBrowser(browser, temp.Key))
                {
                    return(false);
                }

                var browserSize = SetWidthAndHeight(browser);
                if (browserSize.Height == 0)          //happens when we run into the as-yet-unreproduced-or-fixed bl-254
                {
                    return(false);                    // will try again later
                }
                try
                {
                    Logger.WriteMinorEvent("HtmlThumNailer ({2}): browser.GetBitmap({0},{1})", browserSize.Width,
                                           (uint)browserSize.Height,
                                           Thread.CurrentThread.ManagedThreadId);
                    //BUG (April 2013) found that the initial call to GetBitMap always had a zero width, leading to an exception which
                    //the user doesn't see and then all is well. So at the moment, we avoid the exception, and just leave with
                    //the placeholder thumbnail.
                    if (browserSize.Width == 0 || browserSize.Height == 0)
                    {
                        var paperSizeName = GetPaperSizeName(order.Document.RawDom);
                        throw new ApplicationException("Problem getting thumbnail browser for document with Paper Size: " + paperSizeName);
                    }

                    int topOfCoverImage    = -1;
                    int bottomOfCoverImage = -1;
                    _syncControl.Invoke((Action)(() =>
                    {
                        Guard.AgainstNull(browser.Document.ActiveElement, "browser.Document.ActiveElement");
                        var div = browser.Document.ActiveElement.EvaluateXPath("//div[contains(@class, 'bloom-imageContainer')]").GetNodes().FirstOrDefault() as GeckoHtmlElement;
                        if (div != null)
                        {
                            // Note that div.GetBoundingClientRect() returns nothing useful in Geckofx60: these values appear to work okay.
                            topOfCoverImage = div.OffsetTop;
                            bottomOfCoverImage = topOfCoverImage + div.OffsetHeight;
                        }
                    }));

                    using (Image fullsizeImage = CreateImage(browser, coverColor, topOfCoverImage, bottomOfCoverImage))
                    {
                        if (_disposed)
                        {
                            return(false);
                        }
                        thumbnail = MakeThumbNail(fullsizeImage, order.Options);
                        return(true);
                    }
                }
                catch (Exception error)
                {
                    Logger.WriteEvent("HtmlThumbNailer ({0}) got {1}", Thread.CurrentThread.ManagedThreadId, error.Message);
                    Logger.WriteEvent("Disposing of all browsers in hopes of getting a fresh start on life");
                    foreach (var browserCacheForDifferentPaperSize in _browserCacheForDifferentPaperSizes)
                    {
                        try
                        {
                            Logger.WriteEvent("Disposing of browser {0}", browserCacheForDifferentPaperSize.Key);
                            browserCacheForDifferentPaperSize.Value.Dispose();
                        }
                        catch (Exception e2)
                        {
                            Logger.WriteEvent(
                                "While trying to dispose of thumbnailer browsers as a result of an exception, go another: " + e2.Message);
                        }
                    }
                    _browserCacheForDifferentPaperSizes.Clear();
#if DEBUG
                    _syncControl.Invoke((Action)(() => Debug.Fail(error.Message)));
#endif
                }
            }
            return(false);
        }
 public virtual void OneTimeSetup()
 {
     s_collectionSettings = new CollectionSettings();
     s_testServer         = GetTestServer();
 }
Exemplo n.º 21
0
 public void OneTimeTearDown()
 {
     _server?.Dispose();
     _server = null;
 }
Exemplo n.º 22
0
        private void ShowNotifyDialog(string severity, string messageText, Exception exception,
                                      string reportButtonLabel, string secondaryButtonLabel)
        {
            // Before we do anything that might be "risky", put the problem in the log.
            ProblemReportApi.LogProblem(exception, messageText, severity);

            // ENHANCE: Allow the caller to pass in the control, which would be at the front of this.
            //System.Windows.Forms.Control control = Form.ActiveForm ?? FatalExceptionHandler.ControlOnUIThread;
            var control        = GetControlToUse();
            var isSyncRequired = false;

            SafeInvoke.InvokeIfPossible("Show Error Reporter", control, isSyncRequired, () =>
            {
                // Uses a browser dialog to show the problem report
                try
                {
                    StartupScreenManager.CloseSplashScreen();                     // if it's still up, it'll be on top of the dialog

                    var message = GetMessage(messageText, exception);

                    if (!Api.BloomServer.ServerIsListening)
                    {
                        // There's no hope of using the HtmlErrorReporter dialog if our server is not yet running.
                        // We'll likely get errors, maybe Javascript alerts, that won't lead to a clean fallback to
                        // the exception handler below. Besides, failure of HtmlErrorReporter in these circumstances
                        // is expected; we just want to cleanly report the original problem, not to report a
                        // failure of error handling.

                        // Note: HtmlErrorReporter supports up to 3 buttons (OK, Report, and [Secondary action]), but the fallback reporter only supports a max of two.
                        // Well, just going to have to drop the secondary action.

                        ShowFallbackProblemDialog(severity, exception, messageText, null, false);
                        return;
                    }

                    object props = new { level = ProblemLevel.kNotify, reportLabel = reportButtonLabel, secondaryLabel = secondaryButtonLabel, message = message };

                    // Precondition: we must be on the UI thread for Gecko to work.
                    using (var dlg = BrowserDialogFactory.CreateReactDialog("problemReportBundle", props))
                    {
                        dlg.FormBorderStyle = FormBorderStyle.FixedToolWindow; // Allows the window to be dragged around
                        dlg.ControlBox      = true;                            // Add controls like the X button back to the top bar
                        dlg.Text            = "";                              // Remove the title from the WinForms top bar

                        dlg.Width = 620;

                        // 360px was experimentally determined as what was needed for the longest known text for NotifyUserOfProblem
                        // (which is "Before saving, Bloom did an integrity check of your book [...]" from BookStorage.cs)
                        // You can make this height taller if need be.
                        // A scrollbar will appear if the height is not tall enough for the text
                        dlg.Height = 360;

                        // ShowDialog will cause this thread to be blocked (because it spins up a modal) until the dialog is closed.
                        BloomServer.RegisterThreadBlocking();

                        try
                        {
                            dlg.ShowDialog();

                            // Take action if the user clicked a button other than Close
                            if (dlg.CloseSource == "closedByAlternateButton" && OnSecondaryActionPressed != null)
                            {
                                OnSecondaryActionPressed(exception, message);
                            }
                            else if (dlg.CloseSource == "closedByReportButton")
                            {
                                if (OnReportButtonPressed != null)
                                {
                                    OnReportButtonPressed(exception, message);
                                }
                                else
                                {
                                    DefaultOnReportPressed(exception, message);
                                }
                            }

                            // Note: With the way LibPalaso's ErrorReport is designed,
                            // its intention is that after OnShowDetails is invoked and closed, you will not come back to the Notify Dialog
                            // This code has been implemented to follow that model
                            //
                            // But now that we have more options, it might be nice to come back to this dialog.
                            // If so, you'd need to add/update some code in this section.
                        }
                        finally
                        {
                            ResetToDefaults();
                            BloomServer.RegisterThreadUnblocked();
                        }
                    }
                }
                catch (Exception errorReporterException)
                {
                    Logger.WriteError("*** HtmlErrorReporter threw an exception trying to display", errorReporterException);
                    // At this point our problem reporter has failed for some reason, so we want the old WinForms handler
                    // to report both the original error for which we tried to open our dialog and this new one where
                    // the dialog itself failed.
                    // In order to do that, we create a new exception with the original exception (if there was one) as the
                    // inner exception. We include the message of the exception we just caught. Then we call the
                    // old WinForms fatal exception report directly.
                    // In any case, both of the errors will be logged by now.
                    var message = "Bloom's error reporting failed: " + errorReporterException.Message;

                    // Fallback to Winforms in case of trouble getting the browser to work
                    var fallbackReporter = new WinFormsErrorReporter();
                    // Food for thought: is it really fatal of the Notify Dialog had an exception? Maybe NonFatal makes more sense
                    fallbackReporter.ReportFatalException(new ApplicationException(message, exception ?? errorReporterException));
                }
            });
        }