diff --git a/server/cmd/api/api/api.go b/server/cmd/api/api/api.go index 544938ac..2fd6580b 100644 --- a/server/cmd/api/api/api.go +++ b/server/cmd/api/api/api.go @@ -61,6 +61,10 @@ type ApiService struct { upstreamMgr *devtoolsproxy.UpstreamManager stz scaletozero.PinnedController + // chromiumConfigMu serializes configuration changes that may restart Chromium + // or mutate its runtime flags and policies. + chromiumConfigMu sync.Mutex + // inputMu serializes input-related operations (mouse, keyboard, screenshot) inputMu sync.Mutex diff --git a/server/cmd/api/api/chromium.go b/server/cmd/api/api/chromium.go index bd4c4c7a..09a2ac55 100644 --- a/server/cmd/api/api/chromium.go +++ b/server/cmd/api/api/chromium.go @@ -28,13 +28,38 @@ type extensionZipItem struct { name string } -// chromiumFlagsPath is the runtime flags file read by the chromium-launcher at startup. -const chromiumFlagsPath = "/chromium/flags" +const ( + // chromiumFlagsPath is the runtime flags file read by the chromium-launcher at startup. + chromiumFlagsPath = "/chromium/flags" + extensionsBaseDir = "/home/kernel/extensions" +) -// UploadExtensionsAndRestart handles multipart upload of one or more extension zips, extracts -// them under /home/kernel/extensions/, writes /chromium/flags to enable them, restarts -// Chromium via supervisord, and waits (via UpstreamManager) until DevTools is ready. +// UploadExtensionsAndRestart uploads extensions and always restarts Chromium. func (s *ApiService) UploadExtensionsAndRestart(ctx context.Context, request oapi.UploadExtensionsAndRestartRequestObject) (oapi.UploadExtensionsAndRestartResponseObject, error) { + return s.uploadExtensions(ctx, request, true) +} + +// UploadExtensions uploads extensions and activates ordinary unpacked extensions over CDP. +func (s *ApiService) UploadExtensions(ctx context.Context, request oapi.UploadExtensionsRequestObject) (oapi.UploadExtensionsResponseObject, error) { + response, err := s.uploadExtensions(ctx, oapi.UploadExtensionsAndRestartRequestObject{Body: request.Body}, false) + if err != nil { + return nil, err + } + + switch response := response.(type) { + case oapi.UploadExtensionsAndRestart201Response: + return oapi.UploadExtensions201Response{}, nil + case oapi.UploadExtensionsAndRestart400JSONResponse: + return oapi.UploadExtensions400JSONResponse{BadRequestErrorJSONResponse: response.BadRequestErrorJSONResponse}, nil + case oapi.UploadExtensionsAndRestart500JSONResponse: + return oapi.UploadExtensions500JSONResponse{InternalErrorJSONResponse: response.InternalErrorJSONResponse}, nil + default: + logger.FromContext(ctx).Error("unexpected extension upload response", "type", fmt.Sprintf("%T", response)) + return oapi.UploadExtensions500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "internal error"}}, nil + } +} + +func (s *ApiService) uploadExtensions(ctx context.Context, request oapi.UploadExtensionsAndRestartRequestObject, forceRestart bool) (oapi.UploadExtensionsAndRestartResponseObject, error) { log := logger.FromContext(ctx) start := time.Now() log.Info("upload extensions: begin") @@ -145,7 +170,10 @@ func (s *ApiService) UploadExtensionsAndRestart(ctx context.Context, request oap extItems = append(extItems, extensionZipItem{zipTemp: p.zipTemp, name: p.name}) } - reqMsg, err := s.applyExtensionZipItems(ctx, extItems) + s.chromiumConfigMu.Lock() + defer s.chromiumConfigMu.Unlock() + + requiresRestart, reqMsg, err := s.applyExtensionZipItems(ctx, extItems) if reqMsg != "" { return oapi.UploadExtensionsAndRestart400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: reqMsg}}, nil } @@ -153,33 +181,44 @@ func (s *ApiService) UploadExtensionsAndRestart(ctx context.Context, request oap return oapi.UploadExtensionsAndRestart500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: err.Error()}}, nil } - // Restart Chromium and wait for DevTools to be ready - if err := s.restartChromiumAndWait(ctx, "extension upload"); err != nil { - return oapi.UploadExtensionsAndRestart500JSONResponse{ - InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: err.Error()}, - }, nil + restarted := forceRestart || requiresRestart + if restarted { + if err := s.restartChromiumAndWait(ctx, "extension upload"); err != nil { + return oapi.UploadExtensionsAndRestart500JSONResponse{ + InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: err.Error()}, + }, nil + } + } else if loadErr := s.loadUnpackedExtensions(ctx, extItems); loadErr != nil { + log.Warn("CDP extension load failed, restarting Chromium", "error", loadErr) + if restartErr := s.restartChromiumAndWait(ctx, "extension upload fallback"); restartErr != nil { + return oapi.UploadExtensionsAndRestart500JSONResponse{ + InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{ + Message: fmt.Sprintf("CDP extension load failed (%v), and fallback restart failed: %v", loadErr, restartErr), + }, + }, nil + } + restarted = true } - log.Info("devtools ready", "elapsed", time.Since(start).String()) + log.Info("extensions ready", "restarted", restarted, "elapsed", time.Since(start).String()) return oapi.UploadExtensionsAndRestart201Response{}, nil } -// applyExtensionZipItems applies name+zipTemp extension pairs (merge flags for --load-extension). -// On validation errors returns (reqMsg, nil); on internal errors returns ("", err). -func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensionZipItem) (reqMsg string, err error) { +// applyExtensionZipItems installs name+zipTemp extension pairs and persists their startup +// configuration. The boolean result reports whether enterprise policy requires a restart. +func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensionZipItem) (bool, string, error) { log := logger.FromContext(ctx) - extBase := "/home/kernel/extensions" - if err := os.MkdirAll(extBase, 0o755); err != nil { - return "", fmt.Errorf("failed to create extension base dir: %w", err) + if err := os.MkdirAll(extensionsBaseDir, 0o755); err != nil { + return false, "", fmt.Errorf("failed to create extension base dir: %w", err) } for _, p := range items { - dest := filepath.Join(extBase, p.name) + dest := filepath.Join(extensionsBaseDir, p.name) if _, err := os.Stat(dest); err == nil { - return fmt.Sprintf("extension name already exists: %s", p.name), nil + return false, fmt.Sprintf("extension name already exists: %s", p.name), nil } else if !os.IsNotExist(err) { log.Error("failed to check extension dir", "error", err) - return "", fmt.Errorf("failed to check extension dir: %w", err) + return false, "", fmt.Errorf("failed to check extension dir: %w", err) } } @@ -197,15 +236,15 @@ func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensi }() for _, p := range items { - dest := filepath.Join(extBase, p.name) + dest := filepath.Join(extensionsBaseDir, p.name) if err := os.MkdirAll(dest, 0o755); err != nil { log.Error("failed to create extension dir", "error", err) - return "", fmt.Errorf("failed to create extension dir: %w", err) + return false, "", fmt.Errorf("failed to create extension dir: %w", err) } createdDests = append(createdDests, dest) if err := ziputil.Unzip(p.zipTemp, dest); err != nil { log.Error("failed to unzip zip file", "error", err) - return "invalid zip file", nil + return false, "invalid zip file", nil } updateXMLPath := filepath.Join(dest, "update.xml") @@ -215,23 +254,24 @@ func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensi if err := exec.Command("chown", "-R", "kernel:kernel", dest).Run(); err != nil { log.Error("failed to chown extension dir", "error", err) - return "", fmt.Errorf("failed to chown extension dir: %w", err) + return false, "", fmt.Errorf("failed to chown extension dir: %w", err) } log.Info("installed extension", "name", p.name) } var pathsNeedingFlags []string + requiresRestart := false for _, p := range items { - extensionPath := filepath.Join(extBase, p.name) + extensionPath := filepath.Join(extensionsBaseDir, p.name) extensionName := p.name manifestPath := filepath.Join(extensionPath, "manifest.json") updateXMLPath := filepath.Join(extensionPath, "update.xml") requiresEntPolicy, err := s.policy.RequiresEnterprisePolicy(manifestPath) if err != nil { - log.Warn("failed to read manifest for policy check", "error", err, "extension", extensionName) + return false, fmt.Sprintf("invalid extension %s: %v", extensionName, err), nil } chromeExtensionID := extensionName @@ -252,7 +292,7 @@ func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensi if _, err := os.Stat(updateXMLPath); err == nil { if extractionErr != nil { - return fmt.Sprintf("extension %s requires enterprise policy but update.xml is invalid: %v", extensionName, extractionErr), nil + return false, fmt.Sprintf("extension %s requires enterprise policy but update.xml is invalid: %v", extensionName, extractionErr), nil } hasUpdateXML = true log.Info("found update.xml in extension zip", "name", extensionName) @@ -274,6 +314,8 @@ func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensi "name", extensionName, "hasUpdateXML", hasUpdateXML, "hasCRX", hasCRX) requiresEntPolicy = false pathsNeedingFlags = append(pathsNeedingFlags, extensionPath) + } else { + requiresRestart = true } } else { pathsNeedingFlags = append(pathsNeedingFlags, extensionPath) @@ -281,7 +323,7 @@ func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensi if err := s.policy.AddExtension(extensionName, chromeExtensionID, extensionPath, requiresEntPolicy); err != nil { log.Error("failed to update enterprise policy", "error", err, "extension", extensionName) - return "", fmt.Errorf("failed to update enterprise policy for %s: %w", extensionName, err) + return false, "", fmt.Errorf("failed to update enterprise policy for %s: %w", extensionName, err) } log.Info("updated enterprise policy", "extension", extensionName, "chromeExtensionID", chromeExtensionID, "requiresEnterprisePolicy", requiresEntPolicy) @@ -295,11 +337,27 @@ func (s *ApiService) applyExtensionZipItems(ctx context.Context, items []extensi } if _, err := s.mergeAndWriteChromiumFlags(ctx, newTokens); err != nil { - return "", err + return false, "", err } success = true - return "", nil + return requiresRestart, "", nil +} + +func (s *ApiService) loadUnpackedExtensions(ctx context.Context, items []extensionZipItem) error { + log := logger.FromContext(ctx) + timeout := time.Duration(len(items)) * 10 * time.Second + return s.withCDPClientTimeout(ctx, timeout, func(cdpCtx context.Context, client *cdpclient.Client) error { + for _, item := range items { + path := filepath.Join(extensionsBaseDir, item.name) + id, err := client.LoadUnpackedExtension(cdpCtx, path) + if err != nil { + return fmt.Errorf("failed to load extension %s: %w", item.name, err) + } + log.Info("loaded unpacked extension over CDP", "name", item.name, "id", id) + } + return nil + }) } // mergeAndWriteChromiumFlags reads existing flags, merges them with new flags, @@ -574,6 +632,9 @@ func (s *ApiService) PatchChromiumPolicies(ctx context.Context, request oapi.Pat return oapi.PatchChromiumPolicies400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil } + s.chromiumConfigMu.Lock() + defer s.chromiumConfigMu.Unlock() + if err := s.policy.ApplyOverrides(overrides); err != nil { if strings.Contains(err.Error(), "invalid chromium policy overrides") || strings.Contains(err.Error(), "cannot be overridden") { return oapi.PatchChromiumPolicies400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: err.Error()}}, nil @@ -619,6 +680,9 @@ func (s *ApiService) PatchChromiumFlags(ctx context.Context, request oapi.PatchC } } + s.chromiumConfigMu.Lock() + defer s.chromiumConfigMu.Unlock() + // Merge and write flags if _, err := s.mergeAndWriteChromiumFlags(ctx, request.Body.Flags); err != nil { return oapi.PatchChromiumFlags500JSONResponse{ diff --git a/server/cmd/api/api/chromium_configure.go b/server/cmd/api/api/chromium_configure.go index 7d995314..b3ea7abc 100644 --- a/server/cmd/api/api/chromium_configure.go +++ b/server/cmd/api/api/chromium_configure.go @@ -77,6 +77,9 @@ func (s *ApiService) ChromiumConfigure(ctx context.Context, request oapi.Chromiu return cfg400("no configuration fields provided"), nil } + s.chromiumConfigMu.Lock() + defer s.chromiumConfigMu.Unlock() + needsStop := chromiumNeedsStopCycle(st) chromiumStopped := false restartAfterStop := func() error { @@ -696,7 +699,7 @@ func chromiumDisplayApplyWhileStopped(ctx context.Context, s *ApiService, plan * } func chromiumRunPatchDisplay(ctx context.Context, s *ApiService, body *oapi.PatchDisplayJSONRequestBody) oapi.ChromiumConfigureResponseObject { - resp, err := s.PatchDisplay(ctx, oapi.PatchDisplayRequestObject{Body: body}) + resp, err := s.patchDisplayLocked(ctx, oapi.PatchDisplayRequestObject{Body: body}) if err != nil { return cfg500ConfigureStep(chromiumConfigureStepDisplay, err.Error()) } @@ -752,7 +755,8 @@ func chromiumApplyExtensions(ctx context.Context, s *ApiService, items []extensi if len(items) == 0 { return "", nil } - return s.applyExtensionZipItems(ctx, items) + _, reqMsg, err := s.applyExtensionZipItems(ctx, items) + return reqMsg, err } func chromiumValidateFlags(raw *string) (*chromiumFlagsPlan, error) { diff --git a/server/cmd/api/api/display.go b/server/cmd/api/api/display.go index 6395dedc..285ae8ff 100644 --- a/server/cmd/api/api/display.go +++ b/server/cmd/api/api/display.go @@ -24,6 +24,12 @@ import ( // This method automatically detects whether the system is running with Xorg (headful) // or Xvfb (headless) and uses the appropriate method to change resolution. func (s *ApiService) PatchDisplay(ctx context.Context, req oapi.PatchDisplayRequestObject) (oapi.PatchDisplayResponseObject, error) { + s.chromiumConfigMu.Lock() + defer s.chromiumConfigMu.Unlock() + return s.patchDisplayLocked(ctx, req) +} + +func (s *ApiService) patchDisplayLocked(ctx context.Context, req oapi.PatchDisplayRequestObject) (oapi.PatchDisplayResponseObject, error) { log := logger.FromContext(ctx) if req.Body == nil { @@ -394,14 +400,16 @@ func (s *ApiService) backgroundResizeXvfb(ctx context.Context, width, height int // withCDPClient dials the current devtools upstream with a 10s timeout, // hands the connected client to fn, and closes the connection on return. -// Lets the small per-call CDP helpers below avoid duplicating the dial + -// timeout + defer-close scaffolding. func (s *ApiService) withCDPClient(ctx context.Context, fn func(context.Context, *cdpclient.Client) error) error { + return s.withCDPClientTimeout(ctx, 10*time.Second, fn) +} + +func (s *ApiService) withCDPClientTimeout(ctx context.Context, timeout time.Duration, fn func(context.Context, *cdpclient.Client) error) error { upstreamURL := s.upstreamMgr.Current() if upstreamURL == "" { return fmt.Errorf("devtools upstream not available") } - cdpCtx, cancel := context.WithTimeout(ctx, 10*time.Second) + cdpCtx, cancel := context.WithTimeout(ctx, timeout) defer cancel() client, err := cdpclient.Dial(cdpCtx, upstreamURL) if err != nil { diff --git a/server/cmd/api/api/display_test.go b/server/cmd/api/api/display_test.go index c37700c3..008472ea 100644 --- a/server/cmd/api/api/display_test.go +++ b/server/cmd/api/api/display_test.go @@ -570,3 +570,27 @@ func TestAdjustParamsForRemainingBudget(t *testing.T) { assert.Nil(t, adjusted.MaxDurationInSeconds, "should remain nil when not set") }) } + +func TestPatchDisplayLockedDoesNotRelockChromiumConfig(t *testing.T) { + s := &ApiService{} + s.chromiumConfigMu.Lock() + defer s.chromiumConfigMu.Unlock() + + type result struct { + resp oapi.PatchDisplayResponseObject + err error + } + done := make(chan result, 1) + go func() { + resp, err := s.patchDisplayLocked(context.Background(), oapi.PatchDisplayRequestObject{}) + done <- result{resp: resp, err: err} + }() + + select { + case got := <-done: + require.NoError(t, got.err) + require.IsType(t, oapi.PatchDisplay400JSONResponse{}, got.resp) + case <-time.After(time.Second): + t.Fatal("patchDisplayLocked tried to reacquire chromiumConfigMu") + } +} diff --git a/server/e2e/e2e_chromium_test.go b/server/e2e/e2e_chromium_test.go index 95e186ea..965cc80d 100644 --- a/server/e2e/e2e_chromium_test.go +++ b/server/e2e/e2e_chromium_test.go @@ -20,6 +20,7 @@ import ( "time" _ "github.com/glebarez/sqlite" + "github.com/kernel/kernel-images/server/lib/cdpclient" instanceoapi "github.com/kernel/kernel-images/server/lib/oapi" "github.com/samber/lo" "github.com/stretchr/testify/require" @@ -258,7 +259,11 @@ func TestExtensionUploadAndActivation(t *testing.T) { extZip, err := zipDirToBytes(extDir) require.NoError(t, err, "zip ext") - // Use new API to upload extension and restart Chromium + versionURL := "http" + strings.TrimPrefix(c.CDPURL(), "ws") + "json/version" + browserWebSocketBefore, err := cdpclient.BrowserWebSocketURL(ctx, versionURL) + require.NoError(t, err, "get browser WebSocket URL before extension upload") + + // Upload and activate the unpacked extension without restarting Chromium. { client, err := c.APIClient() require.NoError(t, err) @@ -273,13 +278,17 @@ func TestExtensionUploadAndActivation(t *testing.T) { err = w.Close() require.NoError(t, err) start := time.Now() - rsp, err := client.UploadExtensionsAndRestartWithBodyWithResponse(ctx, w.FormDataContentType(), &body) + rsp, err := client.UploadExtensionsWithBodyWithResponse(ctx, w.FormDataContentType(), &body) elapsed := time.Since(start) - require.NoError(t, err, "uploadExtensionsAndRestart request error") + require.NoError(t, err, "uploadExtensions request error") require.Equal(t, http.StatusCreated, rsp.StatusCode(), "unexpected status: %s body=%s", rsp.Status(), string(rsp.Body)) - t.Logf("/chromium/upload-extensions-and-restart completed in %s (%d ms)", elapsed.String(), elapsed.Milliseconds()) + t.Logf("/chromium/upload-extensions completed in %s (%d ms)", elapsed.String(), elapsed.Milliseconds()) } + browserWebSocketAfter, err := cdpclient.BrowserWebSocketURL(ctx, versionURL) + require.NoError(t, err, "get browser WebSocket URL after extension upload") + require.Equal(t, browserWebSocketBefore, browserWebSocketAfter, "Chromium restarted during unpacked extension upload") + // Verify the content script updated the title on an allowed URL { cmd := exec.CommandContext(ctx, "pnpm", "exec", "tsx", "index.ts", @@ -293,6 +302,28 @@ func TestExtensionUploadAndActivation(t *testing.T) { out, err := cmd.CombinedOutput() require.NoError(t, err, "title verify failed: %v output=%s", err, string(out)) } + + // The legacy endpoint retains its unconditional restart behavior. + { + client, err := c.APIClient() + require.NoError(t, err) + var body bytes.Buffer + w := multipart.NewWriter(&body) + fw, err := w.CreateFormFile("extensions.zip_file", "ext.zip") + require.NoError(t, err) + _, err = io.Copy(fw, bytes.NewReader(extZip)) + require.NoError(t, err) + require.NoError(t, w.WriteField("extensions.name", "restart-testext")) + require.NoError(t, w.Close()) + + rsp, err := client.UploadExtensionsAndRestartWithBodyWithResponse(ctx, w.FormDataContentType(), &body) + require.NoError(t, err, "uploadExtensionsAndRestart request error") + require.Equal(t, http.StatusCreated, rsp.StatusCode(), "unexpected status: %s body=%s", rsp.Status(), string(rsp.Body)) + } + + browserWebSocketAfterRestart, err := cdpclient.BrowserWebSocketURL(ctx, versionURL) + require.NoError(t, err, "get browser WebSocket URL after legacy extension upload") + require.NotEqual(t, browserWebSocketAfter, browserWebSocketAfterRestart, "legacy endpoint did not restart Chromium") } func TestScreenshotHeadless(t *testing.T) { diff --git a/server/e2e/e2e_combined_flow_test.go b/server/e2e/e2e_combined_flow_test.go index 5ccdb391..3e0ef394 100644 --- a/server/e2e/e2e_combined_flow_test.go +++ b/server/e2e/e2e_combined_flow_test.go @@ -138,21 +138,30 @@ func TestMultipleCDPConnectionsAfterRestart(t *testing.T) { t.Log("[test] result: all CDP connections successful") } -// uploadExtension uploads a simple MV3 extension and waits for Chromium to restart. +// uploadExtension uploads an enterprise-policy extension and waits for Chromium to restart. func uploadExtension(t *testing.T, ctx context.Context, client *instanceoapi.ClientWithResponses) { t.Helper() - // Build simple MV3 extension zip in-memory extDir := t.TempDir() manifest := `{ "manifest_version": 3, "version": "1.0", "name": "Test Extension for Combined Flow", - "description": "Minimal extension for testing CDP connections after restart" + "description": "Extension for testing CDP connections after restart", + "permissions": ["webRequest"] }` err := os.WriteFile(filepath.Join(extDir, "manifest.json"), []byte(manifest), 0600) require.NoError(t, err, "write manifest") + updateXML := ` + + + + +` + require.NoError(t, os.WriteFile(filepath.Join(extDir, "update.xml"), []byte(updateXML), 0600), "write update.xml") + require.NoError(t, os.WriteFile(filepath.Join(extDir, "extension.crx"), []byte("test crx"), 0600), "write extension.crx") + extZip, err := zipDirToBytes(extDir) require.NoError(t, err, "zip ext") diff --git a/server/lib/cdpclient/cdpclient.go b/server/lib/cdpclient/cdpclient.go index a59073c5..ec1cbdff 100644 --- a/server/lib/cdpclient/cdpclient.go +++ b/server/lib/cdpclient/cdpclient.go @@ -162,6 +162,25 @@ func (c *Client) GetBrowserVersion(ctx context.Context) (*BrowserVersion, error) return &v, nil } +// LoadUnpackedExtension installs an unpacked extension from an absolute path +// visible to Chromium and returns its extension ID. +func (c *Client) LoadUnpackedExtension(ctx context.Context, path string) (string, error) { + raw, err := c.send(ctx, "Extensions.loadUnpacked", map[string]string{"path": path}, "") + if err != nil { + return "", fmt.Errorf("Extensions.loadUnpacked: %w", err) + } + var result struct { + ID string `json:"id"` + } + if err := json.Unmarshal(raw, &result); err != nil { + return "", fmt.Errorf("unmarshal Extensions.loadUnpacked: %w", err) + } + if result.ID == "" { + return "", fmt.Errorf("Extensions.loadUnpacked returned no extension ID") + } + return result.ID, nil +} + // Histogram is a snapshot of a Chrome UMA histogram as returned by // Browser.getHistograms. Values are cumulative since browser start and the // units follow the UMA definition of the histogram (PageLoad timings are diff --git a/server/lib/cdpclient/cdpclient_test.go b/server/lib/cdpclient/cdpclient_test.go index 8154b361..ac652492 100644 --- a/server/lib/cdpclient/cdpclient_test.go +++ b/server/lib/cdpclient/cdpclient_test.go @@ -31,6 +31,10 @@ type fakeCDP struct { getVersionCalled bool failGetVersion bool productResponse string + loadUnpackedCalled bool + loadUnpackedPath string + loadUnpackedID string + failLoadUnpacked bool navigateCalled bool navigateCalls int navigateURL string @@ -109,6 +113,16 @@ func (f *fakeCDP) handler(w http.ResponseWriter, r *http.Request) { "jsVersion": "1.2.3", } } + case "Extensions.loadUnpacked": + f.loadUnpackedCalled = true + var params map[string]string + _ = json.Unmarshal(req.Params, ¶ms) + f.loadUnpackedPath = params["path"] + if f.failLoadUnpacked { + cdpErr = &cdpError{Code: -4, Message: "invalid extension"} + } else { + result = map[string]string{"id": f.loadUnpackedID} + } case "Page.navigate": f.navigateCalled = true f.navigateCalls++ @@ -347,3 +361,45 @@ func TestGetBrowserVersion(t *testing.T) { assert.Contains(t, err.Error(), "Browser.getVersion") }) } + +func TestLoadUnpackedExtension(t *testing.T) { + t.Run("happy path", func(t *testing.T) { + f := &fakeCDP{loadUnpackedID: "abcdefghijklmnopabcdefghijklmnop"} + url := startFakeCDP(t, f) + + client, err := Dial(context.Background(), url) + require.NoError(t, err) + defer client.Close() + + id, err := client.LoadUnpackedExtension(context.Background(), "/home/kernel/extensions/test") + require.NoError(t, err) + assert.Equal(t, f.loadUnpackedID, id) + assert.True(t, f.loadUnpackedCalled) + assert.Equal(t, "/home/kernel/extensions/test", f.loadUnpackedPath) + }) + + t.Run("CDP error from chromium", func(t *testing.T) { + f := &fakeCDP{failLoadUnpacked: true} + url := startFakeCDP(t, f) + + client, err := Dial(context.Background(), url) + require.NoError(t, err) + defer client.Close() + + _, err = client.LoadUnpackedExtension(context.Background(), "/bad-extension") + require.Error(t, err) + assert.Contains(t, err.Error(), "Extensions.loadUnpacked") + }) + + t.Run("missing extension ID", func(t *testing.T) { + f := &fakeCDP{} + url := startFakeCDP(t, f) + + client, err := Dial(context.Background(), url) + require.NoError(t, err) + defer client.Close() + + _, err = client.LoadUnpackedExtension(context.Background(), "/home/kernel/extensions/test") + require.EqualError(t, err, "Extensions.loadUnpacked returned no extension ID") + }) +} diff --git a/server/lib/events/category_gen.go b/server/lib/events/category_gen.go index e7fa54b5..4c9ba5fa 100644 --- a/server/lib/events/category_gen.go +++ b/server/lib/events/category_gen.go @@ -97,6 +97,7 @@ var categoryByOperationID = map[string]oapi.TelemetryEventCategory{ "StreamTelemetryEvents": oapi.TelemetryEventCategory("platform"), "TakeScreenshot": oapi.TelemetryEventCategory("control"), "TypeText": oapi.TelemetryEventCategory("control"), + "UploadExtensions": oapi.TelemetryEventCategory("platform"), "UploadExtensionsAndRestart": oapi.TelemetryEventCategory("platform"), "UploadFiles": oapi.TelemetryEventCategory("platform"), "UploadZip": oapi.TelemetryEventCategory("platform"), diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 2104712e..2876dc03 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -3891,6 +3891,18 @@ type PatchChromiumFlagsJSONBody struct { // PatchChromiumPoliciesJSONBody defines parameters for PatchChromiumPolicies. type PatchChromiumPoliciesJSONBody map[string]interface{} +// UploadExtensionsMultipartBody defines parameters for UploadExtensions. +type UploadExtensionsMultipartBody struct { + // Extensions List of extensions to upload and activate + Extensions []struct { + // Name Folder name to place the extension under /home/kernel/extensions/ + Name string `json:"name"` + + // ZipFile Zip archive containing an unpacked Chromium extension (must include manifest.json) + ZipFile openapi_types.File `json:"zip_file"` + } `json:"extensions"` +} + // UploadExtensionsAndRestartMultipartBody defines parameters for UploadExtensionsAndRestart. type UploadExtensionsAndRestartMultipartBody struct { // Extensions List of extensions to upload and activate @@ -4046,6 +4058,9 @@ type PatchChromiumFlagsJSONRequestBody PatchChromiumFlagsJSONBody // PatchChromiumPoliciesJSONRequestBody defines body for PatchChromiumPolicies for application/json ContentType. type PatchChromiumPoliciesJSONRequestBody PatchChromiumPoliciesJSONBody +// UploadExtensionsMultipartRequestBody defines body for UploadExtensions for multipart/form-data ContentType. +type UploadExtensionsMultipartRequestBody UploadExtensionsMultipartBody + // UploadExtensionsAndRestartMultipartRequestBody defines body for UploadExtensionsAndRestart for multipart/form-data ContentType. type UploadExtensionsAndRestartMultipartRequestBody UploadExtensionsAndRestartMultipartBody @@ -5223,6 +5238,9 @@ type ClientInterface interface { PatchChromiumPolicies(ctx context.Context, body PatchChromiumPoliciesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // UploadExtensionsWithBody request with any body + UploadExtensionsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + // UploadExtensionsAndRestartWithBody request with any body UploadExtensionsAndRestartWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -5494,6 +5512,18 @@ func (c *Client) PatchChromiumPolicies(ctx context.Context, body PatchChromiumPo return c.Client.Do(req) } +func (c *Client) UploadExtensionsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUploadExtensionsRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) UploadExtensionsAndRestartWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewUploadExtensionsAndRestartRequestWithBody(c.Server, contentType, body) if err != nil { @@ -6582,6 +6612,35 @@ func NewPatchChromiumPoliciesRequestWithBody(server string, contentType string, return req, nil } +// NewUploadExtensionsRequestWithBody generates requests for UploadExtensions with any type of body +func NewUploadExtensionsRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/chromium/upload-extensions") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewUploadExtensionsAndRestartRequestWithBody generates requests for UploadExtensionsAndRestart with any type of body func NewUploadExtensionsAndRestartRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { var err error @@ -8809,6 +8868,9 @@ type ClientWithResponsesInterface interface { PatchChromiumPoliciesWithResponse(ctx context.Context, body PatchChromiumPoliciesJSONRequestBody, reqEditors ...RequestEditorFn) (*PatchChromiumPoliciesResponse, error) + // UploadExtensionsWithBodyWithResponse request with any body + UploadExtensionsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UploadExtensionsResponse, error) + // UploadExtensionsAndRestartWithBodyWithResponse request with any body UploadExtensionsAndRestartWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UploadExtensionsAndRestartResponse, error) @@ -9078,6 +9140,29 @@ func (r PatchChromiumPoliciesResponse) StatusCode() int { return 0 } +type UploadExtensionsResponse struct { + Body []byte + HTTPResponse *http.Response + JSON400 *BadRequestError + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r UploadExtensionsResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UploadExtensionsResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type UploadExtensionsAndRestartResponse struct { Body []byte HTTPResponse *http.Response @@ -10398,6 +10483,15 @@ func (c *ClientWithResponses) PatchChromiumPoliciesWithResponse(ctx context.Cont return ParsePatchChromiumPoliciesResponse(rsp) } +// UploadExtensionsWithBodyWithResponse request with arbitrary body returning *UploadExtensionsResponse +func (c *ClientWithResponses) UploadExtensionsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UploadExtensionsResponse, error) { + rsp, err := c.UploadExtensionsWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUploadExtensionsResponse(rsp) +} + // UploadExtensionsAndRestartWithBodyWithResponse request with arbitrary body returning *UploadExtensionsAndRestartResponse func (c *ClientWithResponses) UploadExtensionsAndRestartWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UploadExtensionsAndRestartResponse, error) { rsp, err := c.UploadExtensionsAndRestartWithBody(ctx, contentType, body, reqEditors...) @@ -11190,6 +11284,39 @@ func ParsePatchChromiumPoliciesResponse(rsp *http.Response) (*PatchChromiumPolic return response, nil } +// ParseUploadExtensionsResponse parses an HTTP response from a UploadExtensionsWithResponse call +func ParseUploadExtensionsResponse(rsp *http.Response) (*UploadExtensionsResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UploadExtensionsResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BadRequestError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseUploadExtensionsAndRestartResponse parses an HTTP response from a UploadExtensionsAndRestartWithResponse call func ParseUploadExtensionsAndRestartResponse(rsp *http.Response) (*UploadExtensionsAndRestartResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -13264,6 +13391,9 @@ type ServerInterface interface { // Update Chromium enterprise policies and restart // (PATCH /chromium/policies) PatchChromiumPolicies(w http.ResponseWriter, r *http.Request) + // Upload and activate one or more unpacked extensions + // (POST /chromium/upload-extensions) + UploadExtensions(w http.ResponseWriter, r *http.Request) // Upload one or more unpacked extensions (as zips) and restart Chromium // (POST /chromium/upload-extensions-and-restart) UploadExtensionsAndRestart(w http.ResponseWriter, r *http.Request) @@ -13444,6 +13574,12 @@ func (_ Unimplemented) PatchChromiumPolicies(w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusNotImplemented) } +// Upload and activate one or more unpacked extensions +// (POST /chromium/upload-extensions) +func (_ Unimplemented) UploadExtensions(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotImplemented) +} + // Upload one or more unpacked extensions (as zips) and restart Chromium // (POST /chromium/upload-extensions-and-restart) func (_ Unimplemented) UploadExtensionsAndRestart(w http.ResponseWriter, r *http.Request) { @@ -13805,6 +13941,20 @@ func (siw *ServerInterfaceWrapper) PatchChromiumPolicies(w http.ResponseWriter, handler.ServeHTTP(w, r) } +// UploadExtensions operation middleware +func (siw *ServerInterfaceWrapper) UploadExtensions(w http.ResponseWriter, r *http.Request) { + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.UploadExtensions(w, r) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + // UploadExtensionsAndRestart operation middleware func (siw *ServerInterfaceWrapper) UploadExtensionsAndRestart(w http.ResponseWriter, r *http.Request) { @@ -14984,6 +15134,9 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl r.Group(func(r chi.Router) { r.Patch(options.BaseURL+"/chromium/policies", wrapper.PatchChromiumPolicies) }) + r.Group(func(r chi.Router) { + r.Post(options.BaseURL+"/chromium/upload-extensions", wrapper.UploadExtensions) + }) r.Group(func(r chi.Router) { r.Post(options.BaseURL+"/chromium/upload-extensions-and-restart", wrapper.UploadExtensionsAndRestart) }) @@ -15226,6 +15379,40 @@ func (response PatchChromiumPolicies500JSONResponse) VisitPatchChromiumPoliciesR return json.NewEncoder(w).Encode(response) } +type UploadExtensionsRequestObject struct { + Body *multipart.Reader +} + +type UploadExtensionsResponseObject interface { + VisitUploadExtensionsResponse(w http.ResponseWriter) error +} + +type UploadExtensions201Response struct { +} + +func (response UploadExtensions201Response) VisitUploadExtensionsResponse(w http.ResponseWriter) error { + w.WriteHeader(201) + return nil +} + +type UploadExtensions400JSONResponse struct{ BadRequestErrorJSONResponse } + +func (response UploadExtensions400JSONResponse) VisitUploadExtensionsResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type UploadExtensions500JSONResponse struct{ InternalErrorJSONResponse } + +func (response UploadExtensions500JSONResponse) VisitUploadExtensionsResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + + return json.NewEncoder(w).Encode(response) +} + type UploadExtensionsAndRestartRequestObject struct { Body *multipart.Reader } @@ -17521,6 +17708,9 @@ type StrictServerInterface interface { // Update Chromium enterprise policies and restart // (PATCH /chromium/policies) PatchChromiumPolicies(ctx context.Context, request PatchChromiumPoliciesRequestObject) (PatchChromiumPoliciesResponseObject, error) + // Upload and activate one or more unpacked extensions + // (POST /chromium/upload-extensions) + UploadExtensions(ctx context.Context, request UploadExtensionsRequestObject) (UploadExtensionsResponseObject, error) // Upload one or more unpacked extensions (as zips) and restart Chromium // (POST /chromium/upload-extensions-and-restart) UploadExtensionsAndRestart(ctx context.Context, request UploadExtensionsAndRestartRequestObject) (UploadExtensionsAndRestartResponseObject, error) @@ -17776,6 +17966,37 @@ func (sh *strictHandler) PatchChromiumPolicies(w http.ResponseWriter, r *http.Re } } +// UploadExtensions operation middleware +func (sh *strictHandler) UploadExtensions(w http.ResponseWriter, r *http.Request) { + var request UploadExtensionsRequestObject + + if reader, err := r.MultipartReader(); err != nil { + sh.options.RequestErrorHandlerFunc(w, r, fmt.Errorf("can't decode multipart body: %w", err)) + return + } else { + request.Body = reader + } + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.UploadExtensions(ctx, request.(UploadExtensionsRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "UploadExtensions") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(UploadExtensionsResponseObject); ok { + if err := validResponse.VisitUploadExtensionsResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + // UploadExtensionsAndRestart operation middleware func (sh *strictHandler) UploadExtensionsAndRestart(w http.ResponseWriter, r *http.Request) { var request UploadExtensionsAndRestartRequestObject @@ -19369,392 +19590,395 @@ func (sh *strictHandler) StreamTelemetryEvents(w http.ResponseWriter, r *http.Re // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "CR3d+5eWHksOsFnAf/r0/wcAAP//oIjT6DrpAQA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/server/openapi.yaml b/server/openapi.yaml index 20dfdef9..d65c4785 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -1180,6 +1180,49 @@ paths: "500": $ref: "#/components/responses/InternalError" + /chromium/upload-extensions: + post: + summary: Upload and activate one or more unpacked extensions + description: | + Upload one or more extension zip archives and extract them under + /home/kernel/extensions/. Ordinary unpacked extensions are activated immediately over + CDP without restarting Chromium, while their runtime flags are persisted for future starts. + Content scripts are applied to existing pages after their next navigation or reload. + Extensions that require enterprise policy still restart Chromium and wait for DevTools + readiness before returning success. + operationId: uploadExtensions + x-telemetry-category: platform + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + extensions: + type: array + description: List of extensions to upload and activate + items: + type: object + properties: + zip_file: + type: string + format: binary + description: Zip archive containing an unpacked Chromium extension (must include manifest.json) + name: + type: string + description: Folder name to place the extension under /home/kernel/extensions/ + pattern: "^[A-Za-z0-9._-]{1,255}$" + required: [zip_file, name] + required: [extensions] + responses: + "201": + description: Extensions uploaded and activated + "400": + $ref: "#/components/responses/BadRequestError" + "500": + $ref: "#/components/responses/InternalError" + /chromium/policies: patch: summary: Update Chromium enterprise policies and restart