Lesson 11-Electron Source Code Architecture

Electron Core Module Source Code

Inter-Process Communication (IPC) Mechanism

Core IPC Implementation

// ipc/ipc_message.h - IPC message definition
struct IPCMessage {
  int32_t routing_id;  // Routing ID (identifies target process/window)
  uint32_t type;       // Message type identifier
  std::vector<uint8_t> data; // Message payload
};

// ipc/ipc_channel_posix.cc - IPC channel implementation for POSIX systems
bool IPCChannelPosix::Send(IPCMessage* message) {
  // 1. Serialize message
  std::vector<uint8_t> serialized = SerializeMessage(message);

  // 2. Send via Unix domain socket
  ssize_t bytes_written = write(socket_fd_, serialized.data(), serialized.size());

  // 3. Error handling
  if (bytes_written < 0) {
    LOG(ERROR) << "IPC send failed: " << strerror(errno);
    return false;
  }
  return true;
}

// Main process message handling
void IPC::ChannelProxy::OnMessageReceived(const IPCMessage& message) {
  // 1. Deserialize message
  auto* ipc_message = DeserializeMessage(message);

  // 2. Dispatch based on message type
  switch (ipc_message->type) {
    case MSG_RENDER_PROCESS_CREATED:
      OnRenderProcessCreated(ipc_message);
      break;
    case MSG_RENDERER_TO_MAIN:
      DispatchToMainThread(ipc_message);
      break;
    // ...other message type handlers
  }
}

JavaScript Layer IPC Bridge

// lib/renderer/ipc.js - Renderer process IPC implementation
const { contextBridge, ipcRenderer } = require('electron');

// Expose safe IPC API to renderer process
contextBridge.exposeInMainWorld('electronIPC', {
  send: (channel, ...args) => {
    // Security validation: Whitelist check
    if (VALID_CHANNELS.includes(channel)) {
      ipcRenderer.send(channel, ...args);
    }
  },
  invoke: (channel, ...args) => {
    return new Promise((resolve, reject) => {
      ipcRenderer.invoke(channel, ...args)
        .then(resolve)
        .catch(reject);
    });
  }
});

// Main process IPC core logic
// lib/main/ipcMain.js
const ipcMain = {
  _channels: new Map(),

  handle(channel, listener) {
    if (!VALID_CHANNELS.includes(channel)) {
      throw new Error(`Channel ${channel} is not allowed`);
    }
    this._channels.set(channel, listener);
  },

  _onMessage(message) {
    const listener = this._channels.get(message.channel);
    if (listener) {
      listener(message.args);
    }
  }
};

Chromium and Node.js Integration Source Code

Key Integration Architecture Points

// content/renderer/render_process_impl.cc - Chromium renderer process initialization
void RenderProcessImpl::Init() {
  // 1. Initialize Chromium renderer process components
  RenderProcess::Init();

  // 2. Initialize Node.js runtime
  node::InitializeV8Platform(1); // Single-threaded V8 platform
  node::Start(0, nullptr);        // Start Node.js

  // 3. Establish bridge between Chromium and Node.js
  node::Environment* env = node::CreateEnvironment(
      node::IsolateData::FromV8(isolate_), 
      v8::Local<v8::Context>::New(isolate_, context_));

  // 4. Expose Node.js APIs to Chromium
  SetupNodeBindings(env);
}

// electron/lib/renderer/init.js - Node.js integration initialization
function initializeNodeIntegration() {
  // 1. Create Node.js context isolation environment
  const nodeContext = vm.createContext({
    require: restrictedRequire, // Restricted require implementation
    process: createSafeProcess(), // Safe process object
    Buffer: safeBuffer // Safe Buffer implementation
  });

  // 2. Inject predefined global variables
  Object.defineProperty(global, 'nodeRequire', {
    value: restrictedRequire,
    enumerable: false
  });

  // 3. Set context isolation flag
  process._electronIsContextIsolated = true;
}

Application Packaging and Distribution Source Code (electron-builder)

Core Packaging Process Code

// electron-builder/out/appBuilder.ts - Main packaging logic
async function build(appOutDir, packager) {
  // 1. Prepare packaging environment
  await packager.prepareApplicationStageDirectory(appOutDir);

  // 2. Copy application resources
  await copyApplicationResources(appOutDir, packager);

  // 3. Process native modules
  await processNativeModules(appOutDir, packager);

  // 4. Generate platform-specific installer
  switch (process.platform) {
    case 'win32':
      await buildWindowsInstaller(appOutDir, packager);
      break;
    case 'darwin':
      await buildMacDMG(appOutDir, packager);
      break;
    case 'linux':
      await buildLinuxDEB(appOutDir, packager);
      break;
  }

  // 5. Generate version metadata
  generateVersionMetadata(appOutDir, packager);
}

// Windows NSIS installer generation
async function buildWindowsInstaller(appOutDir, packager) {
  // 1. Generate NSIS script
  const nsisScript = generateNSISScript(packager);

  // 2. Call makensis to compile installer
  await execa('makensis', ['/NOCD', nsisScript.path]);

  // 3. Handle installer output
  await moveFile(nsisScript.outputPath, packager.outputPath);
}

Process Management Source Code

Process Creation and Management

// electron/lib/browser/process_manager.cc - Process management implementation
class ProcessManager {
 public:
  // Create renderer process
  std::unique_ptr<RenderProcessHost> CreateRenderProcess(
      int render_process_id,
      const content::RenderProcessHost::CreateParams& params) {
    // 1. Create base Chromium renderer process
    auto process = content::RenderProcessHost::Create(params);

    // 2. Inject Electron-specific initialization
    process->InitializeElectronExtensions();

    // 3. Set process priority
    SetProcessPriority(process.get());

    // 4. Register process to manager
    render_processes_[render_process_id] = std::move(process);
    return render_processes_[render_process_id];
  }

  // Terminate process
  void TerminateProcess(int render_process_id, int exit_code) {
    auto it = render_processes_.find(render_process_id);
    if (it != render_processes_.end()) {
      it->second->Terminate(exit_code);
      render_processes_.erase(it);
    }
  }
};

Renderer Process Lifecycle Management

// lib/renderer/init.js - Renderer process initialization
function initializeRendererProcess() {
  // 1. Initialize IPC communication
  initIPC();

  // 2. Load preload scripts
  loadPreloadScripts();

  // 3. Initialize security sandbox
  if (process._electronIsSandboxed) {
    initSandbox();
  }

  // 4. Set up process exception handling
  process.on('uncaughtException', (error) => {
    ipcRenderer.send('renderer-error', error);
  });

  // 5. Notify main process that renderer is ready
  ipcRenderer.send('renderer-ready');
}

Security Model Source Code

Security Isolation Implementation

// electron/lib/browser/security_context.cc - Security context implementation
class SecurityContext {
 public:
  // Initialize security context
  void Initialize(content::RenderFrameHost* frame_host) {
    // 1. Set context isolation flag
    frame_host->SetIsolatedWorldInfo(
        ISOLATED_WORLD_ID_ELECTRON,
        { /* CSP policies */ },
        { /* Custom attributes */ });

    // 2. Configure sandbox policies
    if (IsSandboxEnabled()) {
      ConfigureSandbox(frame_host);
    }

    // 3. Set permission policies
    SetPermissionPolicy(frame_host);
  }

  // Configure sandbox
  void ConfigureSandbox(content::RenderFrameHost* frame_host) {
    // 1. Disable dangerous APIs
    frame_host->DisableBlinkFeatures({"SharedArrayBuffer", "WebAssembly"});

    // 2. Restrict file system access
    frame_host->SetFileSystemAccessPolicy(
        content::FileSystemAccessPolicy::kRestricted);

    // 3. Enable sandbox CSS isolation
    frame_host->SetSandboxFlags(
        network::mojom::WebSandboxFlags::kAll &
        ~network::mojom::WebSandboxFlags::kOrigin);
  }
};

Context Isolation Implementation

// lib/renderer/contextIsolation.js - Context isolation implementation
function setupContextIsolation() {
  // 1. Create isolated JavaScript context
  const isolatedContext = vm.createContext({
    // Expose only safe APIs
    require: createRestrictedRequire(),
    process: createSafeProcessProxy(),
    Buffer: createSafeBuffer()
  });

  // 2. Inject predefined global variables
  isolatedContext.global.electron = {
    ipcRenderer: createSafeIPCRenderer(),
    clipboard: createSafeClipboard()
  };

  // 3. Execute preload script in isolated context
  vm.runInContext(preloadScript, isolatedContext);

  // 4. Expose limited APIs to renderer global object
  exposeLimitedAPIsToGlobal();
}

Renderer Process and UI Source Code

Browser Window Source Code (BrowserWindow)

Core Window Creation Logic

// electron/lib/browser/browser_window.cc - Window creation implementation
void BrowserWindow::CreateBrowserWindow(
    const BrowserWindow::Options& options) {
  // 1. Create native window
  native_window_ = NativeWindow::Create(options);

  // 2. Initialize Chromium view
  web_contents_ = content::WebContents::Create(
      content::WebContents::CreateParams(profile_));

  // 3. Associate window with web contents
  native_window_->SetWebContents(web_contents_.get());

  // 4. Apply window options
  ApplyWindowOptions(options);

  // 5. Initialize window event handlers
  InitWindowEvents();
}

// Window event handling
void BrowserWindow::InitWindowEvents() {
  // 1. Bind window close event
  native_window_->SetCloseCallback(base::BindRepeating(
      &BrowserWindow::OnWindowClose, base::Unretained(this)));

  // 2. Bind window resize event
  native_window_->SetResizeCallback(base::BindRepeating(
      &BrowserWindow::OnWindowSizeChanged, base::Unretained(this)));

  // 3. Bind window focus event
  native_window_->SetFocusCallback(base::BindRepeating(
      &BrowserWindow::OnWindowFocusChanged, base::Unretained(this)));
}

Page Loading and Rendering Source Code

Page Loading Process

// content/browser/renderer_host/render_view_host_impl.cc - Page loading process
void RenderViewHostImpl::Navigate(const GURL& url) {
  // 1. Create navigation request
  NavigationController::LoadURLParams params(url);

  // 2. Check navigation permissions
  if (!CanNavigate(params)) {
    NotifyNavigationFailed(url, net::ERR_ACCESS_DENIED);
    return;
  }

  // 3. Initiate navigation
  controller_.LoadURL(params);

  // 4. Notify renderer process to start navigation
  Send(new ViewMsg_Navigate(render_view_id_, params));
}

// Renderer process navigation handling
void RenderViewImpl::OnNavigate(const ViewMsg_Navigate_Params& params) {
  // 1. Create new navigation entry
  navigation_controller_.LoadURL(params);

  // 2. Start loading page
  webview_->LoadURL(params.url);

  // 3. Notify main process of navigation status
  Send(new ViewHostMsg_DidStartNavigation(
      routing_id(), params.url, params.transition_type));
}

Native Menu and Tray Source Code

// electron/lib/browser/menu.cc - Menu implementation
void Menu::PopupAt(const gfx::Point& location) {
  // 1. Create native menu
  native_menu_ = NativeMenu::Create();

  // 2. Convert menu items
  for (const auto& item : items_) {
    NativeMenuItem* native_item = native_menu_->AddItem(
        item->label(), item->type(), item->accelerator());

    // Set click callback
    native_item->SetCallback(base::BindRepeating(
        &Menu::OnMenuItemClicked, base::Unretained(this), item->id()));
  }

  // 3. Show menu
  native_menu_->Popup(location);
}

// Tray icon implementation
void Tray::SetIcon(const gfx::Image& icon) {
  // 1. Create native tray icon
  native_tray_ = NativeTray::Create();

  // 2. Set icon
  native_tray_->SetIcon(icon);

  // 3. Set click callback
  native_tray_->SetClickCallback(base::BindRepeating(
      &Tray::OnTrayIconClicked, base::Unretained(this)));
}

System Dialog Source Code

Dialog Module Implementation

// electron/lib/browser/dialog.cc - Dialog implementation
void Dialog::ShowOpenDialog(const ShowOpenDialogOptions& options) {
  // 1. Prepare file filters
  std::vector<NativeFileDialog::Filter> filters;
  for (const auto& filter : options.filters) {
    filters.emplace_back(filter.name, filter.extensions);
  }

  // 2. Create native file dialog
  NativeFileDialog dialog(
      NativeFileDialog::Type::OPEN,
      options.defaultPath,
      filters,
      options.properties);

  // 3. Show dialog and wait for result
  std::vector<base::FilePath> paths = dialog.ShowModal();

  // 4. Return result to renderer process
  if (options.callback) {
    options.callback(paths);
  }
}

// Message box implementation
void Dialog::ShowMessageBox(const ShowMessageBoxOptions& options) {
  // 1. Create native message box
  NativeMessageBox box(
      options.type,
      options.title,
      options.message,
      options.buttons);

  // 2. Show message box and wait for result
  int response = box.ShowModal();

  // 3. Return result to renderer process
  if (options.callback) {
    options.callback(response);
  }
}

Clipboard Operation Source Code

Core Clipboard Logic

// electron/lib/browser/clipboard.cc - Clipboard implementation
void Clipboard::WriteText(const std::string& text) {
  // 1. Get system clipboard
  auto clipboard = ui::Clipboard::GetForCurrentThread();

  // 2. Prepare clipboard data
  ui::ScopedClipboardWriter writer(clipboard);

  // 3. Write text content
  writer.WriteText(base::UTF8ToUTF16(text));
}

std::string Clipboard::ReadText() {
  // 1. Get system clipboard
  auto clipboard = ui::Clipboard::GetForCurrentThread();

  // 2. Read text content
  base::string16 text;
  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &text);

  // 3. Convert encoding and return
  return base::UTF16ToUTF8(text);
}

// Image clipboard operations
void Clipboard::WriteImage(const gfx::Image& image) {
  // 1. Get system clipboard
  auto clipboard = ui::Clipboard::GetForCurrentThread();

  // 2. Prepare image data
  ui::ScopedClipboardWriter writer(clipboard);

  // 3. Write image data
  writer.WriteImage(image.AsBitmap());
}
Share your love