feat: Allow WebContentsView to accept webContents object. (#42086)
feat: Allow WebContentsView to accept webContents object
This commit is contained in:
		
					parent
					
						
							
								d92a80dfe3
							
						
					
				
			
			
				commit
				
					
						85df2a86dd
					
				
			
		
					 3 changed files with 69 additions and 2 deletions
				
			
		|  | @ -36,8 +36,9 @@ Process: [Main](../glossary.md#main-process) | ||||||
| 
 | 
 | ||||||
| * `options` Object (optional) | * `options` Object (optional) | ||||||
|   * `webPreferences` [WebPreferences](structures/web-preferences.md) (optional) - Settings of web page's features. |   * `webPreferences` [WebPreferences](structures/web-preferences.md) (optional) - Settings of web page's features. | ||||||
|  |   * `webContents` [WebContents](web-contents.md) (optional) - If present, the given WebContents will be adopted by the WebContentsView. A WebContents may only be presented in one WebContentsView at a time. | ||||||
| 
 | 
 | ||||||
| Creates an empty WebContentsView. | Creates a WebContentsView. | ||||||
| 
 | 
 | ||||||
| ### Instance Properties | ### Instance Properties | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -138,6 +138,7 @@ v8::Local<v8::Function> WebContentsView::GetConstructor(v8::Isolate* isolate) { | ||||||
| // static
 | // static
 | ||||||
| gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) { | gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) { | ||||||
|   gin_helper::Dictionary web_preferences; |   gin_helper::Dictionary web_preferences; | ||||||
|  |   v8::Local<v8::Value> existing_web_contents_value; | ||||||
|   { |   { | ||||||
|     v8::Local<v8::Value> options_value; |     v8::Local<v8::Value> options_value; | ||||||
|     if (args->GetNext(&options_value)) { |     if (args->GetNext(&options_value)) { | ||||||
|  | @ -154,12 +155,33 @@ gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) { | ||||||
|           return nullptr; |           return nullptr; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       if (options.Get("webContents", &existing_web_contents_value)) { | ||||||
|  |         gin::Handle<WebContents> existing_web_contents; | ||||||
|  |         if (!gin::ConvertFromV8(args->isolate(), existing_web_contents_value, | ||||||
|  |                                 &existing_web_contents)) { | ||||||
|  |           args->ThrowError("options.webContents must be a WebContents"); | ||||||
|  |           return nullptr; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (existing_web_contents->owner_window() != nullptr) { | ||||||
|  |           args->ThrowError( | ||||||
|  |               "options.webContents is already attached to a window"); | ||||||
|  |           return nullptr; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   if (web_preferences.IsEmpty()) |   if (web_preferences.IsEmpty()) | ||||||
|     web_preferences = gin_helper::Dictionary::CreateEmpty(args->isolate()); |     web_preferences = gin_helper::Dictionary::CreateEmpty(args->isolate()); | ||||||
|   if (!web_preferences.Has(options::kShow)) |   if (!web_preferences.Has(options::kShow)) | ||||||
|     web_preferences.Set(options::kShow, false); |     web_preferences.Set(options::kShow, false); | ||||||
|  | 
 | ||||||
|  |   if (!existing_web_contents_value.IsEmpty()) { | ||||||
|  |     web_preferences.SetHidden("webContents", existing_web_contents_value); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   auto web_contents = |   auto web_contents = | ||||||
|       WebContents::CreateFromWebPreferences(args->isolate(), web_preferences); |       WebContents::CreateFromWebPreferences(args->isolate(), web_preferences); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,10 @@ | ||||||
| import { closeAllWindows } from './lib/window-helpers'; | import { closeAllWindows } from './lib/window-helpers'; | ||||||
| import { expect } from 'chai'; | import { expect } from 'chai'; | ||||||
| 
 | 
 | ||||||
| import { BaseWindow, View, WebContentsView } from 'electron/main'; | import { BaseWindow, View, WebContentsView, webContents } from 'electron/main'; | ||||||
| import { once } from 'node:events'; | import { once } from 'node:events'; | ||||||
|  | import { defer } from './lib/spec-helpers'; | ||||||
|  | import { BrowserWindow } from 'electron'; | ||||||
| 
 | 
 | ||||||
| describe('WebContentsView', () => { | describe('WebContentsView', () => { | ||||||
|   afterEach(closeAllWindows); |   afterEach(closeAllWindows); | ||||||
|  | @ -17,6 +19,48 @@ describe('WebContentsView', () => { | ||||||
|     new WebContentsView({}); |     new WebContentsView({}); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   it('accepts existing webContents object', async () => { | ||||||
|  |     const currentWebContentsCount = webContents.getAllWebContents().length; | ||||||
|  | 
 | ||||||
|  |     const wc = (webContents as typeof ElectronInternal.WebContents).create({ sandbox: true }); | ||||||
|  |     defer(() => wc.destroy()); | ||||||
|  |     await wc.loadURL('about:blank'); | ||||||
|  | 
 | ||||||
|  |     const webContentsView = new WebContentsView({ | ||||||
|  |       webContents: wc | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     expect(webContentsView.webContents).to.eq(wc); | ||||||
|  |     expect(webContents.getAllWebContents().length).to.equal(currentWebContentsCount + 1, 'expected only single webcontents to be created'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should throw error when created with already attached webContents to BrowserWindow', () => { | ||||||
|  |     const browserWindow = new BrowserWindow(); | ||||||
|  |     defer(() => browserWindow.webContents.destroy()); | ||||||
|  | 
 | ||||||
|  |     const webContentsView = new WebContentsView(); | ||||||
|  |     defer(() => webContentsView.webContents.destroy()); | ||||||
|  | 
 | ||||||
|  |     browserWindow.contentView.addChildView(webContentsView); | ||||||
|  |     defer(() => browserWindow.contentView.removeChildView(webContentsView)); | ||||||
|  | 
 | ||||||
|  |     expect(() => new WebContentsView({ | ||||||
|  |       webContents: webContentsView.webContents | ||||||
|  |     })).to.throw('options.webContents is already attached to a window'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should throw error when created with already attached webContents to other WebContentsView', () => { | ||||||
|  |     const browserWindow = new BrowserWindow(); | ||||||
|  | 
 | ||||||
|  |     const webContentsView = new WebContentsView(); | ||||||
|  |     defer(() => webContentsView.webContents.destroy()); | ||||||
|  |     webContentsView.webContents.loadURL('about:blank'); | ||||||
|  | 
 | ||||||
|  |     expect(() => new WebContentsView({ | ||||||
|  |       webContents: browserWindow.webContents | ||||||
|  |     })).to.throw('options.webContents is already attached to a window'); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|   it('can be used as content view', () => { |   it('can be used as content view', () => { | ||||||
|     const w = new BaseWindow({ show: false }); |     const w = new BaseWindow({ show: false }); | ||||||
|     w.setContentView(new WebContentsView()); |     w.setContentView(new WebContentsView()); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Krzysztof Halwa
				Krzysztof Halwa