1

I am writing a browser extension that has different services for Firefox and Chrome. The proper version of each service needs to be injected depending on the environment variable. While I can properly inject the appropriate service in the AppModule, I am unsure of how to get the proper services in my root component without a hacky workaround.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './index';
import { environment } from '../environments/environment';
import { MessageService } from './messaging.service';
import { MessageServiceFirefox } from './ff.messaging.service';
import { ScreenshotService } from './screenshot.service';
import { ScreenshotServiceFirefox } from './ff.screenshot.service';

export function screenshotFactory() {
  if (environment.envName == 'prod-ff' || environment.envName == 'ff') {
    return new ScreenshotServiceFirefox();
  } else {
    return new ScreenshotService();
  }
}

export function messageFactory() {
  if (environment.envName == 'prod-ff' || environment.envName == 'ff') {
    return new MessageServiceFirefox();
  } else {
    return new MessageService();
  }
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
  ],
  providers: [
    {
      provide: ScreenshotService,
      useFactory: screenshotFactory
    },
    {
      provide: MessageService,
      useFactory: messageFactory
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';
import { ScreenshotService } from './screenshot.service';
import { MessageService } from './messaging.service';
// Would need to import ScreenshotServiceFirefox and MessageServiceFirefox
// and have conditional logic to establish correct ScreenshotService and MessageService

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ScreenshotService, MessageService]
})


export class AppComponent {
  constructor(private screenshotService: ScreenshotService, private messageService: MessageService) {}

  takeScreenshot (){
    this.messageService.injectScript()
      .then(this.screenshotService.takeScreenshot)
      .then(this.screenshotService.convertToBlob)
      .then(this.screenshotService.downloadLocally)
  }
}

I've also tries using solutions here, here and here but none deal with accessing the injected service from within the root component without using the same conditional logic.

I'm open to suggestions of other ways to achieve this.

Community
  • 1
  • 1
  • Why do not you use base service? – yurzui Apr 25 '17 at 21:16
  • I'm not sure what you mean by a base service? – Micky Shaked Apr 25 '17 at 21:24
  • You already are getting whatever service your factories return when you inject a service in `AppComponent`. Is there something you want to do with the firefox version of the services that isn't on the API of the generic versions? – rob Apr 25 '17 at 21:38
  • The signature of the API methods used in the services is different for Chrome and Firefox. Chrome uses callbacks while Firefox returns promises so while the difference is slight, it's significant enough to have two versions. I thought I was getting the right service but when I loaded the extension into Firefox I determined after some debugging that it was using the chrome version of my services. – Micky Shaked Apr 25 '17 at 21:43

0 Answers0