docs: function pdfViewInitialize(appConfig) {
      configure(pdfjsLib.PDFJS);
      this.appConfig = appConfig;
  
      var eventBus = appConfig.eventBus || getGlobalEventBus();
      this.eventBus = eventBus;
      this.bindEvents();
  
      var pdfRenderingQueue = new PDFRenderingQueue();
      pdfRenderingQueue.onIdle = this.cleanup.bind(this);
      this.pdfRenderingQueue = pdfRenderingQueue;
  
      var pdfLinkService = new PDFLinkService({
        eventBus: eventBus
      });
      this.pdfLinkService = pdfLinkService;
  
      var downloadManager = this.externalServices.createDownloadManager();
      this.downloadManager = downloadManager;
  
      var container = appConfig.mainContainer;
      var viewer = appConfig.viewerContainer;
      this.pdfViewer = new PDFViewer({
        container: container,
        viewer: viewer,
        eventBus: eventBus,
        renderingQueue: pdfRenderingQueue,
        linkService: pdfLinkService,
        downloadManager: downloadManager
      });
      pdfRenderingQueue.setViewer(this.pdfViewer);
      pdfLinkService.setViewer(this.pdfViewer);
  
      var thumbnailContainer = appConfig.sidebar.thumbnailView;
      this.pdfThumbnailViewer = new PDFThumbnailViewer({
        container: thumbnailContainer,
        renderingQueue: pdfRenderingQueue,
        linkService: pdfLinkService
      });
      pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
  
      Preferences.initialize();
      this.preferences = Preferences;
  
      this.pdfHistory = new PDFHistory({
        linkService: pdfLinkService,
        eventBus: this.eventBus
      });
      pdfLinkService.setHistory(this.pdfHistory);
  
      this.findController = new PDFFindController({
        pdfViewer: this.pdfViewer
      });
      this.findController.onUpdateResultsCount = function (matchCount) {
        if (this.supportsIntegratedFind) {
          return;
        }
        this.findBar.updateResultsCount(matchCount);
      }.bind(this);
      this.findController.onUpdateState = function (state, previous, matchCount) {
        if (this.supportsIntegratedFind) {
          this.externalServices.updateFindControlState(
            {result: state, findPrevious: previous});
        } else {
          this.findBar.updateUIState(state, previous, matchCount);
        }
      }.bind(this);
  
      this.pdfViewer.setFindController(this.findController);
  
      // FIXME better PDFFindBar constructor parameters
      var findBarConfig = Object.create(appConfig.findBar);
      findBarConfig.findController = this.findController;
      findBarConfig.eventBus = this.eventBus;
      this.findBar = new PDFFindBar(findBarConfig);
  
      this.overlayManager = OverlayManager;
  
      this.handTool = new HandTool({
        container: container,
        eventBus: this.eventBus,
      });
  
      this.pdfDocumentProperties =
        new PDFDocumentProperties(appConfig.documentProperties);
  
      this.secondaryToolbar =
        new SecondaryToolbar(appConfig.secondaryToolbar, eventBus);
  
      if (this.supportsFullscreen) {
        this.pdfPresentationMode = new PDFPresentationMode({
          container: container,
          viewer: viewer,
          pdfViewer: this.pdfViewer,
          eventBus: this.eventBus,
          contextMenuItems: appConfig.fullscreen
        });
      }
  
      this.passwordPrompt = new PasswordPrompt(appConfig.passwordOverlay);
  
      this.pdfOutlineViewer = new PDFOutlineViewer({
        container: appConfig.sidebar.outlineView,
        eventBus: this.eventBus,
        linkService: pdfLinkService,
      });
  
      this.pdfAttachmentViewer = new PDFAttachmentViewer({
        container: appConfig.sidebar.attachmentsView,
        eventBus: this.eventBus,
        downloadManager: downloadManager
      });
  
      // FIXME better PDFSidebar constructor parameters
      var sidebarConfig = Object.create(appConfig.sidebar);
      sidebarConfig.pdfViewer = this.pdfViewer;
      sidebarConfig.pdfThumbnailViewer = this.pdfThumbnailViewer;
      sidebarConfig.pdfOutlineViewer = this.pdfOutlineViewer;
      sidebarConfig.eventBus = this.eventBus;
      this.pdfSidebar = new PDFSidebar(sidebarConfig);
      this.pdfSidebar.onToggled = this.forceRendering.bind(this);
  
      var self = this;
      var PDFJS = pdfjsLib.PDFJS;
      var initializedPromise = Promise.all([
        Preferences.get('enableWebGL').then(function resolved(value) {
          PDFJS.disableWebGL = !value;
        }),
        Preferences.get('sidebarViewOnLoad').then(function resolved(value) {
          self.preferenceSidebarViewOnLoad = value;
        }),
        Preferences.get('pdfBugEnabled').then(function resolved(value) {
          self.preferencePdfBugEnabled = value;
        }),
        Preferences.get('showPreviousViewOnLoad').then(function resolved(value) {
          self.preferenceShowPreviousViewOnLoad = value;
        }),
        Preferences.get('defaultZoomValue').then(function resolved(value) {
          self.preferenceDefaultZoomValue = value;
        }),
        Preferences.get('disableTextLayer').then(function resolved(value) {
          if (PDFJS.disableTextLayer === true) {
            return;
          }
          PDFJS.disableTextLayer = value;
        }),
        Preferences.get('disableRange').then(function resolved(value) {
          if (PDFJS.disableRange === true) {
            return;
          }
          PDFJS.disableRange = value;
        }),
        Preferences.get('disableStream').then(function resolved(value) {
          if (PDFJS.disableStream === true) {
            return;
          }
          PDFJS.disableStream = value;
        }),
        Preferences.get('disableAutoFetch').then(function resolved(value) {
          PDFJS.disableAutoFetch = value;
        }),
        Preferences.get('disableFontFace').then(function resolved(value) {
          if (PDFJS.disableFontFace === true) {
            return;
          }
          PDFJS.disableFontFace = value;
        }),
        Preferences.get('useOnlyCssZoom').then(function resolved(value) {
          PDFJS.useOnlyCssZoom = value;
        }),
        Preferences.get('externalLinkTarget').then(function resolved(value) {
          if (PDFJS.isExternalLinkTargetSet()) {
            return;
          }
          PDFJS.externalLinkTarget = value;
        }),
        // TODO move more preferences and other async stuff here
      ]).catch(function (reason) { });
  
      return initializedPromise.then(function () {
        if (self.isViewerEmbedded && !PDFJS.isExternalLinkTargetSet()) {
          // Prevent external links from "replacing" the viewer,
          // when it's embedded in e.g. an iframe or an object.
          PDFJS.externalLinkTarget = PDFJS.LinkTarget.TOP;
        }
  
        self.initialized = true;
      });
    }